]>
The Tcpdump Group git mirrors - tcpdump/blob - print-snmp.c
2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15 * This implementation 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 implementation 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
24 * This started out as a very simple program, but the incremental decoding
25 * (into the BE structure) complicated things.
27 # Los Alamos National Laboratory
29 # Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
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
44 static const char rcsid
[] =
45 "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.37 1999-11-21 09:37:01 fenner Exp $ (LBL)";
52 #include <sys/param.h>
62 #include "interface.h"
63 #include "addrtoname.h"
66 * Universal ASN.1 types
67 * (we only care about the tag values for those allowed in the Internet SMI)
82 "U-8","U-9","U-10","U-11", /* 8-11 */
83 "U-12","U-13","U-14","U-15", /* 12-15 */
90 * Application-wide ASN.1 types from the Internet SMI and their tags
92 char *Application
[] = {
109 * Context-specific ASN.1 types for the SNMP PDUs and their tags
133 * Context-specific ASN.1 types for the SNMP Exceptions and their tags
135 char *Exceptions
[] = {
137 #define NOSUCHOBJECT 0
139 #define NOSUCHINSTANCE 1
141 #define ENDOFMIBVIEW 2
145 * Private ASN.1 types
146 * The Internet SMI does not specify any
153 * error-status values for any SNMP PDU
155 char *ErrorStatus
[] = {
169 "resourceUnavailable",
172 "authorizationError",
176 #define DECODE_ErrorStatus(e) \
177 ( e >= 0 && e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
178 ? ErrorStatus[e] : (sprintf(errbuf, "err=%u", e), errbuf))
181 * generic-trap values in the SNMP Trap-PDU
183 char *GenericTrap
[] = {
188 "authenticationFailure",
191 #define GT_ENTERPRISE 7
193 #define DECODE_GenericTrap(t) \
194 ( t >= 0 && t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
195 ? GenericTrap[t] : (sprintf(buf, "gt=%d", t), buf))
198 * ASN.1 type class table
199 * Ties together the preceding Universal, Application, Context, and Private
202 #define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
208 defineCLASS(Universal
),
210 defineCLASS(Application
),
211 #define APPLICATION 1
212 defineCLASS(Context
),
214 defineCLASS(Private
),
216 defineCLASS(Exceptions
),
221 * defined forms for ASN.1 types
227 #define CONSTRUCTED 1
231 * A structure for the OID tree for the compiled-in MIB.
232 * This is stored as a general-order tree.
235 char *desc
; /* name of object */
236 u_char oid
; /* sub-id following parent */
237 u_char type
; /* object type (unused) */
238 struct obj
*child
, *next
; /* child and next sibling pointers */
242 * Include the compiled in SNMP MIB. "mib.h" is produced by feeding
243 * RFC-1156 format files into "makemib". "mib.h" MUST define at least
244 * a value for `mibroot'.
246 * In particular, this is gross, as this is including initialized structures,
247 * and by right shouldn't be an "include" file.
252 * This defines a list of OIDs which will be abbreviated on output.
253 * Currently, this includes the prefixes for the Internet MIB, the
254 * private enterprises tree, and the experimental tree.
257 char *prefix
; /* prefix for this abrev */
258 struct obj
*node
; /* pointer into object table */
259 char *oid
; /* ASN.1 encoded OID */
260 } obj_abrev_list
[] = {
262 /* .iso.org.dod.internet.mgmt.mib */
263 { "", &_mib_obj
, "\53\6\1\2\1" },
265 #ifndef NO_ABREV_ENTER
266 /* .iso.org.dod.internet.private.enterprises */
267 { "E:", &_enterprises_obj
, "\53\6\1\4\1" },
269 #ifndef NO_ABREV_EXPERI
270 /* .iso.org.dod.internet.experimental */
271 { "X:", &_experimental_obj
, "\53\6\1\3" },
273 #ifndef NO_ABBREV_SNMPMODS
274 /* .iso.org.dod.internet.snmpV2.snmpModules */
275 { "S:", &_snmpModules_obj
, "\53\6\1\6\3" },
281 * This is used in the OID print routine to walk down the object tree
282 * rooted at `mibroot'.
284 #define OBJ_PRINT(o, suppressdot) \
288 if ((o) == objp->oid) \
290 } while ((objp = objp->next) != NULL); \
293 printf(suppressdot?"%s":".%s", objp->desc); \
294 objp = objp->child; \
296 printf(suppressdot?"%u":".%u", (o)); \
300 * This is the definition for the Any-Data-Type storage used purely for
301 * temporary internal representation while decoding an ASN.1 data stream.
316 u_char form
, class; /* tag info */
327 #define BE_INETADDR 8
330 #define BE_NOSUCHOBJECT 128
331 #define BE_NOSUCHINST 129
332 #define BE_ENDOFMIBVIEW 130
336 * SNMP versions recognized by this module
338 char *SnmpVersion
[] = {
340 #define SNMP_VERSION_1 0
342 #define SNMP_VERSION_2 1
344 #define SNMP_VERSION_2U 2
346 #define SNMP_VERSION_3 3
350 * Defaults for SNMP PDU components
352 #define DEF_COMMUNITY "public"
355 * constants for ASN.1 decoding
358 #define ASNLEN_INETADDR 4
361 #define ASN_BIT8 0x80
362 #define ASN_LONGLEN 0x80
364 #define ASN_ID_BITS 0x1f
365 #define ASN_FORM_BITS 0x20
366 #define ASN_FORM_SHIFT 5
367 #define ASN_CLASS_BITS 0xc0
368 #define ASN_CLASS_SHIFT 6
370 #define ASN_ID_EXT 0x1f /* extension ID in tag field */
373 * truncated==1 means the packet was complete, but we don't have all of
376 static int truncated
;
377 #define ifNotTruncated if (truncated) fputs("[|snmp]", stdout); else
380 * This decodes the next ASN.1 object in the stream pointed to by "p"
381 * (and of real-length "len") and stores the intermediate data in the
382 * provided BE object.
384 * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
385 * O/w, this returns the number of bytes parsed from "p".
388 asn1_parse(register const u_char
*p
, u_int len
, struct be
*elem
)
390 u_char form
, class, id
;
396 ifNotTruncated
fputs("[nothing to parse]", stdout
);
401 * it would be nice to use a bit field, but you can't depend on them.
402 * +---+---+---+---+---+---+---+---+
404 * +---+---+---+---+---+---+---+---+
407 id
= *p
& ASN_ID_BITS
; /* lower 5 bits, range 00-1f */
409 form
= (*p
& 0xe0) >> 5; /* move upper 3 bits to lower 3 */
410 class = form
>> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
411 form
&= 0x1; /* bit 5 -> bit 0, range 0-1 */
413 form
= (u_char
)(*p
& ASN_FORM_BITS
) >> ASN_FORM_SHIFT
;
414 class = (u_char
)(*p
& ASN_CLASS_BITS
) >> ASN_CLASS_SHIFT
;
422 /* extended tag field */
423 if (id
== ASN_ID_EXT
) {
424 for (id
= 0; *p
& ASN_BIT8
&& len
> 0; len
--, hdr
++, p
++) {
427 id
= (id
<< 7) | (*p
& ~ASN_BIT8
);
429 if (len
== 0 && *p
& ASN_BIT8
) {
430 ifNotTruncated
fputs("[Xtagfield?]", stdout
);
433 elem
->id
= id
= (id
<< 7) | *p
;
439 ifNotTruncated
fputs("[no asnlen]", stdout
);
446 if (elem
->asnlen
& ASN_BIT8
) {
447 int noct
= elem
->asnlen
% ASN_BIT8
;
450 ifNotTruncated
printf("[asnlen? %d<%d]", len
, noct
);
453 for (; noct
-- > 0; len
--, hdr
++) {
456 elem
->asnlen
= (elem
->asnlen
<< ASN_SHIFT8
) | *p
++;
459 if (len
< elem
->asnlen
) {
461 printf("[len%d<asnlen%u]", len
, elem
->asnlen
);
464 /* maybe should check at least 4? */
467 if (form
>= sizeof(Form
)/sizeof(Form
[0])) {
468 ifNotTruncated
printf("[form?%d]", form
);
471 if (class >= sizeof(Class
)/sizeof(Class
[0])) {
472 ifNotTruncated
printf("[class?%c/%d]", *Form
[form
], class);
475 if ((int)id
>= Class
[class].numIDs
) {
476 ifNotTruncated
printf("[id?%c/%s/%d]", *Form
[form
],
477 Class
[class].name
, id
);
492 register int32_t data
;
496 if (*p
& ASN_BIT8
) /* negative */
498 for (i
= elem
->asnlen
; i
-- > 0; p
++)
499 data
= (data
<< ASN_SHIFT8
) | *p
;
500 elem
->data
.integer
= data
;
506 elem
->data
.raw
= (caddr_t
)p
;
510 elem
->type
= BE_NULL
;
511 elem
->data
.raw
= NULL
;
515 elem
->type
= BE_OCTET
;
516 elem
->data
.raw
= (caddr_t
)p
;
518 Class
[class].Id
[id
]);
526 elem
->type
= BE_INETADDR
;
527 elem
->data
.raw
= (caddr_t
)p
;
533 register u_int32_t data
;
536 for (i
= elem
->asnlen
; i
-- > 0; p
++)
537 data
= (data
<< 8) + *p
;
538 elem
->data
.uns
= data
;
543 register u_int32_t high
, low
;
544 elem
->type
= BE_UNS64
;
546 for (i
= elem
->asnlen
; i
-- > 0; p
++) {
548 ((low
& 0xFF000000) >> 24);
549 low
= (low
<< 8) | *p
;
551 elem
->data
.uns64
.high
= high
;
552 elem
->data
.uns64
.low
= low
;
557 elem
->type
= BE_OCTET
;
558 elem
->data
.raw
= (caddr_t
)p
;
560 Class
[class].Id
[id
]);
568 elem
->type
= BE_NOSUCHOBJECT
;
569 elem
->data
.raw
= NULL
;
573 elem
->type
= BE_NOSUCHINST
;
574 elem
->data
.raw
= NULL
;
578 elem
->type
= BE_ENDOFMIBVIEW
;
579 elem
->data
.raw
= NULL
;
585 elem
->type
= BE_OCTET
;
586 elem
->data
.raw
= (caddr_t
)p
;
588 Class
[class].name
, Class
[class].Id
[id
]);
599 elem
->data
.raw
= (caddr_t
)p
;
603 elem
->type
= BE_OCTET
;
604 elem
->data
.raw
= (caddr_t
)p
;
605 printf("C/U/%s", Class
[class].Id
[id
]);
612 elem
->data
.raw
= (caddr_t
)p
;
616 elem
->type
= BE_OCTET
;
617 elem
->data
.raw
= (caddr_t
)p
;
619 Class
[class].name
, Class
[class].Id
[id
]);
626 return elem
->asnlen
+ hdr
;
630 * Display the ASN.1 object represented by the BE object.
631 * This used to be an integral part of asn1_parse() before the intermediate
635 asn1_print(struct be
*elem
)
637 u_char
*p
= (u_char
*)elem
->data
.raw
;
638 u_int32_t asnlen
= elem
->asnlen
;
641 switch (elem
->type
) {
644 for (i
= asnlen
; i
-- > 0; p
++);
652 int o
= 0, first
= -1, i
= asnlen
;
654 if (!nflag
&& asnlen
> 2) {
655 struct obj_abrev
*a
= &obj_abrev_list
[0];
656 for (; a
->node
; a
++) {
657 if (!memcmp(a
->oid
, (char *)p
,
659 objp
= a
->node
->child
;
662 fputs(a
->prefix
, stdout
);
668 for (; i
-- > 0; p
++) {
669 o
= (o
<< ASN_SHIFT7
) + (*p
& ~ASN_BIT8
);
670 if (*p
& ASN_LONGLEN
)
674 * first subitem encodes two items with 1st*OIDMUX+2nd
680 OBJ_PRINT(o
/OIDMUX
, first
);
692 printf("%d", elem
->data
.integer
);
696 printf("%d", elem
->data
.uns
);
699 case BE_UNS64
: { /* idea borrowed from by Marshall Rose */
702 char *cpf
, *cpl
, last
[6], first
[30];
703 if (elem
->data
.uns64
.high
== 0) {
704 printf("%u", elem
->data
.uns64
.low
);
707 d
= elem
->data
.uns64
.high
* 4294967296.0; /* 2^32 */
708 if (elem
->data
.uns64
.high
<= 0x1fffff) {
709 d
+= elem
->data
.uns64
.low
;
713 d
+= (elem
->data
.uns64
.low
& 0xfffff000);
714 sprintf(first
, "%.f", d
);
715 sprintf(last
, "%5.5d", elem
->data
.uns64
.low
& 0xfff);
716 for (carry
= 0, cpf
= first
+strlen(first
)-1, cpl
= last
+4;
719 j
= carry
+ (*cpf
- '0') + (*cpl
- '0');
728 fputs(first
, stdout
);
733 register int printable
= 1, first
= 1;
734 const u_char
*p
= elem
->data
.str
;
735 for (i
= asnlen
; printable
&& i
-- > 0; p
++)
736 printable
= isprint(*p
) || isspace(*p
);
740 (void)fn_print(p
, p
+ asnlen
);
743 for (i
= asnlen
; i
-- > 0; p
++) {
744 printf(first
? "%.2x" : "_%.2x", *p
);
751 printf("Seq(%u)", elem
->asnlen
);
756 if (asnlen
!= ASNLEN_INETADDR
)
757 printf("[inetaddr len!=%d]", ASNLEN_INETADDR
);
759 for (i
= asnlen
; i
-- > 0; p
++) {
760 printf("%c%u", sep
, *p
);
767 case BE_NOSUCHOBJECT
:
769 case BE_ENDOFMIBVIEW
:
770 printf("[%s]", Class
[EXCEPTIONS
].Id
[elem
->id
]);
775 Class
[CONTEXT
].Id
[elem
->id
], elem
->asnlen
);
779 fputs("[BE_ANY!?]", stdout
);
783 fputs("[be!?]", stdout
);
790 * This is a brute force ASN.1 printer: recurses to dump an entire structure.
791 * This will work for any ASN.1 stream, not just an SNMP PDU.
793 * By adding newlines and spaces at the correct places, this would print in
796 * This is not currently used.
799 asn1_decode(u_char
*p
, u_int length
)
804 while (i
>= 0 && length
> 0) {
805 i
= asn1_parse(p
, length
, &elem
);
809 if (elem
.type
== BE_SEQ
|| elem
.type
== BE_PDU
) {
811 asn1_decode(elem
.data
.raw
, elem
.asnlen
);
822 * General SNMP header
824 * version INTEGER {version-1(0)},
825 * community OCTET STRING,
828 * PDUs for all but Trap: (see rfc1157 from page 15 on)
830 * request-id INTEGER,
831 * error-status INTEGER,
832 * error-index INTEGER,
833 * varbindlist SEQUENCE OF
841 * enterprise OBJECT IDENTIFIER,
842 * agent-addr NetworkAddress,
843 * generic-trap INTEGER,
844 * specific-trap INTEGER,
845 * time-stamp TimeTicks,
846 * varbindlist SEQUENCE OF
855 * Decode SNMP varBind
858 varbind_print(u_char pduid
, const u_char
*np
, u_int length
, int error
)
863 /* Sequence of varBind */
864 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
866 if (elem
.type
!= BE_SEQ
) {
867 fputs("[!SEQ of varbind]", stdout
);
872 printf("[%d extra after SEQ of varbind]", length
- count
);
874 length
= elem
.asnlen
;
875 np
= (u_char
*)elem
.data
.raw
;
877 for (ind
= 1; length
> 0; ind
++) {
881 if (!error
|| ind
== error
)
885 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
887 if (elem
.type
!= BE_SEQ
) {
888 fputs("[!varbind]", stdout
);
893 vblength
= length
- count
;
895 length
= elem
.asnlen
;
896 np
= (u_char
*)elem
.data
.raw
;
899 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
901 if (elem
.type
!= BE_OID
) {
902 fputs("[objName!=OID]", stdout
);
906 if (!error
|| ind
== error
)
911 if (pduid
!= GETREQ
&& pduid
!= GETNEXTREQ
912 && pduid
!= GETBULKREQ
&& !error
)
916 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
918 if (pduid
== GETREQ
|| pduid
== GETNEXTREQ
919 || pduid
== GETBULKREQ
) {
920 if (elem
.type
!= BE_NULL
) {
921 fputs("[objVal!=NULL]", stdout
);
925 if (error
&& ind
== error
&& elem
.type
!= BE_NULL
)
926 fputs("[err objVal!=NULL]", stdout
);
927 if (!error
|| ind
== error
)
936 * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
937 * GetBulk, Inform, V2Trap, and Report
940 snmppdu_print(u_char pduid
, const u_char
*np
, u_int length
)
943 int count
= 0, error
;
945 /* reqId (Integer) */
946 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
948 if (elem
.type
!= BE_INT
) {
949 fputs("[reqId!=INT]", stdout
);
953 /* ignore the reqId */
957 /* errorStatus (Integer) */
958 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
960 if (elem
.type
!= BE_INT
) {
961 fputs("[errorStatus!=INT]", stdout
);
966 if ((pduid
== GETREQ
|| pduid
== GETNEXTREQ
|| pduid
== SETREQ
967 || pduid
== INFORMREQ
|| pduid
== V2TRAP
|| pduid
== REPORT
)
968 && elem
.data
.integer
!= 0) {
970 printf("[errorStatus(%s)!=0]",
971 DECODE_ErrorStatus(elem
.data
.integer
));
972 } else if (pduid
== GETBULKREQ
) {
973 printf(" N=%d", elem
.data
.integer
);
974 } else if (elem
.data
.integer
!= 0) {
976 printf(" %s", DECODE_ErrorStatus(elem
.data
.integer
));
977 error
= elem
.data
.integer
;
982 /* errorIndex (Integer) */
983 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
985 if (elem
.type
!= BE_INT
) {
986 fputs("[errorIndex!=INT]", stdout
);
990 if ((pduid
== GETREQ
|| pduid
== GETNEXTREQ
|| pduid
== SETREQ
991 || pduid
== INFORMREQ
|| pduid
== V2TRAP
|| pduid
== REPORT
)
992 && elem
.data
.integer
!= 0)
993 printf("[errorIndex(%d)!=0]", elem
.data
.integer
);
994 else if (pduid
== GETBULKREQ
)
995 printf(" M=%d", elem
.data
.integer
);
996 else if (elem
.data
.integer
!= 0) {
998 printf("[errorIndex(%d) w/o errorStatus]",
1001 printf("@%d", elem
.data
.integer
);
1002 error
= elem
.data
.integer
;
1005 fputs("[errorIndex==0]", stdout
);
1011 varbind_print(pduid
, np
, length
, error
);
1016 * Decode SNMP Trap PDU
1019 trappdu_print(const u_char
*np
, u_int length
)
1022 int count
= 0, generic
;
1026 /* enterprise (oid) */
1027 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1029 if (elem
.type
!= BE_OID
) {
1030 fputs("[enterprise!=OID]", stdout
);
1040 /* agent-addr (inetaddr) */
1041 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1043 if (elem
.type
!= BE_INETADDR
) {
1044 fputs("[agent-addr!=INETADDR]", stdout
);
1052 /* generic-trap (Integer) */
1053 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1055 if (elem
.type
!= BE_INT
) {
1056 fputs("[generic-trap!=INT]", stdout
);
1060 generic
= elem
.data
.integer
;
1063 printf(" %s", DECODE_GenericTrap(generic
));
1068 /* specific-trap (Integer) */
1069 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1071 if (elem
.type
!= BE_INT
) {
1072 fputs("[specific-trap!=INT]", stdout
);
1076 if (generic
!= GT_ENTERPRISE
) {
1077 if (elem
.data
.integer
!= 0)
1078 printf("[specific-trap(%d)!=0]", elem
.data
.integer
);
1080 printf(" s=%d", elem
.data
.integer
);
1086 /* time-stamp (TimeTicks) */
1087 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1089 if (elem
.type
!= BE_UNS
) { /* XXX */
1090 fputs("[time-stamp!=TIMETICKS]", stdout
);
1098 varbind_print (TRAP
, np
, length
, 0);
1103 * Decode arbitrary SNMP PDUs.
1106 pdu_print(const u_char
*np
, u_int length
, int version
)
1112 if ((count
= asn1_parse(np
, length
, &pdu
)) < 0)
1114 if (pdu
.type
!= BE_PDU
) {
1115 fputs("[no PDU]", stdout
);
1119 printf("[%d extra after PDU]", length
- count
);
1121 /* descend into PDU */
1122 length
= pdu
.asnlen
;
1123 np
= (u_char
*)pdu
.data
.raw
;
1125 if (version
== SNMP_VERSION_1
&&
1126 (pdu
.id
== GETBULKREQ
|| pdu
.id
== INFORMREQ
||
1127 pdu
.id
== V2TRAP
|| pdu
.id
== REPORT
)) {
1128 printf("[v2 PDU in v1 message]");
1132 if (version
== SNMP_VERSION_2
&& pdu
.id
== TRAP
) {
1133 printf("[v1 PDU in v2 message]");
1139 trappdu_print(np
, length
);
1149 snmppdu_print(pdu
.id
, np
, length
);
1155 * Decode a scoped SNMP PDU.
1158 scopedpdu_print(const u_char
*np
, u_int length
, int version
)
1164 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1166 if (elem
.type
!= BE_SEQ
) {
1167 fputs("[!scoped PDU]", stdout
);
1171 length
= elem
.asnlen
;
1172 np
= (u_char
*)elem
.data
.raw
;
1174 /* contextEngineID (OCTET STRING) */
1175 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1177 if (elem
.type
!= BE_STR
) {
1178 fputs("[contextEngineID!=STR]", stdout
);
1185 fputs("E= ", stdout
);
1186 for (i
= 0; i
< (int)elem
.asnlen
; i
++) {
1187 printf("0x%02X", elem
.data
.str
[i
]);
1191 /* contextName (OCTET STRING) */
1192 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1194 if (elem
.type
!= BE_STR
) {
1195 fputs("[contextName!=STR]", stdout
);
1202 printf("C=%.*s ", (int)elem
.asnlen
, elem
.data
.str
);
1204 pdu_print(np
, length
, version
);
1208 * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
1211 community_print(const u_char
*np
, u_int length
, int version
)
1216 /* Community (String) */
1217 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1219 if (elem
.type
!= BE_STR
) {
1220 fputs("[comm!=STR]", stdout
);
1224 /* default community */
1225 if (strncmp((char *)elem
.data
.str
, DEF_COMMUNITY
,
1226 sizeof(DEF_COMMUNITY
) - 1))
1228 printf("C=%.*s ", (int)elem
.asnlen
, elem
.data
.str
);
1232 pdu_print(np
, length
, version
);
1236 * Decode SNMPv3 User-based Security Message Header (SNMPv3)
1239 usm_print(const u_char
*np
, u_int length
)
1245 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1247 if (elem
.type
!= BE_SEQ
) {
1248 fputs("[!usm]", stdout
);
1252 length
= elem
.asnlen
;
1253 np
= (u_char
*)elem
.data
.raw
;
1255 /* msgAuthoritativeEngineID (OCTET STRING) */
1256 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1258 if (elem
.type
!= BE_STR
) {
1259 fputs("[msgAuthoritativeEngineID!=STR]", stdout
);
1266 /* msgAuthoritativeEngineBoots (INTEGER) */
1267 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1269 if (elem
.type
!= BE_INT
) {
1270 fputs("[msgAuthoritativeEngineBoots!=INT]", stdout
);
1275 printf("B=%d ", elem
.data
.integer
);
1279 /* msgAuthoritativeEngineTime (INTEGER) */
1280 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1282 if (elem
.type
!= BE_INT
) {
1283 fputs("[msgAuthoritativeEngineTime!=INT]", stdout
);
1288 printf("T=%d ", elem
.data
.integer
);
1292 /* msgUserName (OCTET STRING) */
1293 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1295 if (elem
.type
!= BE_STR
) {
1296 fputs("[msgUserName!=STR]", stdout
);
1303 printf("U=%.*s ", (int)elem
.asnlen
, elem
.data
.str
);
1305 /* msgAuthenticationParameters (OCTET STRING) */
1306 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1308 if (elem
.type
!= BE_STR
) {
1309 fputs("[msgAuthenticationParameters!=STR]", stdout
);
1316 /* msgPrivacyParameters (OCTET STRING) */
1317 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1319 if (elem
.type
!= BE_STR
) {
1320 fputs("[msgPrivacyParameters!=STR]", stdout
);
1328 printf("[%d extra after usm SEQ]", length
- count
);
1332 * Decode SNMPv3 Message Header (SNMPv3)
1335 v3msg_print(const u_char
*np
, u_int length
)
1341 const u_char
*xnp
= np
;
1342 int xlength
= length
;
1345 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1347 if (elem
.type
!= BE_SEQ
) {
1348 fputs("[!message]", stdout
);
1352 length
= elem
.asnlen
;
1353 np
= (u_char
*)elem
.data
.raw
;
1355 /* msgID (INTEGER) */
1356 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1358 if (elem
.type
!= BE_INT
) {
1359 fputs("[msgID!=INT]", stdout
);
1366 /* msgMaxSize (INTEGER) */
1367 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1369 if (elem
.type
!= BE_INT
) {
1370 fputs("[msgMaxSize!=INT]", stdout
);
1377 /* msgFlags (OCTET STRING) */
1378 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1380 if (elem
.type
!= BE_STR
) {
1381 fputs("[msgFlags!=STR]", stdout
);
1385 if (elem
.asnlen
!= 1) {
1386 printf("[msgFlags size %d]", elem
.asnlen
);
1389 flags
= elem
.data
.str
[0];
1390 if (flags
!= 0x00 && flags
!= 0x01 && flags
!= 0x03
1391 && flags
!= 0x04 && flags
!= 0x05 && flags
!= 0x07) {
1392 printf("[msgFlags=0x%02X]", flags
);
1398 fputs("F=", stdout
);
1399 if (flags
& 0x01) fputs("a", stdout
);
1400 if (flags
& 0x02) fputs("p", stdout
);
1401 if (flags
& 0x04) fputs("r", stdout
);
1404 /* msgSecurityModel (INTEGER) */
1405 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1407 if (elem
.type
!= BE_INT
) {
1408 fputs("[msgSecurityModel!=INT]", stdout
);
1412 model
= elem
.data
.integer
;
1417 printf("[%d extra after message SEQ]", length
- count
);
1421 fputs("USM ", stdout
);
1424 printf("[security model %d]", model
);
1428 np
= xnp
+ (np
- xnp
);
1429 length
= xlength
- (np
- xnp
);
1431 /* msgSecurityParameters (OCTET STRING) */
1432 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1434 if (elem
.type
!= BE_STR
) {
1435 fputs("[msgSecurityParameters!=STR]", stdout
);
1443 usm_print(elem
.data
.str
, elem
.asnlen
);
1447 fputs("ScopedPDU ", stdout
);
1450 scopedpdu_print(np
, length
, 3);
1454 * Decode SNMP header and pass on to PDU printing routines
1457 snmp_print(const u_char
*np
, u_int length
)
1465 /* truncated packet? */
1466 if (np
+ length
> snapend
) {
1468 length
= snapend
- np
;
1473 /* initial Sequence */
1474 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1476 if (elem
.type
!= BE_SEQ
) {
1477 fputs("[!init SEQ]", stdout
);
1482 printf("[%d extra after iSEQ]", length
- count
);
1484 length
= elem
.asnlen
;
1485 np
= (u_char
*)elem
.data
.raw
;
1487 /* Version (INTEGER) */
1488 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1490 if (elem
.type
!= BE_INT
) {
1491 fputs("[version!=INT]", stdout
);
1496 switch (elem
.data
.integer
) {
1497 case SNMP_VERSION_1
:
1498 case SNMP_VERSION_2
:
1499 case SNMP_VERSION_3
:
1501 printf("%s ", SnmpVersion
[elem
.data
.integer
]);
1504 printf("[version = %d]", elem
.data
.integer
);
1507 version
= elem
.data
.integer
;
1512 case SNMP_VERSION_1
:
1513 case SNMP_VERSION_2
:
1514 community_print(np
, length
, version
);
1516 case SNMP_VERSION_3
:
1517 v3msg_print(np
, length
);
1520 printf("[version = %d]", elem
.data
.integer
);