KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > agent > agentx > AgentXProtocol


1 /*_############################################################################
2   _##
3   _## SNMP4J-AgentX - AgentXProtocol.java
4   _##
5   _## Copyright (C) 2005-2007 Frank Fock (SNMP4J.org)
6   _##
7   _## This program is free software; you can redistribute it and/or modify
8   _## it under the terms of the GNU General Public License version 2 as
9   _## published by the Free Software Foundation.
10   _##
11   _## This program is distributed in the hope that it will be useful,
12   _## but WITHOUT ANY WARRANTY; without even the implied warranty of
13   _## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   _## GNU General Public License for more details.
15   _##
16   _## You should have received a copy of the GNU General Public License
17   _## along with this program; if not, write to the Free Software
18   _## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19   _## MA 02110-1301 USA
20   _##
21   _##########################################################################*/

22
23 package org.snmp4j.agent.agentx;
24
25 import java.net.*;
26 import java.nio.*;
27 import java.util.*;
28
29 import org.snmp4j.agent.*;
30 import org.snmp4j.smi.*;
31 import org.snmp4j.transport.MessageLengthDecoder;
32 import org.snmp4j.transport.MessageLength;
33 import java.io.IOException JavaDoc;
34 import org.snmp4j.log.LogAdapter;
35 import org.snmp4j.log.LogFactory;
36
37 public class AgentXProtocol implements MessageLengthDecoder {
38
39   private static final LogAdapter logger =
40       LogFactory.getLogger(AgentXProtocol.class);
41
42   public static final byte VERSION_1_0 = 1;
43
44   public static final byte REASON_OTHER = 1;
45   public static final byte REASON_PARSE_ERROR = 2;
46   public static final byte REASON_PROTOCOL_ERROR = 3;
47   public static final byte REASON_TIMEOUTS = 4;
48   public static final byte REASON_SHUTDOWN = 5;
49   public static final byte REASON_BY_MANAGER = 6;
50
51   public static final int AGENTX_OPEN_FAILED = 256;
52   public static final int AGENTX_NOT_OPEN = 257;
53   public static final int AGENTX_INDEX_WRONG_TYPE = 258;
54   public static final int AGENTX_INDEX_ALREADY_ALLOCATED= 259;
55   public static final int AGENTX_INDEX_NONE_AVAILABLE = 260;
56   public static final int AGENTX_INDEX_NOT_ALLOCATED = 261;
57   public static final int AGENTX_UNSUPPORTED_CONTEXT = 262;
58   public static final int AGENTX_DUPLICATE_REGISTRATION = 263;
59   public static final int AGENTX_UNKNOWN_REGISTRATION = 264;
60   public static final int AGENTX_UNKNOWN_AGENTCAPS = 265;
61   public static final int AGENTX_PARSE_ERROR = 266;
62   public static final int AGENTX_REQUEST_DENIED = 267;
63   public static final int AGENTX_PROCESSING_ERROR = 268;
64
65   /* General errors */
66
67   public static final int AGENTX_SUCCESS = 0;
68   public static final int AGENTX_ERROR = -1;
69   public static final int AGENTX_DISCONNECT = -5;
70   public static final int AGENTX_BADVER =-10;
71   public static final int AGENTX_TIMEOUT =-11;
72
73   /* User errors */
74   public static final int AGENTX_NOREG = -40;
75   public static final int AGENTX_DUPMAP = -41;
76
77   public static final byte FLAG_INSTANCE_REGISTRATION = 0x01;
78   public static final byte FLAG_NEW_INDEX = 0x02;
79   public static final byte FLAG_ANY_INDEX = 0x04;
80   public static final byte FLAG_NON_DEFAULT_CONTEXT = 0x08;
81   public static final byte FLAG_NETWORK_BYTE_ORDER = 0x10;
82
83   private static final OID INTERNET = new OID(new int[]{ 1,3,6,1 });
84
85   private static final int IPADDRESS_OCTETS = 4;
86
87   protected static final int AGENTX_INT_SIZE = 4;
88
89   public static final int HEADER_LENGTH = 5 * AGENTX_INT_SIZE;
90
91   public static final int DEFAULT_TIMEOUT_SECONDS = 5;
92   public static final int DEFAULT_MAX_CONSECUTIVE_TIMEOUTS = 3;
93   public static final int DEFAULT_MAX_PARSE_ERRORS = -1;
94   public static final int MAX_TIMEOUT_SECONDS = 255;
95
96
97   private static boolean nonDefaultContextEnabled = true;
98
99
100   public static void encodeOID(ByteBuffer buf,
101                                OID oid,
102                                boolean include) {
103     if (oid == null) {
104       buf.put(new byte[] { 0,0,0,0 });
105     }
106     else {
107       int startPos = 0;
108       if ((oid.size() > INTERNET.size()) && (oid.startsWith(INTERNET))) {
109         buf.put((byte) (oid.size() - (INTERNET.size() + 1)));
110         buf.put((byte) oid.get(INTERNET.size()));
111         startPos = INTERNET.size() + 1;
112       }
113       else {
114         buf.put((byte) oid.size());
115         buf.put((byte) 0);
116       }
117       if ((include) && (oid.size() > 0)) {
118         buf.put((byte) 1);
119         buf.put((byte) 0);
120       }
121       else {
122         buf.put(new byte[] {0, 0});
123       }
124       for (int i = startPos; i < oid.size(); i++) {
125         buf.putInt(oid.get(i));
126       }
127     }
128   }
129
130   public static int getOIDLength(OID oid) {
131     if (oid == null) {
132       return AGENTX_INT_SIZE;
133     }
134     int startPos = 0;
135     if ((oid.size() > INTERNET.size()) && (oid.startsWith(INTERNET))) {
136       startPos = INTERNET.size()+1;
137     }
138     return AGENTX_INT_SIZE + (AGENTX_INT_SIZE * (oid.size() - startPos));
139   }
140
141   public static boolean decodeOID(ByteBuffer buf, OID oid) {
142     int size = buf.get();
143     int first = buf.get();
144     int[] value = new int[size+((first != 0) ? INTERNET.size()+1 : 0)];
145     int startPos = 0;
146     if (first != 0) {
147       System.arraycopy(INTERNET.getValue(), 0, value, 0, INTERNET.size());
148       value[INTERNET.size()] = first;
149       startPos = INTERNET.size()+1;
150     }
151     boolean include = (buf.get() != 0);
152     buf.get(); // reserved
153
for (int i=0; i<size; i++) {
154       value[startPos+i] = buf.getInt();
155     }
156     oid.setValue(value);
157     return include;
158   }
159
160   public static void encodeVariableData(ByteBuffer buf, Variable v) {
161     if (v == null) {
162       return;
163     }
164     switch (v.getSyntax()) {
165       //case sNMP_SYNTAX_INT:
166
case SMIConstants.SYNTAX_GAUGE32:
167       case SMIConstants.SYNTAX_TIMETICKS:
168       case SMIConstants.SYNTAX_COUNTER32: {
169         buf.putInt((int)(((UnsignedInteger32)v).getValue() & 0xFFFFFFFFL));
170         break;
171       }
172       case SMIConstants.SYNTAX_INTEGER32: {
173         buf.putInt(((Integer32)v).getValue());
174         break;
175       }
176       case SMIConstants.SYNTAX_COUNTER64: {
177         buf.putLong(((Counter64)v).getValue());
178         break;
179       }
180       case SMIConstants.SYNTAX_OCTET_STRING:
181       case SMIConstants.SYNTAX_OPAQUE: {
182         encodeOctetString(buf, (OctetString)v);
183         break;
184       }
185       case SMIConstants.SYNTAX_IPADDRESS: {
186         encodeOctetString(buf,
187                new OctetString(((IpAddress)v).getInetAddress().getAddress()));
188         //buf.put(((IpAddress)v).getInetAddress().getAddress());
189
break;
190       }
191       case SMIConstants.SYNTAX_OBJECT_IDENTIFIER: {
192         encodeOID(buf, (OID)v, false);
193         break;
194       }
195       default:
196         break;
197     }
198   }
199
200   public static int getVariableDataLength(Variable v) {
201     if (v == null) {
202       return 0;
203     }
204     switch (v.getSyntax()) {
205       //case sNMP_SYNTAX_INT:
206
case SMIConstants.SYNTAX_GAUGE32:
207       case SMIConstants.SYNTAX_TIMETICKS:
208       case SMIConstants.SYNTAX_COUNTER32:
209       case SMIConstants.SYNTAX_INTEGER32: {
210         return AGENTX_INT_SIZE;
211       }
212       case SMIConstants.SYNTAX_COUNTER64: {
213         return 2 * AGENTX_INT_SIZE;
214       }
215       case SMIConstants.SYNTAX_OCTET_STRING:
216       case SMIConstants.SYNTAX_OPAQUE: {
217         return getOctetStringLength((OctetString)v);
218       }
219       case SMIConstants.SYNTAX_IPADDRESS: {
220         return 2 * AGENTX_INT_SIZE;
221       }
222       case SMIConstants.SYNTAX_OBJECT_IDENTIFIER: {
223         return getOIDLength((OID)v);
224       }
225       default:
226         break;
227     }
228     return 0;
229   }
230
231   public static Variable decodeVariableData(ByteBuffer buf, int syntax) {
232     switch (syntax) {
233       //case sNMP_SYNTAX_INT:
234
case SMIConstants.SYNTAX_GAUGE32:
235         return new Gauge32((buf.getInt() & 0xFFFFFFFFL));
236       case SMIConstants.SYNTAX_TIMETICKS:
237         return new TimeTicks((buf.getInt() & 0xFFFFFFFFL));
238       case SMIConstants.SYNTAX_COUNTER32:
239         return new Counter32((buf.getInt() & 0xFFFFFFFFL));
240       case SMIConstants.SYNTAX_INTEGER32:
241         return new Integer32(buf.getInt());
242       case SMIConstants.SYNTAX_COUNTER64:
243         return new Counter64(buf.getLong());
244       case SMIConstants.SYNTAX_OCTET_STRING:
245         return decodeOctetString(buf);
246       case SMIConstants.SYNTAX_OPAQUE:
247         return new Opaque(decodeOctetString(buf).getValue());
248       case SMIConstants.SYNTAX_IPADDRESS: {
249         byte[] addrBytes = decodeOctetString(buf).getValue();
250         // Workaround for incorrectly implemented sub-agents like
251
// NET-SNMP 5.4, that return addresses with more than 4 bytes
252
if (addrBytes.length > IPADDRESS_OCTETS) {
253           logger.warn("Subagent returned IpAddress with length "+
254                       addrBytes.length+
255                       " > "+IPADDRESS_OCTETS+
256                       " which violates AgentX protocol specification");
257           byte[] fourBytes = new byte[IPADDRESS_OCTETS];
258           System.arraycopy(addrBytes, 0, fourBytes, 0, IPADDRESS_OCTETS);
259           addrBytes = fourBytes;
260         }
261         InetAddress addr = null;
262         try {
263           addr = InetAddress.getByAddress(addrBytes);
264         }
265         catch (UnknownHostException ex) {
266           logger.error("Failed to create IpAddress from address bytes "+
267                        " with length "+addrBytes.length+
268                        ", using default IpAddress instead", ex);
269           return new IpAddress();
270         }
271         return new IpAddress(addr);
272       }
273       case SMIConstants.SYNTAX_OBJECT_IDENTIFIER: {
274         OID oid = new OID();
275         decodeOID(buf, oid);
276         return oid;
277       }
278       case SMIConstants.EXCEPTION_END_OF_MIB_VIEW:
279       case SMIConstants.EXCEPTION_NO_SUCH_INSTANCE:
280       case SMIConstants.EXCEPTION_NO_SUCH_OBJECT: {
281         return new Null(syntax);
282       }
283       case SMIConstants.SYNTAX_NULL: {
284         return new Null();
285       }
286       default: {
287         logger.error("Unknown AgentX variable syntax '"+syntax+
288                      "', using Null instead");
289         return new Null();
290       }
291     }
292   }
293
294   public static VariableBinding[] decodeVariableBindings(ByteBuffer buf) {
295     ArrayList vbs = new ArrayList();
296     while (buf.remaining() > 0) {
297       int type = buf.getShort() & 0xFFFF;
298       buf.getShort();
299       OID oid = new OID();
300       decodeOID(buf, oid);
301       Variable v = decodeVariableData(buf, type);
302       vbs.add(new VariableBinding(oid, v));
303     }
304     return (VariableBinding[]) vbs.toArray(new VariableBinding[vbs.size()]);
305   }
306
307   public static void encodeVaribleBindings(ByteBuffer buf, VariableBinding[] vbs) {
308     for (int i=0; i<vbs.length; i++) {
309       buf.putShort((short)vbs[i].getSyntax());
310       buf.put(new byte[] { 0,0 }); // reserved
311
encodeOID(buf, vbs[i].getOid(), false);
312       encodeVariableData(buf, vbs[i].getVariable());
313     }
314   }
315
316   public static void encodeRanges(ByteBuffer buf, MOScope[] searchRanges) {
317     for (int i=0; i<searchRanges.length; i++) {
318       encodeOID(buf, searchRanges[i].getLowerBound(),
319                 searchRanges[i].isLowerIncluded());
320       if (searchRanges[i].isUpperIncluded()) {
321         encodeOID(buf, searchRanges[i].getUpperBound().successor(), false);
322       }
323       else {
324         encodeOID(buf, searchRanges[i].getUpperBound(), false);
325       }
326     }
327   }
328
329   public static int getOctetStringLength(OctetString os) {
330     int padding = 0;
331     if ((os.length() % AGENTX_INT_SIZE) > 0) {
332       padding = AGENTX_INT_SIZE - (os.length() % AGENTX_INT_SIZE);
333     }
334     return AGENTX_INT_SIZE + os.length() + padding;
335   }
336
337   public static void encodeOctetString(ByteBuffer buf, OctetString os) {
338     buf.putInt(os.length());
339     buf.put(os.getValue());
340     if ((os.length() % AGENTX_INT_SIZE) > 0) {
341       for (int i=0; i < AGENTX_INT_SIZE - (os.length() % AGENTX_INT_SIZE); i++) {
342         buf.put((byte)0);
343       }
344     }
345   }
346
347   public static OctetString decodeOctetString(ByteBuffer buf) {
348     int size = buf.getInt();
349     byte[] value = new byte[size];
350     buf.get(value);
351     if ((size % AGENTX_INT_SIZE) > 0) {
352       for (int i=0; i < AGENTX_INT_SIZE - (size % AGENTX_INT_SIZE); i++) {
353         buf.get(); // skip 0 bytes
354
}
355     }
356     return new OctetString(value);
357   }
358
359   public static MOScope[] decodeRanges(ByteBuffer buf) {
360     return decodeRanges(buf, false);
361   }
362
363   public static MOScope[] decodeRanges(ByteBuffer buf,
364                                        boolean lowerAlwaysIncluded) {
365     ArrayList ranges = new ArrayList();
366     while (buf.hasRemaining()) {
367       OID lowerBound = new OID();
368       boolean isLowerIncluded= lowerAlwaysIncluded | decodeOID(buf, lowerBound);
369       OID upperBound = new OID();
370       decodeOID(buf, upperBound);
371       if (upperBound.size() == 0) {
372         upperBound = null;
373       }
374       ranges.add(new DefaultMOScope(lowerBound, isLowerIncluded,
375                                     upperBound, false));
376     }
377     return (MOScope[]) ranges.toArray(new MOScope[ranges.size()]);
378   }
379
380   public static int getRangesLength(MOScope[] ranges) {
381     int length = 0;
382     for (int i=0; i<ranges.length; i++) {
383       length += AgentXProtocol.getOIDLength(ranges[i].getLowerBound());
384       if (ranges[i].isUpperIncluded()) {
385         length +=
386             AgentXProtocol.getOIDLength(ranges[i].getUpperBound().successor());
387       }
388       else {
389         length += AgentXProtocol.getOIDLength(ranges[i].getUpperBound());
390       }
391     }
392     return length;
393   }
394
395   public static int getVariableBindingsLength(VariableBinding[] vbs) {
396     int length = 0;
397     for (int i=0; i<vbs.length; i++) {
398       length += AGENTX_INT_SIZE + getOIDLength(vbs[i].getOid()) +
399           getVariableDataLength(vbs[i].getVariable());
400     }
401     return length;
402   }
403
404   public int getMinHeaderLength() {
405     return HEADER_LENGTH;
406   }
407
408   public MessageLength getMessageLength(ByteBuffer buf) throws IOException JavaDoc {
409     return decodeHeader(buf);
410   }
411
412   public static final AgentXMessageHeader decodeHeader(ByteBuffer buf)
413       throws IOException JavaDoc
414   {
415     byte version = buf.get();
416     if (version != AgentXProtocol.VERSION_1_0) {
417       throw new IOException JavaDoc("Unknown AgentX version: "+version);
418     }
419     byte type = buf.get();
420     byte flags = buf.get();
421     buf.get();
422     ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
423     if ((flags & AgentXProtocol.FLAG_NETWORK_BYTE_ORDER) != 0) {
424       byteOrder = ByteOrder.BIG_ENDIAN;
425     }
426     buf.order(byteOrder);
427     int sessionID = buf.getInt();
428     int transactionID = buf.getInt();
429     int packetID = buf.getInt();
430     int length = buf.getInt();
431     return new AgentXMessageHeader(type, flags, sessionID, transactionID,
432                                    packetID, length);
433   }
434
435   public static void setNonDefaultContextsEnabled(boolean enabled) {
436     nonDefaultContextEnabled = enabled;
437   }
438
439   public static boolean isNonDefaultContextsEnabled() {
440     return nonDefaultContextEnabled;
441   }
442
443   public static final byte DEFAULT_PRIORITY = 127;
444   public static final int FLAG_ALLOCATE_INDEX = 0;
445 }
446
Popular Tags