1. /*
  2. * @(#)file SnmpMib.java
  3. * @(#)author Sun Microsystems, Inc.
  4. * @(#)version 4.29
  5. * @(#)date 04/09/15
  6. *
  7. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  8. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  9. *
  10. */
  11. package com.sun.jmx.snmp.agent;
  12. // java imports
  13. //
  14. import java.io.Serializable;
  15. import java.util.Vector;
  16. import java.util.Enumeration;
  17. import java.lang.IllegalAccessException;
  18. // jmx imports
  19. //
  20. import javax.management.ObjectName;
  21. import javax.management.MBeanServer;
  22. import javax.management.MalformedObjectNameException;
  23. import javax.management.InstanceAlreadyExistsException;
  24. import javax.management.MBeanRegistrationException;
  25. import javax.management.NotCompliantMBeanException;
  26. import com.sun.jmx.snmp.SnmpOid;
  27. import com.sun.jmx.snmp.SnmpVarBind;
  28. import com.sun.jmx.snmp.SnmpDefinitions;
  29. import com.sun.jmx.snmp.SnmpStatusException;
  30. import com.sun.jmx.snmp.SnmpEngine;
  31. import com.sun.jmx.snmp.SnmpUnknownModelException;
  32. // SNMP Runtime imports
  33. import com.sun.jmx.trace.Trace;
  34. import com.sun.jmx.snmp.internal.SnmpAccessControlModel;
  35. import com.sun.jmx.snmp.internal.SnmpEngineImpl;
  36. /**
  37. * This list is used in order to construct the OID during the getnext.
  38. * The constructed oid is checked by the checker AcmChecker.
  39. */
  40. final class LongList {
  41. public static int DEFAULT_CAPACITY = 10;
  42. public static int DEFAULT_INCREMENT = 10;
  43. private final int DELTA;
  44. private int size;
  45. /**
  46. * The list content. Any access to this variable must be protected
  47. * by a synchronized block on the LongList object.
  48. * Only read-only action should be performed on this object.
  49. **/
  50. public long[] list;
  51. LongList() {
  52. this(DEFAULT_CAPACITY,DEFAULT_INCREMENT);
  53. }
  54. LongList(int initialCapacity) {
  55. this(initialCapacity,DEFAULT_INCREMENT);
  56. }
  57. LongList(int initialCapacity, int delta) {
  58. size = 0;
  59. DELTA = delta;
  60. list = allocate(initialCapacity);
  61. }
  62. /**
  63. * Same behaviour than size() in {@link java.util.List}.
  64. **/
  65. public final int size() { return size;}
  66. /**
  67. * Same behaviour than add(long o) in {@link java.util.List}.
  68. * Any access to this method should be protected in a synchronized
  69. * block on the LongList object.
  70. **/
  71. public final boolean add(final long o) {
  72. if (size >= list.length)
  73. resize();
  74. list[size++]=o;
  75. return true;
  76. }
  77. /**
  78. * Same behaviour than add(int index, long o) in
  79. * {@link java.util.List}.
  80. * Any access to this method should be protected in a synchronized
  81. * block on the LongList object.
  82. **/
  83. public final void add(final int index, final long o) {
  84. if (index > size) throw new IndexOutOfBoundsException();
  85. if (index >= list.length) resize();
  86. if (index == size) {
  87. list[size++]=o;
  88. return;
  89. }
  90. java.lang.System.arraycopy(list,index,list,index+1,size-index);
  91. list[index]=o;
  92. size++;
  93. }
  94. /**
  95. * Adds <var>count</var> elements to the list.
  96. * @param at index at which the elements must be inserted. The
  97. * first element will be inserted at this index.
  98. * @param src An array containing the elements we want to insert.
  99. * @param from Index of the first element from <var>src</var> that
  100. * must be inserted.
  101. * @param count number of elements to insert.
  102. * Any access to this method should be protected in a synchronized
  103. * block on the LongList object.
  104. **/
  105. public final void add(final int at,final long[] src, final int from,
  106. final int count) {
  107. if (count <= 0) return;
  108. if (at > size) throw new IndexOutOfBoundsException();
  109. ensure(size+count);
  110. if (at < size) {
  111. java.lang.System.arraycopy(list,at,list,at+count,size-at);
  112. }
  113. java.lang.System.arraycopy(src,from,list,at,count);
  114. size+=count;
  115. }
  116. /**
  117. * Any access to this method should be protected in a synchronized
  118. * block on the LongList object.
  119. **/
  120. public final long remove(final int from, final int count) {
  121. if (count < 1 || from < 0) return -1;
  122. if (from+count > size) return -1;
  123. final long o = list[from];
  124. final int oldsize = size;
  125. size = size - count;
  126. if (from == size) return o;
  127. java.lang.System.arraycopy(list,from+count,list,from,
  128. size-from);
  129. return o;
  130. }
  131. /**
  132. * Same behaviour than remove(int index) in {@link java.util.List}.
  133. * Any access to this method should be protected in a synchronized
  134. * block on the LongList object.
  135. **/
  136. public final long remove(final int index) {
  137. if (index >= size) return -1;
  138. final long o = list[index];
  139. list[index]=0;
  140. if (index == --size) return o;
  141. java.lang.System.arraycopy(list,index+1,list,index,
  142. size-index);
  143. return o;
  144. }
  145. /**
  146. * Same behaviour than the toArray(long[] a) method in
  147. * {@link java.util.List}.
  148. * Any access to this method should be protected in a synchronized
  149. * block on the LongList object.
  150. **/
  151. public final long[] toArray(long[] a) {
  152. java.lang.System.arraycopy(list,0,a,0,size);
  153. return a;
  154. }
  155. /**
  156. * Same behaviour than the toArray() method in
  157. * {@link java.util.List}.
  158. * Any access to this method should be protected in a synchronized
  159. * block on the LongList object.
  160. **/
  161. public final long[] toArray() {
  162. return toArray(new long[size]);
  163. }
  164. /**
  165. * Resize the list. Increase its capacity by DELTA elements.
  166. * Any call to this method must be protected by a synchronized
  167. * block on this LongList.
  168. **/
  169. private final void resize() {
  170. final long[] newlist = allocate(list.length + DELTA);
  171. java.lang.System.arraycopy(list,0,newlist,0,size);
  172. list = newlist;
  173. }
  174. /**
  175. * Resize the list. Insure that the new length will be at
  176. * least equal to <var>length</var>.
  177. * @param length new minimal length requested.
  178. * Any call to this method must be protected by a synchronized
  179. * block on this LongList.
  180. **/
  181. private final void ensure(int length) {
  182. if (list.length < length) {
  183. final int min = list.length+DELTA;
  184. length=(length<min)?min:length;
  185. final long[] newlist = allocate(length);
  186. java.lang.System.arraycopy(list,0,newlist,0,size);
  187. list = newlist;
  188. }
  189. }
  190. /**
  191. * Allocate a new array of object of specified length.
  192. **/
  193. private final long[] allocate(final int length) {
  194. return new long[length];
  195. }
  196. }
  197. /**
  198. * Oid Checker makes use of ACM to check each OID during the getnext process.
  199. */
  200. class AcmChecker {
  201. SnmpAccessControlModel model = null;
  202. String principal = null;
  203. int securityLevel = -1;
  204. int version = -1;
  205. int pduType = -1;
  206. int securityModel = -1;
  207. byte[] contextName = null;
  208. SnmpEngineImpl engine = null;
  209. LongList l = null;
  210. AcmChecker(SnmpMibRequest req) {
  211. engine = (SnmpEngineImpl) req.getEngine();
  212. //We are in V3 architecture, ACM is in the picture.
  213. if(engine != null) {
  214. if(engine.isCheckOidActivated()) {
  215. try {
  216. if (isDebugOn())
  217. debug("AcmChecker",
  218. " SNMP V3 Access Control to be done.");
  219. model = (SnmpAccessControlModel)
  220. engine.getAccessControlSubSystem().
  221. getModel(SnmpDefinitions.snmpVersionThree);
  222. principal = req.getPrincipal();
  223. securityLevel = req.getSecurityLevel();
  224. pduType = req.getPdu().type;
  225. version = req.getRequestPduVersion();
  226. securityModel = req.getSecurityModel();
  227. contextName = req.getAccessContextName();
  228. l = new LongList();
  229. if (isDebugOn())
  230. debug("AcmChecker",
  231. "Will check oid for : principal : " + principal +
  232. ";securityLevel : " +
  233. securityLevel +";pduType : " + pduType +
  234. ";version : "
  235. + version + ";securityModel : " +
  236. securityModel +";contextName : " +
  237. (contextName == null ? null :
  238. new String(contextName)));
  239. }catch(SnmpUnknownModelException e) {
  240. if (isDebugOn())
  241. debug("AcmChecker",
  242. " Unknown Model, no ACM check.");
  243. }
  244. }
  245. }
  246. }
  247. void add(int index, long arc) {
  248. if(model != null)
  249. l.add(index, arc);
  250. }
  251. void remove(int index) {
  252. if(model != null)
  253. l.remove(index);
  254. }
  255. void add(final int at,final long[] src, final int from,
  256. final int count) {
  257. if(model != null)
  258. l.add(at,src,from,count);
  259. }
  260. void remove(final int from, final int count) {
  261. if(model != null)
  262. l.remove(from,count);
  263. }
  264. void checkCurrentOid() throws SnmpStatusException {
  265. if(model != null) {
  266. SnmpOid oid = new SnmpOid(l.toArray());
  267. if (isDebugOn())
  268. debug("check",
  269. " Checking access for : " + oid);
  270. model.checkAccess(version,
  271. principal,
  272. securityLevel,
  273. pduType,
  274. securityModel,
  275. contextName,
  276. oid);
  277. }
  278. }
  279. // Returns true if debug is on
  280. private final static boolean isDebugOn() {
  281. return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
  282. }
  283. // Prints a debug message
  284. private final static void debug(String func, String info) {
  285. Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP,
  286. "AcmChecker", func, info);
  287. }
  288. }
  289. /**
  290. * Abstract class for representing an SNMP MIB.
  291. * <P>
  292. * When compiling a SNMP MIB, among all the classes generated by
  293. * <CODE>mibgen</CODE>, there is one which extends <CODE>SnmpMib</CODE>
  294. * for representing a whole MIB.
  295. * <BR>The class is used by the SNMP protocol adaptor as the entry point in
  296. * the MIB.
  297. *
  298. * <p>This generated class can be subclassed in your code in order to
  299. * plug in your own specific behaviour.
  300. * </p>
  301. *
  302. * <p><b>This API is a Sun Microsystems internal API and is subject
  303. * to change without notice.</b></p>
  304. * @version 4.29 02/25/04
  305. * @author Sun Microsystems, Inc
  306. */
  307. public abstract class SnmpMib extends SnmpMibAgent implements Serializable {
  308. /**
  309. * Default constructor.
  310. * Initializes the OID tree.
  311. */
  312. public SnmpMib() {
  313. root= new SnmpMibOid();
  314. }
  315. // --------------------------------------------------------------------
  316. // POLYMORHIC METHODS
  317. // --------------------------------------------------------------------
  318. /**
  319. * <p>
  320. * This callback should return the OID associated to the group
  321. * identified by the given <code>groupName</code>.
  322. * </p>
  323. *
  324. * <p>
  325. * This method is provided as a hook to plug-in some custom
  326. * specific behavior. Although doing so is discouraged you might
  327. * want to subclass this method in order to store & provide more metadata
  328. * information (mapping OID <-> symbolic name) within the agent,
  329. * or to "change" the root of the MIB OID by prefixing the
  330. * defaultOid by an application dependant OID string, for instance.
  331. * </p>
  332. *
  333. * <p>
  334. * The default implementation of this method is to return the given
  335. * <code>defaultOid</code>
  336. * </p>
  337. *
  338. * @param groupName The java-ized name of the SNMP group.
  339. * @param defaultOid The OID defined in the MIB for that group
  340. * (in dot notation).
  341. *
  342. * @return The OID of the group identified by <code>groupName</code>,
  343. * in dot-notation.
  344. */
  345. protected String getGroupOid(String groupName, String defaultOid) {
  346. return defaultOid;
  347. }
  348. /**
  349. * <p>
  350. * This callback should return the ObjectName associated to the
  351. * group identified by the given <code>groupName</code>.
  352. * </p>
  353. *
  354. * <p>
  355. * This method is provided as a hook to plug-in some custom
  356. * specific behavior. You might want to override this method
  357. * in order to provide a different object naming scheme than
  358. * that proposed by default by <code>mibgen</code>.
  359. * </p>
  360. *
  361. * <p>
  362. * This method is only meaningful if the MIB is registered
  363. * in the MBeanServer, otherwise, it will not be called.
  364. * </p>
  365. *
  366. * <p>
  367. * The default implementation of this method is to return an ObjectName
  368. * built from the given <code>defaultName</code>.
  369. * </p>
  370. *
  371. * @param name The java-ized name of the SNMP group.
  372. * @param oid The OID returned by getGroupOid() - in dot notation.
  373. * @param defaultName The name by default generated by <code>
  374. * mibgen</code>
  375. *
  376. * @return The ObjectName of the group identified by <code>name</code>
  377. */
  378. protected ObjectName getGroupObjectName(String name, String oid,
  379. String defaultName)
  380. throws MalformedObjectNameException {
  381. return new ObjectName(defaultName);
  382. }
  383. /**
  384. * <p>
  385. * Register an SNMP group and its metadata node in the MIB.
  386. * </p>
  387. *
  388. * <p>
  389. * This method is provided as a hook to plug-in some custom
  390. * specific behavior. You might want to override this method
  391. * if you want to set special links between the MBean, its metadata
  392. * node, its OID or ObjectName etc..
  393. * </p>
  394. *
  395. * <p>
  396. * If the MIB is not registered in the MBeanServer, the <code>
  397. * server</code> and <code>groupObjName</code> parameters will be
  398. * <code>null</code>.<br>
  399. * If the given group MBean is not <code>null</code>, and if the
  400. * <code>server</code> and <code>groupObjName</code> parameters are
  401. * not null, then this method will also automatically register the
  402. * group MBean with the given MBeanServer <code>server</code>.
  403. * </p>
  404. *
  405. * @param groupName The java-ized name of the SNMP group.
  406. * @param groupOid The OID as returned by getGroupOid() - in dot
  407. * notation.
  408. * @param groupObjName The ObjectName as returned by getGroupObjectName().
  409. * This parameter may be <code>null</code> if the
  410. * MIB is not registered in the MBeanServer.
  411. * @param node The metadata node, as returned by the metadata
  412. * factory method for this group.
  413. * @param group The MBean for this group, as returned by the
  414. * MBean factory method for this group.
  415. * @param server The MBeanServer in which the groups are to be
  416. * registered. This parameter will be <code>null</code>
  417. * if the MIB is not registered, otherwise it is a
  418. * reference to the MBeanServer in which the MIB is
  419. * registered.
  420. *
  421. */
  422. protected void registerGroupNode(String groupName, String groupOid,
  423. ObjectName groupObjName, SnmpMibNode node,
  424. Object group, MBeanServer server)
  425. throws NotCompliantMBeanException, MBeanRegistrationException,
  426. InstanceAlreadyExistsException, IllegalAccessException {
  427. root.registerNode(groupOid,node);
  428. if (server != null && groupObjName != null && group != null)
  429. server.registerMBean(group,groupObjName);
  430. }
  431. /**
  432. * <p>
  433. * Register an SNMP Table metadata node in the MIB.
  434. * </p>
  435. *
  436. * <p>
  437. * <b><i>
  438. * This method is used internally and you should never need to
  439. * call it directly.</i></b><br> It is used to establish the link
  440. * between an SNMP table metadata node and its bean-like counterpart.
  441. * <br>
  442. * The group metadata nodes will create and register their
  443. * underlying table metadata nodes in the MIB using this
  444. * method. <br>
  445. * The metadata nodes will be later retrieved from the MIB by the
  446. * bean-like table objects using the getRegisterTableMeta() method.
  447. * </p>
  448. *
  449. * @param name The java-ized name of the SNMP table.
  450. * @param table The SNMP table metadata node - usually this
  451. * corresponds to a <code>mibgen</code> generated
  452. * object.
  453. */
  454. public abstract void registerTableMeta(String name, SnmpMibTable table);
  455. /**
  456. * Returns a registered SNMP Table metadata node.
  457. *
  458. * <p><b><i>
  459. * This method is used internally and you should never need to
  460. * call it directly.
  461. * </i></b></p>
  462. *
  463. */
  464. public abstract SnmpMibTable getRegisteredTableMeta(String name);
  465. // --------------------------------------------------------------------
  466. // PUBLIC METHODS
  467. // --------------------------------------------------------------------
  468. /**
  469. * Processes a <CODE>get</CODE> operation.
  470. *
  471. **/
  472. // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
  473. // for java-doc
  474. //
  475. public void get(SnmpMibRequest req) throws SnmpStatusException {
  476. // Builds the request tree: creation is not allowed, operation
  477. // is not atomic.
  478. final int reqType = SnmpDefinitions.pduGetRequestPdu;
  479. SnmpRequestTree handlers = getHandlers(req,false,false,reqType);
  480. SnmpRequestTree.Handler h = null;
  481. SnmpMibNode meta = null;
  482. if (isDebugOn())
  483. debug("get","Processing handlers for GET... ");
  484. // For each sub-request stored in the request-tree, invoke the
  485. // get() method.
  486. for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
  487. h = (SnmpRequestTree.Handler) eh.nextElement();
  488. // Gets the Meta node. It can be either a Group Meta or a
  489. // Table Meta.
  490. //
  491. meta = handlers.getMetaNode(h);
  492. // Gets the depth of the Meta node in the OID tree
  493. final int depth = handlers.getOidDepth(h);
  494. for (Enumeration rqs=handlers.getSubRequests(h);
  495. rqs.hasMoreElements();) {
  496. // Invoke the get() operation.
  497. meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
  498. }
  499. }
  500. }
  501. /**
  502. * Processes a <CODE>set</CODE> operation.
  503. *
  504. */
  505. // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
  506. // for java-doc
  507. //
  508. public void set(SnmpMibRequest req) throws SnmpStatusException {
  509. SnmpRequestTree handlers = null;
  510. // Optimization: we're going to get the whole SnmpRequestTree
  511. // built in the "check" method, so that we don't have to rebuild
  512. // it here.
  513. //
  514. if (req instanceof SnmpMibRequestImpl)
  515. handlers = ((SnmpMibRequestImpl)req).getRequestTree();
  516. // Optimization didn't work: we have to rebuild the tree.
  517. //
  518. // Builds the request tree: creation is not allowed, operation
  519. // is atomic.
  520. //
  521. final int reqType = SnmpDefinitions.pduSetRequestPdu;
  522. if (handlers == null) handlers = getHandlers(req,false,true,reqType);
  523. handlers.switchCreationFlag(false);
  524. handlers.setPduType(reqType);
  525. SnmpRequestTree.Handler h = null;
  526. SnmpMibNode meta = null;
  527. if (isDebugOn())
  528. debug("set","Processing handlers for SET... ");
  529. // For each sub-request stored in the request-tree, invoke the
  530. // get() method.
  531. for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
  532. h = (SnmpRequestTree.Handler) eh.nextElement();
  533. // Gets the Meta node. It can be either a Group Meta or a
  534. // Table Meta.
  535. //
  536. meta = handlers.getMetaNode(h);
  537. // Gets the depth of the Meta node in the OID tree
  538. final int depth = handlers.getOidDepth(h);
  539. for (Enumeration rqs=handlers.getSubRequests(h);
  540. rqs.hasMoreElements();) {
  541. // Invoke the set() operation
  542. meta.set((SnmpMibSubRequest)rqs.nextElement(),depth);
  543. }
  544. }
  545. }
  546. /**
  547. * Checks if a <CODE>set</CODE> operation can be performed.
  548. * If the operation cannot be performed, the method will raise a
  549. * <CODE>SnmpStatusException</CODE>.
  550. *
  551. */
  552. // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
  553. // for java-doc
  554. //
  555. public void check(SnmpMibRequest req) throws SnmpStatusException {
  556. final int reqType = SnmpDefinitions.pduWalkRequest;
  557. // Builds the request tree: creation is allowed, operation
  558. // is atomic.
  559. SnmpRequestTree handlers = getHandlers(req,true,true,reqType);
  560. SnmpRequestTree.Handler h = null;
  561. SnmpMibNode meta = null;
  562. if (isDebugOn())
  563. debug("check","Processing handlers for CHECK... ");
  564. // For each sub-request stored in the request-tree, invoke the
  565. // check() method.
  566. for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
  567. h = (SnmpRequestTree.Handler) eh.nextElement();
  568. // Gets the Meta node. It can be either a Group Meta or a
  569. // Table Meta.
  570. //
  571. meta = handlers.getMetaNode(h);
  572. // Gets the depth of the Meta node in the OID tree
  573. final int depth = handlers.getOidDepth(h);
  574. for (Enumeration rqs=handlers.getSubRequests(h);
  575. rqs.hasMoreElements();) {
  576. // Invoke the check() operation
  577. meta.check((SnmpMibSubRequest)rqs.nextElement(),depth);
  578. }
  579. }
  580. // Optimization: we're going to pass the whole SnmpRequestTree
  581. // to the "set" method, so that we don't have to rebuild it there.
  582. //
  583. if (req instanceof SnmpMibRequestImpl) {
  584. ((SnmpMibRequestImpl)req).setRequestTree(handlers);
  585. }
  586. }
  587. /**
  588. * Processes a <CODE>getNext</CODE> operation.
  589. *
  590. */
  591. // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
  592. // for java-doc
  593. //
  594. public void getNext(SnmpMibRequest req) throws SnmpStatusException {
  595. // Build the request tree for the operation
  596. // The subrequest stored in the request tree are valid GET requests
  597. SnmpRequestTree handlers = getGetNextHandlers(req);
  598. SnmpRequestTree.Handler h = null;
  599. SnmpMibNode meta = null;
  600. if (isDebugOn())
  601. debug("getNext","Processing handlers for GET-NEXT... ");
  602. // Now invoke get() for each subrequest of the request tree.
  603. for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) {
  604. h = (SnmpRequestTree.Handler) eh.nextElement();
  605. // Gets the Meta node. It can be either a Group Meta or a
  606. // Table Meta.
  607. //
  608. meta = handlers.getMetaNode(h);
  609. // Gets the depth of the Meta node in the OID tree
  610. int depth = handlers.getOidDepth(h);
  611. for (Enumeration rqs=handlers.getSubRequests(h);
  612. rqs.hasMoreElements();) {
  613. // Invoke the get() operation
  614. meta.get((SnmpMibSubRequest)rqs.nextElement(),depth);
  615. }
  616. }
  617. }
  618. /**
  619. * Processes a <CODE>getBulk</CODE> operation.
  620. * The method implements the <CODE>getBulk</CODE> operation by calling
  621. * appropriately the <CODE>getNext</CODE> method.
  622. *
  623. */
  624. // Implements the method defined in SnmpMibAgent. See SnmpMibAgent
  625. // for java-doc
  626. //
  627. public void getBulk(SnmpMibRequest req, int nonRepeat, int maxRepeat)
  628. throws SnmpStatusException {
  629. getBulkWithGetNext(req, nonRepeat, maxRepeat);
  630. }
  631. /**
  632. * Gets the root object identifier of the MIB.
  633. * <P>In order to be accurate, the method should be called once the
  634. * MIB is fully initialized (that is, after a call to <CODE>init</CODE>
  635. * or <CODE>preRegister</CODE>).
  636. *
  637. * @return The root object identifier.
  638. */
  639. public long[] getRootOid() {
  640. if( rootOid == null) {
  641. Vector list= new Vector(10);
  642. // Ask the tree to do the job !
  643. //
  644. root.getRootOid(list);
  645. // Now format the result
  646. //
  647. rootOid= new long[list.size()];
  648. int i=0;
  649. for(Enumeration e= list.elements(); e.hasMoreElements(); ) {
  650. Integer val= (Integer) e.nextElement();
  651. rootOid[i++]= val.longValue();
  652. }
  653. }
  654. return rootOid;
  655. }
  656. // --------------------------------------------------------------------
  657. // PRIVATE METHODS
  658. //---------------------------------------------------------------------
  659. /**
  660. * This method builds the temporary request-tree that will be used to
  661. * perform the SNMP request associated with the given vector of varbinds
  662. * `list'.
  663. *
  664. * @param req The SnmpMibRequest object holding the varbind list
  665. * concerning this MIB.
  666. * @param createflag Indicates whether the operation allow for creation
  667. * of new instances (ie: it is a SET).
  668. * @param atomic Indicates whether the operation is atomic or not.
  669. * @param type Request type (from SnmpDefinitions).
  670. *
  671. * @return The request-tree where the original varbind list has been
  672. * dispatched to the appropriate nodes.
  673. */
  674. private SnmpRequestTree getHandlers(SnmpMibRequest req,
  675. boolean createflag, boolean atomic,
  676. int type)
  677. throws SnmpStatusException {
  678. // Build an empty request tree
  679. SnmpRequestTree handlers =
  680. new SnmpRequestTree(req,createflag,type);
  681. int index=0;
  682. SnmpVarBind var = null;
  683. final int ver= req.getVersion();
  684. // For each varbind in the list finds its handling node.
  685. for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
  686. var= (SnmpVarBind) e.nextElement();
  687. try {
  688. // Find the handling node for this varbind.
  689. root.findHandlingNode(var,var.oid.longValue(false),
  690. 0,handlers);
  691. } catch(SnmpStatusException x) {
  692. if (isDebugOn())
  693. debug("getHandlers","Couldn't find a handling node for "
  694. + var.oid.toString());
  695. // If the operation is atomic (Check/Set) or the version
  696. // is V1 we must generate an exception.
  697. //
  698. if (ver == SnmpDefinitions.snmpVersionOne) {
  699. if (isDebugOn())
  700. debug("getHandlers","\tV1: Throwing exception");
  701. // The index in the exception must correspond to the
  702. // SNMP index ...
  703. //
  704. final SnmpStatusException sse =
  705. new SnmpStatusException(x, index + 1);
  706. sse.initCause(x);
  707. throw sse;
  708. } else if ((type == SnmpDefinitions.pduWalkRequest) ||
  709. (type == SnmpDefinitions.pduSetRequestPdu)) {
  710. final int status =
  711. SnmpRequestTree.mapSetException(x.getStatus(),ver);
  712. if (isDebugOn())
  713. debug("getHandlers","\tSET: Throwing exception");
  714. final SnmpStatusException sse =
  715. new SnmpStatusException(status, index + 1);
  716. sse.initCause(x);
  717. throw sse;
  718. } else if (atomic) {
  719. // Should never come here...
  720. if (isDebugOn())
  721. debug("getHandlers","\tATOMIC: Throwing exception");
  722. final SnmpStatusException sse =
  723. new SnmpStatusException(x, index + 1);
  724. sse.initCause(x);
  725. throw sse;
  726. }
  727. final int status =
  728. SnmpRequestTree.mapGetException(x.getStatus(),ver);
  729. if (status == SnmpStatusException.noSuchInstance) {
  730. if (isDebugOn())
  731. debug("getHandlers",
  732. "\tGET: Registering noSuchInstance");
  733. var.value= SnmpVarBind.noSuchInstance;
  734. } else if (status == SnmpStatusException.noSuchObject) {
  735. if (isDebugOn())
  736. debug("getHandlers",
  737. "\tGET: Registering noSuchObject");
  738. var.value= SnmpVarBind.noSuchObject;
  739. } else {
  740. if (isDebugOn())
  741. debug("getHandlers",
  742. "\tGET: Registering global error: "
  743. + status);
  744. final SnmpStatusException sse =
  745. new SnmpStatusException(status, index + 1);
  746. sse.initCause(x);
  747. throw sse;
  748. }
  749. }
  750. }
  751. return handlers;
  752. }
  753. /**
  754. * This method builds the temporary request-tree that will be used to
  755. * perform the SNMP GET-NEXT request associated with the given vector
  756. * of varbinds `list'.
  757. *
  758. * @param req The SnmpMibRequest object holding the varbind list
  759. * concerning this MIB.
  760. *
  761. * @return The request-tree where the original varbind list has been
  762. * dispatched to the appropriate nodes, and where the original
  763. * OIDs have been replaced with the correct "next" OID.
  764. */
  765. private SnmpRequestTree getGetNextHandlers(SnmpMibRequest req)
  766. throws SnmpStatusException {
  767. // Creates an empty request tree, no entry creation is allowed (false)
  768. SnmpRequestTree handlers = new
  769. SnmpRequestTree(req,false,SnmpDefinitions.pduGetNextRequestPdu);
  770. // Sets the getNext flag: if version=V2, status exception are
  771. // transformed in endOfMibView
  772. handlers.setGetNextFlag();
  773. if (isDebugOn())
  774. debug("getGetNextHandlers","Received MIB request : " + req);
  775. AcmChecker checker = new AcmChecker(req);
  776. int index=0;
  777. SnmpVarBind var = null;
  778. final int ver= req.getVersion();
  779. SnmpOid original = null;
  780. // For each varbind, finds the handling node.
  781. // This function has the side effect of transforming a GET-NEXT
  782. // request into a valid GET request, replacing the OIDs in the
  783. // original GET-NEXT request with the OID of the first leaf that
  784. // follows.
  785. for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) {
  786. var = (SnmpVarBind) e.nextElement();
  787. SnmpOid result = null;
  788. try {
  789. // Find the node handling the OID that follows the varbind
  790. // OID. `result' contains this next leaf OID.
  791. //ACM loop.
  792. if (isDebugOn())
  793. debug("getGetNextHandlers"," Next Oid of :" + var.oid);
  794. result = new SnmpOid(root.findNextHandlingNode
  795. (var,var.oid.longValue(false),0,
  796. 0,handlers, checker));
  797. if (isDebugOn())
  798. debug("getGetNextHandlers"," is :" + result);
  799. // We replace the varbind original OID with the OID of the
  800. // leaf object we have to return.
  801. var.oid = result;
  802. } catch(SnmpStatusException x) {
  803. // if (isDebugOn())
  804. // debug("getGetNextHandlers",
  805. // "Couldn't find a handling node for "
  806. // + var.oid.toString());
  807. if (ver == SnmpDefinitions.snmpVersionOne) {
  808. if (isDebugOn())
  809. debug("getGetNextHandlers","\tThrowing exception" +
  810. x.toString());
  811. // The index in the exception must correspond to the
  812. // SNMP index ...
  813. //
  814. throw new SnmpStatusException(x, index + 1);
  815. }
  816. if (isDebugOn())
  817. debug("getGetNextHandlers","Exception : " + x.getStatus());
  818. var.setSnmpValue(SnmpVarBind.endOfMibView);
  819. }
  820. }
  821. return handlers;
  822. }
  823. // Returns true if debug is on
  824. private final static boolean isDebugOn() {
  825. return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
  826. }
  827. // Prints a debug message
  828. private final static void debug(String func, String info) {
  829. Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP,
  830. "SnmpMib", func, info);
  831. }
  832. // --------------------------------------------------------------------
  833. // PROTECTED VARIABLES
  834. // --------------------------------------------------------------------
  835. /**
  836. * The top element in the Mib tree.
  837. * @serial
  838. */
  839. protected SnmpMibOid root;
  840. // --------------------------------------------------------------------
  841. // PRIVATE VARIABLES
  842. // --------------------------------------------------------------------
  843. /**
  844. * The root object identifier of the MIB.
  845. */
  846. private transient long[] rootOid= null;
  847. }