Bug Summary

File:src/usr.sbin/tcpdump/print-snmp.c
Warning:line 640, column 2
Value stored to 'p' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name print-snmp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/tcpdump/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/tcpdump/../../sbin/pfctl -I /usr/src/usr.sbin/tcpdump/../hostapd -I /usr/src/usr.sbin/tcpdump/../../lib/libpcap -D CSLIP -D PPP -D HAVE_FDDI -D ETHER_SERVICE -D HAVE_ETHER_NTOHOST -D INET6 -I /usr/src/usr.sbin/tcpdump/../../sbin/pfctl -D FAKE_PF_KERNEL -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/tcpdump/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/tcpdump/print-snmp.c
1/* $OpenBSD: print-snmp.c,v 1.28 2021/10/23 10:47:50 martijn Exp $ */
2
3/*
4 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
5 * John Robert LoVerso. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 *
30 * This implementation has been influenced by the CMU SNMP release,
31 * by Steve Waldbusser. However, this shares no code with that system.
32 * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
33 * Earlier forms of this implementation were derived and/or inspired by an
34 * awk script originally written by C. Philip Wood of LANL (but later
35 * heavily modified by John Robert LoVerso). The copyright notice for
36 * that work is preserved below, even though it may not rightly apply
37 * to this file.
38 *
39 * This started out as a very simple program, but the incremental decoding
40 * (into the BE structure) complicated things.
41 *
42 # Los Alamos National Laboratory
43 #
44 # Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
45 # This software was produced under a U.S. Government contract
46 # (W-7405-ENG-36) by Los Alamos National Laboratory, which is
47 # operated by the University of California for the U.S. Department
48 # of Energy. The U.S. Government is licensed to use, reproduce,
49 # and distribute this software. Permission is granted to the
50 # public to copy and use this software without charge, provided
51 # that this Notice and any statement of authorship are reproduced
52 # on all copies. Neither the Government nor the University makes
53 # any warranty, express or implied, or assumes any liability or
54 # responsibility for the use of this software.
55 # @(#)snmp.awk.x 1.1 (LANL) 1/15/90
56 */
57
58#include <sys/time.h>
59
60#include <ctype.h>
61#include <stdio.h>
62#include <string.h>
63
64#include "interface.h"
65#include "addrtoname.h"
66
67/*
68 * Universal ASN.1 types
69 * (we only care about the tag values for those allowed in the Internet SMI)
70 */
71char *Universal[] = {
72 "U-0",
73 "Boolean",
74 "Integer",
75#define INTEGER2 2
76 "Bitstring",
77 "String",
78#define STRING4 4
79 "Null",
80#define ASN_NULL5 5
81 "ObjID",
82#define OBJECTID6 6
83 "ObjectDes",
84 "U-8","U-9","U-10","U-11", /* 8-11 */
85 "U-12","U-13","U-14","U-15", /* 12-15 */
86 "Sequence",
87#define SEQUENCE16 16
88 "Set"
89};
90
91/*
92 * Application-wide ASN.1 types from the Internet SMI and their tags
93 */
94char *Application[] = {
95 "IpAddress",
96#define IPADDR0 0
97 "Counter",
98#define COUNTER1 1
99 "Gauge",
100#define GAUGE2 2
101 "TimeTicks",
102#define TIMETICKS3 3
103 "Opaque",
104#define OPAQUE4 4
105 "NsapAddress",
106#define NSAPADDR5 5
107 "Counter64",
108#define COUNTER646 6
109 "UInteger32" /* Defined in RFC1442, removed since RFC1902 */
110#define UINTEGER327 7
111};
112
113/*
114 * Context-specific ASN.1 types for the SNMP PDUs and their tags
115 */
116char *Context[] = {
117 "GetRequest",
118#define GETREQ0 0
119 "GetNextRequest",
120#define GETNEXTREQ1 1
121 "GetResponse",
122#define GETRESP2 2
123 "SetRequest",
124#define SETREQ3 3
125 "Trap",
126#define TRAP4 4
127 "GetBulkReq",
128#define GETBULKREQ5 5
129 "InformReq",
130#define INFORMREQ6 6
131 "TrapV2",
132#define TRAPV27 7
133 "Report"
134#define REPORT8 8
135};
136
137char *ContextVarbind[] = {
138 "noSuchObject",
139#define NOSUCHOBJECT0 0
140 "noSuchInstance",
141#define NOSUCHINSTANCE1 1
142 "endOfMibView"
143#define ENDOFMIBVIEW2 2
144};
145
146/*
147 * Private ASN.1 types
148 * The Internet SMI does not specify any
149 */
150char *Private[] = {
151 "P-0"
152};
153
154/*
155 * error-status values for any SNMP PDU
156 */
157char *ErrorStatus[] = {
158 "noError",
159 "tooBig",
160 "noSuchName",
161 "badValue",
162 "readOnly",
163 "genErr",
164 "noAccess",
165 "wrongType",
166 "wrongLength",
167 "wrongEnc",
168 "wrongValue",
169 "noCreation",
170 "inconValue",
171 "resUnavail",
172 "commitFailed",
173 "undoFailed",
174 "authError",
175 "notWritable",
176 "inconName"
177};
178#define DECODE_ErrorStatus(e)( e >= 0 && e <= sizeof(ErrorStatus)/sizeof(ErrorStatus
[0]) ? ErrorStatus[e] : (snprintf(errbuf, sizeof(errbuf), "err=%u"
, e), errbuf))
\
179 ( e >= 0 && e <= sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
180 ? ErrorStatus[e] : (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf))
181
182/*
183 * generic-trap values in the SNMP Trap-PDU
184 */
185char *GenericTrap[] = {
186 "coldStart",
187 "warmStart",
188 "linkDown",
189 "linkUp",
190 "authenticationFailure",
191 "egpNeighborLoss",
192 "enterpriseSpecific"
193#define GT_ENTERPRISE6 6
194};
195#define DECODE_GenericTrap(t)( t >= 0 && t < sizeof(GenericTrap)/sizeof(GenericTrap
[0]) ? GenericTrap[t] : (snprintf(buf, sizeof(buf), "gt=%d", t
), buf))
\
196 ( t >= 0 && t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
197 ? GenericTrap[t] : (snprintf(buf, sizeof(buf), "gt=%d", t), buf))
198
199/*
200 * ASN.1 type class table
201 * Ties together the preceding Universal, Application, Context, and Private
202 * type definitions.
203 */
204#define defineCLASS(x){ "x", x, sizeof(x)/sizeof(x[0]) } { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
205struct {
206 char *name;
207 char **Id;
208 int numIDs;
209 } Class[] = {
210 defineCLASS(Universal){ "x", Universal, sizeof(Universal)/sizeof(Universal[0]) },
211#define UNIVERSAL0 0
212 defineCLASS(Application){ "x", Application, sizeof(Application)/sizeof(Application[0]
) }
,
213#define APPLICATION1 1
214 defineCLASS(Context){ "x", Context, sizeof(Context)/sizeof(Context[0]) },
215#define CONTEXT2 2
216 defineCLASS(Private){ "x", Private, sizeof(Private)/sizeof(Private[0]) },
217#define PRIVATE3 3
218};
219
220/*
221 * defined forms for ASN.1 types
222 */
223char *Form[] = {
224 "Primitive",
225#define PRIMITIVE0 0
226 "Constructed",
227#define CONSTRUCTED1 1
228};
229
230/*
231 * A structure for the OID tree for the compiled-in MIB.
232 * This is stored as a general-order tree.
233 */
234struct obj {
235 char *desc; /* name of object */
236 u_int oid; /* sub-id following parent */
237 u_char type; /* object type (unused) */
238 struct obj *child, *next; /* child and next sibling pointers */
239} *objp = NULL((void *)0);
240
241/*
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'.
245 *
246 * In particular, this is gross, as this is including initialized structures,
247 * and by right shouldn't be an "include" file.
248 */
249#include "mib.h"
250
251/*
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.
255 */
256struct obj_abrev {
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[] = {
261#ifndef NO_ABREV_MIB
262 /* .iso.org.dod.internet.mgmt.mib */
263 { "", &_mib_obj, "\53\6\1\2\1" },
264#endif
265#ifndef NO_ABREV_ENTER
266 /* .iso.org.dod.internet.private.enterprises */
267 { "E:", &_enterprises_obj, "\53\6\1\4\1" },
268#endif
269#ifndef NO_ABREV_EXPERI
270 /* .iso.org.dod.internet.experimental */
271 { "X:", &_experimental_obj, "\53\6\1\3" },
272#endif
273#ifndef NO_ABREV_SNMPMIBOBJECTS
274 /* .iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects */
275 { "S:", &_snmpmibobjects_obj, "\53\6\1\6\3\1\1" },
276#endif
277 { 0,0,0 }
278};
279
280/*
281 * This is used in the OID print routine to walk down the object tree
282 * rooted at `mibroot'.
283 */
284#define OBJ_PRINT(o, suppressdot){ if (objp) { do { if ((o) == objp->oid) break; } while ((
objp = objp->next) != ((void *)0)); } if (objp) { printf(suppressdot
?"%s":".%s", objp->desc); objp = objp->child; } else printf
(suppressdot?"%u":".%u", (o)); }
\
285{ \
286 if (objp) { \
287 do { \
288 if ((o) == objp->oid) \
289 break; \
290 } while ((objp = objp->next) != NULL((void *)0)); \
291 } \
292 if (objp) { \
293 printf(suppressdot?"%s":".%s", objp->desc); \
294 objp = objp->child; \
295 } else \
296 printf(suppressdot?"%u":".%u", (o)); \
297}
298
299/*
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.
302 */
303struct be {
304 u_int32_t asnlen;
305 union {
306 caddr_t raw;
307 int32_t integer;
308 u_int32_t uns;
309 u_int64_t uns64;
310 const u_char *str;
311 } data;
312 u_short id;
313 u_char form, class; /* tag info */
314 u_char type;
315#define BE_ANY255 255
316#define BE_NONE0 0
317#define BE_NULL1 1
318#define BE_OCTET2 2
319#define BE_OID3 3
320#define BE_INT4 4
321#define BE_UNS5 5
322#define BE_STR6 6
323#define BE_SEQ7 7
324#define BE_INETADDR8 8
325#define BE_PDU9 9
326#define BE_UNS6410 10
327#define BE_VB11 11
328};
329
330
331/*
332 * SNMP components
333 */
334static int snmp3_print_usmparams(const u_char *, u_int);
335
336enum snmp_version {
337 SNMP_V1 = 0,
338 SNMP_V2C = 1,
339 SNMP_V3 = 3
340};
341#define SNMP3_AUTH(f)(f & 0x01) (f & 0x01)
342#define SNMP3_PRIV(f)(f & 0x02) (f & 0x02)
343#define SNMP3_REPORT(f)(f & 0x04) (f & 0x04)
344
345struct snmp3_sm {
346 int id;
347 char *name;
348 int (*parse_params)(const u_char *, u_int);
349} snmp3_securitymodel[] = {
350 {3, "USM", snmp3_print_usmparams},
351 {0, NULL((void *)0), NULL((void *)0)}
352};
353
354/*
355 * constants for ASN.1 decoding
356 */
357#define OIDMUX40 40
358#define ASNLEN_INETADDR4 4
359#define ASN_SHIFT77 7
360#define ASN_SHIFT88 8
361#define ASN_BIT80x80 0x80
362#define ASN_LONGLEN0x80 0x80
363
364#define ASN_ID_BITS0x1f 0x1f
365#define ASN_FORM_BITS0x20 0x20
366#define ASN_FORM_SHIFT5 5
367#define ASN_CLASS_BITS0xc0 0xc0
368#define ASN_CLASS_SHIFT6 6
369
370#define ASN_ID_EXT0x1f 0x1f /* extension ID in tag field */
371
372/*
373 * truncated==1 means the packet was complete, but we don't have all of
374 * it to decode.
375 */
376static int truncated;
377
378/*
379 * This decodes the next ASN.1 object in the stream pointed to by "p"
380 * (and of real-length "len") and stores the intermediate data in the
381 * provided BE object.
382 *
383 * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
384 * O/w, this returns the number of bytes parsed from "p".
385 */
386static int
387asn1_parse(const u_char *p, u_int len, struct be *elem)
388{
389 u_char form, class, id;
390 int i, hdr;
391
392 elem->asnlen = 0;
393 elem->type = BE_ANY255;
394 if (len < 1) {
395 if (truncated)
396 printf("[|snmp]");
397 else
398 printf("[nothing to parse]");
399 return -1;
400 }
401
402 /*
403 * it would be nice to use a bit field, but you can't depend on them.
404 * +---+---+---+---+---+---+---+---+
405 * + class |frm| id |
406 * +---+---+---+---+---+---+---+---+
407 * 7 6 5 4 3 2 1 0
408 */
409 id = *p & ASN_ID_BITS0x1f; /* lower 5 bits, range 00-1f */
410#ifdef notdef
411 form = (*p & 0xe0) >> 5; /* move upper 3 bits to lower 3 */
412 class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
413 form &= 0x1; /* bit 5 -> bit 0, range 0-1 */
414#else
415 form = (u_char)(*p & ASN_FORM_BITS0x20) >> ASN_FORM_SHIFT5;
416 class = (u_char)(*p & ASN_CLASS_BITS0xc0) >> ASN_CLASS_SHIFT6;
417#endif
418 elem->form = form;
419 elem->class = class;
420 elem->id = id;
421 if (vflag > 1)
422 printf("|%.2x", *p);
423 p++; len--; hdr = 1;
424 /* extended tag field */
425 if (id == ASN_ID_EXT0x1f) {
426 for (id = 0; *p & ASN_BIT80x80 && len > 0; len--, hdr++, p++) {
427 if (vflag > 1)
428 printf("|%.2x", *p);
429 id = (id << 7) | (*p & ~ASN_BIT80x80);
430 }
431 if (len == 0 && *p & ASN_BIT80x80) {
432 if (truncated)
433 printf("[|snmp]");
434 else
435 printf("[Xtagfield?]");
436 return -1;
437 }
438 elem->id = id = (id << 7) | *p;
439 --len;
440 ++hdr;
441 ++p;
442 }
443 if (len < 1) {
444 if (truncated)
445 printf("[|snmp]");
446 else
447 printf("[no asnlen]");
448 return -1;
449 }
450 elem->asnlen = *p;
451 if (vflag > 1)
452 printf("|%.2x", *p);
453 p++; len--; hdr++;
454 if (elem->asnlen & ASN_BIT80x80) {
455 int noct = elem->asnlen % ASN_BIT80x80;
456 elem->asnlen = 0;
457 if (len < noct) {
458 if (truncated)
459 printf("[|snmp]");
460 else
461 printf("[asnlen? %d<%d]", len, noct);
462 return -1;
463 }
464 for (; noct-- > 0; len--, hdr++) {
465 if (vflag > 1)
466 printf("|%.2x", *p);
467 elem->asnlen = (elem->asnlen << ASN_SHIFT88) | *p++;
468 }
469 }
470 if (len < elem->asnlen) {
471 if (!truncated) {
472 printf("[len%d<asnlen%u]", len, elem->asnlen);
473 return -1;
474 }
475 /* maybe should check at least 4? */
476 elem->asnlen = len;
477 }
478 if (form >= sizeof(Form)/sizeof(Form[0])) {
479 if (truncated)
480 printf("[|snmp]");
481 else
482 printf("[form?%d]", form);
483 return -1;
484 }
485 if (class >= sizeof(Class)/sizeof(Class[0])) {
486 if (truncated)
487 printf("[|snmp]");
488 else
489 printf("[class?%c/%d]", *Form[form], class);
490 return -1;
491 }
492 if ((int)id >= Class[class].numIDs) {
493 if (truncated)
494 printf("[|snmp]");
495 else
496 printf("[id?%c/%s/%d]", *Form[form],
497 Class[class].name, id);
498 return -1;
499 }
500
501 switch (form) {
502 case PRIMITIVE0:
503 switch (class) {
504 case UNIVERSAL0:
505 switch (id) {
506 case STRING4:
507 elem->type = BE_STR6;
508 elem->data.str = p;
509 break;
510
511 case INTEGER2: {
512 int32_t data;
513 elem->type = BE_INT4;
514 data = 0;
515
516 if (*p & ASN_BIT80x80) /* negative */
517 data = -1;
518 for (i = elem->asnlen; i-- > 0; p++)
519 data = (data << ASN_SHIFT88) | *p;
520 elem->data.integer = data;
521 break;
522 }
523
524 case OBJECTID6:
525 elem->type = BE_OID3;
526 elem->data.raw = (caddr_t)p;
527 break;
528
529 case ASN_NULL5:
530 elem->type = BE_NULL1;
531 elem->data.raw = NULL((void *)0);
532 break;
533
534 default:
535 elem->type = BE_OCTET2;
536 elem->data.raw = (caddr_t)p;
537 printf("[P/U/%s]",
538 Class[class].Id[id]);
539 break;
540 }
541 break;
542
543 case APPLICATION1:
544 switch (id) {
545 case IPADDR0:
546 elem->type = BE_INETADDR8;
547 elem->data.raw = (caddr_t)p;
548 break;
549
550 case COUNTER1:
551 case GAUGE2:
552 case TIMETICKS3:
553 case OPAQUE4:
554 case NSAPADDR5:
555 case UINTEGER327: {
556 u_int32_t data;
557 elem->type = BE_UNS5;
558 data = 0;
559 for (i = elem->asnlen; i-- > 0; p++)
560 data = (data << 8) + *p;
561 elem->data.uns = data;
562 break;
563 }
564
565 case COUNTER646: {
566 u_int64_t data;
567 elem->type = BE_UNS6410;
568 data = 0;
569 for (i = elem->asnlen; i-- > 0; p++)
570 data = (data << 8) + *p;
571 elem->data.uns64 = data;
572 break;
573 }
574
575 default:
576 elem->type = BE_OCTET2;
577 elem->data.raw = (caddr_t)p;
578 printf("[P/A/%s]",
579 Class[class].Id[id]);
580 break;
581 }
582 break;
583
584 case CONTEXT2:
585 switch (id) {
586 case NOSUCHOBJECT0:
587 case NOSUCHINSTANCE1:
588 case ENDOFMIBVIEW2:
589 elem->type = BE_VB11;
590 elem->data.raw = NULL((void *)0);
591 break;
592 default:
593 elem->type = BE_OCTET2;
594 elem->data.raw = (caddr_t)p;
595 printf("[P/C/%d]", id);
596 break;
597 }
598 break;
599
600 default:
601 elem->type = BE_OCTET2;
602 elem->data.raw = (caddr_t)p;
603 printf("[P/%s/%s]",
604 Class[class].name, Class[class].Id[id]);
605 break;
606 }
607 break;
608
609 case CONSTRUCTED1:
610 switch (class) {
611 case UNIVERSAL0:
612 switch (id) {
613 case SEQUENCE16:
614 elem->type = BE_SEQ7;
615 elem->data.raw = (caddr_t)p;
616 break;
617
618 default:
619 elem->type = BE_OCTET2;
620 elem->data.raw = (caddr_t)p;
621 printf("C/U/%s", Class[class].Id[id]);
622 break;
623 }
624 break;
625
626 case CONTEXT2:
627 elem->type = BE_PDU9;
628 elem->data.raw = (caddr_t)p;
629 break;
630
631 default:
632 elem->type = BE_OCTET2;
633 elem->data.raw = (caddr_t)p;
634 printf("C/%s/%s",
635 Class[class].name, Class[class].Id[id]);
636 break;
637 }
638 break;
639 }
640 p += elem->asnlen;
Value stored to 'p' is never read
641 len -= elem->asnlen;
642 return elem->asnlen + hdr;
643}
644
645/*
646 * Display the ASN.1 object represented by the BE object.
647 * This used to be an integral part of asn1_parse() before the intermediate
648 * BE form was added.
649 */
650static void
651asn1_print(struct be *elem)
652{
653 u_char *p = (u_char *)elem->data.raw;
654 u_int32_t asnlen = elem->asnlen;
655 int i;
656
657 switch (elem->type) {
658 case BE_OCTET2:
659 for (i = asnlen; i-- > 0; p++)
660 printf("_%.2x", *p);
661 break;
662 case BE_NULL1:
663 break;
664 case BE_OID3: {
665 int o = 0, first = -1, i = asnlen;
666
667 if (!nflag && asnlen > 2) {
668 struct obj_abrev *a = &obj_abrev_list[0];
669 for (; a->node; a++) {
670 if (!memcmp(a->oid, (char *)p,
671 strlen(a->oid))) {
672 objp = a->node->child;
673 i -= strlen(a->oid);
674 p += strlen(a->oid);
675 printf("%s", a->prefix);
676 first = 1;
677 break;
678 }
679 }
680 }
681 for (; i-- > 0; p++) {
682 o = (o << ASN_SHIFT77) + (*p & ~ASN_BIT80x80);
683 if (*p & ASN_LONGLEN0x80)
684 continue;
685
686 /*
687 * first subitem encodes two items with 1st*OIDMUX+2nd
688 */
689 if (first < 0) {
690 if (!nflag)
691 objp = mibroot;
692 first = 0;
693 OBJ_PRINT(o/OIDMUX, first){ if (objp) { do { if ((o/40) == objp->oid) break; } while
((objp = objp->next) != ((void *)0)); } if (objp) { printf
(first?"%s":".%s", objp->desc); objp = objp->child; } else
printf(first?"%u":".%u", (o/40)); }
;
694 o %= OIDMUX40;
695 }
696 OBJ_PRINT(o, first){ if (objp) { do { if ((o) == objp->oid) break; } while ((
objp = objp->next) != ((void *)0)); } if (objp) { printf(first
?"%s":".%s", objp->desc); objp = objp->child; } else printf
(first?"%u":".%u", (o)); }
;
697 if (--first < 0)
698 first = 0;
699 o = 0;
700 }
701 break;
702 }
703 case BE_INT4:
704 printf("%d", elem->data.integer);
705 break;
706 case BE_UNS5:
707 printf("%d", elem->data.uns);
708 break;
709 case BE_UNS6410:
710 printf("%lld", elem->data.uns64);
711 break;
712 case BE_STR6: {
713 int printable = 1, first = 1;
714 const u_char *p = elem->data.str;
715 for (i = asnlen; printable && i-- > 0; p++)
716 printable = isprint(*p) || isspace(*p);
717 p = elem->data.str;
718 if (printable) {
719 putchar('"')(!__isthreaded ? __sputc('"', (&__sF[1])) : (putc)('"', (
&__sF[1])))
;
720 (void)fn_print(p, p + asnlen);
721 putchar('"')(!__isthreaded ? __sputc('"', (&__sF[1])) : (putc)('"', (
&__sF[1])))
;
722 } else
723 for (i = asnlen; i-- > 0; p++) {
724 printf(first ? "%.2x" : "_%.2x", *p);
725 first = 0;
726 }
727 break;
728 }
729 case BE_SEQ7:
730 printf("Seq(%u)", elem->asnlen);
731 break;
732 case BE_INETADDR8: {
733 char sep;
734 if (asnlen != ASNLEN_INETADDR4)
735 printf("[inetaddr len!=%d]", ASNLEN_INETADDR4);
736 sep='[';
737 for (i = asnlen; i-- > 0; p++) {
738 printf("%c%u", sep, *p);
739 sep='.';
740 }
741 putchar(']')(!__isthreaded ? __sputc(']', (&__sF[1])) : (putc)(']', (
&__sF[1])))
;
742 break;
743 }
744 case BE_PDU9:
745 printf("%s(%u)",
746 Class[CONTEXT2].Id[elem->id], elem->asnlen);
747 break;
748 case BE_VB11:
749 if (elem->id > sizeof(ContextVarbind)/sizeof(ContextVarbind[0]))
750 break;
751 printf("%s", ContextVarbind[elem->id]);
752 break;
753 case BE_ANY255:
754 printf("[BE_ANY!?]");
755 break;
756 default:
757 printf("[be!?]");
758 break;
759 }
760}
761
762#ifdef notdef
763/*
764 * This is a brute force ASN.1 printer: recurses to dump an entire structure.
765 * This will work for any ASN.1 stream, not just an SNMP PDU.
766 *
767 * By adding newlines and spaces at the correct places, this would print in
768 * Rose-Normal-Form.
769 *
770 * This is not currently used.
771 */
772static void
773asn1_decode(u_char *p, u_int length)
774{
775 struct be elem;
776 int i = 0;
777
778 while (i >= 0 && length > 0) {
779 i = asn1_parse(p, length, &elem);
780 if (i >= 0) {
781 printf(" ");
782 asn1_print(&elem);
783 if (elem.type == BE_SEQ7 || elem.type == BE_PDU9) {
784 printf(" {");
785 asn1_decode(elem.data.raw, elem.asnlen);
786 printf(" }");
787 }
788 length -= i;
789 p += i;
790 }
791 }
792}
793#endif
794
795/*
796 * General SNMP header
797 * SEQUENCE {
798 * version INTEGER {version-1(0)},
799 * community OCTET STRING,
800 * data ANY -- PDUs
801 * }
802 * PDUs for all but Trap: (see rfc1157 from page 15 on)
803 * SEQUENCE {
804 * request-id INTEGER,
805 * error-status INTEGER,
806 * error-index INTEGER,
807 * varbindlist SEQUENCE OF
808 * SEQUENCE {
809 * name ObjectName,
810 * value ObjectValue
811 * }
812 * }
813 * PDU for Trap:
814 * SEQUENCE {
815 * enterprise OBJECT IDENTIFIER,
816 * agent-addr NetworkAddress,
817 * generic-trap INTEGER,
818 * specific-trap INTEGER,
819 * time-stamp TimeTicks,
820 * varbindlist SEQUENCE OF
821 * SEQUENCE {
822 * name ObjectName,
823 * value ObjectValue
824 * }
825 * }
826 */
827
828/*
829 * Decode SNMP varBind
830 */
831static void
832varbind_print(u_char pduid, const u_char *np, u_int length, int error)
833{
834 struct be elem;
835 int count = 0, ind;
836
837 /* Sequence of varBind */
838 if ((count = asn1_parse(np, length, &elem)) < 0)
839 return;
840 if (elem.type != BE_SEQ7) {
841 printf("[!SEQ of varbind]");
842 asn1_print(&elem);
843 return;
844 }
845 if (count < length)
846 printf("[%d extra after SEQ of varbind]", length - count);
847 /* descend */
848 length = elem.asnlen;
849 np = (u_char *)elem.data.raw;
850
851 for (ind = 1; length > 0; ind++) {
852 const u_char *vbend;
853 u_int vblength;
854
855 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
856 /* Sequence */
857 if ((count = asn1_parse(np, length, &elem)) < 0)
858 return;
859 if (elem.type != BE_SEQ7) {
860 printf("[!varbind]");
861 asn1_print(&elem);
862 return;
863 }
864 vbend = np + count;
865 vblength = length - count;
866 /* descend */
867 length = elem.asnlen;
868 np = (u_char *)elem.data.raw;
869
870 /* objName (OID) */
871 if ((count = asn1_parse(np, length, &elem)) < 0)
872 return;
873 if (elem.type != BE_OID3) {
874 printf("[objName!=OID]");
875 asn1_print(&elem);
876 return;
877 }
878 if (!error || ind == error)
879 asn1_print(&elem);
880 length -= count;
881 np += count;
882
883 if (pduid != GETREQ0 && pduid != GETNEXTREQ1 && !error)
884 printf("=");
885
886 /* objVal (ANY) */
887 if ((count = asn1_parse(np, length, &elem)) < 0)
888 return;
889 if (pduid == GETREQ0 || pduid == GETNEXTREQ1 || pduid == GETBULKREQ5) {
890 if (elem.type != BE_NULL1) {
891 printf("[objVal!=NULL]");
892 asn1_print(&elem);
893 }
894 } else {
895 if (error && ind == error && elem.type != BE_NULL1)
896 printf("[err objVal!=NULL]");
897 if (!error || ind == error)
898 asn1_print(&elem);
899 }
900
901 length = vblength;
902 np = vbend;
903 }
904}
905
906/*
907 * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest
908 */
909static void
910snmppdu_print(u_char pduid, const u_char *np, u_int length)
911{
912 struct be elem;
913 int count = 0, error;
914
915 /* reqId (Integer) */
916 if ((count = asn1_parse(np, length, &elem)) < 0)
917 return;
918 if (elem.type != BE_INT4) {
919 printf("[reqId!=INT]");
920 asn1_print(&elem);
921 return;
922 }
923 if (vflag)
924 printf(" reqId=%d", elem.data.integer);
925 length -= count;
926 np += count;
927
928 /* errorStatus (Integer) */
929 if ((count = asn1_parse(np, length, &elem)) < 0)
930 return;
931 if (elem.type != BE_INT4) {
932 printf("[errorStatus!=INT]");
933 asn1_print(&elem);
934 return;
935 }
936 error = 0;
937 if ((pduid == GETREQ0 || pduid == GETNEXTREQ1)
938 && elem.data.integer != 0) {
939 char errbuf[20];
940 printf("[errorStatus(%s)!=0]",
941 DECODE_ErrorStatus(elem.data.integer)( elem.data.integer >= 0 && elem.data.integer <=
sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) ? ErrorStatus[elem
.data.integer] : (snprintf(errbuf, sizeof(errbuf), "err=%u", elem
.data.integer), errbuf))
);
942 } else if (pduid == GETBULKREQ5)
943 printf(" non-repeaters=%d", elem.data.integer);
944 else if (elem.data.integer != 0) {
945 char errbuf[20];
946 printf(" %s", DECODE_ErrorStatus(elem.data.integer)( elem.data.integer >= 0 && elem.data.integer <=
sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) ? ErrorStatus[elem
.data.integer] : (snprintf(errbuf, sizeof(errbuf), "err=%u", elem
.data.integer), errbuf))
);
947 error = elem.data.integer;
948 }
949 length -= count;
950 np += count;
951
952 /* errorIndex (Integer) */
953 if ((count = asn1_parse(np, length, &elem)) < 0)
954 return;
955 if (elem.type != BE_INT4) {
956 printf("[errorIndex!=INT]");
957 asn1_print(&elem);
958 return;
959 }
960 if ((pduid == GETREQ0 || pduid == GETNEXTREQ1)
961 && elem.data.integer != 0)
962 printf("[errorIndex(%d)!=0]", elem.data.integer);
963 else if (pduid == GETBULKREQ5)
964 printf(" max-repetitions=%d", elem.data.integer);
965 else if (elem.data.integer != 0) {
966 if (!error)
967 printf("[errorIndex(%d) w/o errorStatus]",
968 elem.data.integer);
969 else {
970 printf("@%d", elem.data.integer);
971 error = elem.data.integer;
972 }
973 } else if (error) {
974 printf("[errorIndex==0]");
975 error = 0;
976 }
977 length -= count;
978 np += count;
979
980 varbind_print(pduid, np, length, error);
981 return;
982}
983
984/*
985 * Decode SNMP Trap PDU
986 */
987static void
988trap_print(const u_char *np, u_int length)
989{
990 struct be elem;
991 int count = 0, generic;
992
993 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
994
995 /* enterprise (oid) */
996 if ((count = asn1_parse(np, length, &elem)) < 0)
997 return;
998 if (elem.type != BE_OID3) {
999 printf("[enterprise!=OID]");
1000 asn1_print(&elem);
1001 return;
1002 }
1003 asn1_print(&elem);
1004 length -= count;
1005 np += count;
1006
1007 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
1008
1009 /* agent-addr (inetaddr) */
1010 if ((count = asn1_parse(np, length, &elem)) < 0)
1011 return;
1012 if (elem.type != BE_INETADDR8) {
1013 printf("[agent-addr!=INETADDR]");
1014 asn1_print(&elem);
1015 return;
1016 }
1017 asn1_print(&elem);
1018 length -= count;
1019 np += count;
1020
1021 /* generic-trap (Integer) */
1022 if ((count = asn1_parse(np, length, &elem)) < 0)
1023 return;
1024 if (elem.type != BE_INT4) {
1025 printf("[generic-trap!=INT]");
1026 asn1_print(&elem);
1027 return;
1028 }
1029 generic = elem.data.integer;
1030 {
1031 char buf[20];
1032 printf(" %s", DECODE_GenericTrap(generic)( generic >= 0 && generic < sizeof(GenericTrap)
/sizeof(GenericTrap[0]) ? GenericTrap[generic] : (snprintf(buf
, sizeof(buf), "gt=%d", generic), buf))
);
1033 }
1034 length -= count;
1035 np += count;
1036
1037 /* specific-trap (Integer) */
1038 if ((count = asn1_parse(np, length, &elem)) < 0)
1039 return;
1040 if (elem.type != BE_INT4) {
1041 printf("[specific-trap!=INT]");
1042 asn1_print(&elem);
1043 return;
1044 }
1045 if (generic != GT_ENTERPRISE6) {
1046 if (elem.data.integer != 0)
1047 printf("[specific-trap(%d)!=0]", elem.data.integer);
1048 } else
1049 printf(" s=%d", elem.data.integer);
1050 length -= count;
1051 np += count;
1052
1053 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
1054
1055 /* time-stamp (TimeTicks) */
1056 if ((count = asn1_parse(np, length, &elem)) < 0)
1057 return;
1058 if (elem.type != BE_UNS5) { /* XXX */
1059 printf("[time-stamp!=TIMETICKS]");
1060 asn1_print(&elem);
1061 return;
1062 }
1063 asn1_print(&elem);
1064 length -= count;
1065 np += count;
1066
1067 varbind_print (TRAP4, np, length, 0);
1068 return;
1069}
1070
1071/*
1072 * Decode SNMP header and pass on to PDU printing routines
1073 */
1074static void
1075snmp12_print(const u_char *np, u_int length)
1076{
1077 struct be elem;
1078 int count;
1079
1080 /* Community (String) */
1081 if ((count = asn1_parse(np, length, &elem)) < 0)
1082 return;
1083 if (elem.type != BE_STR6) {
1084 printf("[comm!=STR]");
1085 asn1_print(&elem);
1086 return;
1087 }
1088 printf("C=%.*s ", (int)elem.asnlen, elem.data.str);
1089 length -= count;
1090 np += count;
1091
1092 /* PDU (Context) */
1093 if ((count = asn1_parse(np, length, &elem)) < 0)
1094 return;
1095 if (elem.type != BE_PDU9) {
1096 printf("[no PDU]");
1097 return;
1098 }
1099 if (count < length)
1100 printf("[%d extra after PDU]", length - count);
1101 asn1_print(&elem);
1102 /* descend into PDU */
1103 length = elem.asnlen;
1104 np = (u_char *)elem.data.raw;
1105
1106 switch (elem.id) {
1107 case TRAP4:
1108 trap_print(np, length);
1109 break;
1110 case GETREQ0:
1111 case GETNEXTREQ1:
1112 case GETRESP2:
1113 case SETREQ3:
1114 case GETBULKREQ5:
1115 case INFORMREQ6:
1116 case TRAPV27:
1117 case REPORT8:
1118 snmppdu_print(elem.id, np, length);
1119 break;
1120 }
1121 return;
1122}
1123
1124static int
1125snmp3_print_usmparams(const u_char *np, u_int length)
1126{
1127 struct be elem;
1128 int count;
1129 int i;
1130
1131 if ((count = asn1_parse(np, length, &elem)) < 0)
1132 return -1;
1133 if (elem.type != BE_SEQ7) {
1134 printf("[!usmSM SEQ]");
1135 asn1_print(&elem);
1136 return -1;
1137 }
1138 if (count < length) {
1139 printf("[%d extra after usmSM]", length - count);
1140 return -1;
1141 }
1142 /* descend */
1143 length = elem.asnlen;
1144 np = (u_char *)elem.data.raw;
1145
1146 /* msgAuthoritativeEngineID */
1147 if ((count = asn1_parse(np, length, &elem)) < 0)
1148 return -1;
1149 if (elem.type != BE_STR6) {
1150 printf("[umsEID!=STR]");
1151 asn1_print(&elem);
1152 return -1;
1153 }
1154 if (vflag && elem.asnlen > 0) {
1155 printf("umsEID=0x");
1156 for (i = 0; i < elem.asnlen; i++)
1157 printf("%02hhX", elem.data.str[i]);
1158 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
1159 }
1160 length -= count;
1161 np += count;
1162
1163 /* msgAuthoritativeEngineBoots */
1164 if ((count = asn1_parse(np, length, &elem)) < 0)
1165 return -1;
1166 if (elem.type != BE_INT4) {
1167 printf("[EBoots!=INT]");
1168 asn1_print(&elem);
1169 return -1;
1170 }
1171 if (vflag)
1172 printf("EBoots=%d ", elem.data.integer);
1173 length -= count;
1174 np += count;
1175
1176 /* msgAuthoritativeEngineTime */
1177 if ((count = asn1_parse(np, length, &elem)) < 0)
1178 return -1;
1179 if (elem.type != BE_INT4) {
1180 printf("[ETime!=INT]");
1181 asn1_print(&elem);
1182 return -1;
1183 }
1184 if (vflag)
1185 printf("ETime=%d ", elem.data.integer);
1186 length -= count;
1187 np += count;
1188
1189 if ((count = asn1_parse(np, length, &elem)) < 0)
1190 return -1;
1191 if (elem.type != BE_STR6) {
1192 printf("[User!=STR]");
1193 asn1_print(&elem);
1194 return -1;
1195 }
1196 if (elem.asnlen > 0) {
1197 printf("User=");
1198 asn1_print(&elem);
1199 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
1200 }
1201 length -= count;
1202 np += count;
1203
1204 /* msgAuthenticationParameters */
1205 if ((count = asn1_parse(np, length, &elem)) < 0)
1206 return -1;
1207 if (elem.type != BE_STR6) {
1208 printf("[AuthParam!=STR]");
1209 asn1_print(&elem);
1210 return -1;
1211 }
1212 /* Can't validate msgAuthenticationParameters without pass */
1213 length -= count;
1214 np += count;
1215
1216 /* msgPrivacyParameters */
1217 if ((count = asn1_parse(np, length, &elem)) < 0)
1218 return -1;
1219 if (elem.type != BE_STR6) {
1220 printf("[PrivParam!=STR]");
1221 asn1_print(&elem);
1222 return -1;
1223 }
1224 /* Salt is not useful if we can't decrypt */
1225 if (length - count != 0) {
1226 printf("[%d extra after usmSM]", length - count);
1227 return -1;
1228 }
1229 return 0;
1230}
1231
1232static void
1233snmp3_print(const u_char *np, u_int length)
1234{
1235 struct be elem;
1236 struct snmp3_sm *sm = NULL((void *)0);
1237 int count;
1238 int sublen;
1239 int i;
1240 int authpriv;
1241 u_char *subnp;
1242
1243 /* Header sequence */
1244 if ((count = asn1_parse(np, length, &elem)) < 0)
1245 return;
1246 if (elem.type != BE_SEQ7) {
1247 printf("[!header SEQ]");
1248 asn1_print(&elem);
1249 return;
1250 }
1251 np += count;
1252 length -= count;
1253 /* descend */
1254 /* msgID */
1255 sublen = elem.asnlen;
1256 subnp = (u_char *)elem.data.raw;
1257 if ((count = asn1_parse(subnp, sublen, &elem)) < 0)
1258 return;
1259 if (elem.type != BE_INT4) {
1260 printf("[msgID!=INT]");
1261 asn1_print(&elem);
1262 return;
1263 }
1264 if (vflag)
1265 printf("msgID=%d ", elem.data.integer);
1266 sublen -= count;
1267 subnp += count;
1268
1269 /* msgMaxSize */
1270 if ((count = asn1_parse(subnp, sublen, &elem)) < 0)
1271 return;
1272 if (elem.type != BE_INT4) {
1273 printf("[msgMS!=INT]");
1274 asn1_print(&elem);
1275 return;
1276 }
1277 if (vflag)
1278 printf("msgMS=%d ", elem.data.integer);
1279 sublen -= count;
1280 subnp += count;
1281
1282 /* msgFlags */
1283 if ((count = asn1_parse(subnp, sublen, &elem)) < 0)
1284 return;
1285 if (elem.type != BE_STR6) {
1286 printf("[msgFl!=STR]");
1287 asn1_print(&elem);
1288 return;
1289 }
1290 if (elem.asnlen != 1)
1291 printf("[%d extra after msgFl]", elem.asnlen - 1);
1292 authpriv = *elem.data.str & 0x3;
1293 if (vflag && (*elem.data.str & 0x7) != 0) {
1294 printf("(%suth%sPriv%s) ",
1295 SNMP3_AUTH(*elem.data.str)(*elem.data.str & 0x01) ? "a" : "noA",
1296 SNMP3_PRIV(*elem.data.str)(*elem.data.str & 0x02) ? "" : "No",
1297 SNMP3_REPORT(*elem.data.str)(*elem.data.str & 0x04) ? "|Reportable" : ""
1298 );
1299 }
1300 sublen -= count;
1301 subnp += count;
1302
1303 /* msgSecurityModel */
1304 if ((count = asn1_parse(subnp, sublen, &elem)) < 0)
1305 return;
1306 if (elem.type != BE_INT4) {
1307 printf("[msgSM!=INT]");
1308 asn1_print(&elem);
1309 return;
1310 }
1311 for (i = 0; snmp3_securitymodel[i].id != 0; i++) {
1312 if (snmp3_securitymodel[i].id == elem.data.integer) {
1313 sm = &(snmp3_securitymodel[i]);
1314 break;
1315 }
1316 }
1317 if (vflag) {
1318 if (sm != NULL((void *)0) && nflag == 0)
1319 printf("msgSM=%s ", sm->name);
1320 else
1321 printf("msgSM=%d ", elem.data.integer);
1322 }
1323 if (sublen - count != 0) {
1324 printf("[%d extra after header]", sublen - count);
1325 return;
1326 }
1327
1328 /* ascend */
1329 if ((count = asn1_parse(np, length, &elem)) < 0)
1330 return;
1331 if (elem.type != BE_STR6) {
1332 printf("msgSP!=STR]");
1333 asn1_print(&elem);
1334 return;
1335 }
1336 if (sm != NULL((void *)0) && sm->parse_params != NULL((void *)0)) {
1337 if (sm->parse_params(elem.data.raw, elem.asnlen) == -1)
1338 return;
1339 }
1340 length -= count;
1341 np += count;
1342
1343 if (SNMP3_PRIV(authpriv)(authpriv & 0x02) != 0) {
1344 printf("[encrypted PDU]");
1345 return;
1346 }
1347
1348 /* msgData */
1349 if ((count = asn1_parse(np, length, &elem)) < 0)
1350 return;
1351 if (elem.type != BE_SEQ7) {
1352 printf("[ScPDU!=SEQ]");
1353 asn1_print(&elem);
1354 return;
1355 }
1356 if (count < length)
1357 printf("[%d extra after ScPDU]", length - count);
1358 /* descend */
1359 length = elem.asnlen;
1360 np = (u_char *)elem.data.raw;
1361
1362 /* contextEngineID */
1363 if ((count = asn1_parse(np, length, &elem)) < 0)
1364 return;
1365 if (elem.type != BE_STR6) {
1366 printf("ctxEID!=STR]");
1367 asn1_print(&elem);
1368 return;
1369 }
1370 if (vflag && elem.asnlen > 0) {
1371 printf("ctxEID=0x");
1372 for (i = 0; i < elem.asnlen; i++)
1373 printf("%02hhX", elem.data.str[i]);
1374 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
1375 }
1376 length -= count;
1377 np += count;
1378
1379 /* contextName */
1380 if ((count = asn1_parse(np, length, &elem)) < 0)
1381 return;
1382 if (elem.type != BE_STR6) {
1383 printf("[ctxEName!=STR]");
1384 asn1_print(&elem);
1385 return;
1386 }
1387 if (vflag && elem.asnlen > 0) {
1388 printf("ctxName=");
1389 asn1_print(&elem);
1390 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
1391 }
1392 length -= count;
1393 np += count;
1394
1395 /* Data */
1396 if ((count = asn1_parse(np, length, &elem)) < 0)
1397 return;
1398 if (elem.type != BE_PDU9) {
1399 printf("[data!=PDU]");
1400 asn1_print(&elem);
1401 return;
1402 }
1403 if (count < length)
1404 printf("[%d extra after PDU]", length - count);
1405 asn1_print(&elem);
1406 /* descend into PDU */
1407 length = elem.asnlen;
1408 np = (u_char *)elem.data.raw;
1409 switch (elem.id) {
1410 case TRAP4:
1411 trap_print(np, length);
1412 break;
1413 case GETREQ0:
1414 case GETNEXTREQ1:
1415 case GETRESP2:
1416 case SETREQ3:
1417 case GETBULKREQ5:
1418 case INFORMREQ6:
1419 case TRAPV27:
1420 case REPORT8:
1421 snmppdu_print(elem.id, np, length);
1422 break;
1423 }
1424}
1425
1426void
1427snmp_print(const u_char *np, u_int length)
1428{
1429 struct be elem;
1430 int count = 0;
1431
1432 truncated = 0;
1433
1434 /* truncated packet? */
1435 if (np + length > snapend) {
1436 truncated = 1;
1437 length = snapend - np;
1438 }
1439
1440 /* initial Sequence */
1441 if ((count = asn1_parse(np, length, &elem)) < 0)
1442 return;
1443 if (elem.type != BE_SEQ7) {
1444 printf("[!init SEQ]");
1445 asn1_print(&elem);
1446 return;
1447 }
1448 if (count < length)
1449 printf("[%d extra after iSEQ]", length - count);
1450 /* descend */
1451 length = elem.asnlen;
1452 np = (u_char *)elem.data.raw;
1453 /* Version (Integer) */
1454 if ((count = asn1_parse(np, length, &elem)) < 0)
1455 return;
1456 if (elem.type != BE_INT4) {
1457 printf("[version!=INT]");
1458 asn1_print(&elem);
1459 return;
1460 }
1461 length -= count;
1462 np += count;
1463 switch (elem.data.integer) {
1464 case SNMP_V1:
1465 case SNMP_V2C:
1466 if (vflag)
1467 printf("SNMPv%s ", elem.data.integer == SNMP_V1 ?
1468 "1" : "2c");
1469 snmp12_print(np, length);
1470 return;
1471 case SNMP_V3:
1472 if (vflag)
1473 printf("SNMPv3 ");
1474 snmp3_print(np, length);
1475 return;
1476 default:
1477 printf("[snmp version(%d)]", elem.data.integer);
1478 return;
1479 }
1480}