1 20 21 package org.snmp4j.agent.request; 22 23 import java.util.*; 24 25 import org.snmp4j.*; 26 import org.snmp4j.agent.security.*; 27 import org.snmp4j.mp.*; 28 import org.snmp4j.smi.*; 29 import org.snmp4j.agent.DefaultMOContextScope; 30 import org.snmp4j.agent.MOScope; 31 import org.snmp4j.agent.ManagedObject; 32 import org.snmp4j.log.LogAdapter; 33 import org.snmp4j.log.LogFactory; 34 import org.snmp4j.agent.mo.snmp.CoexistenceInfo; 35 import org.snmp4j.agent.MOQuery; 36 37 43 public class SnmpRequest extends AbstractRequest { 44 45 private static final LogAdapter logger = 46 LogFactory.getLogger(SnmpRequest.class); 47 48 public static final OctetString DEFAULT_CONTEXT = new OctetString(); 49 50 private CommandResponderEvent requestEvent; 51 private CoexistenceInfo coexistenceInfo; 52 53 private PDU response; 54 private OctetString viewName; 55 56 private static int nextTransactionID = 0; 57 58 public SnmpRequest(CommandResponderEvent request, CoexistenceInfo cinfo) { 59 this.requestEvent = request; 60 this.coexistenceInfo = cinfo; 61 correctRequestValues(); 62 this.transactionID = nextTransactionID(); 63 } 64 65 public static int nextTransactionID() { 66 return nextTransactionID++; 67 } 68 69 protected synchronized void setupSubRequests() { 70 int capacity = requestEvent.getPDU().size(); 71 int totalRepetitions = (requestEvent.getPDU() instanceof PDUv1) ? 0 : 72 repeaterRowSize*requestEvent.getPDU().getMaxRepetitions(); 73 subrequests = new ArrayList(capacity + totalRepetitions); 74 if (response == null) { 75 response = createResponse(); 76 } 77 for (int i=0; i<requestEvent.getPDU().size(); i++) { 78 SnmpSubRequest subReq = 79 new SnmpSubRequest(requestEvent.getPDU().get(i), i); 80 addSubRequest(subReq); 81 } 82 if (logger.isDebugEnabled()) { 83 logger.debug("SnmpSubRequests initialized: "+subrequests); 84 } 85 } 86 87 95 public synchronized int getCompleteRepetitions() { 96 int i = 0; 97 for (Iterator it = subrequests.iterator(); it.hasNext(); i++) { 98 SnmpSubRequest sreq = (SnmpSubRequest) it.next(); 99 if (!sreq.isComplete()) { 100 return i/getRepeaterCount(); 101 } 102 } 103 return i/getRepeaterCount(); 104 } 105 106 public int getMaxRepetitions() { 107 return requestEvent.getPDU().getMaxRepetitions(); 108 } 109 110 public int getNonRepeaters() { 111 return requestEvent.getPDU().getNonRepeaters(); 112 } 113 114 private void addSubRequest(SubRequest subReq) { 115 subrequests.add(subReq); 116 response.add(subReq.getVariableBinding()); 117 } 118 119 protected int getMaxPhase() { 120 return (is2PC()) ? PHASE_2PC_CLEANUP : PHASE_1PC; 121 } 122 123 133 134 public int size() { 135 return requestEvent.getPDU().size(); 136 } 137 138 public Object getSource() { 139 return requestEvent; 140 } 141 142 public CommandResponderEvent getInitiatingEvent() { 143 return requestEvent; 144 } 145 146 public void setRequestEvent(CommandResponderEvent requestEvent) { 147 this.requestEvent = requestEvent; 148 } 149 150 protected void assignErrorStatus2Response() { 151 int errStatus = getErrorStatus(); 152 if (requestEvent.getMessageProcessingModel() == MessageProcessingModel.MPv1) { 153 switch (errStatus) { 154 case SnmpConstants.SNMP_ERROR_NOT_WRITEABLE: 155 case SnmpConstants.SNMP_ERROR_NO_ACCESS: 156 case SnmpConstants.SNMP_ERROR_NO_CREATION: 157 case SnmpConstants.SNMP_ERROR_INCONSISTENT_NAME: { 158 response.setErrorStatus(SnmpConstants.SNMP_ERROR_NO_SUCH_NAME); 159 break; 160 } 161 case SnmpConstants.SNMP_ERROR_AUTHORIZATION_ERROR: 162 case SnmpConstants.SNMP_ERROR_RESOURCE_UNAVAILABLE: 163 case SnmpConstants.SNMP_ERROR_COMMIT_FAILED: 164 case SnmpConstants.SNMP_ERROR_UNDO_FAILED: { 165 response.setErrorStatus(SnmpConstants.SNMP_ERROR_GENERAL_ERROR); 166 break; 167 } 168 case SnmpConstants.SNMP_ERROR_WRONG_VALUE: 169 case SnmpConstants.SNMP_ERROR_WRONG_LENGTH: 170 case SnmpConstants.SNMP_ERROR_INCONSISTENT_VALUE: 171 case SnmpConstants.SNMP_ERROR_WRONG_TYPE: { 172 response.setErrorStatus(SnmpConstants.SNMP_ERROR_BAD_VALUE); 173 break; 174 } 175 default: { 176 response.setErrorStatus(errStatus); 177 } 178 } 179 for (int i=0; i<response.size(); i++) { 180 VariableBinding vb = response.get(i); 181 if (vb.isException()) { 182 response.setErrorStatus(PDU.noSuchName); 183 response.setErrorIndex(i+1); 184 response.set(i, new VariableBinding(vb.getOid())); 185 return; 186 } 187 } 188 } 189 else { 190 response.setErrorStatus(errStatus); 191 } 192 response.setErrorIndex(getErrorIndex()); 193 } 194 195 private PDU createResponse() { 196 PDU resp = (PDU) requestEvent.getPDU().clone(); 197 resp.clear(); 198 resp.setType(PDU.RESPONSE); 199 resp.setRequestID(requestEvent.getPDU().getRequestID()); 200 resp.setErrorIndex(0); 201 resp.setErrorStatus(PDU.noError); 202 return resp; 203 } 204 205 private void correctRequestValues() { 206 PDU request = requestEvent.getPDU(); 207 if (!(request instanceof PDUv1)) { 208 if (request.getMaxRepetitions() < 0) { 209 request.setMaxRepetitions(0); 210 } 211 if (request.getNonRepeaters() < 0) { 212 request.setNonRepeaters(0); 213 } 214 repeaterStartIndex = request.getNonRepeaters(); 215 repeaterRowSize = 216 Math.max(request.size() - repeaterStartIndex, 0); 217 } 218 else { 219 repeaterStartIndex = 0; 220 repeaterRowSize = request.size(); 221 } 222 } 223 224 public PDU getResponsePDU() { 225 return (PDU) getResponse(); 226 } 227 228 public Object getResponse() { 229 if (response == null) { 230 response = createResponse(); 231 } 232 assignErrorStatus2Response(); 233 return response; 234 } 235 236 241 public Iterator iterator() { 242 initSubRequests(); 243 return new SnmpSubRequestIterator(); 244 } 245 246 protected boolean is2PC() { 247 return (requestEvent.getPDU().getType() == PDU.SET); 248 } 249 250 public OctetString getContext() { 251 if (coexistenceInfo != null) { 252 return coexistenceInfo.getContextName(); 253 } 254 else if (requestEvent.getPDU() instanceof ScopedPDU) { 255 return ((ScopedPDU)requestEvent.getPDU()).getContextName(); 256 } 257 return DEFAULT_CONTEXT; 258 } 259 260 public OctetString getViewName() { 261 return viewName; 262 } 263 264 public void setViewName(OctetString viewName) { 265 this.viewName = viewName; 266 } 267 268 public int getSecurityLevel() { 269 return requestEvent.getSecurityLevel(); 270 } 271 272 public int getSecurityModel() { 273 return requestEvent.getSecurityModel(); 274 } 275 276 public OctetString getSecurityName() { 277 if (coexistenceInfo != null) { 278 return coexistenceInfo.getSecurityName(); 279 } 280 return new OctetString(requestEvent.getSecurityName()); 281 } 282 283 public int getViewType() { 284 return getViewType(requestEvent.getPDU().getType()); 285 } 286 287 294 public static final int getViewType(int pduType) { 295 switch (pduType) { 296 case PDU.GETNEXT: 297 case PDU.GET: 298 case PDU.GETBULK: { 299 return VACM.VIEW_READ; 300 } 301 case PDU.INFORM: 302 case PDU.TRAP: 303 case PDU.V1TRAP: { 304 return VACM.VIEW_NOTIFY; 305 } 306 default: { 307 return VACM.VIEW_WRITE; 308 } 309 } 310 } 311 312 protected synchronized void addRepeaterSubRequest() { 313 int predecessorIndex = subrequests.size() - repeaterRowSize; 314 SnmpSubRequest sreq = 315 new SnmpSubRequest((SnmpSubRequest)subrequests.get(predecessorIndex), 316 subrequests.size()); 317 addSubRequest(sreq); 318 } 319 320 public int getErrorIndex() { 321 if (errorStatus == SnmpConstants.SNMP_ERROR_SUCCESS) { 322 return 0; 323 } 324 initSubRequests(); 325 int index = 1; 326 for (Iterator it = subrequests.iterator(); it.hasNext(); index++) { 327 SubRequest sreq = (SubRequest) it.next(); 328 if (sreq.getStatus().getErrorStatus() != SnmpConstants.SNMP_ERROR_SUCCESS) { 329 return index; 330 } 331 } 332 return 0; 333 } 334 335 336 public int getTransactionID() { 337 return transactionID; 338 } 339 340 public CoexistenceInfo getCoexistenceInfo() { 341 return coexistenceInfo; 342 } 343 344 353 private List lastRow(int upperBoundIndex) { 354 if ((repeaterRowSize == 0) || (upperBoundIndex <= repeaterStartIndex)) { 355 return null; 356 } 357 int rows = (upperBoundIndex - repeaterStartIndex) / repeaterRowSize; 358 int startIndex = repeaterStartIndex + (repeaterRowSize*(rows-1)); 359 int endIndex = repeaterStartIndex + (repeaterRowSize*rows); 360 if ((startIndex < repeaterStartIndex) || (endIndex > subrequests.size())) { 361 return null; 362 } 363 return subrequests.subList(startIndex, endIndex); 364 } 365 366 public int getMessageProcessingModel() { 367 return this.requestEvent.getMessageProcessingModel(); 368 } 369 370 public int getRepeaterCount() { 371 PDU reqPDU = requestEvent.getPDU(); 372 return Math.max(reqPDU.size() - reqPDU.getNonRepeaters(), 0); 373 } 374 375 public boolean isPhaseComplete() { 376 if (errorStatus == SnmpConstants.SNMP_ERROR_SUCCESS) { 377 initSubRequests(); 378 for (Iterator it = subrequests.iterator(); it.hasNext(); ) { 379 SubRequest subreq = (SubRequest) it.next(); 380 RequestStatus status = subreq.getStatus(); 381 if (status.getErrorStatus() != SnmpConstants.SNMP_ERROR_SUCCESS) { 382 return true; 383 } 384 else if (!status.isPhaseComplete()) { 385 return false; 386 } 387 } 388 } 389 if (requestEvent.getPDU().getType() == PDU.GETBULK) { 390 SnmpSubRequestIterator it = 391 new SnmpSubRequestIterator(subrequests.size(), 1); 392 return !it.hasNext(); 393 } 394 return true; 395 } 396 397 public boolean isBulkRequest() { 398 return (requestEvent.getPDU().getType() == PDU.GETBULK); 399 } 400 401 406 public class SnmpSubRequestIterator implements SubRequestIterator { 407 408 private int cursor = 0; 409 private int increment = 1; 410 private boolean noAppending; 411 412 protected SnmpSubRequestIterator() { 413 this.cursor = 0; 414 } 415 416 protected SnmpSubRequestIterator(int offset, int increment) { 417 this.cursor = offset; 418 this.increment = increment; 419 } 420 421 protected void setNoAppending(boolean noAppending) { 422 this.noAppending = noAppending; 423 } 424 425 430 public boolean hasNext() { 431 synchronized (SnmpRequest.this) { 432 PDU reqPDU = requestEvent.getPDU(); 433 if (reqPDU.getType() == PDU.GETBULK) { 434 if (noAppending && (cursor >= subrequests.size())) { 435 return false; 436 } 437 if (cursor < Math.min(reqPDU.size(), reqPDU.getNonRepeaters())) { 438 return true; 439 } 440 else { 441 if (cursor < reqPDU.getNonRepeaters() + 442 reqPDU.getMaxRepetitions() * getRepeaterCount()) { 443 List lastRow = lastRow(cursor); 444 if (lastRow != null) { 445 boolean allEndOfMibView = true; 446 SubRequest sreq = null; 447 for (Iterator it = lastRow.iterator(); it.hasNext(); ) { 448 sreq = (SubRequest) it.next(); 449 if (sreq.getVariableBinding().getSyntax() != 450 SMIConstants.EXCEPTION_END_OF_MIB_VIEW) { 451 allEndOfMibView = false; 452 break; 453 } 454 } 455 if (allEndOfMibView) { 456 if ((sreq != null) && 458 (sreq.getIndex() < subrequests.size())) { 459 int lastElementIndex = sreq.getIndex(); 460 List tail = subrequests.subList(lastElementIndex + 1, 461 subrequests.size()); 462 tail.clear(); 463 tail = response.getVariableBindings(). 464 subList(lastElementIndex + 1, response.size()); 465 tail.clear(); 466 } 467 return false; 468 } 469 } 470 return (response.getBERLength() < 471 requestEvent.getMaxSizeResponsePDU()); 472 } 473 } 474 return false; 475 } 476 return (cursor < reqPDU.size()); 477 } 478 } 479 480 public SubRequest nextSubRequest() { 481 if (!hasNext()) { 482 throw new NoSuchElementException(); 483 } 484 if ((requestEvent.getPDU().getType() == PDU.GETBULK) && 485 (cursor >= subrequests.size())) { 486 while (cursor >= subrequests.size()) { 487 addRepeaterSubRequest(); 488 } 489 } 490 SubRequest sreq = (SubRequest) subrequests.get(cursor); 491 cursor += increment; 492 return sreq; 493 } 494 495 public void remove() { 496 throw new UnsupportedOperationException ("Remove is not supported "+ 497 "on sub-requests"); 498 } 499 500 public Object next() { 501 return nextSubRequest(); 502 } 503 504 public boolean equals(Object other) { 505 if (other instanceof Request) { 506 return ((Request)other).getTransactionID() == getTransactionID(); 507 } 508 return false; 509 } 510 511 public int hashCode() { 512 return getTransactionID(); 513 } 514 } 515 516 517 522 public class SnmpSubRequest 523 implements org.snmp4j.agent.request.SnmpSubRequest, RequestStatusListener { 524 525 private RequestStatus status; 526 private VariableBinding vb; 527 private Object undoValue; 528 private MOScope scope; 529 private ManagedObject targetMO; 530 private MOQuery query; 531 private int index; 532 533 private volatile Object userObject; 534 535 protected SnmpSubRequest(VariableBinding subrequest, int index) { 536 this.vb = subrequest; 537 this.index = index; 538 switch (requestEvent.getPDU().getType()) { 539 case PDU.GETBULK: 540 case PDU.GETNEXT: { 541 this.scope = getNextScope(this.vb.getOid()); 542 break; 543 } 544 default: { 545 OID oid = this.vb.getOid(); 546 this.scope = new DefaultMOContextScope(getContext(), 547 oid, true, oid, true); 548 } 549 } 550 status = new RequestStatus(); 551 status.addRequestStatusListener(this); 552 if (logger.isDebugEnabled()) { 553 logger.debug("Created subrequest "+index+" with scope "+scope+ 554 " from "+subrequest); 555 } 556 } 557 558 protected MOScope getNextScope(OID previousOID) { 559 return new DefaultMOContextScope(getContext(), previousOID, false, 560 null, false); 561 } 562 563 protected SnmpSubRequest(SnmpSubRequest predecessor, int index) { 564 this((VariableBinding)predecessor.getVariableBinding().clone(), index); 565 } 568 569 public Request getRequest() { 570 return SnmpRequest.this; 571 } 572 573 public RequestStatus getStatus() { 574 return status; 575 } 576 577 public VariableBinding getVariableBinding() { 578 return vb; 579 } 580 581 public void setStatus(RequestStatus status) { 582 this.status = status; 583 } 584 585 public Object getUndoValue() { 586 return undoValue; 587 } 588 589 public void setUndoValue(Object undoInformation) { 590 this.undoValue = undoInformation; 591 } 592 593 public void requestStatusChanged(RequestStatusEvent event) { 594 int newStatus = event.getStatus().getErrorStatus(); 595 setErrorStatus(newStatus); 596 if (logger.isDebugEnabled() && 597 (newStatus != SnmpConstants.SNMP_ERROR_SUCCESS)) { 598 new Exception ("Error '"+ 599 PDU.toErrorStatusText(event.getStatus().getErrorStatus())+ 600 "' generated at: "+vb).printStackTrace(); 601 } 602 } 603 604 public MOScope getScope() { 605 return scope; 606 } 607 608 public void completed() { 609 status.setPhaseComplete(true); 610 } 611 612 public boolean hasError() { 613 return getStatus().getErrorStatus() != SnmpConstants.SNMP_ERROR_SUCCESS; 614 } 615 616 public boolean isComplete() { 617 return status.isPhaseComplete(); 618 } 619 620 public void setTargetMO(ManagedObject managedObject) { 621 this.targetMO = managedObject; 622 } 623 624 public ManagedObject getTargetMO() { 625 return targetMO; 626 } 627 628 public SnmpRequest getSnmpRequest() { 629 return SnmpRequest.this; 630 } 631 632 public void setErrorStatus(int errorStatus) { 633 SnmpRequest.this.setErrorStatus(errorStatus); 634 } 635 636 public int getIndex() { 637 return index; 638 } 639 640 public void setQuery(MOQuery query) { 641 this.query = query; 642 } 643 644 public MOQuery getQuery() { 645 return query; 646 } 647 648 public String toString() { 649 return getClass().getName()+"[scope="+scope+ 650 ",vb="+vb+",status="+status+",query="+query+",index="+index+ 651 ",targetMO="+targetMO+"]"; 652 } 653 654 public SubRequestIterator repetitions() { 655 return repetitions(false); 656 } 657 658 private SubRequestIterator repetitions(boolean noAppending) { 659 initSubRequests(); 660 if (isBulkRequest()) { 661 int repeaters = requestEvent.getPDU().size() - 662 requestEvent.getPDU().getNonRepeaters(); 663 SnmpSubRequestIterator it = 664 new SnmpSubRequestIterator(getIndex(), repeaters); 665 it.setNoAppending(noAppending); 666 return it; 667 } 668 return new SubRequestIteratorSupport(Collections.EMPTY_LIST.iterator()); 669 } 670 671 public void updateNextRepetition() { 672 if (!isBulkRequest()) { 673 return; 674 } 675 this.query = null; 676 SubRequestIterator repetitions = repetitions(true); 677 repetitions.next(); 679 while (repetitions.hasNext()) { 680 SnmpSubRequest nsreq = (SnmpSubRequest) repetitions.nextSubRequest(); 681 if ((getStatus().getErrorStatus() == PDU.noError) && 682 (!this.vb.isException())) { 683 nsreq.query = null; 684 nsreq.scope = getNextScope(this.vb.getOid()); 685 nsreq.getVariableBinding().setOid(this.vb.getOid()); 686 } 687 else if (this.vb.isException()) { 688 nsreq.query = null; 689 nsreq.getVariableBinding().setOid(this.vb.getOid()); 690 nsreq.getVariableBinding().setVariable(this.vb.getVariable()); 691 nsreq.getStatus().setPhaseComplete(true); 692 } 693 } 694 } 695 696 public final int getErrorStatus() { 697 return getStatus().getErrorStatus(); 698 } 699 700 public Object getUserObject() { 701 return userObject; 702 } 703 704 public void setUserObject(Object userObject) { 705 this.userObject = userObject; 706 } 707 708 } 709 710 } 711 712 | Popular Tags |