1 20 21 package org.snmp4j.agent.mo.snmp; 22 23 import java.io.*; 24 import java.util.*; 25 26 import org.snmp4j.*; 27 import org.snmp4j.agent.*; 28 import org.snmp4j.agent.mo.*; 29 import org.snmp4j.agent.mo.snmp.SnmpProxyMIB.*; 30 import org.snmp4j.agent.mo.snmp.SnmpTargetMIB.*; 31 import org.snmp4j.agent.request.*; 32 import org.snmp4j.agent.security.*; 33 import org.snmp4j.event.*; 34 import org.snmp4j.log.*; 35 import org.snmp4j.mp.*; 36 import org.snmp4j.smi.*; 37 import org.snmp4j.util.*; 38 import java.net.InetAddress ; 39 40 49 public class ProxyForwarderImpl implements ProxyForwarder { 50 51 private static final LogAdapter logger = 52 LogFactory.getLogger(ProxyForwarderImpl.class); 53 54 private Snmp session; 55 private SnmpProxyMIB proxyMIB; 56 private SnmpTargetMIB targetMIB; 57 private transient Vector counterListeners; 58 59 71 public ProxyForwarderImpl(Snmp session, 72 SnmpProxyMIB proxyMIB, SnmpTargetMIB targetMIB) { 73 this.session = session; 74 this.proxyMIB = proxyMIB; 75 this.targetMIB = targetMIB; 76 } 77 78 88 public boolean forward(ProxyForwardRequest request) { 89 int pduType = request.getCommandEvent().getPDU().getType(); 90 if (SnmpRequest.getViewType(pduType) == VACM.VIEW_NOTIFY) { 91 return multipleForward(request); 92 } 93 else { 94 ResponseEvent resp = singleForward(request); 95 if ((resp != null) && (resp.getResponse() != null)) { 96 PDU respPDU = resp.getResponse(); 97 PDU translatedResponse = DefaultPDUFactory.createPDU( 98 request.getCommandEvent().getSecurityModel()); 99 if (!translatedResponse.getClass().equals(respPDU.getClass())) { 100 translatedResponse.setType(respPDU.getType()); 102 translatedResponse.addAll(respPDU.toArray()); 103 translatedResponse.setErrorIndex(respPDU.getErrorIndex()); 104 translatedResponse.setErrorStatus(respPDU.getErrorStatus()); 105 } 106 else { 107 translatedResponse = respPDU; 108 } 109 if (translatedResponse.getType() == PDU.RESPONSE) { 110 translatedResponse.setRequestID( 111 request.getCommandEvent().getPDU().getRequestID()); 112 if ((translatedResponse instanceof ScopedPDU) && 113 (request.getCommandEvent().getPDU() instanceof ScopedPDU)) { 114 ScopedPDU scopedPDUReq = 115 (ScopedPDU) request.getCommandEvent().getPDU(); 116 ScopedPDU scopedPDUResp = (ScopedPDU) translatedResponse; 117 scopedPDUResp.setContextEngineID(scopedPDUReq.getContextEngineID()); 118 scopedPDUResp.setContextName(scopedPDUReq.getContextName()); 119 } 120 } 121 request.setResponsePDU(translatedResponse); 122 return true; 123 } 124 } 125 return false; 126 } 127 128 protected List getMatches(ProxyForwardRequest request) { 129 List matches = 130 proxyMIB.getProxyRows(request.getProxyType(), 131 request.getContextEngineID(), 132 request.getContext()); 133 for (Iterator it = matches.iterator(); it.hasNext(); ) { 134 SnmpProxyRow possibleMatch = 135 (SnmpProxyRow) (MOTableRow) it.next(); 136 OctetString paramIn = possibleMatch.getSnmpProxyTargetParamsIn(); 137 if (logger.isDebugEnabled()) { 138 logger.debug("Checking possible match for in parameter: "+paramIn); 139 } 140 if (!matchParameters(request, paramIn)) { 141 it.remove(); 142 } 143 } 144 return matches; 145 } 146 147 protected boolean matchParameters(ProxyForwardRequest request, 148 OctetString paramIn) { 149 MOTableRow param2Match = targetMIB.getTargetParamsRow(paramIn, true); 150 if (param2Match != null) { 151 int mpModel = param2Match.getValue( 152 SnmpTargetMIB.idxSnmpTargetParamsMPModel).toInt(); 153 int secModel = param2Match.getValue( 154 SnmpTargetMIB.idxSnmpTargetParamsSecurityModel).toInt(); 155 int secLevel = param2Match.getValue( 156 SnmpTargetMIB.idxSnmpTargetParamsSecurityLevel).toInt(); 157 OctetString secName = (OctetString) param2Match.getValue( 158 SnmpTargetMIB.idxSnmpTargetParamsSecurityName); 159 if (logger.isDebugEnabled()) { 160 logger.debug("Matching request "+request+" with mpModel="+mpModel+ 161 ", secModel="+secModel+", secLevel="+secLevel+ 162 ", secName="+secName); 163 } 164 if ((mpModel == request.getCommandEvent().getMessageProcessingModel()) && 165 (secName.equals(request.getSecurityName())) && 166 ((secModel == 0) || 167 (secModel == request.getCommandEvent().getSecurityModel())) && 168 (secLevel == request.getCommandEvent().getSecurityLevel())) { 169 return true; 170 } 171 } 172 return false; 173 } 174 175 protected ResponseEvent singleForward(ProxyForwardRequest request) { 176 List matches = getMatches(request); 177 if ((matches == null) || (matches.isEmpty())) { 178 if (logger.isInfoEnabled()) { 179 logger.info("No matching proxy entry found for contextEngineID="+ 180 request.getContextEngineID()+ 181 ", context="+request.getContext()+" and request="+ 182 request); 183 } 184 return null; 185 } 186 OctetString outParam = (OctetString) 187 ((MOTableRow) 188 matches.get(0)).getValue(SnmpProxyMIB.idxSnmpProxySingleTargetOut); 189 Target target = targetMIB.getTarget(outParam, 190 request.getContextEngineID(), 191 request.getContext()); 192 if (target == null) { 193 if (logger.isInfoEnabled()) { 194 logger.info("No matching target with name '" + outParam + "'"); 195 } 196 return null; 197 } 198 if (logger.isInfoEnabled()) { 200 logger.info("Forwarding proxy request "+request+" to "+target); 201 } 202 PDU reqPDU = request.getCommandEvent().getPDU(); 203 PDU pdu = DefaultPDUFactory.createPDU(target, reqPDU.getType()); 204 setScope(request, pdu); 205 try { 206 proxyForwardTranslation(request, reqPDU, pdu); 207 ResponseEvent response = null; 208 do { 209 response = session.send(pdu, target); 210 if (logger.isInfoEnabled()) { 211 logger.info("Received proxy response from " + 212 response.getPeerAddress() + 213 " is " + response.getResponse()); 214 } 215 } 216 while (proxyBackwardTranslation(reqPDU, pdu, response)); 217 return response; 218 } 219 catch (Exception ex) { 220 if (logger.isDebugEnabled()) { 221 ex.printStackTrace(); 222 } 223 logger.error("Failed to send proxy request to "+target+" because: "+ 224 ex.getMessage()); 225 fireIncrementCounter(new CounterEvent(this, SnmpConstants.snmpProxyDrops)); 226 if (SNMP4JSettings.isFowardRuntimeExceptions()) { 227 throw new RuntimeException (ex); 228 } 229 return null; 230 } 231 } 232 233 protected boolean proxyBackwardTranslation(PDU reqPDU, PDU pdu, 234 ResponseEvent response) { 235 if (response.getResponse() == null) { 236 return false; 237 } 238 PDU resp = response.getResponse(); 239 if ((resp.getErrorStatus() == PDU.tooBig) && 240 (reqPDU.getType() != PDU.GETBULK)) { 241 response.getResponse().clear(); 242 response.getResponse().setErrorStatus(PDU.noError); 243 response.getResponse().setErrorIndex(0); 244 return false; 245 } 246 if ((resp.getErrorStatus() == PDU.tooBig) && 247 (reqPDU.getType() == PDU.GETBULK) && (pdu.getType() == PDU.GETBULK)) { 248 249 if (pdu.size() == 1) { 250 response.getResponse().clear(); 251 response.getResponse().setErrorStatus(PDU.noError); 252 response.getResponse().setErrorIndex(0); 253 return false; 254 } 255 else { 256 while (pdu.size() > 1) { 257 pdu.trim(); 258 } 259 pdu.setType(PDU.GETNEXT); 260 return true; 261 } 262 } 263 if ((reqPDU instanceof PDUv1) && 264 (!(response.getResponse() instanceof PDUv1))) { 265 boolean resendNeeded = false; 266 for (int i=0; i<resp.size(); i++) { 267 VariableBinding vb = resp.get(i); 268 if (vb.getVariable() instanceof Counter64) { 269 OID nextOID = new OID(vb.getOid()); 270 if (nextOID.last() < 65535) { 271 nextOID.set(nextOID.size()-1, 65535); 272 } 273 else { 274 nextOID.set(nextOID.size()-1, OID.MAX_SUBID_VALUE); 275 } 276 pdu.get(i).setOid(vb.getOid()); 277 resendNeeded = true; 278 } 279 } 280 if (resendNeeded && (reqPDU.getType() != PDU.GETNEXT)) { 281 throw new IllegalArgumentException ( 282 "GET response with Counter64 cannot be proxied"); 283 } 284 else { 285 return true; 286 } 287 } 288 return false; 289 } 290 291 304 protected void proxyForwardTranslation(ProxyForwardRequest request, 305 PDU source, PDU target) 306 throws IllegalArgumentException 307 { 308 target.clear(); 309 target.setType(source.getType()); 310 if (!(target instanceof PDUv1) && !(source instanceof PDUv1)) { 311 target.setMaxRepetitions(source.getMaxRepetitions()); 312 target.setNonRepeaters(source.getNonRepeaters()); 313 } 314 if ((source.getType() == PDU.V1TRAP) && 315 (source instanceof PDUv1) && 316 (!(target instanceof PDUv1))) { 317 PDUv1 sourceV1 = (PDUv1)source; 318 target.setType(PDU.NOTIFICATION); 319 target.add(new VariableBinding(SnmpConstants.sysUpTime, 320 new TimeTicks(sourceV1.getTimestamp()))); 321 target.add(new VariableBinding(SnmpConstants.snmpTrapOID, 322 SnmpConstants.getTrapOID( 323 sourceV1.getEnterprise(), 324 sourceV1.getGenericTrap(), 325 sourceV1.getSpecificTrap()))); 326 target.addAll(source.toArray()); 327 target.add(new VariableBinding(SnmpConstants.snmpTrapAddress, 328 sourceV1.getAgentAddress())); 329 target.add(new VariableBinding(SnmpConstants.snmpTrapEnterprise, 330 sourceV1.getEnterprise())); 331 OctetString community = 332 new OctetString(request.getCommandEvent().getSecurityName()); 333 target.add(new VariableBinding(SnmpConstants.snmpTrapCommunity, 334 community)); 335 } 336 else if (((source.getType() == PDU.NOTIFICATION) || 337 (source.getType() == PDU.INFORM)) && 338 (target instanceof PDUv1)) { 339 PDUv1 targetV1 = (PDUv1)target; 340 target.setType(PDU.V1TRAP); 341 if ((source.size() < 2) || 342 (!(source.get(0).getVariable() instanceof TimeTicks)) || 343 (!(source.get(1).getVariable() instanceof OID))) { 344 throw new IllegalArgumentException ("Proxy source invalid notification PDU: "+ 345 source); 346 } 347 TimeTicks sysUpTime = (TimeTicks) source.get(0).getVariable(); 348 OID trapOID = (OID)source.get(1).getVariable(); 349 int genericID = SnmpConstants.getGenericTrapID(trapOID); 350 if (genericID < 0) { 353 targetV1.setGenericTrap(6); 354 if ((trapOID.size() > 2) && (trapOID.get(trapOID.size() - 2) == 0)) { 355 targetV1.setSpecificTrap(trapOID.get(trapOID.size() - 1)); 356 OID enterprise = new OID(trapOID); 357 enterprise.trim(2); 358 targetV1.setEnterprise(enterprise); 359 } 360 else if (trapOID.size() > 1) { 361 targetV1.setSpecificTrap(trapOID.get(trapOID.size() - 1)); 362 OID enterprise = new OID(trapOID); 363 enterprise.trim(1); 364 targetV1.setEnterprise(enterprise); 365 } 366 } 367 else { 368 targetV1.setGenericTrap(genericID); 369 targetV1.setSpecificTrap(0); 370 } 371 target.addAll(source.toArray()); 372 if (request.getCommandEvent().getPeerAddress() instanceof IpAddress) { 373 InetAddress agentAddress = ((IpAddress) 374 request.getCommandEvent().getPeerAddress()).getInetAddress(); 375 targetV1.setAgentAddress(new IpAddress(agentAddress)); 376 } 377 else { 378 targetV1.setAgentAddress(new IpAddress("0.0.0.0")); 379 } 380 targetV1.setTimestamp(sysUpTime.getValue()); 381 } 382 else { 383 target.addAll(source.toArray()); 384 } 385 } 386 387 protected boolean multipleForward(ProxyForwardRequest request) { 388 List matches = getMatches(request); 389 boolean allOK = true; 390 for (Iterator it = matches.iterator(); it.hasNext(); ) { 391 SnmpProxyRow item = (SnmpProxyRow) it.next(); 392 OctetString outParam = item.getSnmpProxyMultipleTargetOut(); 393 Set tags = SnmpTagList.getTags(outParam); 394 if (logger.isDebugEnabled()) { 395 logger.debug("Proxy multiple targets out with tags "+tags); 396 } 397 for (Iterator tagit = tags.iterator (); tagit.hasNext(); ) { 398 OctetString tag = (OctetString) tagit.next(); 399 Collection targets = this.targetMIB.getTargetAddrRowsForTag(tag); 400 for (Iterator tit = targets.iterator(); tit.hasNext(); ) { 401 SnmpTargetAddrEntryRow targetRow = 402 (SnmpTargetAddrEntryRow) tit.next(); 403 Target target = targetRow.getTarget(request.getContextEngineID(), 404 request.getContext()); 405 if (target != null) { 406 try { 407 PDU reqPDU = request.getCommandEvent().getPDU(); 408 PDU pdu = DefaultPDUFactory.createPDU(target, reqPDU.getType()); 409 setScope(request, pdu); 410 proxyForwardTranslation(request, reqPDU, pdu); 411 ResponseEvent resp = session.send(pdu, target); 412 if (logger.isInfoEnabled()) { 413 logger.info("Forwarded " + request.getCommandEvent() + 414 " to target " + target + " with response " + resp); 415 } 416 if (request.getCommandEvent().getPDU().getType() == PDU.INFORM) { 417 if ((resp.getResponse() == null) || 418 (resp.getResponse().getType() == PDU.REPORT) || 419 (resp.getResponse().getErrorStatus() != PDU.noError)) { 420 allOK = false; 421 } 422 } 423 } 424 catch (IOException ex) { 425 if (logger.isDebugEnabled()) { 426 ex.printStackTrace(); 427 } 428 logger.error("Failed to forward request " + request + 429 " to target " + target); 430 allOK = false; 431 } 432 } 433 else { 434 if (logger.isDebugEnabled()) { 435 logger.debug("Parameters for target " + targetRow + " not found"); 436 } 437 } 438 } 439 } 440 } 441 return allOK; 442 } 443 444 private void setScope(ProxyForwardRequest request, PDU pdu) { 445 if (pdu instanceof ScopedPDU) { 446 ScopedPDU scopedPDU = (ScopedPDU)pdu; 447 scopedPDU.setContextEngineID(request.getContextEngineID()); 448 scopedPDU.setContextName(request.getContext()); 449 } 450 } 451 452 public synchronized void addCounterListener(CounterListener l) { 453 if (counterListeners == null) { 454 counterListeners = new Vector(2); 455 } 456 counterListeners.add(l); 457 } 458 459 public synchronized void removeCounterListener(CounterListener l) { 460 if (counterListeners != null) { 461 counterListeners.remove(l); 462 } 463 } 464 465 protected void fireIncrementCounter(CounterEvent event) { 466 if (counterListeners != null) { 467 Vector listeners = counterListeners; 468 int count = listeners.size(); 469 for (int i = 0; i < count; i++) { 470 ((CounterListener) listeners.elementAt(i)).incrementCounter(event); 471 } 472 } 473 } 474 475 } 476 | Popular Tags |