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