blob: c2f8b61b98f25dde34b1aad11bad61f34e564560 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27package com.sun.jmx.snmp.daemon;
28
29
30// java imports
31//
32import java.util.Vector;
33import java.util.Enumeration;
34import java.util.logging.Level;
35import java.net.DatagramSocket;
36import java.net.DatagramPacket;
37import java.net.InetAddress;
38import java.net.SocketException;
39import java.net.UnknownHostException;
40import java.io.ObjectInputStream;
41import java.io.IOException;
42import java.io.InterruptedIOException;
43
44
45// jmx imports
46//
47import javax.management.MBeanServer;
48import javax.management.MBeanRegistration;
49import javax.management.ObjectName;
50import javax.management.InstanceAlreadyExistsException;
51import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
52import com.sun.jmx.snmp.SnmpIpAddress;
53import com.sun.jmx.snmp.SnmpMessage;
54import com.sun.jmx.snmp.SnmpOid;
55import com.sun.jmx.snmp.SnmpPduFactory;
56import com.sun.jmx.snmp.SnmpPduPacket;
57import com.sun.jmx.snmp.SnmpPduRequest;
58import com.sun.jmx.snmp.SnmpPduTrap;
59import com.sun.jmx.snmp.SnmpTimeticks;
60import com.sun.jmx.snmp.SnmpVarBind;
61import com.sun.jmx.snmp.SnmpVarBindList;
62import com.sun.jmx.snmp.SnmpDefinitions;
63import com.sun.jmx.snmp.SnmpStatusException;
64import com.sun.jmx.snmp.SnmpTooBigException;
65import com.sun.jmx.snmp.InetAddressAcl;
66import com.sun.jmx.snmp.SnmpPeer;
67import com.sun.jmx.snmp.SnmpParameters;
68// SNMP Runtime imports
69//
70import com.sun.jmx.snmp.SnmpPduFactoryBER;
71import com.sun.jmx.snmp.agent.SnmpMibAgent;
72import com.sun.jmx.snmp.agent.SnmpMibHandler;
73import com.sun.jmx.snmp.agent.SnmpUserDataFactory;
74import com.sun.jmx.snmp.agent.SnmpErrorHandlerAgent;
75
76import com.sun.jmx.snmp.IPAcl.SnmpAcl;
77
78import com.sun.jmx.snmp.tasks.ThreadService;
79
80/**
81 * Implements an adaptor on top of the SNMP protocol.
82 * <P>
83 * When this SNMP protocol adaptor is started it creates a datagram socket
84 * and is able to receive requests and send traps or inform requests.
85 * When it is stopped, the socket is closed and neither requests
86 * and nor traps/inform request are processed.
87 * <P>
88 * The default port number of the socket is 161. This default value can be
89 * changed by specifying a port number:
90 * <UL>
91 * <LI>in the object constructor</LI>
92 * <LI>using the {@link com.sun.jmx.snmp.daemon.CommunicatorServer#setPort
93 * setPort} method before starting the adaptor</LI>
94 * </UL>
95 * The default object name is defined by {@link
96 * com.sun.jmx.snmp.ServiceName#DOMAIN com.sun.jmx.snmp.ServiceName.DOMAIN}
97 * and {@link com.sun.jmx.snmp.ServiceName#SNMP_ADAPTOR_SERVER
98 * com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER}.
99 * <P>
100 * The SNMP protocol adaptor supports versions 1 and 2 of the SNMP protocol
101 * in a stateless way: when it receives a v1 request, it replies with a v1
102 * response, when it receives a v2 request it replies with a v2 response.
103 * <BR>The method {@link #snmpV1Trap snmpV1Trap} sends traps using SNMP v1
104 * format.
105 * The method {@link #snmpV2Trap snmpV2Trap} sends traps using SNMP v2 format.
106 * The method {@link #snmpInformRequest snmpInformRequest} sends inform
107 * requests using SNMP v2 format.
108 * <P>
109 * To receive data packets, the SNMP protocol adaptor uses a buffer
110 * which size can be configured using the property <CODE>bufferSize</CODE>
111 * (default value is 1024).
112 * Packets which do not fit into the buffer are rejected.
113 * Increasing <CODE>bufferSize</CODE> allows the exchange of bigger packets.
114 * However, the underlying networking system may impose a limit on the size
115 * of UDP packets.
116 * Packets which size exceed this limit will be rejected, no matter what
117 * the value of <CODE>bufferSize</CODE> actually is.
118 * <P>
119 * An SNMP protocol adaptor may serve several managers concurrently. The
120 * number of concurrent managers can be limited using the property
121 * <CODE>maxActiveClientCount</CODE>.
122 * <p>
123 * The SNMP protocol adaptor specifies a default value (10) for the
124 * <CODE>maxActiveClientCount</CODE> property. When the adaptor is stopped,
125 * the active requests are interrupted and an error result is sent to
126 * the managers.
127 * <p><b>This API is a Sun Microsystems internal API and is subject
128 * to change without notice.</b></p>
129 */
130
131public class SnmpAdaptorServer extends CommunicatorServer
132 implements SnmpAdaptorServerMBean, MBeanRegistration, SnmpDefinitions,
133 SnmpMibHandler {
134
135 // PRIVATE VARIABLES
136 //------------------
137
138 /**
139 * Port number for sending SNMP traps.
140 * <BR>The default value is 162.
141 */
142 private int trapPort = 162;
143
144 /**
145 * Port number for sending SNMP inform requests.
146 * <BR>The default value is 162.
147 */
148 private int informPort = 162;
149
150 /**
151 * The <CODE>InetAddress</CODE> used when creating the datagram socket.
152 * <BR>It is specified when creating the SNMP protocol adaptor.
153 * If not specified, the local host machine is used.
154 */
155 InetAddress address = null;
156
157 /**
158 * The IP address based ACL used by this SNMP protocol adaptor.
159 */
160 private Object ipacl = null;
161
162 /**
163 * The factory object.
164 */
165 private SnmpPduFactory pduFactory = null;
166
167 /**
168 * The user-data factory object.
169 */
170 private SnmpUserDataFactory userDataFactory = null;
171
172 /**
173 * Indicates if the SNMP protocol adaptor sends a response in case
174 * of authentication failure
175 */
176 private boolean authRespEnabled = true;
177
178 /**
179 * Indicates if authentication traps are enabled.
180 */
181 private boolean authTrapEnabled = true;
182
183 /**
184 * The enterprise OID.
185 * <BR>The default value is "1.3.6.1.4.1.42".
186 */
187 private SnmpOid enterpriseOid = new SnmpOid("1.3.6.1.4.1.42");
188
189 /**
190 * The buffer size of the SNMP protocol adaptor.
191 * This buffer size is used for both incoming request and outgoing
192 * inform requests.
193 * <BR>The default value is 1024.
194 */
195 int bufferSize = 1024;
196
197 private transient long startUpTime = 0;
198 private transient DatagramSocket socket = null;
199 transient DatagramSocket trapSocket = null;
200 private transient SnmpSession informSession = null;
201 private transient DatagramPacket packet = null;
202 transient Vector<SnmpMibAgent> mibs = new Vector<SnmpMibAgent>();
203 private transient SnmpMibTree root;
204
205 /**
206 * Whether ACL must be used.
207 */
208 private transient boolean useAcl = true;
209
210
211 // SENDING SNMP INFORMS STUFF
212 //---------------------------
213
214 /**
215 * Number of times to try an inform request before giving up.
216 * The default number is 3.
217 */
218 private int maxTries = 3 ;
219
220 /**
221 * The amount of time to wait for an inform response from the manager.
222 * The default amount of time is 3000 millisec.
223 */
224 private int timeout = 3 * 1000 ;
225
226 // VARIABLES REQUIRED FOR IMPLEMENTING SNMP GROUP (MIBII)
227 //-------------------------------------------------------
228
229 /**
230 * The <CODE>snmpOutTraps</CODE> value defined in MIB-II.
231 */
232 int snmpOutTraps=0;
233
234 /**
235 * The <CODE>snmpOutGetResponses</CODE> value defined in MIB-II.
236 */
237 private int snmpOutGetResponses=0;
238
239 /**
240 * The <CODE>snmpOutGenErrs</CODE> value defined in MIB-II.
241 */
242 private int snmpOutGenErrs=0;
243
244 /**
245 * The <CODE>snmpOutBadValues</CODE> value defined in MIB-II.
246 */
247 private int snmpOutBadValues=0;
248
249 /**
250 * The <CODE>snmpOutNoSuchNames</CODE> value defined in MIB-II.
251 */
252 private int snmpOutNoSuchNames=0;
253
254 /**
255 * The <CODE>snmpOutTooBigs</CODE> value defined in MIB-II.
256 */
257 private int snmpOutTooBigs=0;
258
259 /**
260 * The <CODE>snmpOutPkts</CODE> value defined in MIB-II.
261 */
262 int snmpOutPkts=0;
263
264 /**
265 * The <CODE>snmpInASNParseErrs</CODE> value defined in MIB-II.
266 */
267 private int snmpInASNParseErrs=0;
268
269 /**
270 * The <CODE>snmpInBadCommunityUses</CODE> value defined in MIB-II.
271 */
272 private int snmpInBadCommunityUses=0;
273
274 /**
275 * The <CODE>snmpInBadCommunityNames</CODE> value defined in MIB-II.
276 */
277 private int snmpInBadCommunityNames=0;
278
279 /**
280 * The <CODE>snmpInBadVersions</CODE> value defined in MIB-II.
281 */
282 private int snmpInBadVersions=0;
283
284 /**
285 * The <CODE>snmpInGetRequests</CODE> value defined in MIB-II.
286 */
287 private int snmpInGetRequests=0;
288
289 /**
290 * The <CODE>snmpInGetNexts</CODE> value defined in MIB-II.
291 */
292 private int snmpInGetNexts=0;
293
294 /**
295 * The <CODE>snmpInSetRequests</CODE> value defined in MIB-II.
296 */
297 private int snmpInSetRequests=0;
298
299 /**
300 * The <CODE>snmpInPkts</CODE> value defined in MIB-II.
301 */
302 private int snmpInPkts=0;
303
304 /**
305 * The <CODE>snmpInTotalReqVars</CODE> value defined in MIB-II.
306 */
307 private int snmpInTotalReqVars=0;
308
309 /**
310 * The <CODE>snmpInTotalSetVars</CODE> value defined in MIB-II.
311 */
312 private int snmpInTotalSetVars=0;
313
314 /**
315 * The <CODE>snmpInTotalSetVars</CODE> value defined in rfc 1907 MIB-II.
316 */
317 private int snmpSilentDrops=0;
318
319 private static final String InterruptSysCallMsg =
320 "Interrupted system call";
321 static final SnmpOid sysUpTimeOid = new SnmpOid("1.3.6.1.2.1.1.3.0") ;
322 static final SnmpOid snmpTrapOidOid = new SnmpOid("1.3.6.1.6.3.1.1.4.1.0");
323
324 private ThreadService threadService;
325
326 private static int threadNumber = 6;
327
328 static {
329 String s = System.getProperty("com.sun.jmx.snmp.threadnumber");
330
331 if (s != null) {
332 try {
333 threadNumber = Integer.parseInt(System.getProperty(s));
334 } catch (Exception e) {
335 SNMP_ADAPTOR_LOGGER.logp(Level.FINER,
336 SnmpAdaptorServer.class.getName(),
337 "<static init>",
338 "Got wrong value for com.sun.jmx.snmp.threadnumber: " +
339 s + ". Use the default value: " + threadNumber);
340 }
341 }
342 }
343
344 // PUBLIC CONSTRUCTORS
345 //--------------------
346
347 /**
348 * Initializes this SNMP protocol adaptor using the default port (161).
349 * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
350 * implementation of the <CODE>InetAddressAcl</CODE> interface.
351 */
352 public SnmpAdaptorServer() {
353 this(true, null, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
354 null) ;
355 }
356
357 /**
358 * Initializes this SNMP protocol adaptor using the specified port.
359 * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
360 * implementation of the <CODE>InetAddressAcl</CODE> interface.
361 *
362 * @param port The port number for sending SNMP responses.
363 */
364 public SnmpAdaptorServer(int port) {
365 this(true, null, port, null) ;
366 }
367
368 /**
369 * Initializes this SNMP protocol adaptor using the default port (161)
370 * and the specified IP address based ACL implementation.
371 *
372 * @param acl The <CODE>InetAddressAcl</CODE> implementation.
373 * <code>null</code> means no ACL - everybody is authorized.
374 *
375 * @since 1.5
376 */
377 public SnmpAdaptorServer(InetAddressAcl acl) {
378 this(false, acl, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
379 null) ;
380 }
381
382 /**
383 * Initializes this SNMP protocol adaptor using the default port (161)
384 * and the
385 * specified <CODE>InetAddress</CODE>.
386 * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
387 * implementation of the <CODE>InetAddressAcl</CODE> interface.
388 *
389 * @param addr The IP address to bind.
390 */
391 public SnmpAdaptorServer(InetAddress addr) {
392 this(true, null, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
393 addr) ;
394 }
395
396 /**
397 * Initializes this SNMP protocol adaptor using the specified port and the
398 * specified IP address based ACL implementation.
399 *
400 * @param acl The <CODE>InetAddressAcl</CODE> implementation.
401 * <code>null</code> means no ACL - everybody is authorized.
402 * @param port The port number for sending SNMP responses.
403 *
404 * @since 1.5
405 */
406 public SnmpAdaptorServer(InetAddressAcl acl, int port) {
407 this(false, acl, port, null) ;
408 }
409
410 /**
411 * Initializes this SNMP protocol adaptor using the specified port and the
412 * specified <CODE>InetAddress</CODE>.
413 * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default
414 * implementation of the <CODE>InetAddressAcl</CODE> interface.
415 *
416 * @param port The port number for sending SNMP responses.
417 * @param addr The IP address to bind.
418 */
419 public SnmpAdaptorServer(int port, InetAddress addr) {
420 this(true, null, port, addr) ;
421 }
422
423 /**
424 * Initializes this SNMP protocol adaptor using the specified IP
425 * address based ACL implementation and the specified
426 * <CODE>InetAddress</CODE>.
427 *
428 * @param acl The <CODE>InetAddressAcl</CODE> implementation.
429 * @param addr The IP address to bind.
430 *
431 * @since 1.5
432 */
433 public SnmpAdaptorServer(InetAddressAcl acl, InetAddress addr) {
434 this(false, acl, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT,
435 addr) ;
436 }
437
438 /**
439 * Initializes this SNMP protocol adaptor using the specified port, the
440 * specified address based ACL implementation and the specified
441 * <CODE>InetAddress</CODE>.
442 *
443 * @param acl The <CODE>InetAddressAcl</CODE> implementation.
444 * @param port The port number for sending SNMP responses.
445 * @param addr The IP address to bind.
446 *
447 * @since 1.5
448 */
449 public SnmpAdaptorServer(InetAddressAcl acl, int port, InetAddress addr) {
450 this(false, acl, port, addr);
451 }
452
453 /**
454 * Initializes this SNMP protocol adaptor using the specified port and the
455 * specified <CODE>InetAddress</CODE>.
456 * This constructor allows to initialize an SNMP adaptor without using
457 * the ACL mechanism (by setting the <CODE>useAcl</CODE> parameter to
458 * false).
459 * <br>This constructor must be used in particular with a platform that
460 * does not support the <CODE>java.security.acl</CODE> package like pJava.
461 *
462 * @param useAcl Specifies if this new SNMP adaptor uses the ACL mechanism.
463 * If the specified parameter is set to <CODE>true</CODE>, this
464 * constructor is equivalent to
465 * <CODE>SnmpAdaptorServer((int)port,(InetAddress)addr)</CODE>.
466 * @param port The port number for sending SNMP responses.
467 * @param addr The IP address to bind.
468 */
469 public SnmpAdaptorServer(boolean useAcl, int port, InetAddress addr) {
470 this(useAcl,null,port,addr);
471 }
472
473 // If forceAcl is `true' and InetAddressAcl is null, then a default
474 // SnmpAcl object is created.
475 //
476 private SnmpAdaptorServer(boolean forceAcl, InetAddressAcl acl,
477 int port, InetAddress addr) {
478 super(CommunicatorServer.SNMP_TYPE) ;
479
480
481 // Initialize the ACL implementation.
482 //
483 if (acl == null && forceAcl) {
484 try {
485 acl = (InetAddressAcl)
486 new SnmpAcl("SNMP protocol adaptor IP ACL");
487 } catch (UnknownHostException e) {
488 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
489 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
490 "constructor", "UnknowHostException when creating ACL",e);
491 }
492 }
493 } else {
494 this.useAcl = (acl!=null) || forceAcl;
495 }
496
497 init(acl, port, addr) ;
498 }
499
500 // GETTERS AND SETTERS
501 //--------------------
502
503 /**
504 * Gets the number of managers that have been processed by this
505 * SNMP protocol adaptor since its creation.
506 *
507 * @return The number of managers handled by this SNMP protocol adaptor
508 * since its creation. This counter is not reset by the <CODE>stop</CODE>
509 * method.
510 */
511 public int getServedClientCount() {
512 return super.getServedClientCount();
513 }
514
515 /**
516 * Gets the number of managers currently being processed by this
517 * SNMP protocol adaptor.
518 *
519 * @return The number of managers currently being processed by this
520 * SNMP protocol adaptor.
521 */
522 public int getActiveClientCount() {
523 return super.getActiveClientCount();
524 }
525
526 /**
527 * Gets the maximum number of managers that this SNMP protocol adaptor can
528 * process concurrently.
529 *
530 * @return The maximum number of managers that this SNMP protocol adaptor
531 * can process concurrently.
532 */
533 public int getMaxActiveClientCount() {
534 return super.getMaxActiveClientCount();
535 }
536
537 /**
538 * Sets the maximum number of managers this SNMP protocol adaptor can
539 * process concurrently.
540 *
541 * @param c The number of managers.
542 *
543 * @exception java.lang.IllegalStateException This method has been invoked
544 * while the communicator was <CODE>ONLINE</CODE> or <CODE>STARTING</CODE>.
545 */
546 public void setMaxActiveClientCount(int c)
547 throws java.lang.IllegalStateException {
548 super.setMaxActiveClientCount(c);
549 }
550
551 /**
552 * Returns the Ip address based ACL used by this SNMP protocol adaptor.
553 * @return The <CODE>InetAddressAcl</CODE> implementation.
554 *
555 * @since 1.5
556 */
557 public InetAddressAcl getInetAddressAcl() {
558 return (InetAddressAcl)ipacl;
559 }
560
561 /**
562 * Returns the port used by this SNMP protocol adaptor for sending traps.
563 * By default, port 162 is used.
564 *
565 * @return The port number for sending SNMP traps.
566 */
567 public Integer getTrapPort() {
568 return new Integer(trapPort) ;
569 }
570
571 /**
572 * Sets the port used by this SNMP protocol adaptor for sending traps.
573 *
574 * @param port The port number for sending SNMP traps.
575 */
576 public void setTrapPort(Integer port) {
577 setTrapPort(port.intValue());
578 }
579
580 /**
581 * Sets the port used by this SNMP protocol adaptor for sending traps.
582 *
583 * @param port The port number for sending SNMP traps.
584 */
585 public void setTrapPort(int port) {
586 int val= port ;
587 if (val < 0) throw new
588 IllegalArgumentException("Trap port cannot be a negative value");
589 trapPort= val ;
590 }
591
592 /**
593 * Returns the port used by this SNMP protocol adaptor for sending
594 * inform requests. By default, port 162 is used.
595 *
596 * @return The port number for sending SNMP inform requests.
597 */
598 public int getInformPort() {
599 return informPort;
600 }
601
602 /**
603 * Sets the port used by this SNMP protocol adaptor for sending
604 * inform requests.
605 *
606 * @param port The port number for sending SNMP inform requests.
607 */
608 public void setInformPort(int port) {
609 if (port < 0)
610 throw new IllegalArgumentException("Inform request port "+
611 "cannot be a negative value");
612 informPort= port ;
613 }
614
615 /**
616 * Returns the protocol of this SNMP protocol adaptor.
617 *
618 * @return The string "snmp".
619 */
620 public String getProtocol() {
621 return "snmp";
622 }
623
624 /**
625 * Returns the buffer size of this SNMP protocol adaptor.
626 * This buffer size is used for both incoming request and outgoing
627 * inform requests.
628 * By default, buffer size 1024 is used.
629 *
630 * @return The buffer size.
631 */
632 public Integer getBufferSize() {
633 return new Integer(bufferSize) ;
634 }
635
636 /**
637 * Sets the buffer size of this SNMP protocol adaptor.
638 * This buffer size is used for both incoming request and outgoing
639 * inform requests.
640 *
641 * @param s The buffer size.
642 *
643 * @exception java.lang.IllegalStateException This method has been invoked
644 * while the communicator was <CODE>ONLINE</CODE> or <CODE>STARTING</CODE>.
645 */
646 public void setBufferSize(Integer s)
647 throws java.lang.IllegalStateException {
648 if ((state == ONLINE) || (state == STARTING)) {
649 throw new IllegalStateException("Stop server before carrying out"+
650 " this operation");
651 }
652 bufferSize = s.intValue() ;
653 }
654
655 /**
656 * Gets the number of times to try sending an inform request before
657 * giving up.
658 * By default, a maximum of 3 tries is used.
659 * @return The maximun number of tries.
660 */
661 final public int getMaxTries() {
662 return maxTries;
663 }
664
665 /**
666 * Changes the maximun number of times to try sending an inform
667 * request before giving up.
668 * @param newMaxTries The maximun number of tries.
669 */
670 final public synchronized void setMaxTries(int newMaxTries) {
671 if (newMaxTries < 0)
672 throw new IllegalArgumentException();
673 maxTries = newMaxTries;
674 }
675
676 /**
677 * Gets the timeout to wait for an inform response from the manager.
678 * By default, a timeout of 3 seconds is used.
679 * @return The value of the timeout property.
680 */
681 final public int getTimeout() {
682 return timeout;
683 }
684
685 /**
686 * Changes the timeout to wait for an inform response from the manager.
687 * @param newTimeout The timeout (in milliseconds).
688 */
689 final public synchronized void setTimeout(int newTimeout) {
690 if (newTimeout < 0)
691 throw new IllegalArgumentException();
692 timeout= newTimeout;
693 }
694
695 /**
696 * Returns the message factory of this SNMP protocol adaptor.
697 *
698 * @return The factory object.
699 */
700 public SnmpPduFactory getPduFactory() {
701 return pduFactory ;
702 }
703
704 /**
705 * Sets the message factory of this SNMP protocol adaptor.
706 *
707 * @param factory The factory object (null means the default factory).
708 */
709 public void setPduFactory(SnmpPduFactory factory) {
710 if (factory == null)
711 pduFactory = new SnmpPduFactoryBER() ;
712 else
713 pduFactory = factory ;
714 }
715
716 /**
717 * Set the user-data factory of this SNMP protocol adaptor.
718 *
719 * @param factory The factory object (null means no factory).
720 * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory
721 */
722 public void setUserDataFactory(SnmpUserDataFactory factory) {
723 userDataFactory = factory ;
724 }
725
726 /**
727 * Get the user-data factory associated with this SNMP protocol adaptor.
728 *
729 * @return The factory object (null means no factory).
730 * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory
731 */
732 public SnmpUserDataFactory getUserDataFactory() {
733 return userDataFactory;
734 }
735
736 /**
737 * Returns <CODE>true</CODE> if authentication traps are enabled.
738 * <P>
739 * When this feature is enabled, the SNMP protocol adaptor sends
740 * an <CODE>authenticationFailure</CODE> trap each time an
741 * authentication fails.
742 * <P>
743 * The default behaviour is to send authentication traps.
744 *
745 * @return <CODE>true</CODE> if authentication traps are enabled,
746 * <CODE>false</CODE> otherwise.
747 */
748 public boolean getAuthTrapEnabled() {
749 return authTrapEnabled ;
750 }
751
752 /**
753 * Sets the flag indicating if traps need to be sent in case of
754 * authentication failure.
755 *
756 * @param enabled Flag indicating if traps need to be sent.
757 */
758 public void setAuthTrapEnabled(boolean enabled) {
759 authTrapEnabled = enabled ;
760 }
761
762 /**
763 * Returns <code>true</code> if this SNMP protocol adaptor sends a
764 * response in case of authentication failure.
765 * <P>
766 * When this feature is enabled, the SNMP protocol adaptor sends a
767 * response with <CODE>noSuchName</CODE> or <CODE>readOnly</CODE> when
768 * the authentication failed. If the flag is disabled, the
769 * SNMP protocol adaptor trashes the PDU silently.
770 * <P>
771 * The default behavior is to send responses.
772 *
773 * @return <CODE>true</CODE> if responses are sent.
774 */
775 public boolean getAuthRespEnabled() {
776 return authRespEnabled ;
777 }
778
779 /**
780 * Sets the flag indicating if responses need to be sent in case of
781 * authentication failure.
782 *
783 * @param enabled Flag indicating if responses need to be sent.
784 */
785 public void setAuthRespEnabled(boolean enabled) {
786 authRespEnabled = enabled ;
787 }
788
789 /**
790 * Returns the enterprise OID. It is used by
791 * {@link #snmpV1Trap snmpV1Trap} to fill the 'enterprise' field of the
792 * trap request.
793 *
794 * @return The OID in string format "x.x.x.x".
795 */
796 public String getEnterpriseOid() {
797 return enterpriseOid.toString() ;
798 }
799
800 /**
801 * Sets the enterprise OID.
802 *
803 * @param oid The OID in string format "x.x.x.x".
804 *
805 * @exception IllegalArgumentException The string format is incorrect
806 */
807 public void setEnterpriseOid(String oid) throws IllegalArgumentException {
808 enterpriseOid = new SnmpOid(oid) ;
809 }
810
811 /**
812 * Returns the names of the MIBs available in this SNMP protocol adaptor.
813 *
814 * @return An array of MIB names.
815 */
816 public String[] getMibs() {
817 String[] result = new String[mibs.size()] ;
818 int i = 0 ;
819 for (Enumeration e = mibs.elements() ; e.hasMoreElements() ;) {
820 SnmpMibAgent mib = (SnmpMibAgent)e.nextElement() ;
821 result[i++] = mib.getMibName();
822 }
823 return result ;
824 }
825
826 // GETTERS FOR SNMP GROUP (MIBII)
827 //-------------------------------
828
829 /**
830 * Returns the <CODE>snmpOutTraps</CODE> value defined in MIB-II.
831 *
832 * @return The <CODE>snmpOutTraps</CODE> value.
833 */
834 public Long getSnmpOutTraps() {
835 return new Long(snmpOutTraps);
836 }
837
838 /**
839 * Returns the <CODE>snmpOutGetResponses</CODE> value defined in MIB-II.
840 *
841 * @return The <CODE>snmpOutGetResponses</CODE> value.
842 */
843 public Long getSnmpOutGetResponses() {
844 return new Long(snmpOutGetResponses);
845 }
846
847 /**
848 * Returns the <CODE>snmpOutGenErrs</CODE> value defined in MIB-II.
849 *
850 * @return The <CODE>snmpOutGenErrs</CODE> value.
851 */
852 public Long getSnmpOutGenErrs() {
853 return new Long(snmpOutGenErrs);
854 }
855
856 /**
857 * Returns the <CODE>snmpOutBadValues</CODE> value defined in MIB-II.
858 *
859 * @return The <CODE>snmpOutBadValues</CODE> value.
860 */
861 public Long getSnmpOutBadValues() {
862 return new Long(snmpOutBadValues);
863 }
864
865 /**
866 * Returns the <CODE>snmpOutNoSuchNames</CODE> value defined in MIB-II.
867 *
868 * @return The <CODE>snmpOutNoSuchNames</CODE> value.
869 */
870 public Long getSnmpOutNoSuchNames() {
871 return new Long(snmpOutNoSuchNames);
872 }
873
874 /**
875 * Returns the <CODE>snmpOutTooBigs</CODE> value defined in MIB-II.
876 *
877 * @return The <CODE>snmpOutTooBigs</CODE> value.
878 */
879 public Long getSnmpOutTooBigs() {
880 return new Long(snmpOutTooBigs);
881 }
882
883 /**
884 * Returns the <CODE>snmpInASNParseErrs</CODE> value defined in MIB-II.
885 *
886 * @return The <CODE>snmpInASNParseErrs</CODE> value.
887 */
888 public Long getSnmpInASNParseErrs() {
889 return new Long(snmpInASNParseErrs);
890 }
891
892 /**
893 * Returns the <CODE>snmpInBadCommunityUses</CODE> value defined in MIB-II.
894 *
895 * @return The <CODE>snmpInBadCommunityUses</CODE> value.
896 */
897 public Long getSnmpInBadCommunityUses() {
898 return new Long(snmpInBadCommunityUses);
899 }
900
901 /**
902 * Returns the <CODE>snmpInBadCommunityNames</CODE> value defined in
903 * MIB-II.
904 *
905 * @return The <CODE>snmpInBadCommunityNames</CODE> value.
906 */
907 public Long getSnmpInBadCommunityNames() {
908 return new Long(snmpInBadCommunityNames);
909 }
910
911 /**
912 * Returns the <CODE>snmpInBadVersions</CODE> value defined in MIB-II.
913 *
914 * @return The <CODE>snmpInBadVersions</CODE> value.
915 */
916 public Long getSnmpInBadVersions() {
917 return new Long(snmpInBadVersions);
918 }
919
920 /**
921 * Returns the <CODE>snmpOutPkts</CODE> value defined in MIB-II.
922 *
923 * @return The <CODE>snmpOutPkts</CODE> value.
924 */
925 public Long getSnmpOutPkts() {
926 return new Long(snmpOutPkts);
927 }
928
929 /**
930 * Returns the <CODE>snmpInPkts</CODE> value defined in MIB-II.
931 *
932 * @return The <CODE>snmpInPkts</CODE> value.
933 */
934 public Long getSnmpInPkts() {
935 return new Long(snmpInPkts);
936 }
937
938 /**
939 * Returns the <CODE>snmpInGetRequests</CODE> value defined in MIB-II.
940 *
941 * @return The <CODE>snmpInGetRequests</CODE> value.
942 */
943 public Long getSnmpInGetRequests() {
944 return new Long(snmpInGetRequests);
945 }
946
947 /**
948 * Returns the <CODE>snmpInGetNexts</CODE> value defined in MIB-II.
949 *
950 * @return The <CODE>snmpInGetNexts</CODE> value.
951 */
952 public Long getSnmpInGetNexts() {
953 return new Long(snmpInGetNexts);
954 }
955
956 /**
957 * Returns the <CODE>snmpInSetRequests</CODE> value defined in MIB-II.
958 *
959 * @return The <CODE>snmpInSetRequests</CODE> value.
960 */
961 public Long getSnmpInSetRequests() {
962 return new Long(snmpInSetRequests);
963 }
964
965 /**
966 * Returns the <CODE>snmpInTotalSetVars</CODE> value defined in MIB-II.
967 *
968 * @return The <CODE>snmpInTotalSetVars</CODE> value.
969 */
970 public Long getSnmpInTotalSetVars() {
971 return new Long(snmpInTotalSetVars);
972 }
973
974 /**
975 * Returns the <CODE>snmpInTotalReqVars</CODE> value defined in MIB-II.
976 *
977 * @return The <CODE>snmpInTotalReqVars</CODE> value.
978 */
979 public Long getSnmpInTotalReqVars() {
980 return new Long(snmpInTotalReqVars);
981 }
982
983 /**
984 * Returns the <CODE>snmpSilentDrops</CODE> value defined in RFC
985 * 1907 NMPv2-MIB .
986 *
987 * @return The <CODE>snmpSilentDrops</CODE> value.
988 *
989 * @since 1.5
990 */
991 public Long getSnmpSilentDrops() {
992 return new Long(snmpSilentDrops);
993 }
994
995 /**
996 * Returns the <CODE>snmpProxyDrops</CODE> value defined in RFC
997 * 1907 NMPv2-MIB .
998 *
999 * @return The <CODE>snmpProxyDrops</CODE> value.
1000 *
1001 * @since 1.5
1002 */
1003 public Long getSnmpProxyDrops() {
1004 return new Long(0);
1005 }
1006
1007
1008 // PUBLIC METHODS
1009 //---------------
1010
1011 /**
1012 * Allows the MBean to perform any operations it needs before being
1013 * registered in the MBean server.
1014 * If the name of the SNMP protocol adaptor MBean is not specified,
1015 * it is initialized with the default value:
1016 * {@link com.sun.jmx.snmp.ServiceName#DOMAIN
1017 * com.sun.jmx.snmp.ServiceName.DOMAIN}:{@link
1018 * com.sun.jmx.snmp.ServiceName#SNMP_ADAPTOR_SERVER
1019 * com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER}.
1020 * If any exception is raised, the SNMP protocol adaptor MBean will
1021 * not be registered in the MBean server.
1022 *
1023 * @param server The MBean server to register the service with.
1024 * @param name The object name.
1025 *
1026 * @return The name of the SNMP protocol adaptor registered.
1027 *
1028 * @exception java.lang.Exception
1029 */
1030 public ObjectName preRegister(MBeanServer server, ObjectName name)
1031 throws java.lang.Exception {
1032
1033 if (name == null) {
1034 name = new ObjectName(server.getDefaultDomain() + ":" +
1035 com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER);
1036 }
1037 return (super.preRegister(server, name));
1038 }
1039
1040 /**
1041 * Not used in this context.
1042 */
1043 public void postRegister (Boolean registrationDone) {
1044 super.postRegister(registrationDone);
1045 }
1046
1047 /**
1048 * Not used in this context.
1049 */
1050 public void preDeregister() throws java.lang.Exception {
1051 super.preDeregister();
1052 }
1053
1054 /**
1055 * Not used in this context.
1056 */
1057 public void postDeregister() {
1058 super.postDeregister();
1059 }
1060
1061 /**
1062 * Adds a new MIB in the SNMP MIB handler.
1063 *
1064 * @param mib The MIB to add.
1065 *
1066 * @return A reference to the SNMP MIB handler.
1067 *
1068 * @exception IllegalArgumentException If the parameter is null.
1069 */
1070 public SnmpMibHandler addMib(SnmpMibAgent mib)
1071 throws IllegalArgumentException {
1072 if (mib == null) {
1073 throw new IllegalArgumentException() ;
1074 }
1075
1076 if(!mibs.contains(mib))
1077 mibs.addElement(mib);
1078
1079 root.register(mib);
1080
1081 return this;
1082 }
1083
1084 /**
1085 * Adds a new MIB in the SNMP MIB handler.
1086 * This method is to be called to set a specific agent to a specific OID.
1087 * This can be useful when dealing with MIB overlapping.
1088 * Some OID can be implemented in more than one MIB. In this case,
1089 * the OID nearer agent will be used on SNMP operations.
1090 *
1091 * @param mib The MIB to add.
1092 * @param oids The set of OIDs this agent implements.
1093 *
1094 * @return A reference to the SNMP MIB handler.
1095 *
1096 * @exception IllegalArgumentException If the parameter is null.
1097 *
1098 * @since 1.5
1099 */
1100 public SnmpMibHandler addMib(SnmpMibAgent mib, SnmpOid[] oids)
1101 throws IllegalArgumentException {
1102 if (mib == null) {
1103 throw new IllegalArgumentException() ;
1104 }
1105
1106 //If null oid array, just add it to the mib.
1107 if(oids == null)
1108 return addMib(mib);
1109
1110 if(!mibs.contains(mib))
1111 mibs.addElement(mib);
1112
1113 for (int i = 0; i < oids.length; i++) {
1114 root.register(mib, oids[i].longValue());
1115 }
1116 return this;
1117 }
1118
1119 /**
1120 * Adds a new MIB in the SNMP MIB handler. In SNMP V1 and V2 the
1121 * <CODE>contextName</CODE> is useless and this method
1122 * is equivalent to <CODE>addMib(SnmpMibAgent mib)</CODE>.
1123 *
1124 * @param mib The MIB to add.
1125 * @param contextName The MIB context name.
1126 * @return A reference on the SNMP MIB handler.
1127 *
1128 * @exception IllegalArgumentException If the parameter is null.
1129 *
1130 * @since 1.5
1131 */
1132 public SnmpMibHandler addMib(SnmpMibAgent mib, String contextName)
1133 throws IllegalArgumentException {
1134 return addMib(mib);
1135 }
1136
1137 /**
1138 * Adds a new MIB in the SNMP MIB handler. In SNMP V1 and V2 the
1139 * <CODE>contextName</CODE> is useless and this method
1140 * is equivalent to <CODE>addMib(SnmpMibAgent mib, SnmpOid[] oids)</CODE>.
1141 *
1142 * @param mib The MIB to add.
1143 * @param contextName The MIB context. If null is passed, will be
1144 * registered in the default context.
1145 * @param oids The set of OIDs this agent implements.
1146 *
1147 * @return A reference to the SNMP MIB handler.
1148 *
1149 * @exception IllegalArgumentException If the parameter is null.
1150 *
1151 * @since 1.5
1152 */
1153 public SnmpMibHandler addMib(SnmpMibAgent mib,
1154 String contextName,
1155 SnmpOid[] oids)
1156 throws IllegalArgumentException {
1157 return addMib(mib, oids);
1158 }
1159
1160 /**
1161 * Removes the specified MIB from the SNMP protocol adaptor.
1162 * In SNMP V1 and V2 the <CODE>contextName</CODE> is useless and this
1163 * method is equivalent to <CODE>removeMib(SnmpMibAgent mib)</CODE>.
1164 *
1165 * @param mib The MIB to be removed.
1166 * @param contextName The context name used at registration time.
1167 *
1168 * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was
1169 * a MIB included in the SNMP MIB handler, <CODE>false</CODE>
1170 * otherwise.
1171 *
1172 * @since 1.5
1173 */
1174 public boolean removeMib(SnmpMibAgent mib, String contextName) {
1175 return removeMib(mib);
1176 }
1177
1178 /**
1179 * Removes the specified MIB from the SNMP protocol adaptor.
1180 *
1181 * @param mib The MIB to be removed.
1182 *
1183 * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was a MIB
1184 * included in the SNMP MIB handler, <CODE>false</CODE> otherwise.
1185 */
1186 public boolean removeMib(SnmpMibAgent mib) {
1187 root.unregister(mib);
1188 return (mibs.removeElement(mib)) ;
1189 }
1190
1191 /**
1192 * Removes the specified MIB from the SNMP protocol adaptor.
1193 *
1194 * @param mib The MIB to be removed.
1195 * @param oids The oid the MIB was previously registered for.
1196 * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was
1197 * a MIB included in the SNMP MIB handler, <CODE>false</CODE>
1198 * otherwise.
1199 *
1200 * @since 1.5
1201 */
1202 public boolean removeMib(SnmpMibAgent mib, SnmpOid[] oids) {
1203 root.unregister(mib, oids);
1204 return (mibs.removeElement(mib)) ;
1205 }
1206
1207 /**
1208 * Removes the specified MIB from the SNMP protocol adaptor.
1209 *
1210 * @param mib The MIB to be removed.
1211 * @param contextName The context name used at registration time.
1212 * @param oids The oid the MIB was previously registered for.
1213 * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was
1214 * a MIB included in the SNMP MIB handler, <CODE>false</CODE>
1215 * otherwise.
1216 *
1217 * @since 1.5
1218 */
1219 public boolean removeMib(SnmpMibAgent mib,
1220 String contextName,
1221 SnmpOid[] oids) {
1222 return removeMib(mib, oids);
1223 }
1224
1225 // SUBCLASSING OF COMMUNICATOR SERVER
1226 //-----------------------------------
1227
1228 /**
1229 * Creates the datagram socket.
1230 */
1231 protected void doBind()
1232 throws CommunicationException, InterruptedException {
1233
1234 try {
1235 synchronized (this) {
1236 socket = new DatagramSocket(port, address) ;
1237 }
1238 dbgTag = makeDebugTag();
1239 } catch (SocketException e) {
1240 if (e.getMessage().equals(InterruptSysCallMsg))
1241 throw new InterruptedException(e.toString()) ;
1242 else {
1243 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
1244 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
1245 "doBind", "cannot bind on port " + port);
1246 }
1247 throw new CommunicationException(e) ;
1248 }
1249 }
1250 }
1251
1252 /**
1253 * Return the actual port to which the adaptor is bound.
1254 * Can be different from the port given at construction time if
1255 * that port number was 0.
1256 * @return the actual port to which the adaptor is bound.
1257 **/
1258 public int getPort() {
1259 synchronized (this) {
1260 if (socket != null) return socket.getLocalPort();
1261 }
1262 return super.getPort();
1263 }
1264
1265 /**
1266 * Closes the datagram socket.
1267 */
1268 protected void doUnbind()
1269 throws CommunicationException, InterruptedException {
1270 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1271 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1272 "doUnbind","Finally close the socket");
1273 }
1274 synchronized (this) {
1275 if (socket != null) {
1276 socket.close() ;
1277 socket = null ;
1278 // Important to inform finalize() that the socket is closed...
1279 }
1280 }
1281 closeTrapSocketIfNeeded() ;
1282 closeInformSocketIfNeeded() ;
1283 }
1284
1285 void createSnmpRequestHandler(SnmpAdaptorServer server, int id,
1286 DatagramSocket s, DatagramPacket p,
1287 SnmpMibTree tree, Vector m, Object a,
1288 SnmpPduFactory factory,
1289 SnmpUserDataFactory dataFactory,
1290 MBeanServer f, ObjectName n) {
1291 final SnmpRequestHandler handler =
1292 new SnmpRequestHandler(this, id, s, p, tree, m, a, factory,
1293 dataFactory, f, n);
1294 threadService.submitTask(handler);
1295 }
1296
1297 /**
1298 * Reads a packet from the datagram socket and creates a request
1299 * handler which decodes and processes the request.
1300 */
1301 protected void doReceive()
1302 throws CommunicationException, InterruptedException {
1303
1304 // Let's wait for something to be received.
1305 //
1306 try {
1307 packet = new DatagramPacket(new byte[bufferSize], bufferSize) ;
1308 socket.receive(packet);
1309 int state = getState();
1310
1311 if(state != ONLINE) {
1312 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1313 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1314 "doReceive","received a message but state not online, returning.");
1315 }
1316 return;
1317 }
1318
1319 createSnmpRequestHandler(this, servedClientCount, socket,
1320 packet, root, mibs, ipacl, pduFactory,
1321 userDataFactory, topMBS, objectName);
1322 } catch (SocketException e) {
1323 // Let's check if we have been interrupted by stop().
1324 //
1325 if (e.getMessage().equals(InterruptSysCallMsg))
1326 throw new InterruptedException(e.toString()) ;
1327 else
1328 throw new CommunicationException(e) ;
1329 } catch (InterruptedIOException e) {
1330 throw new InterruptedException(e.toString()) ;
1331 } catch (CommunicationException e) {
1332 throw e ;
1333 } catch (Exception e) {
1334 throw new CommunicationException(e) ;
1335 }
1336 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1337 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1338 "doReceive", "received a message");
1339 }
1340 }
1341
1342 protected void doError(Exception e) throws CommunicationException {
1343 return;
1344 }
1345
1346 /**
1347 * Not used in this context.
1348 */
1349 protected void doProcess()
1350 throws CommunicationException, InterruptedException {
1351 }
1352
1353
1354 /**
1355 * The number of times the communicator server will attempt
1356 * to bind before giving up.
1357 * We attempt only once...
1358 * @return 1
1359 **/
1360 protected int getBindTries() {
1361 return 1;
1362 }
1363
1364 /**
1365 * Stops this SNMP protocol adaptor.
1366 * Closes the datagram socket.
1367 * <p>
1368 * Has no effect if this SNMP protocol adaptor is <CODE>OFFLINE</CODE> or
1369 * <CODE>STOPPING</CODE>.
1370 */
1371 public void stop(){
1372
1373 final int port = getPort();
1374 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1375 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1376 "stop", "Stopping: using port " + port);
1377 }
1378 if ((state == ONLINE) || (state == STARTING)){
1379 super.stop();
1380 try {
1381 DatagramSocket sn = new DatagramSocket(0);
1382 try {
1383 byte[] ob = new byte[1];
1384
1385 DatagramPacket pk;
1386 if (address != null)
1387 pk = new DatagramPacket(ob , 1, address, port);
1388 else
1389 pk = new DatagramPacket(ob , 1,
1390 java.net.InetAddress.getLocalHost(), port);
1391
1392 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1393 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1394 "stop", "Sending: using port " + port);
1395 }
1396 sn.send(pk);
1397 } finally {
1398 sn.close();
1399 }
1400 } catch (Throwable e){
1401 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
1402 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
1403 "stop", "Got unexpected Throwable", e);
1404 }
1405 }
1406 }
1407 }
1408
1409 // SENDING SNMP TRAPS STUFF
1410 //-------------------------
1411
1412 /**
1413 * Sends a trap using SNMP V1 trap format.
1414 * <BR>The trap is sent to each destination defined in the ACL file
1415 * (if available).
1416 * If no ACL file or no destinations are available, the trap is sent
1417 * to the local host.
1418 *
1419 * @param generic The generic number of the trap.
1420 * @param specific The specific number of the trap.
1421 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1422 *
1423 * @exception IOException An I/O error occurred while sending the trap.
1424 * @exception SnmpStatusException If the trap exceeds the limit defined
1425 * by <CODE>bufferSize</CODE>.
1426 */
1427 public void snmpV1Trap(int generic, int specific,
1428 SnmpVarBindList varBindList)
1429 throws IOException, SnmpStatusException {
1430
1431 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1432 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1433 "snmpV1Trap", "generic=" + generic +
1434 ", specific=" + specific);
1435 }
1436
1437 // First, make an SNMP V1 trap pdu
1438 //
1439 SnmpPduTrap pdu = new SnmpPduTrap() ;
1440 pdu.address = null ;
1441 pdu.port = trapPort ;
1442 pdu.type = pduV1TrapPdu ;
1443 pdu.version = snmpVersionOne ;
1444 pdu.community = null ;
1445 pdu.enterprise = enterpriseOid ;
1446 pdu.genericTrap = generic ;
1447 pdu.specificTrap = specific ;
1448 pdu.timeStamp = getSysUpTime();
1449
1450 if (varBindList != null) {
1451 pdu.varBindList = new SnmpVarBind[varBindList.size()] ;
1452 varBindList.copyInto(pdu.varBindList);
1453 }
1454 else
1455 pdu.varBindList = null ;
1456
1457 // If the local host cannot be determined, we put 0.0.0.0 in agentAddr
1458 try {
1459 if (address != null)
1460 pdu.agentAddr = handleMultipleIpVersion(address.getAddress());
1461 else pdu.agentAddr =
1462 handleMultipleIpVersion(InetAddress.getLocalHost().getAddress());
1463 } catch (UnknownHostException e) {
1464 byte[] zeroedAddr = new byte[4];
1465 pdu.agentAddr = handleMultipleIpVersion(zeroedAddr) ;
1466 }
1467
1468 // Next, send the pdu to all destinations defined in ACL
1469 //
1470 sendTrapPdu(pdu) ;
1471 }
1472
1473 private SnmpIpAddress handleMultipleIpVersion(byte[] address) {
1474 if(address.length == 4)
1475 return new SnmpIpAddress(address);
1476 else {
1477 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
1478 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
1479 "handleMultipleIPVersion",
1480 "Not an IPv4 address, return null");
1481 }
1482 return null;
1483 }
1484 }
1485
1486 /**
1487 * Sends a trap using SNMP V1 trap format.
1488 * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
1489 * destination using the specified community string (and the ACL file
1490 * is not used).
1491 *
1492 * @param addr The <CODE>InetAddress</CODE> destination of the trap.
1493 * @param cs The community string to be used for the trap.
1494 * @param generic The generic number of the trap.
1495 * @param specific The specific number of the trap.
1496 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1497 *
1498 * @exception IOException An I/O error occurred while sending the trap.
1499 * @exception SnmpStatusException If the trap exceeds the limit defined
1500 * by <CODE>bufferSize</CODE>.
1501 */
1502 public void snmpV1Trap(InetAddress addr, String cs, int generic,
1503 int specific, SnmpVarBindList varBindList)
1504 throws IOException, SnmpStatusException {
1505
1506 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1507 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1508 "snmpV1Trap", "generic=" + generic + ", specific=" +
1509 specific);
1510 }
1511
1512 // First, make an SNMP V1 trap pdu
1513 //
1514 SnmpPduTrap pdu = new SnmpPduTrap() ;
1515 pdu.address = null ;
1516 pdu.port = trapPort ;
1517 pdu.type = pduV1TrapPdu ;
1518 pdu.version = snmpVersionOne ;
1519
1520 if(cs != null)
1521 pdu.community = cs.getBytes();
1522 else
1523 pdu.community = null ;
1524
1525 pdu.enterprise = enterpriseOid ;
1526 pdu.genericTrap = generic ;
1527 pdu.specificTrap = specific ;
1528 pdu.timeStamp = getSysUpTime();
1529
1530 if (varBindList != null) {
1531 pdu.varBindList = new SnmpVarBind[varBindList.size()] ;
1532 varBindList.copyInto(pdu.varBindList);
1533 }
1534 else
1535 pdu.varBindList = null ;
1536
1537 // If the local host cannot be determined, we put 0.0.0.0 in agentAddr
1538 try {
1539 if (address != null)
1540 pdu.agentAddr = handleMultipleIpVersion(address.getAddress());
1541 else pdu.agentAddr =
1542 handleMultipleIpVersion(InetAddress.getLocalHost().getAddress());
1543 } catch (UnknownHostException e) {
1544 byte[] zeroedAddr = new byte[4];
1545 pdu.agentAddr = handleMultipleIpVersion(zeroedAddr) ;
1546 }
1547
1548 // Next, send the pdu to the specified destination
1549 //
1550 if(addr != null)
1551 sendTrapPdu(addr, pdu) ;
1552 else
1553 sendTrapPdu(pdu);
1554 }
1555
1556 /**
1557 * Sends a trap using SNMP V1 trap format.
1558 * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
1559 * destination using the specified parameters (and the ACL file is not
1560 * used).
1561 * Note that if the specified <CODE>InetAddress</CODE> destination is null,
1562 * then the ACL file mechanism is used.
1563 *
1564 * @param addr The <CODE>InetAddress</CODE> destination of the trap.
1565 * @param agentAddr The agent address to be used for the trap.
1566 * @param cs The community string to be used for the trap.
1567 * @param enterpOid The enterprise OID to be used for the trap.
1568 * @param generic The generic number of the trap.
1569 * @param specific The specific number of the trap.
1570 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1571 * @param time The time stamp (overwrite the current time).
1572 *
1573 * @exception IOException An I/O error occurred while sending the trap.
1574 * @exception SnmpStatusException If the trap exceeds the limit defined
1575 * by <CODE>bufferSize</CODE>.
1576 *
1577 * @since 1.5
1578 */
1579 public void snmpV1Trap(InetAddress addr,
1580 SnmpIpAddress agentAddr,
1581 String cs,
1582 SnmpOid enterpOid,
1583 int generic,
1584 int specific,
1585 SnmpVarBindList varBindList,
1586 SnmpTimeticks time)
1587 throws IOException, SnmpStatusException {
1588 snmpV1Trap(addr,
1589 trapPort,
1590 agentAddr,
1591 cs,
1592 enterpOid,
1593 generic,
1594 specific,
1595 varBindList,
1596 time);
1597 }
1598
1599 /**
1600 * Sends a trap using SNMP V1 trap format.
1601 * <BR>The trap is sent to the specified <CODE>SnmpPeer</CODE> destination.
1602 * The community string used is the one located in the
1603 * <CODE>SnmpPeer</CODE> parameters
1604 * (<CODE>SnmpParameters.getRdCommunity() </CODE>).
1605 *
1606 * @param peer The <CODE>SnmpPeer</CODE> destination of the trap.
1607 * @param agentAddr The agent address to be used for the trap.
1608 * @param enterpOid The enterprise OID to be used for the trap.
1609 * @param generic The generic number of the trap.
1610 * @param specific The specific number of the trap.
1611 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1612 * @param time The time stamp (overwrite the current time).
1613 *
1614 * @exception IOException An I/O error occurred while sending the trap.
1615 * @exception SnmpStatusException If the trap exceeds the limit
1616 * defined by <CODE>bufferSize</CODE>.
1617 *
1618 * @since 1.5
1619 */
1620 public void snmpV1Trap(SnmpPeer peer,
1621 SnmpIpAddress agentAddr,
1622 SnmpOid enterpOid,
1623 int generic,
1624 int specific,
1625 SnmpVarBindList varBindList,
1626 SnmpTimeticks time)
1627 throws IOException, SnmpStatusException {
1628 SnmpParameters p = (SnmpParameters) peer.getParams();
1629 snmpV1Trap(peer.getDestAddr(),
1630 peer.getDestPort(),
1631 agentAddr,
1632 p.getRdCommunity(),
1633 enterpOid,
1634 generic,
1635 specific,
1636 varBindList,
1637 time);
1638 }
1639
1640 private void snmpV1Trap(InetAddress addr,
1641 int port,
1642 SnmpIpAddress agentAddr,
1643 String cs,
1644 SnmpOid enterpOid,
1645 int generic,
1646 int specific,
1647 SnmpVarBindList varBindList,
1648 SnmpTimeticks time)
1649 throws IOException, SnmpStatusException {
1650
1651 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1652 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1653 "snmpV1Trap", "generic=" + generic + ", specific=" +
1654 specific);
1655 }
1656
1657 // First, make an SNMP V1 trap pdu
1658 //
1659 SnmpPduTrap pdu = new SnmpPduTrap() ;
1660 pdu.address = null ;
1661 pdu.port = port ;
1662 pdu.type = pduV1TrapPdu ;
1663 pdu.version = snmpVersionOne ;
1664
1665 //Diff start
1666 if(cs != null)
1667 pdu.community = cs.getBytes();
1668 else
1669 pdu.community = null ;
1670 //Diff end
1671
1672 // Diff start
1673 if(enterpOid != null)
1674 pdu.enterprise = enterpOid;
1675 else
1676 pdu.enterprise = enterpriseOid ;
1677 //Diff end
1678 pdu.genericTrap = generic ;
1679 pdu.specificTrap = specific ;
1680 //Diff start
1681 if(time != null)
1682 pdu.timeStamp = time.longValue();
1683 else
1684 pdu.timeStamp = getSysUpTime();
1685 //Diff end
1686
1687 if (varBindList != null) {
1688 pdu.varBindList = new SnmpVarBind[varBindList.size()] ;
1689 varBindList.copyInto(pdu.varBindList);
1690 }
1691 else
1692 pdu.varBindList = null ;
1693
1694 if (agentAddr == null) {
1695 // If the local host cannot be determined,
1696 // we put 0.0.0.0 in agentAddr
1697 try {
1698 final InetAddress inetAddr =
1699 (address!=null)?address:InetAddress.getLocalHost();
1700 agentAddr = handleMultipleIpVersion(inetAddr.getAddress());
1701 } catch (UnknownHostException e) {
1702 byte[] zeroedAddr = new byte[4];
1703 agentAddr = handleMultipleIpVersion(zeroedAddr);
1704 }
1705 }
1706
1707 pdu.agentAddr = agentAddr;
1708
1709 // Next, send the pdu to the specified destination
1710 //
1711 // Diff start
1712 if(addr != null)
1713 sendTrapPdu(addr, pdu) ;
1714 else
1715 sendTrapPdu(pdu);
1716
1717 //End diff
1718 }
1719
1720 /**
1721 * Sends a trap using SNMP V2 trap format.
1722 * <BR>The trap is sent to the specified <CODE>SnmpPeer</CODE> destination.
1723 * <BR>The community string used is the one located in the
1724 * <CODE>SnmpPeer</CODE> parameters
1725 * (<CODE>SnmpParameters.getRdCommunity() </CODE>).
1726 * <BR>The variable list included in the outgoing trap is composed of
1727 * the following items:
1728 * <UL>
1729 * <LI><CODE>sysUpTime.0</CODE> with the value specified by
1730 * <CODE>time</CODE></LI>
1731 * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
1732 * <CODE>trapOid</CODE></LI>
1733 * <LI><CODE>all the (oid,values)</CODE> from the specified
1734 * <CODE>varBindList</CODE></LI>
1735 * </UL>
1736 *
1737 * @param peer The <CODE>SnmpPeer</CODE> destination of the trap.
1738 * @param trapOid The OID identifying the trap.
1739 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1740 * @param time The time stamp (overwrite the current time).
1741 *
1742 * @exception IOException An I/O error occurred while sending the trap.
1743 * @exception SnmpStatusException If the trap exceeds the limit
1744 * defined by <CODE>bufferSize</CODE>.
1745 *
1746 * @since 1.5
1747 */
1748 public void snmpV2Trap(SnmpPeer peer,
1749 SnmpOid trapOid,
1750 SnmpVarBindList varBindList,
1751 SnmpTimeticks time)
1752 throws IOException, SnmpStatusException {
1753 SnmpParameters p = (SnmpParameters) peer.getParams();
1754 snmpV2Trap(peer.getDestAddr(),
1755 peer.getDestPort(),
1756 p.getRdCommunity(),
1757 trapOid,
1758 varBindList,
1759 time);
1760 }
1761
1762 /**
1763 * Sends a trap using SNMP V2 trap format.
1764 * <BR>The trap is sent to each destination defined in the ACL file
1765 * (if available). If no ACL file or no destinations are available,
1766 * the trap is sent to the local host.
1767 * <BR>The variable list included in the outgoing trap is composed of
1768 * the following items:
1769 * <UL>
1770 * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
1771 * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
1772 * <CODE>trapOid</CODE></LI>
1773 * <LI><CODE>all the (oid,values)</CODE> from the specified
1774 * <CODE>varBindList</CODE></LI>
1775 * </UL>
1776 *
1777 * @param trapOid The OID identifying the trap.
1778 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1779 *
1780 * @exception IOException An I/O error occurred while sending the trap.
1781 * @exception SnmpStatusException If the trap exceeds the limit defined
1782 * by <CODE>bufferSize</CODE>.
1783 */
1784 public void snmpV2Trap(SnmpOid trapOid, SnmpVarBindList varBindList)
1785 throws IOException, SnmpStatusException {
1786
1787 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1788 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1789 "snmpV2Trap", "trapOid=" + trapOid);
1790 }
1791
1792 // First, make an SNMP V2 trap pdu
1793 // We clone varBindList and insert sysUpTime and snmpTrapOid
1794 //
1795 SnmpPduRequest pdu = new SnmpPduRequest() ;
1796 pdu.address = null ;
1797 pdu.port = trapPort ;
1798 pdu.type = pduV2TrapPdu ;
1799 pdu.version = snmpVersionTwo ;
1800 pdu.community = null ;
1801
1802 SnmpVarBindList fullVbl ;
1803 if (varBindList != null)
1804 fullVbl = (SnmpVarBindList)varBindList.clone() ;
1805 else
1806 fullVbl = new SnmpVarBindList(2) ;
1807 SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
1808 fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
1809 fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
1810 0);
1811 pdu.varBindList = new SnmpVarBind[fullVbl.size()] ;
1812 fullVbl.copyInto(pdu.varBindList) ;
1813
1814 // Next, send the pdu to all destinations defined in ACL
1815 //
1816 sendTrapPdu(pdu) ;
1817 }
1818
1819 /**
1820 * Sends a trap using SNMP V2 trap format.
1821 * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
1822 * destination using the specified community string (and the ACL file
1823 * is not used).
1824 * <BR>The variable list included in the outgoing trap is composed of
1825 * the following items:
1826 * <UL>
1827 * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
1828 * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
1829 * <CODE>trapOid</CODE></LI>
1830 * <LI><CODE>all the (oid,values)</CODE> from the specified
1831 * <CODE>varBindList</CODE></LI>
1832 * </UL>
1833 *
1834 * @param addr The <CODE>InetAddress</CODE> destination of the trap.
1835 * @param cs The community string to be used for the trap.
1836 * @param trapOid The OID identifying the trap.
1837 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1838 *
1839 * @exception IOException An I/O error occurred while sending the trap.
1840 * @exception SnmpStatusException If the trap exceeds the limit
1841 * defined by <CODE>bufferSize</CODE>.
1842 */
1843 public void snmpV2Trap(InetAddress addr, String cs, SnmpOid trapOid,
1844 SnmpVarBindList varBindList)
1845 throws IOException, SnmpStatusException {
1846
1847 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1848 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1849 "snmpV2Trap", "trapOid=" + trapOid);
1850 }
1851
1852 // First, make an SNMP V2 trap pdu
1853 // We clone varBindList and insert sysUpTime and snmpTrapOid
1854 //
1855 SnmpPduRequest pdu = new SnmpPduRequest() ;
1856 pdu.address = null ;
1857 pdu.port = trapPort ;
1858 pdu.type = pduV2TrapPdu ;
1859 pdu.version = snmpVersionTwo ;
1860
1861 if(cs != null)
1862 pdu.community = cs.getBytes();
1863 else
1864 pdu.community = null;
1865
1866 SnmpVarBindList fullVbl ;
1867 if (varBindList != null)
1868 fullVbl = (SnmpVarBindList)varBindList.clone() ;
1869 else
1870 fullVbl = new SnmpVarBindList(2) ;
1871 SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
1872 fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
1873 fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
1874 0);
1875 pdu.varBindList = new SnmpVarBind[fullVbl.size()] ;
1876 fullVbl.copyInto(pdu.varBindList) ;
1877
1878 // Next, send the pdu to the specified destination
1879 //
1880 if(addr != null)
1881 sendTrapPdu(addr, pdu);
1882 else
1883 sendTrapPdu(pdu);
1884 }
1885
1886 /**
1887 * Sends a trap using SNMP V2 trap format.
1888 * <BR>The trap is sent to the specified <CODE>InetAddress</CODE>
1889 * destination using the specified parameters (and the ACL file is not
1890 * used).
1891 * Note that if the specified <CODE>InetAddress</CODE> destination is null,
1892 * then the ACL file mechanism is used.
1893 * <BR>The variable list included in the outgoing trap is composed of the
1894 * following items:
1895 * <UL>
1896 * <LI><CODE>sysUpTime.0</CODE> with the value specified by
1897 * <CODE>time</CODE></LI>
1898 * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
1899 * <CODE>trapOid</CODE></LI>
1900 * <LI><CODE>all the (oid,values)</CODE> from the specified
1901 * <CODE>varBindList</CODE></LI>
1902 * </UL>
1903 *
1904 * @param addr The <CODE>InetAddress</CODE> destination of the trap.
1905 * @param cs The community string to be used for the trap.
1906 * @param trapOid The OID identifying the trap.
1907 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
1908 * @param time The time stamp (overwrite the current time).
1909 *
1910 * @exception IOException An I/O error occurred while sending the trap.
1911 * @exception SnmpStatusException If the trap exceeds the limit
1912 * defined by <CODE>bufferSize</CODE>.
1913 *
1914 * @since 1.5
1915 */
1916 public void snmpV2Trap(InetAddress addr,
1917 String cs,
1918 SnmpOid trapOid,
1919 SnmpVarBindList varBindList,
1920 SnmpTimeticks time)
1921 throws IOException, SnmpStatusException {
1922
1923 snmpV2Trap(addr,
1924 trapPort,
1925 cs,
1926 trapOid,
1927 varBindList,
1928 time);
1929 }
1930
1931 private void snmpV2Trap(InetAddress addr,
1932 int port,
1933 String cs,
1934 SnmpOid trapOid,
1935 SnmpVarBindList varBindList,
1936 SnmpTimeticks time)
1937 throws IOException, SnmpStatusException {
1938
1939 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
1940 final StringBuilder strb = new StringBuilder()
1941 .append("trapOid=").append(trapOid)
1942 .append("\ncommunity=").append(cs)
1943 .append("\naddr=").append(addr)
1944 .append("\nvarBindList=").append(varBindList)
1945 .append("\ntime=").append(time)
1946 .append("\ntrapPort=").append(port);
1947 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
1948 "snmpV2Trap", strb.toString());
1949 }
1950
1951 // First, make an SNMP V2 trap pdu
1952 // We clone varBindList and insert sysUpTime and snmpTrapOid
1953 //
1954 SnmpPduRequest pdu = new SnmpPduRequest() ;
1955 pdu.address = null ;
1956 pdu.port = port ;
1957 pdu.type = pduV2TrapPdu ;
1958 pdu.version = snmpVersionTwo ;
1959
1960 if(cs != null)
1961 pdu.community = cs.getBytes();
1962 else
1963 pdu.community = null;
1964
1965 SnmpVarBindList fullVbl ;
1966 if (varBindList != null)
1967 fullVbl = (SnmpVarBindList)varBindList.clone() ;
1968 else
1969 fullVbl = new SnmpVarBindList(2) ;
1970
1971 // Only difference with other
1972 SnmpTimeticks sysUpTimeValue = null;
1973 if(time != null)
1974 sysUpTimeValue = time;
1975 else
1976 sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
1977 //End of diff
1978
1979 fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
1980 fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
1981 0);
1982 pdu.varBindList = new SnmpVarBind[fullVbl.size()] ;
1983 fullVbl.copyInto(pdu.varBindList) ;
1984
1985 // Next, send the pdu to the specified destination
1986 //
1987 // Diff start
1988 if(addr != null)
1989 sendTrapPdu(addr, pdu) ;
1990 else
1991 sendTrapPdu(pdu);
1992 //End diff
1993 }
1994
1995 /**
1996 * Send the specified trap PDU to the passed <CODE>InetAddress</CODE>.
1997 * @param address The destination address.
1998 * @param pdu The pdu to send.
1999 * @exception IOException An I/O error occurred while sending the trap.
2000 * @exception SnmpStatusException If the trap exceeds the limit
2001 * defined by <CODE>bufferSize</CODE>.
2002 *
2003 * @since 1.5
2004 */
2005 public void snmpPduTrap(InetAddress address, SnmpPduPacket pdu)
2006 throws IOException, SnmpStatusException {
2007
2008 if(address != null)
2009 sendTrapPdu(address, pdu);
2010 else
2011 sendTrapPdu(pdu);
2012 }
2013
2014 /**
2015 * Send the specified trap PDU to the passed <CODE>SnmpPeer</CODE>.
2016 * @param peer The destination peer. The Read community string is used of
2017 * <CODE>SnmpParameters</CODE> is used as the trap community string.
2018 * @param pdu The pdu to send.
2019 * @exception IOException An I/O error occurred while sending the trap.
2020 * @exception SnmpStatusException If the trap exceeds the limit defined
2021 * by <CODE>bufferSize</CODE>.
2022 * @since 1.5
2023 */
2024 public void snmpPduTrap(SnmpPeer peer,
2025 SnmpPduPacket pdu)
2026 throws IOException, SnmpStatusException {
2027 if(peer != null) {
2028 pdu.port = peer.getDestPort();
2029 sendTrapPdu(peer.getDestAddr(), pdu);
2030 }
2031 else {
2032 pdu.port = getTrapPort().intValue();
2033 sendTrapPdu(pdu);
2034 }
2035 }
2036
2037 /**
2038 * Send the specified trap PDU to every destinations from the ACL file.
2039 */
2040 private void sendTrapPdu(SnmpPduPacket pdu)
2041 throws SnmpStatusException, IOException {
2042
2043 // Make an SNMP message from the pdu
2044 //
2045 SnmpMessage msg = null ;
2046 try {
2047 msg = (SnmpMessage)pduFactory.encodeSnmpPdu(pdu, bufferSize) ;
2048 if (msg == null) {
2049 throw new SnmpStatusException(
2050 SnmpDefinitions.snmpRspAuthorizationError) ;
2051 }
2052 }
2053 catch (SnmpTooBigException x) {
2054 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
2055 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
2056 "sendTrapPdu", "Trap pdu is too big. " +
2057 "Trap hasn't been sent to anyone" );
2058 }
2059 throw new SnmpStatusException(SnmpDefinitions.snmpRspTooBig) ;
2060 // FIXME: is the right exception to throw ?
2061 // We could simply forward SnmpTooBigException ?
2062 }
2063
2064 // Now send the SNMP message to each destination
2065 //
2066 int sendingCount = 0 ;
2067 openTrapSocketIfNeeded() ;
2068 if (ipacl != null) {
2069 Enumeration ed = ((InetAddressAcl)ipacl).getTrapDestinations() ;
2070 while (ed.hasMoreElements()) {
2071 msg.address = (InetAddress)ed.nextElement() ;
2072 Enumeration ec = ((InetAddressAcl)ipacl).
2073 getTrapCommunities(msg.address) ;
2074 while (ec.hasMoreElements()) {
2075 msg.community = ((String)ec.nextElement()).getBytes() ;
2076 try {
2077 sendTrapMessage(msg) ;
2078 sendingCount++ ;
2079 }
2080 catch (SnmpTooBigException x) {
2081 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
2082 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
2083 "sendTrapPdu", "Trap pdu is too big. " +
2084 "Trap hasn't been sent to "+msg.address);
2085 }
2086 }
2087 }
2088 }
2089 }
2090
2091 // If there is no destination defined or if everything has failed
2092 // we tried to send the trap to the local host (as suggested by
2093 // mister Olivier Reisacher).
2094 //
2095 if (sendingCount == 0) {
2096 try {
2097 msg.address = InetAddress.getLocalHost() ;
2098 sendTrapMessage(msg) ;
2099 } catch (SnmpTooBigException x) {
2100 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
2101 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
2102 "sendTrapPdu", "Trap pdu is too big. " +
2103 "Trap hasn't been sent.");
2104 }
2105 } catch (UnknownHostException e) {
2106 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
2107 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
2108 "sendTrapPdu", "Trap pdu is too big. " +
2109 "Trap hasn't been sent.");
2110 }
2111 }
2112 }
2113
2114 closeTrapSocketIfNeeded() ;
2115 }
2116
2117 /**
2118 * Send the specified trap PDU to the specified destination.
2119 */
2120 private void sendTrapPdu(InetAddress addr, SnmpPduPacket pdu)
2121 throws SnmpStatusException, IOException {
2122
2123 // Make an SNMP message from the pdu
2124 //
2125 SnmpMessage msg = null ;
2126 try {
2127 msg = (SnmpMessage)pduFactory.encodeSnmpPdu(pdu, bufferSize) ;
2128 if (msg == null) {
2129 throw new SnmpStatusException(
2130 SnmpDefinitions.snmpRspAuthorizationError) ;
2131 }
2132 } catch (SnmpTooBigException x) {
2133 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
2134 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
2135 "sendTrapPdu", "Trap pdu is too big. " +
2136 "Trap hasn't been sent to the specified host.");
2137 }
2138 throw new SnmpStatusException(SnmpDefinitions.snmpRspTooBig) ;
2139 // FIXME: is the right exception to throw ?
2140 // We could simply forward SnmpTooBigException ?
2141 }
2142
2143 // Now send the SNMP message to specified destination
2144 //
2145 openTrapSocketIfNeeded() ;
2146 if (addr != null) {
2147 msg.address = addr;
2148 try {
2149 sendTrapMessage(msg) ;
2150 } catch (SnmpTooBigException x) {
2151 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
2152 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
2153 "sendTrapPdu", "Trap pdu is too big. " +
2154 "Trap hasn't been sent to " + msg.address);
2155 }
2156 }
2157 }
2158
2159 closeTrapSocketIfNeeded() ;
2160 }
2161
2162 /**
2163 * Send the specified message on trapSocket.
2164 */
2165 private void sendTrapMessage(SnmpMessage msg)
2166 throws IOException, SnmpTooBigException {
2167 byte[] buffer = new byte[bufferSize] ;
2168 DatagramPacket packet = new DatagramPacket(buffer, buffer.length) ;
2169 int encodingLength = msg.encodeMessage(buffer) ;
2170 packet.setLength(encodingLength) ;
2171 packet.setAddress(msg.address) ;
2172 packet.setPort(msg.port) ;
2173 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
2174 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
2175 "sendTrapMessage", "sending trap to " + msg.address + ":" +
2176 msg.port);
2177 }
2178 trapSocket.send(packet) ;
2179 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
2180 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
2181 "sendTrapMessage", "sent to " + msg.address + ":" +
2182 msg.port);
2183 }
2184 snmpOutTraps++;
2185 snmpOutPkts++;
2186 }
2187
2188 /**
2189 * Open trapSocket if it's not already done.
2190 */
2191 synchronized void openTrapSocketIfNeeded() throws SocketException {
2192 if (trapSocket == null) {
2193 trapSocket = new DatagramSocket(0, address) ;
2194 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
2195 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
2196 "openTrapSocketIfNeeded", "using port " +
2197 trapSocket.getLocalPort() + " to send traps");
2198 }
2199 }
2200 }
2201
2202 /**
2203 * Close trapSocket if the SNMP protocol adaptor is not ONLINE.
2204 */
2205 synchronized void closeTrapSocketIfNeeded() {
2206 if ((trapSocket != null) && (state != ONLINE)) {
2207 trapSocket.close() ;
2208 trapSocket = null ;
2209 }
2210 }
2211
2212 // SENDING SNMP INFORMS STUFF
2213 //---------------------------
2214
2215 /**
2216 * Sends an inform using SNMP V2 inform request format.
2217 * <BR>The inform request is sent to each destination defined in the ACL
2218 * file (if available).
2219 * If no ACL file or no destinations are available, the inform request is
2220 * sent to the local host.
2221 * <BR>The variable list included in the outgoing inform is composed of
2222 * the following items:
2223 * <UL>
2224 * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
2225 * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
2226 * <CODE>trapOid</CODE></LI>
2227 * <LI><CODE>all the (oid,values)</CODE> from the specified
2228 * <CODE>varBindList</CODE></LI>
2229 * </UL>
2230 * To send an inform request, the SNMP adaptor server must be active.
2231 *
2232 * @param cb The callback that is invoked when a request is complete.
2233 * @param trapOid The OID identifying the trap.
2234 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
2235 *
2236 * @return A vector of {@link com.sun.jmx.snmp.daemon.SnmpInformRequest}
2237 * objects.
2238 * <P>If there is no destination host for this inform request,
2239 * the returned vector will be empty.
2240 *
2241 * @exception IllegalStateException This method has been invoked while
2242 * the SNMP adaptor server was not active.
2243 * @exception IOException An I/O error occurred while sending the
2244 * inform request.
2245 * @exception SnmpStatusException If the inform request exceeds the
2246 * limit defined by <CODE>bufferSize</CODE>.
2247 */
2248 public Vector snmpInformRequest(SnmpInformHandler cb, SnmpOid trapOid,
2249 SnmpVarBindList varBindList)
2250 throws IllegalStateException, IOException, SnmpStatusException {
2251
2252 if (!isActive()) {
2253 throw new IllegalStateException(
2254 "Start SNMP adaptor server before carrying out this operation");
2255 }
2256 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
2257 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
2258 "snmpInformRequest", "trapOid=" + trapOid);
2259 }
2260
2261 // First, make an SNMP inform pdu:
2262 // We clone varBindList and insert sysUpTime and snmpTrapOid variables.
2263 //
2264 SnmpVarBindList fullVbl ;
2265 if (varBindList != null)
2266 fullVbl = (SnmpVarBindList)varBindList.clone() ;
2267 else
2268 fullVbl = new SnmpVarBindList(2) ;
2269 SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
2270 fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
2271 fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
2272 0);
2273
2274 // Next, send the pdu to the specified destination
2275 //
2276 openInformSocketIfNeeded() ;
2277
2278 // Now send the SNMP message to each destination
2279 //
2280 Vector<SnmpInformRequest> informReqList = new Vector<SnmpInformRequest>();
2281 InetAddress addr = null;
2282 String cs = null;
2283 if (ipacl != null) {
2284 Enumeration ed = ((InetAddressAcl)ipacl).getInformDestinations() ;
2285 while (ed.hasMoreElements()) {
2286 addr = (InetAddress)ed.nextElement() ;
2287 Enumeration ec = ((InetAddressAcl)ipacl).
2288 getInformCommunities(addr) ;
2289 while (ec.hasMoreElements()) {
2290 cs = (String)ec.nextElement() ;
2291 informReqList.addElement(
2292 informSession.makeAsyncRequest(addr, cs, cb,
2293 fullVbl,getInformPort())) ;
2294 }
2295 }
2296 }
2297
2298 return informReqList ;
2299 }
2300
2301 /**
2302 * Sends an inform using SNMP V2 inform request format.
2303 * <BR>The inform is sent to the specified <CODE>InetAddress</CODE>
2304 * destination
2305 * using the specified community string.
2306 * <BR>The variable list included in the outgoing inform is composed
2307 * of the following items:
2308 * <UL>
2309 * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
2310 * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
2311 * <CODE>trapOid</CODE></LI>
2312 * <LI><CODE>all the (oid,values)</CODE> from the specified
2313 * <CODE>varBindList</CODE></LI>
2314 * </UL>
2315 * To send an inform request, the SNMP adaptor server must be active.
2316 *
2317 * @param addr The <CODE>InetAddress</CODE> destination for this inform
2318 * request.
2319 * @param cs The community string to be used for the inform request.
2320 * @param cb The callback that is invoked when a request is complete.
2321 * @param trapOid The OID identifying the trap.
2322 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
2323 *
2324 * @return The inform request object.
2325 *
2326 * @exception IllegalStateException This method has been invoked
2327 * while the SNMP adaptor server was not active.
2328 * @exception IOException An I/O error occurred while sending the
2329 * inform request.
2330 * @exception SnmpStatusException If the inform request exceeds the
2331 * limit defined by <CODE>bufferSize</CODE>.
2332 */
2333 public SnmpInformRequest snmpInformRequest(InetAddress addr,
2334 String cs,
2335 SnmpInformHandler cb,
2336 SnmpOid trapOid,
2337 SnmpVarBindList varBindList)
2338 throws IllegalStateException, IOException, SnmpStatusException {
2339
2340 return snmpInformRequest(addr,
2341 getInformPort(),
2342 cs,
2343 cb,
2344 trapOid,
2345 varBindList);
2346 }
2347
2348 /**
2349 * Sends an inform using SNMP V2 inform request format.
2350 * <BR>The inform is sent to the specified <CODE>SnmpPeer</CODE>
2351 * destination.
2352 * <BR>The community string used is the one located in the
2353 * <CODE>SnmpPeer</CODE> parameters
2354 * (<CODE>SnmpParameters.getInformCommunity() </CODE>).
2355 * <BR>The variable list included in the outgoing inform is composed
2356 * of the following items:
2357 * <UL>
2358 * <LI><CODE>sysUpTime.0</CODE> with its current value</LI>
2359 * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by
2360 * <CODE>trapOid</CODE></LI>
2361 * <LI><CODE>all the (oid,values)</CODE> from the specified
2362 * <CODE>varBindList</CODE></LI>
2363 * </UL>
2364 * To send an inform request, the SNMP adaptor server must be active.
2365 *
2366 * @param peer The <CODE>SnmpPeer</CODE> destination for this inform
2367 * request.
2368 * @param cb The callback that is invoked when a request is complete.
2369 * @param trapOid The OID identifying the trap.
2370 * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null.
2371 *
2372 * @return The inform request object.
2373 *
2374 * @exception IllegalStateException This method has been invoked while
2375 * the SNMP adaptor server was not active.
2376 * @exception IOException An I/O error occurred while sending the
2377 * inform request.
2378 * @exception SnmpStatusException If the inform request exceeds the
2379 * limit defined by <CODE>bufferSize</CODE>.
2380 *
2381 * @since 1.5
2382 */
2383 public SnmpInformRequest snmpInformRequest(SnmpPeer peer,
2384 SnmpInformHandler cb,
2385 SnmpOid trapOid,
2386 SnmpVarBindList varBindList)
2387 throws IllegalStateException, IOException, SnmpStatusException {
2388 SnmpParameters p = (SnmpParameters) peer.getParams();
2389 return snmpInformRequest(peer.getDestAddr(),
2390 peer.getDestPort(),
2391 p.getInformCommunity(),
2392 cb,
2393 trapOid,
2394 varBindList);
2395 }
2396
2397 /**
2398 * Method that maps an SNMP error status in the passed protocolVersion
2399 * according to the provided pdu type.
2400 * @param errorStatus The error status to convert.
2401 * @param protocolVersion The protocol version.
2402 * @param reqPduType The pdu type.
2403 */
2404 public static final int mapErrorStatus(int errorStatus,
2405 int protocolVersion,
2406 int reqPduType) {
2407 return SnmpSubRequestHandler.mapErrorStatus(errorStatus,
2408 protocolVersion,
2409 reqPduType);
2410 }
2411
2412 private SnmpInformRequest snmpInformRequest(InetAddress addr,
2413 int port,
2414 String cs,
2415 SnmpInformHandler cb,
2416 SnmpOid trapOid,
2417 SnmpVarBindList varBindList)
2418 throws IllegalStateException, IOException, SnmpStatusException {
2419 if (!isActive()) {
2420 throw new IllegalStateException(
2421 "Start SNMP adaptor server before carrying out this operation");
2422 }
2423 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
2424 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
2425 "snmpInformRequest", "trapOid=" + trapOid);
2426 }
2427
2428 // First, make an SNMP inform pdu:
2429 // We clone varBindList and insert sysUpTime and snmpTrapOid variables.
2430 //
2431 SnmpVarBindList fullVbl ;
2432 if (varBindList != null)
2433 fullVbl = (SnmpVarBindList)varBindList.clone() ;
2434 else
2435 fullVbl = new SnmpVarBindList(2) ;
2436 SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ;
2437 fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ;
2438 fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue),
2439 0);
2440
2441 // Next, send the pdu to the specified destination
2442 //
2443 openInformSocketIfNeeded() ;
2444 return informSession.makeAsyncRequest(addr, cs, cb, fullVbl, port) ;
2445 }
2446
2447
2448 /**
2449 * Open informSocket if it's not already done.
2450 */
2451 synchronized void openInformSocketIfNeeded() throws SocketException {
2452 if (informSession == null) {
2453 informSession = new SnmpSession(this) ;
2454 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
2455 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
2456 "openInformSocketIfNeeded",
2457 "to send inform requests and receive inform responses");
2458 }
2459 }
2460 }
2461
2462 /**
2463 * Close informSocket if the SNMP protocol adaptor is not ONLINE.
2464 */
2465 synchronized void closeInformSocketIfNeeded() {
2466 if ((informSession != null) && (state != ONLINE)) {
2467 informSession.destroySession() ;
2468 informSession = null ;
2469 }
2470 }
2471
2472 /**
2473 * Gets the IP address to bind.
2474 * This getter is used to initialize the DatagramSocket in the
2475 * SnmpSocket object created for the inform request stuff.
2476 */
2477 InetAddress getAddress() {
2478 return address;
2479 }
2480
2481
2482 // PROTECTED METHODS
2483 //------------------
2484
2485 /**
2486 * Finalizer of the SNMP protocol adaptor objects.
2487 * This method is called by the garbage collector on an object
2488 * when garbage collection determines that there are no more
2489 * references to the object.
2490 * <P>Closes the datagram socket associated to this SNMP protocol adaptor.
2491 */
2492 protected void finalize() {
2493 try {
2494 if (socket != null) {
2495 socket.close() ;
2496 socket = null ;
2497 }
2498
2499 threadService.terminate();
2500 } catch (Exception e) {
2501 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
2502 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
2503 "finalize", "Exception in finalizer", e);
2504 }
2505 }
2506 }
2507
2508 // PACKAGE METHODS
2509 //----------------
2510
2511 /**
2512 * Returns the string used in debug traces.
2513 */
2514 String makeDebugTag() {
2515 return "SnmpAdaptorServer["+ getProtocol() + ":" + getPort() + "]";
2516 }
2517
2518 void updateRequestCounters(int pduType) {
2519 switch(pduType) {
2520
2521 case pduGetRequestPdu:
2522 snmpInGetRequests++;
2523 break;
2524 case pduGetNextRequestPdu:
2525 snmpInGetNexts++;
2526 break;
2527 case pduSetRequestPdu:
2528 snmpInSetRequests++;
2529 break;
2530 default:
2531 break;
2532 }
2533 snmpInPkts++ ;
2534 }
2535
2536 void updateErrorCounters(int errorStatus) {
2537 switch(errorStatus) {
2538
2539 case snmpRspNoError:
2540 snmpOutGetResponses++;
2541 break;
2542 case snmpRspGenErr:
2543 snmpOutGenErrs++;
2544 break;
2545 case snmpRspBadValue:
2546 snmpOutBadValues++;
2547 break;
2548 case snmpRspNoSuchName:
2549 snmpOutNoSuchNames++;
2550 break;
2551 case snmpRspTooBig:
2552 snmpOutTooBigs++;
2553 break;
2554 default:
2555 break;
2556 }
2557 snmpOutPkts++ ;
2558 }
2559
2560 void updateVarCounters(int pduType, int n) {
2561 switch(pduType) {
2562
2563 case pduGetRequestPdu:
2564 case pduGetNextRequestPdu:
2565 case pduGetBulkRequestPdu:
2566 snmpInTotalReqVars += n ;
2567 break ;
2568 case pduSetRequestPdu:
2569 snmpInTotalSetVars += n ;
2570 break ;
2571 }
2572 }
2573
2574 void incSnmpInASNParseErrs(int n) {
2575 snmpInASNParseErrs += n ;
2576 }
2577
2578 void incSnmpInBadVersions(int n) {
2579 snmpInBadVersions += n ;
2580 }
2581
2582 void incSnmpInBadCommunityUses(int n) {
2583 snmpInBadCommunityUses += n ;
2584 }
2585
2586 void incSnmpInBadCommunityNames(int n) {
2587 snmpInBadCommunityNames += n ;
2588 }
2589
2590 void incSnmpSilentDrops(int n) {
2591 snmpSilentDrops += n ;
2592 }
2593 // PRIVATE METHODS
2594 //----------------
2595
2596 /**
2597 * Returns the time (in hundreths of second) elapsed since the SNMP
2598 * protocol adaptor startup.
2599 */
2600 long getSysUpTime() {
2601 return (System.currentTimeMillis() - startUpTime) / 10 ;
2602 }
2603
2604 /**
2605 * Control the way the SnmpAdaptorServer service is deserialized.
2606 */
2607 private void readObject(ObjectInputStream stream)
2608 throws IOException, ClassNotFoundException {
2609
2610 // Call the default deserialization of the object.
2611 //
2612 stream.defaultReadObject();
2613
2614 // Call the specific initialization for the SnmpAdaptorServer service.
2615 // This is for transient structures to be initialized to specific
2616 // default values.
2617 //
2618 mibs = new Vector<SnmpMibAgent>() ;
2619 }
2620
2621 /**
2622 * Common initializations.
2623 */
2624 private void init(Object acl, int p, InetAddress a) {
2625
2626 root= new SnmpMibTree();
2627
2628 // The default Agent is initialized with a SnmpErrorHandlerAgent agent.
2629 root.setDefaultAgent(new SnmpErrorHandlerAgent());
2630
2631 // For the trap time, use the time the agent started ...
2632 //
2633 startUpTime= java.lang.System.currentTimeMillis();
2634 maxActiveClientCount = 10;
2635
2636 // Create the default message factory
2637 pduFactory = new SnmpPduFactoryBER() ;
2638
2639 port = p ;
2640 ipacl = acl ;
2641 address = a ;
2642
2643 if ((ipacl == null) && (useAcl == true))
2644 throw new IllegalArgumentException("ACL object cannot be null") ;
2645
2646 threadService = new ThreadService(threadNumber);
2647 }
2648
2649 SnmpMibAgent getAgentMib(SnmpOid oid) {
2650 return root.getAgentMib(oid);
2651 }
2652
2653 protected Thread createMainThread() {
2654 final Thread t = super.createMainThread();
2655 t.setDaemon(true);
2656 return t;
2657 }
2658
2659}