1 /* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.jmx.snmp.agent; 26 27 import java.util.Vector; 28 import java.util.Hashtable; 29 import java.util.Enumeration; 30 import java.util.Iterator; 31 import java.util.NoSuchElementException; 32 import java.util.Arrays; 33 import java.util.logging.Level; 34 35 import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; 36 import com.sun.jmx.snmp.SnmpVarBind; 37 import com.sun.jmx.snmp.SnmpStatusException; 38 import com.sun.jmx.snmp.SnmpDefinitions; 39 import com.sun.jmx.snmp.SnmpOid; 40 import com.sun.jmx.snmp.SnmpPdu; 41 import com.sun.jmx.snmp.SnmpEngine; 42 43 // XXX: things to do: use SnmpOid rather than `instance' for future 44 // evolutions. 45 // XXX: Maybe use hashlists rather than vectors for entries? 46 // => in that case, the key should be SnmpOid.toString() 47 // 48 /** 49 * This class is used to register varbinds from a SNMP varbind list with 50 * the SnmpMibNode responsible for handling the requests concerning that 51 * varbind. 52 * This class holds a hashtable of Handler nodes, whith the involved 53 * SnmpMibNode as a key. 54 * When the involved SnmpMibNode is a group, the sublist of varbind is 55 * directly stored in the Handler node. 56 * When the involved SnmpMibNode is a table, the sublist is stored in a 57 * sorted array indexed by the OID of the entry involved. 58 */ 59 final class SnmpRequestTree { 60 61 // Constructor: 62 // @param req The SnmpMibRequest that will be segmented in this 63 // tree. It holds the original varbind vector passed 64 // by the SnmpSubRequestHandler to this MIB. This 65 // varbind vector is used to retrieve the "real" 66 // position of a varbind in the vector. There is no other easy 67 // way to do this - since as a result of the segmentation the 68 // original positions will be lost. 69 // @param creationflag indicates whether the operation involved 70 // allows for entry creation (ie: it is a SET request). 71 // @param pdutype indicates the type of the request PDU as defined 72 // in SnmpDefinitions 73 // 74 SnmpRequestTree(SnmpMibRequest req, boolean creationflag, int pdutype) { 75 this.request = req; 76 this.version = req.getVersion(); 77 this.creationflag = creationflag; 78 this.hashtable = new Hashtable<>(); 79 setPduType(pdutype); 80 } 81 82 public static int mapSetException(int errorStatus, int version) 83 throws SnmpStatusException { 84 85 final int errorCode = errorStatus; 86 87 if (version == SnmpDefinitions.snmpVersionOne) 88 return errorCode; 89 90 int mappedErrorCode = errorCode; 91 92 // Now take care of V2 errorCodes that can be stored 93 // in the varbind itself: 94 if (errorCode == SnmpStatusException.noSuchObject) 95 // noSuchObject => notWritable 96 mappedErrorCode = SnmpStatusException.snmpRspNotWritable; 97 98 else if (errorCode == SnmpStatusException.noSuchInstance) 99 // noSuchInstance => notWritable 100 mappedErrorCode = SnmpStatusException.snmpRspNotWritable; 101 102 return mappedErrorCode; 103 } 104 105 public static int mapGetException(int errorStatus, int version) 106 throws SnmpStatusException { 107 108 final int errorCode = errorStatus; 109 if (version == SnmpDefinitions.snmpVersionOne) 110 return errorCode; 111 112 int mappedErrorCode = errorCode; 113 114 // Now take care of V2 errorCodes that can be stored 115 // in the varbind itself: 116 if (errorCode == 117 SnmpStatusException.noSuchObject) 118 // noSuchObject => noSuchObject 119 mappedErrorCode = errorCode; 120 121 else if (errorCode == 122 SnmpStatusException.noSuchInstance) 123 // noSuchInstance => noSuchInstance 124 mappedErrorCode = errorCode; 125 126 // Now we're going to try to transform every other 127 // global code in either noSuchInstance or noSuchObject, 128 // so that the get can return a partial result. 129 // 130 // Only noSuchInstance or noSuchObject can be stored 131 // in the varbind itself. 132 // 133 134 // According to RFC 1905: noAccess is emitted when the 135 // the access is denied because it is not in the MIB view... 136 // 137 else if (errorCode == 138 SnmpStatusException.noAccess) 139 // noAccess => noSuchInstance 140 mappedErrorCode = SnmpStatusException.noSuchInstance; 141 142 // According to RFC 1905: (my interpretation because it is not 143 // really clear) The specified variable name exists - but the 144 // variable does not exists and cannot be created under the 145 // present circumstances (probably because the request specifies 146 // another variable/value which is incompatible, or because the 147 // value of some other variable in the MIB prevents the creation) 148 // 149 // Note that this error should never be raised in a GET context 150 // but who knows? 151 // 152 else if (errorCode == SnmpStatusException.snmpRspInconsistentName) 153 // inconsistentName => noSuchInstance 154 mappedErrorCode = SnmpStatusException.noSuchInstance; 155 156 // All the errors comprised between snmpRspWrongType and 157 // snmpRspInconsistentValue concern values: so we're going 158 // to assume the OID was correct, and reply with noSuchInstance. 159 // 160 // Note that this error should never be raised in a GET context 161 // but who knows? 162 // 163 else if ((errorCode >= SnmpStatusException.snmpRspWrongType) && 164 (errorCode <= SnmpStatusException.snmpRspInconsistentValue)) 165 mappedErrorCode = SnmpStatusException.noSuchInstance; 166 167 // We're going to assume the OID was correct, and reply 168 // with noSuchInstance. 169 // 170 else if (errorCode == SnmpStatusException.readOnly) 171 mappedErrorCode = SnmpStatusException.noSuchInstance; 172 173 // For all other errors but genErr, we're going to reply with 174 // noSuchObject 175 // 176 else if (errorCode != SnmpStatusException.snmpRspAuthorizationError && 177 errorCode != SnmpStatusException.snmpRspGenErr) 178 mappedErrorCode = SnmpStatusException.noSuchObject; 179 180 // Only genErr will abort the GET and be returned as global 181 // error. 182 // 183 return mappedErrorCode; 184 185 } 186 187 //------------------------------------------------------------------- 188 // This class is a package implementation of the enumeration of 189 // SnmSubRequest associated with an Handler node. 190 //------------------------------------------------------------------- 191 192 static final class Enum implements Enumeration<SnmpMibSubRequest> { 193 Enum(SnmpRequestTree hlist,Handler h) { 194 handler = h; 195 this.hlist = hlist; 196 size = h.getSubReqCount(); 197 } 198 private final Handler handler; 199 private final SnmpRequestTree hlist; 200 private int entry = 0; 201 private int iter = 0; 202 private int size = 0; 203 204 @Override 205 public boolean hasMoreElements() { 206 return iter < size; 207 } 208 209 @Override 210 public SnmpMibSubRequest nextElement() throws NoSuchElementException { 211 if (iter == 0) { 212 if (handler.sublist != null) { 213 iter++; 214 return hlist.getSubRequest(handler); 215 } 216 } 217 iter ++; 218 if (iter > size) throw new NoSuchElementException(); 219 SnmpMibSubRequest result = hlist.getSubRequest(handler,entry); 220 entry++; 221 return result; 222 } 223 } 224 225 //------------------------------------------------------------------- 226 // This class is a package implementation of the SnmpMibSubRequest 227 // interface. It can only be instantiated by SnmpRequestTree. 228 //------------------------------------------------------------------- 229 230 static final class SnmpMibSubRequestImpl implements SnmpMibSubRequest { 231 SnmpMibSubRequestImpl(SnmpMibRequest global, Vector<SnmpVarBind> sublist, 232 SnmpOid entryoid, boolean isnew, 233 boolean getnextflag, SnmpVarBind rs) { 234 this.global = global; 235 varbinds = sublist; 236 this.version = global.getVersion(); 237 this.entryoid = entryoid; 238 this.isnew = isnew; 239 this.getnextflag = getnextflag; 240 this.statusvb = rs; 241 } 242 243 final private Vector<SnmpVarBind> varbinds; 244 final private SnmpMibRequest global; 245 final private int version; 246 final private boolean isnew; 247 final private SnmpOid entryoid; 248 final private boolean getnextflag; 249 final private SnmpVarBind statusvb; 250 251 // ------------------------------------------------------------- 252 // Implements the method defined in SnmpMibRequest interface. 253 // See SnmpMibRequest for the java doc. 254 // ------------------------------------------------------------- 255 @Override 256 public Enumeration<SnmpVarBind> getElements() { 257 return varbinds.elements(); 258 } 259 260 // ------------------------------------------------------------- 261 // Implements the method defined in SnmpMibRequest interface. 262 // See SnmpMibRequest for the java doc. 263 // ------------------------------------------------------------- 264 @Override 265 public Vector<SnmpVarBind> getSubList() { 266 return varbinds; 267 } 268 269 // ------------------------------------------------------------- 270 // Implements the method defined in SnmpMibRequest interface. 271 // See SnmpMibRequest for the java doc. 272 // ------------------------------------------------------------- 273 @Override 274 public final int getSize() { 275 if (varbinds == null) return 0; 276 return varbinds.size(); 277 } 278 279 // ------------------------------------------------------------- 280 // Implements the method defined in SnmpMibRequest interface. 281 // See SnmpMibRequest for the java doc. 282 // ------------------------------------------------------------- 283 @Override 284 public void addVarBind(SnmpVarBind varbind) { 285 // XXX not sure we must also add the varbind in the global 286 // request? or whether we should raise an exception: 287 // in principle, this method should not be called! 288 varbinds.addElement(varbind); 289 global.addVarBind(varbind); 290 } 291 292 // ------------------------------------------------------------- 293 // Implements the method defined in SnmpMibSubRequest interface. 294 // See SnmpMibSubRequest for the java doc. 295 // ------------------------------------------------------------- 296 @Override 297 public boolean isNewEntry() { 298 return isnew; 299 } 300 301 // ------------------------------------------------------------- 302 // Implements the method defined in SnmpMibSubRequest interface. 303 // See SnmpMibSubRequest for the java doc. 304 // ------------------------------------------------------------- 305 @Override 306 public SnmpOid getEntryOid() { 307 return entryoid; 308 } 309 310 // ------------------------------------------------------------- 311 // Implements the method defined in SnmpMibRequest interface. 312 // See SnmpMibRequest for the java doc. 313 // ------------------------------------------------------------- 314 @Override 315 public int getVarIndex(SnmpVarBind varbind) { 316 if (varbind == null) return 0; 317 return global.getVarIndex(varbind); 318 } 319 320 // ------------------------------------------------------------- 321 // Implements the method defined in SnmpMibRequest interface. 322 // See SnmpMibRequest for the java doc. 323 // ------------------------------------------------------------- 324 @Override 325 public Object getUserData() { return global.getUserData(); } 326 327 328 // ------------------------------------------------------------- 329 // Implements the method defined in SnmpMibSubRequest interface. 330 // See SnmpMibSubRequest for the java doc. 331 // ------------------------------------------------------------- 332 333 @Override 334 public void registerGetException(SnmpVarBind var, 335 SnmpStatusException exception) 336 throws SnmpStatusException { 337 // The index in the exception must correspond to 338 // the SNMP index ... 339 // 340 if (version == SnmpDefinitions.snmpVersionOne) 341 throw new SnmpStatusException(exception, getVarIndex(var)+1); 342 343 if (var == null) 344 throw exception; 345 346 // If we're doing a getnext ==> endOfMibView 347 if (getnextflag) { 348 var.value = SnmpVarBind.endOfMibView; 349 return; 350 } 351 352 final int errorCode = mapGetException(exception.getStatus(), 353 version); 354 355 // Now take care of V2 errorCodes that can be stored 356 // in the varbind itself: 357 if (errorCode == 358 SnmpStatusException.noSuchObject) 359 // noSuchObject => noSuchObject 360 var.value= SnmpVarBind.noSuchObject; 361 362 else if (errorCode == 363 SnmpStatusException.noSuchInstance) 364 // noSuchInstance => noSuchInstance 365 var.value= SnmpVarBind.noSuchInstance; 366 367 else 368 throw new SnmpStatusException(errorCode, getVarIndex(var)+1); 369 370 } 371 372 // ------------------------------------------------------------- 373 // Implements the method defined in SnmpMibSubRequest interface. 374 // See SnmpMibSubRequest for the java doc. 375 // ------------------------------------------------------------- 376 @Override 377 public void registerSetException(SnmpVarBind var, 378 SnmpStatusException exception) 379 throws SnmpStatusException { 380 // The index in the exception must correspond to 381 // the SNMP index ... 382 // 383 if (version == SnmpDefinitions.snmpVersionOne) 384 throw new SnmpStatusException(exception, getVarIndex(var)+1); 385 386 // Although the first pass of check() did not fail, 387 // the set() phase could not be carried out correctly. 388 // Since we don't know how to make an "undo", and some 389 // assignation may already have been performed, we're going 390 // to throw an snmpRspUndoFailed. 391 // 392 throw new SnmpStatusException(SnmpDefinitions.snmpRspUndoFailed, 393 getVarIndex(var)+1); 394 } 395 396 // ------------------------------------------------------------- 397 // Implements the method defined in SnmpMibSubRequest interface. 398 // See SnmpMibSubRequest for the java doc. 399 // ------------------------------------------------------------- 400 @Override 401 public void registerCheckException(SnmpVarBind var, 402 SnmpStatusException exception) 403 throws SnmpStatusException { 404 // The index in the exception must correspond to 405 // the SNMP index ... 406 // 407 // We throw the exception in order to abort the SET operation 408 // in an atomic way. 409 final int errorCode = exception.getStatus(); 410 final int mappedErrorCode = mapSetException(errorCode, 411 version); 412 413 if (errorCode != mappedErrorCode) 414 throw new 415 SnmpStatusException(mappedErrorCode, getVarIndex(var)+1); 416 else 417 throw new SnmpStatusException(exception, getVarIndex(var)+1); 418 } 419 420 // ------------------------------------------------------------- 421 // Implements the method defined in SnmpMibRequest interface. 422 // See SnmpMibRequest for the java doc. 423 // ------------------------------------------------------------- 424 @Override 425 public int getVersion() { 426 return version; 427 } 428 429 @Override 430 public SnmpVarBind getRowStatusVarBind() { 431 return statusvb; 432 } 433 434 @Override 435 public SnmpPdu getPdu() { 436 return global.getPdu(); 437 } 438 439 @Override 440 public int getRequestPduVersion() { 441 return global.getRequestPduVersion(); 442 } 443 444 @Override 445 public SnmpEngine getEngine() { 446 return global.getEngine(); 447 } 448 449 @Override 450 public String getPrincipal() { 451 return global.getPrincipal(); 452 } 453 454 @Override 455 public int getSecurityLevel() { 456 return global.getSecurityLevel(); 457 } 458 459 @Override 460 public int getSecurityModel() { 461 return global.getSecurityModel(); 462 } 463 464 @Override 465 public byte[] getContextName() { 466 return global.getContextName(); 467 } 468 469 @Override 470 public byte[] getAccessContextName() { 471 return global.getAccessContextName(); 472 } 473 } 474 475 //------------------------------------------------------------------- 476 // This class implements a node in the SnmpRequestTree. 477 // It stores: 478 // o The SnmpMibNode involved (key) 479 // o The sublist of varbind directly handled by this node 480 // o A vector of sublists concerning the entries (existing or not) 481 // of the SnmpMIbNode (when it is a table). 482 //------------------------------------------------------------------- 483 484 static final class Handler { 485 SnmpMibNode meta; // The meta which handles the sublist. 486 int depth; // The depth of the meta node. 487 Vector<SnmpVarBind> sublist; // The sublist of varbinds to be handled. 488 // List entryoids; // Sorted array of entry oids 489 // List entrylists; // Sorted array of entry lists 490 // List isentrynew; // Sorted array of booleans 491 SnmpOid[] entryoids = null; // Sorted array of entry oids 492 Vector<SnmpVarBind>[] entrylists = null; // Sorted array of entry lists 493 boolean[] isentrynew = null; // Sorted array of booleans 494 SnmpVarBind[] rowstatus = null; // RowStatus varbind, if any 495 int entrycount = 0; 496 int entrysize = 0; 497 498 final int type; // request PDU type as defined in SnmpDefinitions 499 final private static int Delta = 10; 500 501 public Handler(int pduType) { 502 this.type = pduType; 503 } 504 505 /** 506 * Adds a varbind in this node sublist. 507 */ 508 public void addVarbind(SnmpVarBind varbind) { 509 if (sublist == null) sublist = new Vector<>(); 510 sublist.addElement(varbind); 511 } 512 513 /** 514 * register an entry for the given oid at the given position with 515 * the given sublist. 516 */ 517 @SuppressWarnings("unchecked") 518 // We need this because of new Vector[n] instead of 519 // new Vector<SnmpVarBind>[n], which is illegal. 520 void add(int pos,SnmpOid oid, Vector<SnmpVarBind> v, boolean isnew, 521 SnmpVarBind statusvb) { 522 523 if (entryoids == null) { 524 // Vectors are null: Allocate new vectors 525 526 entryoids = new SnmpOid[Delta]; 527 entrylists = (Vector<SnmpVarBind>[])new Vector<?>[Delta]; 528 isentrynew = new boolean[Delta]; 529 rowstatus = new SnmpVarBind[Delta]; 530 entrysize = Delta; 531 pos = 0; 532 533 } else if (pos >= entrysize || entrycount == entrysize) { 534 // Vectors must be enlarged 535 536 // Save old vectors 537 SnmpOid[] olde = entryoids; 538 Vector<SnmpVarBind>[] oldl = entrylists; 539 boolean[] oldn = isentrynew; 540 SnmpVarBind[] oldr = rowstatus; 541 542 // Allocate larger vectors 543 entrysize += Delta; 544 entryoids = new SnmpOid[entrysize]; 545 entrylists = (Vector<SnmpVarBind>[])new Vector<?>[entrysize]; 546 isentrynew = new boolean[entrysize]; 547 rowstatus = new SnmpVarBind[entrysize]; 548 549 // Check pos validity 550 if (pos > entrycount) pos = entrycount; 551 if (pos < 0) pos = 0; 552 553 final int l1 = pos; 554 final int l2 = entrycount - pos; 555 556 // Copy original vectors up to `pos' 557 if (l1 > 0) { 558 java.lang.System.arraycopy(olde,0,entryoids, 559 0,l1); 560 java.lang.System.arraycopy(oldl,0,entrylists, 561 0,l1); 562 java.lang.System.arraycopy(oldn,0,isentrynew, 563 0,l1); 564 java.lang.System.arraycopy(oldr,0,rowstatus, 565 0,l1); 566 } 567 568 // Copy original vectors from `pos' to end, leaving 569 // an empty room at `pos' in the new vectors. 570 if (l2 > 0) { 571 final int l3 = l1+1; 572 java.lang.System.arraycopy(olde,l1,entryoids, 573 l3,l2); 574 java.lang.System.arraycopy(oldl,l1,entrylists, 575 l3,l2); 576 java.lang.System.arraycopy(oldn,l1,isentrynew, 577 l3,l2); 578 java.lang.System.arraycopy(oldr,l1,rowstatus, 579 l3,l2); 580 } 581 582 583 } else if (pos < entrycount) { 584 // Vectors are large enough to accommodate one additional 585 // entry. 586 // 587 // Shift vectors, making an empty room at `pos' 588 final int l1 = pos+1; 589 final int l2 = entrycount - pos; 590 591 java.lang.System.arraycopy(entryoids,pos,entryoids, 592 l1,l2); 593 java.lang.System.arraycopy(entrylists,pos,entrylists, 594 l1,l2); 595 java.lang.System.arraycopy(isentrynew,pos,isentrynew, 596 l1,l2); 597 java.lang.System.arraycopy(rowstatus,pos,rowstatus, 598 l1,l2); 599 } 600 601 // Fill the gap at `pos' 602 entryoids[pos] = oid; 603 entrylists[pos] = v; 604 isentrynew[pos] = isnew; 605 rowstatus[pos] = statusvb; 606 entrycount++; 607 } 608 609 public void addVarbind(SnmpVarBind varbind, SnmpOid entryoid, 610 boolean isnew, SnmpVarBind statusvb) 611 throws SnmpStatusException { 612 Vector<SnmpVarBind> v = null; 613 SnmpVarBind rs = statusvb; 614 615 if (entryoids == null) { 616 // entryoids = new ArrayList(); 617 // entrylists = new ArrayList(); 618 // isentrynew = new ArrayList(); 619 v = new Vector<>(); 620 // entryoids.add(entryoid); 621 // entrylists.add(v); 622 // isentrynew.add(new Boolean(isnew)); 623 add(0,entryoid,v,isnew,rs); 624 } else { 625 // int pos = findOid(entryoids,entryoid); 626 // int pos = findOid(entryoids,entrycount,entryoid); 627 final int pos = 628 getInsertionPoint(entryoids,entrycount,entryoid); 629 if (pos > -1 && pos < entrycount && 630 entryoid.compareTo(entryoids[pos]) == 0) { 631 v = entrylists[pos]; 632 rs = rowstatus[pos]; 633 } else { 634 // if (pos == -1 || pos >= entryoids.size() ) { 635 // if (pos == -1 || pos >= entrycount ) { 636 // pos = getInsertionPoint(entryoids,entryoid); 637 // pos = getInsertionPoint(entryoids,entrycount,entryoid); 638 v = new Vector<>(); 639 // entryoids.add(pos,entryoid); 640 // entrylists.add(pos,v); 641 // isentrynew.add(pos,new Boolean(isnew)); 642 add(pos,entryoid,v,isnew,rs); 643 } 644 // } else v = (Vector) entrylists.get(pos); 645 // } else v = entrylists[pos]; 646 if (statusvb != null) { 647 if ((rs != null) && (rs != statusvb) && 648 ((type == SnmpDefinitions.pduWalkRequest) || 649 (type == SnmpDefinitions.pduSetRequestPdu))) { 650 throw new SnmpStatusException( 651 SnmpStatusException.snmpRspInconsistentValue); 652 } 653 rowstatus[pos] = statusvb; 654 } 655 } 656 657 // We do not include the status variable in the varbind, 658 // because we're going to set it separately... 659 // 660 if (statusvb != varbind) 661 v.addElement(varbind); 662 } 663 664 public int getSubReqCount() { 665 int count = 0; 666 if (sublist != null) count++; 667 // if (entryoids != null) count += entryoids.size(); 668 if (entryoids != null) count += entrycount; 669 return count; 670 } 671 672 public Vector<SnmpVarBind> getSubList() { 673 return sublist; 674 } 675 676 public int getEntryPos(SnmpOid entryoid) { 677 // return findOid(entryoids,entryoid); 678 return findOid(entryoids,entrycount,entryoid); 679 } 680 681 public SnmpOid getEntryOid(int pos) { 682 if (entryoids == null) return null; 683 // if (pos == -1 || pos >= entryoids.size() ) return null; 684 if (pos == -1 || pos >= entrycount ) return null; 685 // return (SnmpOid) entryoids.get(pos); 686 return entryoids[pos]; 687 } 688 689 public boolean isNewEntry(int pos) { 690 if (entryoids == null) return false; 691 // if (pos == -1 || pos >= entryoids.size() ) return false; 692 if (pos == -1 || pos >= entrycount ) return false; 693 // return ((Boolean)isentrynew.get(pos)).booleanValue(); 694 return isentrynew[pos]; 695 } 696 697 public SnmpVarBind getRowStatusVarBind(int pos) { 698 if (entryoids == null) return null; 699 // if (pos == -1 || pos >= entryoids.size() ) return false; 700 if (pos == -1 || pos >= entrycount ) return null; 701 // return ((Boolean)isentrynew.get(pos)).booleanValue(); 702 return rowstatus[pos]; 703 } 704 705 public Vector<SnmpVarBind> getEntrySubList(int pos) { 706 if (entrylists == null) return null; 707 // if (pos == -1 || pos >= entrylists.size() ) return null; 708 if (pos == -1 || pos >= entrycount ) return null; 709 // return (Vector) entrylists.get(pos); 710 return entrylists[pos]; 711 } 712 713 public Iterator<SnmpOid> getEntryOids() { 714 if (entryoids == null) return null; 715 // return entryoids.iterator(); 716 return Arrays.asList(entryoids).iterator(); 717 } 718 719 public int getEntryCount() { 720 if (entryoids == null) return 0; 721 // return entryoids.size(); 722 return entrycount; 723 } 724 725 } 726 727 728 //------------------------------------------------------------------- 729 //------------------------------------------------------------------- 730 // Public interface 731 //------------------------------------------------------------------- 732 //------------------------------------------------------------------- 733 734 //------------------------------------------------------------------- 735 // Returns the contextual object containing user-data allocated 736 // through the SnmpUserDataFactory for this request. 737 //------------------------------------------------------------------- 738 739 public Object getUserData() { return request.getUserData(); } 740 741 //------------------------------------------------------------------- 742 // Tells whether creation of new entries is allowed with respect 743 // to the operation involved (GET=>false/SET=>true) 744 //------------------------------------------------------------------- 745 746 public boolean isCreationAllowed() { 747 return creationflag; 748 } 749 750 //------------------------------------------------------------------- 751 // Tells whether we are currently processing a SET request (check/set) 752 //------------------------------------------------------------------- 753 754 public boolean isSetRequest() { 755 return setreqflag; 756 } 757 758 //------------------------------------------------------------------- 759 // Returns the protocol version in which the original request is 760 // evaluated. 761 //------------------------------------------------------------------- 762 763 public int getVersion() { 764 return version; 765 } 766 767 //------------------------------------------------------------------- 768 // Returns the actual protocol version of the request PDU. 769 //------------------------------------------------------------------- 770 771 public int getRequestPduVersion() { 772 return request.getRequestPduVersion(); 773 } 774 775 //------------------------------------------------------------------- 776 // Returns the SnmpMibNode associated with the given handler 777 //------------------------------------------------------------------- 778 779 public SnmpMibNode getMetaNode(Handler handler) { 780 return handler.meta; 781 } 782 783 //------------------------------------------------------------------- 784 // Indicates the depth of the arc in the OID that identifies the 785 // SnmpMibNode associated with the given handler 786 //------------------------------------------------------------------- 787 788 public int getOidDepth(Handler handler) { 789 return handler.depth; 790 } 791 792 //------------------------------------------------------------------- 793 // returns an enumeration of the SnmpMibSubRequest's to be invoked on 794 // the SnmpMibNode associated with a given Handler node. 795 // If this node is a group, there will be a single subrequest. 796 // If it is a table, there will be one subrequest per entry involved. 797 //------------------------------------------------------------------- 798 799 public Enumeration<SnmpMibSubRequest> getSubRequests(Handler handler) { 800 return new Enum(this,handler); 801 } 802 803 //------------------------------------------------------------------- 804 // returns an enumeration of the Handlers stored in the Hashtable. 805 //------------------------------------------------------------------- 806 807 public Enumeration<Handler> getHandlers() { 808 return hashtable.elements(); 809 } 810 811 //------------------------------------------------------------------- 812 // adds a varbind to a handler node sublist 813 //------------------------------------------------------------------- 814 815 public void add(SnmpMibNode meta, int depth, SnmpVarBind varbind) 816 throws SnmpStatusException { 817 registerNode(meta,depth,null,varbind,false,null); 818 } 819 820 //------------------------------------------------------------------- 821 // adds an entry varbind to a handler node sublist 822 //------------------------------------------------------------------- 823 824 public void add(SnmpMibNode meta, int depth, SnmpOid entryoid, 825 SnmpVarBind varbind, boolean isnew) 826 throws SnmpStatusException { 827 registerNode(meta,depth,entryoid,varbind,isnew,null); 828 } 829 830 //------------------------------------------------------------------- 831 // adds an entry varbind to a handler node sublist - specifying the 832 // varbind which holds the row status 833 //------------------------------------------------------------------- 834 835 public void add(SnmpMibNode meta, int depth, SnmpOid entryoid, 836 SnmpVarBind varbind, boolean isnew, 837 SnmpVarBind statusvb) 838 throws SnmpStatusException { 839 registerNode(meta,depth,entryoid,varbind,isnew,statusvb); 840 } 841 842 843 //------------------------------------------------------------------- 844 //------------------------------------------------------------------- 845 // Protected interface 846 //------------------------------------------------------------------- 847 //------------------------------------------------------------------- 848 849 //------------------------------------------------------------------- 850 // Type of the request (see SnmpDefinitions) 851 //------------------------------------------------------------------- 852 853 void setPduType(int pduType) { 854 type = pduType; 855 setreqflag = ((pduType == SnmpDefinitions.pduWalkRequest) || 856 (pduType == SnmpDefinitions.pduSetRequestPdu)); 857 } 858 859 //------------------------------------------------------------------- 860 // We deal with a GET-NEXT request 861 //------------------------------------------------------------------- 862 863 void setGetNextFlag() { 864 getnextflag = true; 865 } 866 867 //------------------------------------------------------------------- 868 // Tell whether creation is allowed. 869 //------------------------------------------------------------------- 870 void switchCreationFlag(boolean flag) { 871 creationflag = flag; 872 } 873 874 875 //------------------------------------------------------------------- 876 // Returns the subrequest handled by the SnmpMibNode itself 877 // (in principle, only for Groups) 878 //------------------------------------------------------------------- 879 880 SnmpMibSubRequest getSubRequest(Handler handler) { 881 if (handler == null) return null; 882 return new SnmpMibSubRequestImpl(request,handler.getSubList(), 883 null,false,getnextflag,null); 884 } 885 886 //------------------------------------------------------------------- 887 // Returns the subrequest associated with the entry identified by 888 // the given entry (only for tables) 889 //------------------------------------------------------------------- 890 891 SnmpMibSubRequest getSubRequest(Handler handler, SnmpOid oid) { 892 if (handler == null) return null; 893 final int pos = handler.getEntryPos(oid); 894 if (pos == -1) return null; 895 return new SnmpMibSubRequestImpl(request, 896 handler.getEntrySubList(pos), 897 handler.getEntryOid(pos), 898 handler.isNewEntry(pos), 899 getnextflag, 900 handler.getRowStatusVarBind(pos)); 901 } 902 903 //------------------------------------------------------------------- 904 // Returns the subrequest associated with the entry identified by 905 // the given entry (only for tables). The `entry' parameter is an 906 // index relative to the position of the entry in the handler sublist. 907 //------------------------------------------------------------------- 908 909 SnmpMibSubRequest getSubRequest(Handler handler, int entry) { 910 if (handler == null) return null; 911 return new 912 SnmpMibSubRequestImpl(request,handler.getEntrySubList(entry), 913 handler.getEntryOid(entry), 914 handler.isNewEntry(entry),getnextflag, 915 handler.getRowStatusVarBind(entry)); 916 } 917 918 //------------------------------------------------------------------- 919 //------------------------------------------------------------------- 920 // Private section 921 //------------------------------------------------------------------- 922 //------------------------------------------------------------------- 923 924 925 //------------------------------------------------------------------- 926 // stores a handler node in the Hashtable 927 //------------------------------------------------------------------- 928 929 private void put(Object key, Handler handler) { 930 if (handler == null) return; 931 if (key == null) return; 932 if (hashtable == null) hashtable = new Hashtable<Object, Handler>(); 933 hashtable.put(key,handler); 934 } 935 936 //------------------------------------------------------------------- 937 // finds a handler node in the Hashtable 938 //------------------------------------------------------------------- 939 940 private Handler get(Object key) { 941 if (key == null) return null; 942 if (hashtable == null) return null; 943 return hashtable.get(key); 944 } 945 946 //------------------------------------------------------------------- 947 // Search for the given oid in `oids'. If none is found, returns -1 948 // otherwise, returns the index at which the oid is located. 949 //------------------------------------------------------------------- 950 951 private static int findOid(SnmpOid[] oids, int count, SnmpOid oid) { 952 final int size = count; 953 int low= 0; 954 int max= size - 1; 955 int curr= low + (max-low)/2; 956 //System.out.println("Try to retrieve: " + oid.toString()); 957 while (low <= max) { 958 959 final SnmpOid pos = oids[curr]; 960 961 //System.out.println("Compare with" + pos.toString()); 962 // never know ...we might find something ... 963 // 964 final int comp = oid.compareTo(pos); 965 if (comp == 0) 966 return curr; 967 968 if (oid.equals(pos)) { 969 return curr; 970 } 971 if (comp > 0) { 972 low = curr + 1; 973 } else { 974 max = curr - 1; 975 } 976 curr = low + (max-low)/2; 977 } 978 return -1; 979 } 980 981 //------------------------------------------------------------------- 982 // Return the index at which the given oid should be inserted in the 983 // `oids' array. 984 //------------------------------------------------------------------- 985 986 private static int getInsertionPoint(SnmpOid[] oids, int count, 987 SnmpOid oid) { 988 final SnmpOid[] localoids = oids; 989 final int size = count; 990 int low= 0; 991 int max= size - 1; 992 int curr= low + (max-low)/2; 993 994 995 while (low <= max) { 996 997 final SnmpOid pos = localoids[curr]; 998 999 // never know ...we might find something ... 1000 // 1001 final int comp= oid.compareTo(pos); 1002 1003 // In the calling method we will have to check for this case... 1004 // if (comp == 0) 1005 // return -1; 1006 // Returning curr instead of -1 avoids having to call 1007 // findOid() first and getInsertionPoint() afterwards. 1008 // We can simply call getInsertionPoint() and then checks whether 1009 // there's an OID at the returned position which equals the 1010 // given OID. 1011 if (comp == 0) 1012 return curr; 1013 1014 if (comp>0) { 1015 low= curr +1; 1016 } else { 1017 max= curr -1; 1018 } 1019 curr= low + (max-low)/2; 1020 } 1021 return curr; 1022 } 1023 1024 //------------------------------------------------------------------- 1025 // adds a varbind in a handler node sublist 1026 //------------------------------------------------------------------- 1027 1028 private void registerNode(SnmpMibNode meta, int depth, SnmpOid entryoid, 1029 SnmpVarBind varbind, boolean isnew, 1030 SnmpVarBind statusvb) 1031 throws SnmpStatusException { 1032 if (meta == null) { 1033 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, 1034 SnmpRequestTree.class.getName(), 1035 "registerNode", "meta-node is null!"); 1036 return; 1037 } 1038 if (varbind == null) { 1039 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, 1040 SnmpRequestTree.class.getName(), 1041 "registerNode", "varbind is null!"); 1042 return ; 1043 } 1044 1045 final Object key = meta; 1046 1047 // retrieve the handler node associated with the given meta, 1048 // if any 1049 Handler handler = get(key); 1050 1051 // If no handler node was found for that meta, create one. 1052 if (handler == null) { 1053 // if (isDebugOn()) 1054 // debug("registerNode", "adding node for " + 1055 // varbind.oid.toString()); 1056 handler = new Handler(type); 1057 handler.meta = meta; 1058 handler.depth = depth; 1059 put(key,handler); 1060 } 1061 // else { 1062 // if (isDebugOn()) 1063 // debug("registerNode","found node for " + 1064 // varbind.oid.toString()); 1065 // } 1066 1067 // Adds the varbind in the handler node's sublist. 1068 if (entryoid == null) 1069 handler.addVarbind(varbind); 1070 else 1071 handler.addVarbind(varbind,entryoid,isnew,statusvb); 1072 } 1073 1074 1075 //------------------------------------------------------------------- 1076 // private variables 1077 //------------------------------------------------------------------- 1078 1079 private Hashtable<Object, Handler> hashtable = null; 1080 // Hashtable of Handler objects 1081 private SnmpMibRequest request = null; // The original list of varbinds 1082 private int version = 0; // The protocol version 1083 private boolean creationflag = false; // Does the operation allow 1084 // creation of entries 1085 private boolean getnextflag = false; // Does the operation allow 1086 // creation of entries 1087 private int type = 0; // Request PDU type as defined 1088 // in SnmpDefinitions 1089 private boolean setreqflag = false; // True if we're processing a 1090 // SET request (check/set). 1091 }