]>
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.36 1999-10-17 22:18:02 mcr Exp $ (LBL)";
48 #include <sys/param.h>
58 #include "interface.h"
59 #include "addrtoname.h"
62 * Universal ASN.1 types
63 * (we only care about the tag values for those allowed in the Internet SMI)
78 "U-8","U-9","U-10","U-11", /* 8-11 */
79 "U-12","U-13","U-14","U-15", /* 12-15 */
86 * Application-wide ASN.1 types from the Internet SMI and their tags
88 char *Application
[] = {
105 * Context-specific ASN.1 types for the SNMP PDUs and their tags
129 * Context-specific ASN.1 types for the SNMP Exceptions and their tags
131 char *Exceptions
[] = {
133 #define NOSUCHOBJECT 0
135 #define NOSUCHINSTANCE 1
137 #define ENDOFMIBVIEW 2
141 * Private ASN.1 types
142 * The Internet SMI does not specify any
149 * error-status values for any SNMP PDU
151 char *ErrorStatus
[] = {
165 "resourceUnavailable",
168 "authorizationError",
172 #define DECODE_ErrorStatus(e) \
173 ( e >= 0 && e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
174 ? ErrorStatus[e] : (sprintf(errbuf, "err=%u", e), errbuf))
177 * generic-trap values in the SNMP Trap-PDU
179 char *GenericTrap
[] = {
184 "authenticationFailure",
187 #define GT_ENTERPRISE 7
189 #define DECODE_GenericTrap(t) \
190 ( t >= 0 && t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
191 ? GenericTrap[t] : (sprintf(buf, "gt=%d", t), buf))
194 * ASN.1 type class table
195 * Ties together the preceding Universal, Application, Context, and Private
198 #define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
204 defineCLASS(Universal
),
206 defineCLASS(Application
),
207 #define APPLICATION 1
208 defineCLASS(Context
),
210 defineCLASS(Private
),
212 defineCLASS(Exceptions
),
217 * defined forms for ASN.1 types
223 #define CONSTRUCTED 1
227 * A structure for the OID tree for the compiled-in MIB.
228 * This is stored as a general-order tree.
231 char *desc
; /* name of object */
232 u_char oid
; /* sub-id following parent */
233 u_char type
; /* object type (unused) */
234 struct obj
*child
, *next
; /* child and next sibling pointers */
238 * Include the compiled in SNMP MIB. "mib.h" is produced by feeding
239 * RFC-1156 format files into "makemib". "mib.h" MUST define at least
240 * a value for `mibroot'.
242 * In particular, this is gross, as this is including initialized structures,
243 * and by right shouldn't be an "include" file.
248 * This defines a list of OIDs which will be abbreviated on output.
249 * Currently, this includes the prefixes for the Internet MIB, the
250 * private enterprises tree, and the experimental tree.
253 char *prefix
; /* prefix for this abrev */
254 struct obj
*node
; /* pointer into object table */
255 char *oid
; /* ASN.1 encoded OID */
256 } obj_abrev_list
[] = {
258 /* .iso.org.dod.internet.mgmt.mib */
259 { "", &_mib_obj
, "\53\6\1\2\1" },
261 #ifndef NO_ABREV_ENTER
262 /* .iso.org.dod.internet.private.enterprises */
263 { "E:", &_enterprises_obj
, "\53\6\1\4\1" },
265 #ifndef NO_ABREV_EXPERI
266 /* .iso.org.dod.internet.experimental */
267 { "X:", &_experimental_obj
, "\53\6\1\3" },
269 #ifndef NO_ABBREV_SNMPMODS
270 /* .iso.org.dod.internet.snmpV2.snmpModules */
271 { "S:", &_snmpModules_obj
, "\53\6\1\6\3" },
277 * This is used in the OID print routine to walk down the object tree
278 * rooted at `mibroot'.
280 #define OBJ_PRINT(o, suppressdot) \
284 if ((o) == objp->oid) \
286 } while ((objp = objp->next) != NULL); \
289 printf(suppressdot?"%s":".%s", objp->desc); \
290 objp = objp->child; \
292 printf(suppressdot?"%u":".%u", (o)); \
296 * This is the definition for the Any-Data-Type storage used purely for
297 * temporary internal representation while decoding an ASN.1 data stream.
312 u_char form
, class; /* tag info */
323 #define BE_INETADDR 8
326 #define BE_NOSUCHOBJECT 128
327 #define BE_NOSUCHINST 129
328 #define BE_ENDOFMIBVIEW 130
332 * SNMP versions recognized by this module
334 char *SnmpVersion
[] = {
336 #define SNMP_VERSION_1 0
338 #define SNMP_VERSION_2 1
340 #define SNMP_VERSION_2U 2
342 #define SNMP_VERSION_3 3
346 * Defaults for SNMP PDU components
348 #define DEF_COMMUNITY "public"
351 * constants for ASN.1 decoding
354 #define ASNLEN_INETADDR 4
357 #define ASN_BIT8 0x80
358 #define ASN_LONGLEN 0x80
360 #define ASN_ID_BITS 0x1f
361 #define ASN_FORM_BITS 0x20
362 #define ASN_FORM_SHIFT 5
363 #define ASN_CLASS_BITS 0xc0
364 #define ASN_CLASS_SHIFT 6
366 #define ASN_ID_EXT 0x1f /* extension ID in tag field */
369 * truncated==1 means the packet was complete, but we don't have all of
372 static int truncated
;
373 #define ifNotTruncated if (truncated) fputs("[|snmp]", stdout); else
376 * This decodes the next ASN.1 object in the stream pointed to by "p"
377 * (and of real-length "len") and stores the intermediate data in the
378 * provided BE object.
380 * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
381 * O/w, this returns the number of bytes parsed from "p".
384 asn1_parse(register const u_char
*p
, u_int len
, struct be
*elem
)
386 u_char form
, class, id
;
392 ifNotTruncated
fputs("[nothing to parse]", stdout
);
397 * it would be nice to use a bit field, but you can't depend on them.
398 * +---+---+---+---+---+---+---+---+
400 * +---+---+---+---+---+---+---+---+
403 id
= *p
& ASN_ID_BITS
; /* lower 5 bits, range 00-1f */
405 form
= (*p
& 0xe0) >> 5; /* move upper 3 bits to lower 3 */
406 class = form
>> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
407 form
&= 0x1; /* bit 5 -> bit 0, range 0-1 */
409 form
= (u_char
)(*p
& ASN_FORM_BITS
) >> ASN_FORM_SHIFT
;
410 class = (u_char
)(*p
& ASN_CLASS_BITS
) >> ASN_CLASS_SHIFT
;
418 /* extended tag field */
419 if (id
== ASN_ID_EXT
) {
420 for (id
= 0; *p
& ASN_BIT8
&& len
> 0; len
--, hdr
++, p
++) {
423 id
= (id
<< 7) | (*p
& ~ASN_BIT8
);
425 if (len
== 0 && *p
& ASN_BIT8
) {
426 ifNotTruncated
fputs("[Xtagfield?]", stdout
);
429 elem
->id
= id
= (id
<< 7) | *p
;
435 ifNotTruncated
fputs("[no asnlen]", stdout
);
442 if (elem
->asnlen
& ASN_BIT8
) {
443 int noct
= elem
->asnlen
% ASN_BIT8
;
446 ifNotTruncated
printf("[asnlen? %d<%d]", len
, noct
);
449 for (; noct
-- > 0; len
--, hdr
++) {
452 elem
->asnlen
= (elem
->asnlen
<< ASN_SHIFT8
) | *p
++;
455 if (len
< elem
->asnlen
) {
457 printf("[len%d<asnlen%u]", len
, elem
->asnlen
);
460 /* maybe should check at least 4? */
463 if (form
>= sizeof(Form
)/sizeof(Form
[0])) {
464 ifNotTruncated
printf("[form?%d]", form
);
467 if (class >= sizeof(Class
)/sizeof(Class
[0])) {
468 ifNotTruncated
printf("[class?%c/%d]", *Form
[form
], class);
471 if ((int)id
>= Class
[class].numIDs
) {
472 ifNotTruncated
printf("[id?%c/%s/%d]", *Form
[form
],
473 Class
[class].name
, id
);
488 register int32_t data
;
492 if (*p
& ASN_BIT8
) /* negative */
494 for (i
= elem
->asnlen
; i
-- > 0; p
++)
495 data
= (data
<< ASN_SHIFT8
) | *p
;
496 elem
->data
.integer
= data
;
502 elem
->data
.raw
= (caddr_t
)p
;
506 elem
->type
= BE_NULL
;
507 elem
->data
.raw
= NULL
;
511 elem
->type
= BE_OCTET
;
512 elem
->data
.raw
= (caddr_t
)p
;
514 Class
[class].Id
[id
]);
522 elem
->type
= BE_INETADDR
;
523 elem
->data
.raw
= (caddr_t
)p
;
529 register u_int32_t data
;
532 for (i
= elem
->asnlen
; i
-- > 0; p
++)
533 data
= (data
<< 8) + *p
;
534 elem
->data
.uns
= data
;
539 register u_int32_t high
, low
;
540 elem
->type
= BE_UNS64
;
542 for (i
= elem
->asnlen
; i
-- > 0; p
++) {
544 ((low
& 0xFF000000) >> 24);
545 low
= (low
<< 8) | *p
;
547 elem
->data
.uns64
.high
= high
;
548 elem
->data
.uns64
.low
= low
;
553 elem
->type
= BE_OCTET
;
554 elem
->data
.raw
= (caddr_t
)p
;
556 Class
[class].Id
[id
]);
564 elem
->type
= BE_NOSUCHOBJECT
;
565 elem
->data
.raw
= NULL
;
569 elem
->type
= BE_NOSUCHINST
;
570 elem
->data
.raw
= NULL
;
574 elem
->type
= BE_ENDOFMIBVIEW
;
575 elem
->data
.raw
= NULL
;
581 elem
->type
= BE_OCTET
;
582 elem
->data
.raw
= (caddr_t
)p
;
584 Class
[class].name
, Class
[class].Id
[id
]);
595 elem
->data
.raw
= (caddr_t
)p
;
599 elem
->type
= BE_OCTET
;
600 elem
->data
.raw
= (caddr_t
)p
;
601 printf("C/U/%s", Class
[class].Id
[id
]);
608 elem
->data
.raw
= (caddr_t
)p
;
612 elem
->type
= BE_OCTET
;
613 elem
->data
.raw
= (caddr_t
)p
;
615 Class
[class].name
, Class
[class].Id
[id
]);
622 return elem
->asnlen
+ hdr
;
626 * Display the ASN.1 object represented by the BE object.
627 * This used to be an integral part of asn1_parse() before the intermediate
631 asn1_print(struct be
*elem
)
633 u_char
*p
= (u_char
*)elem
->data
.raw
;
634 u_int32_t asnlen
= elem
->asnlen
;
637 switch (elem
->type
) {
640 for (i
= asnlen
; i
-- > 0; p
++);
648 int o
= 0, first
= -1, i
= asnlen
;
650 if (!nflag
&& asnlen
> 2) {
651 struct obj_abrev
*a
= &obj_abrev_list
[0];
652 for (; a
->node
; a
++) {
653 if (!memcmp(a
->oid
, (char *)p
,
655 objp
= a
->node
->child
;
658 fputs(a
->prefix
, stdout
);
664 for (; i
-- > 0; p
++) {
665 o
= (o
<< ASN_SHIFT7
) + (*p
& ~ASN_BIT8
);
666 if (*p
& ASN_LONGLEN
)
670 * first subitem encodes two items with 1st*OIDMUX+2nd
676 OBJ_PRINT(o
/OIDMUX
, first
);
688 printf("%d", elem
->data
.integer
);
692 printf("%d", elem
->data
.uns
);
695 case BE_UNS64
: { /* idea borrowed from by Marshall Rose */
698 char *cpf
, *cpl
, last
[6], first
[30];
699 if (elem
->data
.uns64
.high
== 0) {
700 printf("%u", elem
->data
.uns64
.low
);
703 d
= elem
->data
.uns64
.high
* 4294967296.0; /* 2^32 */
704 if (elem
->data
.uns64
.high
<= 0x1fffff) {
705 d
+= elem
->data
.uns64
.low
;
709 d
+= (elem
->data
.uns64
.low
& 0xfffff000);
710 sprintf(first
, "%.f", d
);
711 sprintf(last
, "%5.5d", elem
->data
.uns64
.low
& 0xfff);
712 for (carry
= 0, cpf
= first
+strlen(first
)-1, cpl
= last
+4;
715 j
= carry
+ (*cpf
- '0') + (*cpl
- '0');
724 fputs(first
, stdout
);
729 register int printable
= 1, first
= 1;
730 const u_char
*p
= elem
->data
.str
;
731 for (i
= asnlen
; printable
&& i
-- > 0; p
++)
732 printable
= isprint(*p
) || isspace(*p
);
736 (void)fn_print(p
, p
+ asnlen
);
739 for (i
= asnlen
; i
-- > 0; p
++) {
740 printf(first
? "%.2x" : "_%.2x", *p
);
747 printf("Seq(%u)", elem
->asnlen
);
752 if (asnlen
!= ASNLEN_INETADDR
)
753 printf("[inetaddr len!=%d]", ASNLEN_INETADDR
);
755 for (i
= asnlen
; i
-- > 0; p
++) {
756 printf("%c%u", sep
, *p
);
763 case BE_NOSUCHOBJECT
:
765 case BE_ENDOFMIBVIEW
:
766 printf("[%s]", Class
[EXCEPTIONS
].Id
[elem
->id
]);
771 Class
[CONTEXT
].Id
[elem
->id
], elem
->asnlen
);
775 fputs("[BE_ANY!?]", stdout
);
779 fputs("[be!?]", stdout
);
786 * This is a brute force ASN.1 printer: recurses to dump an entire structure.
787 * This will work for any ASN.1 stream, not just an SNMP PDU.
789 * By adding newlines and spaces at the correct places, this would print in
792 * This is not currently used.
795 asn1_decode(u_char
*p
, u_int length
)
800 while (i
>= 0 && length
> 0) {
801 i
= asn1_parse(p
, length
, &elem
);
805 if (elem
.type
== BE_SEQ
|| elem
.type
== BE_PDU
) {
807 asn1_decode(elem
.data
.raw
, elem
.asnlen
);
818 * General SNMP header
820 * version INTEGER {version-1(0)},
821 * community OCTET STRING,
824 * PDUs for all but Trap: (see rfc1157 from page 15 on)
826 * request-id INTEGER,
827 * error-status INTEGER,
828 * error-index INTEGER,
829 * varbindlist SEQUENCE OF
837 * enterprise OBJECT IDENTIFIER,
838 * agent-addr NetworkAddress,
839 * generic-trap INTEGER,
840 * specific-trap INTEGER,
841 * time-stamp TimeTicks,
842 * varbindlist SEQUENCE OF
851 * Decode SNMP varBind
854 varbind_print(u_char pduid
, const u_char
*np
, u_int length
, int error
)
859 /* Sequence of varBind */
860 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
862 if (elem
.type
!= BE_SEQ
) {
863 fputs("[!SEQ of varbind]", stdout
);
868 printf("[%d extra after SEQ of varbind]", length
- count
);
870 length
= elem
.asnlen
;
871 np
= (u_char
*)elem
.data
.raw
;
873 for (ind
= 1; length
> 0; ind
++) {
877 if (!error
|| ind
== error
)
881 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
883 if (elem
.type
!= BE_SEQ
) {
884 fputs("[!varbind]", stdout
);
889 vblength
= length
- count
;
891 length
= elem
.asnlen
;
892 np
= (u_char
*)elem
.data
.raw
;
895 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
897 if (elem
.type
!= BE_OID
) {
898 fputs("[objName!=OID]", stdout
);
902 if (!error
|| ind
== error
)
907 if (pduid
!= GETREQ
&& pduid
!= GETNEXTREQ
908 && pduid
!= GETBULKREQ
&& !error
)
912 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
914 if (pduid
== GETREQ
|| pduid
== GETNEXTREQ
915 || pduid
== GETBULKREQ
) {
916 if (elem
.type
!= BE_NULL
) {
917 fputs("[objVal!=NULL]", stdout
);
921 if (error
&& ind
== error
&& elem
.type
!= BE_NULL
)
922 fputs("[err objVal!=NULL]", stdout
);
923 if (!error
|| ind
== error
)
932 * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
933 * GetBulk, Inform, V2Trap, and Report
936 snmppdu_print(u_char pduid
, const u_char
*np
, u_int length
)
939 int count
= 0, error
;
941 /* reqId (Integer) */
942 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
944 if (elem
.type
!= BE_INT
) {
945 fputs("[reqId!=INT]", stdout
);
949 /* ignore the reqId */
953 /* errorStatus (Integer) */
954 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
956 if (elem
.type
!= BE_INT
) {
957 fputs("[errorStatus!=INT]", stdout
);
962 if ((pduid
== GETREQ
|| pduid
== GETNEXTREQ
|| pduid
== SETREQ
963 || pduid
== INFORMREQ
|| pduid
== V2TRAP
|| pduid
== REPORT
)
964 && elem
.data
.integer
!= 0) {
966 printf("[errorStatus(%s)!=0]",
967 DECODE_ErrorStatus(elem
.data
.integer
));
968 } else if (pduid
== GETBULKREQ
) {
969 printf(" N=%d", elem
.data
.integer
);
970 } else if (elem
.data
.integer
!= 0) {
972 printf(" %s", DECODE_ErrorStatus(elem
.data
.integer
));
973 error
= elem
.data
.integer
;
978 /* errorIndex (Integer) */
979 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
981 if (elem
.type
!= BE_INT
) {
982 fputs("[errorIndex!=INT]", stdout
);
986 if ((pduid
== GETREQ
|| pduid
== GETNEXTREQ
|| pduid
== SETREQ
987 || pduid
== INFORMREQ
|| pduid
== V2TRAP
|| pduid
== REPORT
)
988 && elem
.data
.integer
!= 0)
989 printf("[errorIndex(%d)!=0]", elem
.data
.integer
);
990 else if (pduid
== GETBULKREQ
)
991 printf(" M=%d", elem
.data
.integer
);
992 else if (elem
.data
.integer
!= 0) {
994 printf("[errorIndex(%d) w/o errorStatus]",
997 printf("@%d", elem
.data
.integer
);
998 error
= elem
.data
.integer
;
1001 fputs("[errorIndex==0]", stdout
);
1007 varbind_print(pduid
, np
, length
, error
);
1012 * Decode SNMP Trap PDU
1015 trappdu_print(const u_char
*np
, u_int length
)
1018 int count
= 0, generic
;
1022 /* enterprise (oid) */
1023 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1025 if (elem
.type
!= BE_OID
) {
1026 fputs("[enterprise!=OID]", stdout
);
1036 /* agent-addr (inetaddr) */
1037 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1039 if (elem
.type
!= BE_INETADDR
) {
1040 fputs("[agent-addr!=INETADDR]", stdout
);
1048 /* generic-trap (Integer) */
1049 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1051 if (elem
.type
!= BE_INT
) {
1052 fputs("[generic-trap!=INT]", stdout
);
1056 generic
= elem
.data
.integer
;
1059 printf(" %s", DECODE_GenericTrap(generic
));
1064 /* specific-trap (Integer) */
1065 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1067 if (elem
.type
!= BE_INT
) {
1068 fputs("[specific-trap!=INT]", stdout
);
1072 if (generic
!= GT_ENTERPRISE
) {
1073 if (elem
.data
.integer
!= 0)
1074 printf("[specific-trap(%d)!=0]", elem
.data
.integer
);
1076 printf(" s=%d", elem
.data
.integer
);
1082 /* time-stamp (TimeTicks) */
1083 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1085 if (elem
.type
!= BE_UNS
) { /* XXX */
1086 fputs("[time-stamp!=TIMETICKS]", stdout
);
1094 varbind_print (TRAP
, np
, length
, 0);
1099 * Decode arbitrary SNMP PDUs.
1102 pdu_print(const u_char
*np
, u_int length
, int version
)
1108 if ((count
= asn1_parse(np
, length
, &pdu
)) < 0)
1110 if (pdu
.type
!= BE_PDU
) {
1111 fputs("[no PDU]", stdout
);
1115 printf("[%d extra after PDU]", length
- count
);
1117 /* descend into PDU */
1118 length
= pdu
.asnlen
;
1119 np
= (u_char
*)pdu
.data
.raw
;
1121 if (version
== SNMP_VERSION_1
&&
1122 (pdu
.id
== GETBULKREQ
|| pdu
.id
== INFORMREQ
||
1123 pdu
.id
== V2TRAP
|| pdu
.id
== REPORT
)) {
1124 printf("[v2 PDU in v1 message]");
1128 if (version
== SNMP_VERSION_2
&& pdu
.id
== TRAP
) {
1129 printf("[v1 PDU in v2 message]");
1135 trappdu_print(np
, length
);
1145 snmppdu_print(pdu
.id
, np
, length
);
1151 * Decode a scoped SNMP PDU.
1154 scopedpdu_print(const u_char
*np
, u_int length
, int version
)
1160 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1162 if (elem
.type
!= BE_SEQ
) {
1163 fputs("[!scoped PDU]", stdout
);
1167 length
= elem
.asnlen
;
1168 np
= (u_char
*)elem
.data
.raw
;
1170 /* contextEngineID (OCTET STRING) */
1171 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1173 if (elem
.type
!= BE_STR
) {
1174 fputs("[contextEngineID!=STR]", stdout
);
1181 fputs("E= ", stdout
);
1182 for (i
= 0; i
< (int)elem
.asnlen
; i
++) {
1183 printf("0x%02X", elem
.data
.str
[i
]);
1187 /* contextName (OCTET STRING) */
1188 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1190 if (elem
.type
!= BE_STR
) {
1191 fputs("[contextName!=STR]", stdout
);
1198 printf("C=%.*s ", (int)elem
.asnlen
, elem
.data
.str
);
1200 pdu_print(np
, length
, version
);
1204 * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
1207 community_print(const u_char
*np
, u_int length
, int version
)
1212 /* Community (String) */
1213 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1215 if (elem
.type
!= BE_STR
) {
1216 fputs("[comm!=STR]", stdout
);
1220 /* default community */
1221 if (strncmp((char *)elem
.data
.str
, DEF_COMMUNITY
,
1222 sizeof(DEF_COMMUNITY
) - 1))
1224 printf("C=%.*s ", (int)elem
.asnlen
, elem
.data
.str
);
1228 pdu_print(np
, length
, version
);
1232 * Decode SNMPv3 User-based Security Message Header (SNMPv3)
1235 usm_print(const u_char
*np
, u_int length
)
1241 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1243 if (elem
.type
!= BE_SEQ
) {
1244 fputs("[!usm]", stdout
);
1248 length
= elem
.asnlen
;
1249 np
= (u_char
*)elem
.data
.raw
;
1251 /* msgAuthoritativeEngineID (OCTET STRING) */
1252 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1254 if (elem
.type
!= BE_STR
) {
1255 fputs("[msgAuthoritativeEngineID!=STR]", stdout
);
1262 /* msgAuthoritativeEngineBoots (INTEGER) */
1263 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1265 if (elem
.type
!= BE_INT
) {
1266 fputs("[msgAuthoritativeEngineBoots!=INT]", stdout
);
1271 printf("B=%d ", elem
.data
.integer
);
1275 /* msgAuthoritativeEngineTime (INTEGER) */
1276 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1278 if (elem
.type
!= BE_INT
) {
1279 fputs("[msgAuthoritativeEngineTime!=INT]", stdout
);
1284 printf("T=%d ", elem
.data
.integer
);
1288 /* msgUserName (OCTET STRING) */
1289 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1291 if (elem
.type
!= BE_STR
) {
1292 fputs("[msgUserName!=STR]", stdout
);
1299 printf("U=%.*s ", (int)elem
.asnlen
, elem
.data
.str
);
1301 /* msgAuthenticationParameters (OCTET STRING) */
1302 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1304 if (elem
.type
!= BE_STR
) {
1305 fputs("[msgAuthenticationParameters!=STR]", stdout
);
1312 /* msgPrivacyParameters (OCTET STRING) */
1313 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1315 if (elem
.type
!= BE_STR
) {
1316 fputs("[msgPrivacyParameters!=STR]", stdout
);
1324 printf("[%d extra after usm SEQ]", length
- count
);
1328 * Decode SNMPv3 Message Header (SNMPv3)
1331 v3msg_print(const u_char
*np
, u_int length
)
1337 const u_char
*xnp
= np
;
1338 int xlength
= length
;
1341 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1343 if (elem
.type
!= BE_SEQ
) {
1344 fputs("[!message]", stdout
);
1348 length
= elem
.asnlen
;
1349 np
= (u_char
*)elem
.data
.raw
;
1351 /* msgID (INTEGER) */
1352 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1354 if (elem
.type
!= BE_INT
) {
1355 fputs("[msgID!=INT]", stdout
);
1362 /* msgMaxSize (INTEGER) */
1363 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1365 if (elem
.type
!= BE_INT
) {
1366 fputs("[msgMaxSize!=INT]", stdout
);
1373 /* msgFlags (OCTET STRING) */
1374 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1376 if (elem
.type
!= BE_STR
) {
1377 fputs("[msgFlags!=STR]", stdout
);
1381 if (elem
.asnlen
!= 1) {
1382 printf("[msgFlags size %d]", elem
.asnlen
);
1385 flags
= elem
.data
.str
[0];
1386 if (flags
!= 0x00 && flags
!= 0x01 && flags
!= 0x03
1387 && flags
!= 0x04 && flags
!= 0x05 && flags
!= 0x07) {
1388 printf("[msgFlags=0x%02X]", flags
);
1394 fputs("F=", stdout
);
1395 if (flags
& 0x01) fputs("a", stdout
);
1396 if (flags
& 0x02) fputs("p", stdout
);
1397 if (flags
& 0x04) fputs("r", stdout
);
1400 /* msgSecurityModel (INTEGER) */
1401 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1403 if (elem
.type
!= BE_INT
) {
1404 fputs("[msgSecurityModel!=INT]", stdout
);
1408 model
= elem
.data
.integer
;
1413 printf("[%d extra after message SEQ]", length
- count
);
1417 fputs("USM ", stdout
);
1420 printf("[security model %d]", model
);
1424 np
= xnp
+ (np
- xnp
);
1425 length
= xlength
- (np
- xnp
);
1427 /* msgSecurityParameters (OCTET STRING) */
1428 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1430 if (elem
.type
!= BE_STR
) {
1431 fputs("[msgSecurityParameters!=STR]", stdout
);
1439 usm_print(elem
.data
.str
, elem
.asnlen
);
1443 fputs("ScopedPDU ", stdout
);
1446 scopedpdu_print(np
, length
, 3);
1450 * Decode SNMP header and pass on to PDU printing routines
1453 snmp_print(const u_char
*np
, u_int length
)
1461 /* truncated packet? */
1462 if (np
+ length
> snapend
) {
1464 length
= snapend
- np
;
1469 /* initial Sequence */
1470 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1472 if (elem
.type
!= BE_SEQ
) {
1473 fputs("[!init SEQ]", stdout
);
1478 printf("[%d extra after iSEQ]", length
- count
);
1480 length
= elem
.asnlen
;
1481 np
= (u_char
*)elem
.data
.raw
;
1483 /* Version (INTEGER) */
1484 if ((count
= asn1_parse(np
, length
, &elem
)) < 0)
1486 if (elem
.type
!= BE_INT
) {
1487 fputs("[version!=INT]", stdout
);
1492 switch (elem
.data
.integer
) {
1493 case SNMP_VERSION_1
:
1494 case SNMP_VERSION_2
:
1495 case SNMP_VERSION_3
:
1497 printf("%s ", SnmpVersion
[elem
.data
.integer
]);
1500 printf("[version = %d]", elem
.data
.integer
);
1503 version
= elem
.data
.integer
;
1508 case SNMP_VERSION_1
:
1509 case SNMP_VERSION_2
:
1510 community_print(np
, length
, version
);
1512 case SNMP_VERSION_3
:
1513 v3msg_print(np
, length
);
1516 printf("[version = %d]", elem
.data
.integer
);