View Javadoc
1   // NAME
2   //      $RCSfile: SnmpContext.java,v $
3   // DESCRIPTION
4   //      [given below in javadoc format]
5   // DELTA
6   //      $Revision: 3.25 $
7   // CREATED
8   //      $Date: 2009/03/05 12:51:29 $
9   // COPYRIGHT
10  //      Westhawk Ltd
11  // TO DO
12  //
13  
14  /*
15   * Copyright (C) 1995, 1996 by West Consulting BV
16   *
17   * Permission to use, copy, modify, and distribute this software
18   * for any purpose and without fee is hereby granted, provided
19   * that the above copyright notices appear in all copies and that
20   * both the copyright notice and this permission notice appear in
21   * supporting documentation.
22   * This software is provided "as is" without express or implied
23   * warranty.
24   * author <a href="mailto:snmp@westhawk.co.uk">Tim Panton</a>
25   */
26  
27  /*
28   * Copyright (C) 1996 - 2006 by Westhawk Ltd
29   * <a href="www.westhawk.co.uk">www.westhawk.co.uk</a>
30   *
31   * Permission to use, copy, modify, and distribute this software
32   * for any purpose and without fee is hereby granted, provided
33   * that the above copyright notices appear in all copies and that
34   * both the copyright notice and this permission notice appear in
35   * supporting documentation.
36   * This software is provided "as is" without express or implied
37   * warranty.
38   * author <a href="mailto:snmp@westhawk.co.uk">Tim Panton</a>
39   */
40  
41  package uk.co.westhawk.snmp.stack;
42  
43  /*-
44   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
45   * SNMP Java Client
46   * ჻჻჻჻჻჻
47   * Copyright 2023 MetricsHub, Westhawk
48   * ჻჻჻჻჻჻
49   * This program is free software: you can redistribute it and/or modify
50   * it under the terms of the GNU Lesser General Public License as
51   * published by the Free Software Foundation, either version 3 of the
52   * License, or (at your option) any later version.
53   *
54   * This program is distributed in the hope that it will be useful,
55   * but WITHOUT ANY WARRANTY; without even the implied warranty of
56   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
57   * GNU General Lesser Public License for more details.
58   *
59   * You should have received a copy of the GNU General Lesser Public
60   * License along with this program.  If not, see
61   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
62   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
63   */
64  
65  import java.net.*;
66  import java.io.*;
67  import java.util.*;
68  import uk.co.westhawk.snmp.event.*;
69  
70  /**
71   * This class contains the SNMP v1 context that is needed by every PDU to
72   * send a SNMP v1 request.
73   *
74   * <p>
75   * <code>destroy()</code> should be called when the context is no longer
76   * used. This is the only way the threads will be stopped and garbage
77   * collected.
78   * </p>
79   *
80   * @see SnmpContextFace
81   * @see SnmpContextPool
82   * @author <a href="mailto:snmp@westhawk.co.uk">Tim Panton</a>
83   * @version $Revision: 3.25 $ $Date: 2009/03/05 12:51:29 $
84   */
85  public class SnmpContext extends AbstractSnmpContext
86          implements SnmpContextFace, Cloneable {
87      private static final String version_id = "@(#)$Id: SnmpContext.java,v 3.25 2009/03/05 12:51:29 birgita Exp $ Copyright Westhawk Ltd";
88  
89      String community = SnmpContextFace.DEFAULT_COMMUNITY;
90  
91      /**
92       * Constructor.
93       *
94       * @param host The host to which the PDU will be sent
95       * @param port The port where the SNMP server will be
96       * @see AbstractSnmpContext#AbstractSnmpContext(String, int)
97       */
98      public SnmpContext(String host, int port) throws IOException {
99          super(host, port);
100     }
101 
102     /**
103      * Constructor.
104      * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
105      * fully qualified classname.
106      *
107      * @param host        The host to which the Pdu will be sent
108      * @param port        The port where the SNMP server will be
109      * @param typeSocketA The local address the server will bind to
110      *
111      * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String)
112      */
113     public SnmpContext(String host, int port, String typeSocketA)
114             throws IOException {
115         super(host, port, typeSocketA);
116     }
117 
118     /**
119      * Constructor.
120      * Parameter typeSocketA should be either STANDARD_SOCKET, TCP_SOCKET or a
121      * fully qualified classname.
122      *
123      * @param host        The host to which the PDU will be sent
124      * @param port        The port where the SNMP server will be
125      * @param bindAddress The local address the server will bind to
126      * @param typeSocketA The type of socket to use.
127      *
128      * @see AbstractSnmpContext#AbstractSnmpContext(String, int, String, String)
129      * @see SnmpContextBasisFace#STANDARD_SOCKET
130      * @see SnmpContextBasisFace#TCP_SOCKET
131      * @since 4_14
132      */
133     public SnmpContext(String host, int port, String bindAddress, String typeSocketA)
134             throws IOException {
135         super(host, port, bindAddress, typeSocketA);
136     }
137 
138     public int getVersion() {
139         return SnmpConstants.SNMP_VERSION_1;
140     }
141 
142     public String getCommunity() {
143         return community;
144     }
145 
146     public void setCommunity(String newCommunity) {
147         community = newCommunity;
148     }
149 
150     public byte[] encodePacket(byte msg_type, int rId, int errstat,
151             int errind, Enumeration ve, Object obj)
152             throws IOException, EncodingException {
153         byte[] packet = null;
154         if (isDestroyed == true) {
155             throw new EncodingException("Context can no longer be used, since it is already destroyed");
156         } else {
157             AsnEncoderv1 enc = new AsnEncoderv1();
158             ByteArrayOutputStream bay = enc.EncodeSNMP(this, msg_type, rId, errstat,
159                     errind, ve);
160 
161             int sz = bay.size();
162             if (sz > maxRecvSize) {
163                 throw new EncodingException("Packet size (" + sz
164                         + ") is > maximum size (" + maxRecvSize + ")");
165             }
166             packet = bay.toByteArray();
167         }
168         return packet;
169     }
170 
171     public byte[] encodePacket(byte msg_type, String enterprise,
172             byte[] IpAddress, int generic_trap, int specific_trap,
173             long timeTicks, Enumeration ve)
174             throws IOException, EncodingException {
175         byte[] packet = null;
176         AsnEncoderv1 enc = new AsnEncoderv1();
177         ByteArrayOutputStream bay = enc.EncodeSNMP(this, msg_type, enterprise,
178                 IpAddress, generic_trap, specific_trap, timeTicks, ve);
179 
180         int sz = bay.size();
181         if (sz > maxRecvSize) {
182             throw new EncodingException("Packet size (" + sz
183                     + ") is > maximum size (" + maxRecvSize + ")");
184         }
185         packet = bay.toByteArray();
186         return packet;
187     }
188 
189     /**
190      * Processes an incoming SNMP v1 response.
191      */
192     protected void processIncomingResponse(ByteArrayInputStream in)
193             throws DecodingException, IOException {
194         AsnDecoderv1 rpdu = new AsnDecoderv1();
195         AsnSequence seqPdu = rpdu.DecodeSNMP(in, getCommunity());
196         if (seqPdu instanceof AsnPduSequence) {
197             AsnPduSequence pduSeq = (AsnPduSequence) seqPdu;
198             if (pduSeq != null) {
199                 // got a message
200                 Integer rid = new Integer(pduSeq.getReqId());
201                 Pdu answ = getPdu(rid);
202                 if (answ != null) {
203                     answ.fillin(pduSeq);
204                 } else {
205                     if (AsnObject.debug > 3) {
206                         System.out.println(getClass().getName() + ".processIncomingResponse(): No Pdu with reqid "
207                                 + rid.intValue());
208                     }
209                 }
210             } else {
211                 if (AsnObject.debug > 3) {
212                     System.out.println(getClass().getName() + ".processIncomingResponse(): Error - missing seq input");
213                 }
214             }
215         } else {
216             // it must be a Trap
217         }
218     }
219 
220     public Pdu processIncomingPdu(byte[] message)
221             throws DecodingException, IOException {
222         AsnDecoderv1 rpdu = new AsnDecoderv1();
223         ByteArrayInputStream in = new ByteArrayInputStream(message);
224 
225         Pdu pdu = null;
226         AsnSequence seqPdu = rpdu.DecodeSNMP(in, getCommunity());
227         if (seqPdu instanceof AsnTrapPduv1Sequence) {
228             AsnTrapPduv1Sequence pduSeq = (AsnTrapPduv1Sequence) seqPdu;
229             if (pduSeq != null) {
230                 TrapPduv1 trapPdu = new TrapPduv1(this);
231                 trapPdu.fillin(pduSeq);
232                 pdu = trapPdu;
233             }
234         } else {
235             // must be an ordinary PDU
236             AsnPduSequence pduSeq = (AsnPduSequence) seqPdu;
237             if (pduSeq != null) {
238                 byte type = pduSeq.getRespType();
239                 switch (type) {
240                     case SnmpConstants.GET_REQ_MSG:
241                         pdu = new GetPdu(this);
242                         break;
243                     case SnmpConstants.GETNEXT_REQ_MSG:
244                         pdu = new GetNextPdu(this);
245                         break;
246                     case SnmpConstants.SET_REQ_MSG:
247                         pdu = new SetPdu(this);
248                         break;
249                     // case SnmpConstants.GET_RSP_MSG:
250                     // A longly response should never be received here.
251                     // They should come in via the processIncomingResponse
252                     // route.
253                     // case SnmpConstants.GETBULK_REQ_MSG:
254                     // not in v1
255                     // case SnmpConstants.INFORM_REQ_MSG:
256                     // not in v1
257                     // case SnmpConstants.GET_RPRT_MSG:
258                     // not in v1
259                     // case SnmpConstants.TRPV2_REQ_MSG:
260                     // not in v1
261                     default:
262                         if (AsnObject.debug > 3) {
263                             System.out.println(getClass().getName()
264                                     + ".ProcessIncomingPdu(): PDU received with type "
265                                     + pduSeq.getRespTypeString()
266                                     + ". Ignoring it.");
267                         }
268                 }
269 
270                 if (pdu != null) {
271                     pdu.fillin(pduSeq);
272                 }
273             }
274         }
275         return pdu;
276     }
277 
278     /**
279      * Returns a clone of this SnmpContext.
280      *
281      * @exception CloneNotSupportedException Thrown when the constructor
282      *                                       generates an IOException
283      */
284     public Object clone() throws CloneNotSupportedException {
285         SnmpContext clContext = null;
286         try {
287             clContext = new SnmpContext(hostname, hostPort, bindAddr, typeSocket);
288             clContext.setCommunity(new String(community));
289         } catch (IOException exc) {
290             throw new CloneNotSupportedException("IOException "
291                     + exc.getMessage());
292         }
293         return clContext;
294     }
295 
296     /**
297      * Returns the hash key. This key is built out of all properties. It
298      * serves as key for a hashtable of (v1) contexts.
299      *
300      * @since 4_14
301      * @return The hash key
302      */
303     public String getHashKey() {
304         String str = hostname
305                 + "_" + hostPort
306                 + "_" + bindAddr
307                 + "_" + typeSocket
308                 + "_" + community
309                 + "_v" + getVersion();
310         return str;
311     }
312 
313     /**
314      * Returns a string representation of the object.
315      *
316      * @return The string
317      */
318     public String toString() {
319         StringBuffer buffer = new StringBuffer("SnmpContext[");
320         buffer.append("host=").append(hostname);
321         buffer.append(", port=").append(hostPort);
322         buffer.append(", bindAddress=").append(bindAddr);
323         buffer.append(", socketType=").append(typeSocket);
324         buffer.append(", community=").append(community);
325         buffer.append(", #trapListeners=").append(trapSupport.getListenerCount());
326         buffer.append(", #pduListeners=").append(pduSupport.getListenerCount());
327         buffer.append("]");
328         return buffer.toString();
329     }
330 
331 }