1 /*
2 * Copyright (c) 1990, by John Robert LoVerso.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by John Robert LoVerso.
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
12 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
13 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 * This implementaion has been influenced by the CMU SNMP release,
16 * by Steve Waldbusser. However, this shares no code with that system.
17 * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
18 * Earlier forms of this implemention were derived and/or inspired by an
19 * awk script originally written by C. Philip Wood of LANL (but later
20 * heavily modified by John Robert LoVerso). The copyright notice for
21 * that work is preserved below, even though it may not rightly apply
22 * to this file.
23 *
24 * This started out as a very simple program, but the incremental decoding
25 * (into the BE structure) complicated things.
26 *
27 # Los Alamos National Laboratory
28 #
29 # Copyright, 1990. The Regents of the University of California.
30 # This software was produced under a U.S. Government contract
31 # (W-7405-ENG-36) by Los Alamos National Laboratory, which is
32 # operated by the University of California for the U.S. Department
33 # of Energy. The U.S. Government is licensed to use, reproduce,
34 # and distribute this software. Permission is granted to the
35 # public to copy and use this software without charge, provided
36 # that this Notice and any statement of authorship are reproduced
37 # on all copies. Neither the Government nor the University makes
38 # any warranty, express or implied, or assumes any liability or
39 # responsibility for the use of this software.
40 # @(#)snmp.awk.x 1.1 (LANL) 1/15/90
41 */
42 #ifndef lint
43 static char rcsid[] =
44 "@(#) $Id: detail-snmp.c,v 1.1 1993/04/22 20:17:17 martinh Exp $ (UW)";
45 #endif
46
47 #include <sys/param.h>
48 #include <sys/types.h>
49 #include <stdio.h>
50 #include <ctype.h>
51
52 #ifdef TCPVIEW
53 #include "tcpview.h"
54 #endif
55
56 #include "interface.h"
57 #include "addrtoname.h"
58 #include "snmp.h"
59
60 /*
61 * truncated==1 means the packet was complete, but we don't have all of
62 * it to decode.
63 */
64 static int truncated;
65
66 /*
67 * Decode SNMP varBind
68 */
varbind_print(pduid,np,length,err)69 static void varbind_print (pduid, np, length, err)
70 u_char pduid, *np;
71 int length, err;
72 {
73 struct be elem;
74 int count = 0, index;
75
76 /* Sequence of varBind */
77 if ((count = asn1_parse(np, length, &elem)) < 0)
78 return;
79 hex(0,count-1);
80 if (elem.type != BE_SEQ) {
81 printf("ERROR: expected Sequence of variables\n");
82 return;
83 }
84 printf("Sequence of VarBind (%d bytes)",count);
85 if (count < length)
86 printf(" [%d extra after Sequence]", length - count);
87 putchar('\n');
88
89 /* descend */
90 length = elem.asnlen;
91 Offset += (u_long)elem.data.raw - (u_long)np;
92 np = (u_char *)elem.data.raw;
93
94 for (index = 1; length > 0; index++) {
95 u_char *vbend;
96 int vblength;
97
98 /* Sequence (VarBind) */
99 if ((count = asn1_parse(np, length, &elem)) < 0)
100 return;
101 hex(0,count-1);
102 if (elem.type != BE_SEQ) {
103 printf(" ERROR: expected VarBind\n");
104 return;
105 }
106 vbend = np + count;
107 vblength = length - count;
108 printf(" VarBind (%d bytes)\n",elem.asnlen);
109
110 /* descend */
111 length = elem.asnlen;
112 Offset += (u_long)elem.data.raw - (u_long)np;
113 np = (u_char *)elem.data.raw;
114
115 /* objName (OID) */
116 if ((count = asn1_parse(np, length, &elem)) < 0)
117 return;
118 hex(0,count-1);
119 if (elem.type != BE_OID) {
120 printf(" ERROR: expected OBJECT ID\n");
121 return;
122 }
123
124 if (err && index == err)
125 printf("UNKNOWN ");
126 printf(" OBJECT: ");
127 asn1_print(&elem);
128
129 putchar('\n');
130 length -= count;
131 np += count;
132 Offset += count;
133
134
135 /* objVal (ANY) */
136 if ((count = asn1_parse(np, length, &elem)) < 0)
137 return;
138 hex(0,count-1);
139 printf(" VALUE: ");
140 if( elem.type == BE_NULL )
141 printf("NULL");
142 else
143 asn1_print(&elem);
144 putchar('\n');
145 length = vblength;
146 np = vbend;
147 Offset += count;
148 }
149 }
150
151 /*
152 * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest
153 */
snmppdu_print(pduid,np,length)154 static void snmppdu_print (pduid, np, length)
155 u_char pduid, *np;
156 int length;
157 {
158 struct be elem;
159 int count = 0, error, index;
160
161 /* reqId (Integer) */
162 if ((count = asn1_parse(np, length, &elem)) < 0)
163 return;
164 hex(0,count-1);
165 if (elem.type != BE_INT) {
166 printf("ERROR: expected INTEGER\n");
167 return;
168 }
169 printf("Request ID: %d\n",elem.data.integer);
170
171 length -= count;
172 np += count;
173 Offset += count;
174
175 /* errorStatus (Integer) */
176 if ((count = asn1_parse(np, length, &elem)) < 0)
177 return;
178 hex(0,count-1);
179 if (elem.type != BE_INT) {
180 printf("ERROR: expected INTEGER\n");
181 return;
182 }
183
184 error = elem.data.integer;
185 printf("Error Status = %d (%s)\n", error, DECODE_ErrorStatus(error));
186
187 length -= count;
188 np += count;
189 Offset += count;
190
191 /* errorIndex (Integer) */
192 if ((count = asn1_parse(np, length, &elem)) < 0)
193 return;
194 hex(0,count-1);
195 if (elem.type != BE_INT) {
196 printf("ERROR: expected INTEGER\n");
197 return;
198 }
199 printf("Error Index = %d\n", elem.data.integer);
200
201 length -= count;
202 np += count;
203 Offset += count;
204
205 if( error )
206 index = elem.data.integer;
207 else
208 index = 0;
209
210 varbind_print(pduid, np, length, index);
211 return;
212 }
213
214 /*
215 * Decode SNMP Trap PDU
216 */
trap_print(np,length)217 static void trap_print (np, length)
218 u_char *np;
219 int length;
220 {
221 struct be elem;
222 int count = 0, generic;
223
224 /* enterprise (oid) */
225 if ((count = asn1_parse(np, length, &elem)) < 0)
226 return;
227 hex(0,count-1);
228 if (elem.type != BE_OID) {
229 printf("ERROR: Expected enterprise OID\n");
230 return;
231 }
232 printf("Enterprise = ");
233 asn1_print(&elem);
234 putchar('\n');
235
236 length -= count;
237 np += count;
238 Offset += count;
239
240 /* agent-addr (inetaddr) */
241 if ((count = asn1_parse(np, length, &elem)) < 0)
242 return;
243 hex(0,count-1);
244 if (elem.type != BE_INETADDR) {
245 printf("ERROR: expected NetworkAddress\n");
246 return;
247 }
248 printf("Agent Address = ");
249 asn1_print(&elem);
250 putchar('\n');
251 length -= count;
252 np += count;
253 Offset += count;
254
255 /* generic-trap (Integer) */
256 if ((count = asn1_parse(np, length, &elem)) < 0)
257 return;
258 hex(0,count-1);
259 if (elem.type != BE_INT) {
260 printf("ERROR: expected INTEGER\n");
261 return;
262 }
263 generic = elem.data.integer;
264 printf("Generic Trap Type = %d (%s)\n", generic, DECODE_GenericTrap(generic));
265 length -= count;
266 np += count;
267 Offset += count;
268
269 /* specific-trap (Integer) */
270 if ((count = asn1_parse(np, length, &elem)) < 0)
271 return;
272 hex(0,count-1);
273 if (elem.type != BE_INT) {
274 printf("ERROR: expected INTEGER\n");
275 return;
276 }
277 printf("Specific Trap = %d\n", elem.data.integer);
278 length -= count;
279 np += count;
280 Offset += count;
281
282 /* time-stamp (TimeTicks) */
283 if ((count = asn1_parse(np, length, &elem)) < 0)
284 return;
285 hex(0,count-1);
286 if (elem.type != BE_UNS) { /* XXX */
287 printf("ERROR: expected TimeTicks\n");
288 return;
289 }
290 printf("TimeStamp = ");
291 asn1_print(&elem);
292 putchar('\n');
293 length -= count;
294 np += count;
295 Offset += count;
296
297 varbind_print (TRAP, np, length, 0);
298 return;
299 }
300
301 /*
302 * Decode SNMP header and pass on to PDU printing routines
303 */
detail_snmp(np,length)304 void detail_snmp (np, length)
305 u_char *np;
306 int length;
307 {
308 struct be elem, pdu;
309 int count = 0;
310
311 truncated = 0;
312
313 /* truncated packet? */
314 if (length > Phdr->caplen-Offset) {
315 truncated = 1;
316 length = Phdr->caplen-Offset;
317 printf("*** SNMP (truncated) ***\n\n");
318 } else
319 printf("----- SNMP -----\n\n");
320 hex( 0, length-1 );
321 hex( -1, -1 ); /* blank line */
322
323 /* initial Sequence */
324 if ((count = asn1_parse(np, length, &elem)) < 0)
325 return;
326 if (elem.type != BE_SEQ) {
327 printf("ERROR: expected SEQUENCE\n");
328 hex(0,count-1);
329 return;
330 }
331 printf("Message Sequence (%d bytes)",count);
332 if (count < length)
333 printf(" [%d extra after SEQ]", length - count);
334 hex(0,count-1);
335 putchar('\n');
336
337 /* descend */
338 Offset += ((u_long)elem.data.raw - (u_long)np);
339 length = elem.asnlen;
340 np = (u_char *)elem.data.raw;
341
342 /* Version (Integer) */
343 if ((count = asn1_parse(np, length, &elem)) < 0)
344 return;
345 hex(0,count-1);
346 if (elem.type != BE_INT) {
347 printf("ERROR: expected INTEGER\n");
348 return;
349 }
350 /* only handle version==0 */
351 printf("Version: %d",elem.data.integer);
352 if (elem.data.integer != DEF_VERSION) {
353 printf("\t[should have been 0]");
354 return;
355 }
356 putchar('\n');
357
358 length -= count;
359 np += count;
360 Offset += count;
361
362 /* Community (String) */
363 if ((count = asn1_parse(np, length, &elem)) < 0)
364 return;
365 hex(0,count-1);
366 if (elem.type != BE_STR) {
367 printf("ERROR: expected STRING\n");
368 return;
369 }
370 /* default community */
371 printf("Community = \"%.*s\"\n", elem.asnlen,elem.data.str);
372 length -= count;
373 np += count;
374 Offset += count;
375
376
377 /* PDU (Context) */
378 if ((count = asn1_parse(np, length, &pdu)) < 0)
379 return;
380 hex(0,count-1);
381 if (pdu.type != BE_PDU) {
382 printf("ERROR: expected PDU\n");
383 return;
384 }
385 asn1_print(&pdu);
386 if (count < length)
387 printf(" [%d extra after PDU]", length - count);
388 putchar('\n');
389
390 /* descend into PDU */
391
392 length = pdu.asnlen;
393 Offset += (u_long)pdu.data.raw -(u_long)np;
394 np = (u_char *)pdu.data.raw;
395
396 switch (pdu.id) {
397 case TRAP:
398 trap_print(np, length);
399 break;
400 case GETREQ:
401 case GETNEXTREQ:
402 case GETRESP:
403 case SETREQ:
404 snmppdu_print(pdu.id, np, length);
405 break;
406 }
407 return;
408 }
409