X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/982b17b22540dfb866148261ca0011831a5a56d7..4c2790a43252b9cac1fe7f6b50b51c3c55d2370a:/print-snmp.c diff --git a/print-snmp.c b/print-snmp.c index 76578ee8..728da6be 100644 --- a/print-snmp.c +++ b/print-snmp.c @@ -1,16 +1,29 @@ /* * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 - * The Regents of the University of California. All rights reserved. + * John Robert LoVerso. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by John Robert LoVerso. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * This implementation has been influenced by the CMU SNMP release, * by Steve Waldbusser. However, this shares no code with that system. @@ -44,18 +57,16 @@ */ #ifndef lint -static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.49 2001-06-15 21:06:59 fenner Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.64 2005-05-06 07:56:53 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include -#include +#include -#include #include #include @@ -66,11 +77,13 @@ static const char rcsid[] = #include "interface.h" #include "addrtoname.h" +#undef OPAQUE /* defined in */ + /* * Universal ASN.1 types * (we only care about the tag values for those allowed in the Internet SMI) */ -char *Universal[] = { +const char *Universal[] = { "U-0", "Boolean", "Integer", @@ -93,7 +106,7 @@ char *Universal[] = { /* * Application-wide ASN.1 types from the Internet SMI and their tags */ -char *Application[] = { +const char *Application[] = { "IpAddress", #define IPADDR 0 "Counter", @@ -112,7 +125,7 @@ char *Application[] = { /* * Context-specific ASN.1 types for the SNMP PDUs and their tags */ -char *Context[] = { +const char *Context[] = { "GetRequest", #define GETREQ 0 "GetNextRequest", @@ -142,7 +155,7 @@ char *Context[] = { /* * Context-specific ASN.1 types for the SNMP Exceptions and their tags */ -char *Exceptions[] = { +const char *Exceptions[] = { "noSuchObject", #define NOSUCHOBJECT 0 "noSuchInstance", @@ -155,14 +168,14 @@ char *Exceptions[] = { * Private ASN.1 types * The Internet SMI does not specify any */ -char *Private[] = { +const char *Private[] = { "P-0" }; /* * error-status values for any SNMP PDU */ -char *ErrorStatus[] = { +const char *ErrorStatus[] = { "noError", "tooBig", "noSuchName", @@ -184,14 +197,14 @@ char *ErrorStatus[] = { "inconsistentName" }; #define DECODE_ErrorStatus(e) \ - ( e >= 0 && e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \ + ( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \ ? ErrorStatus[e] \ : (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf)) /* * generic-trap values in the SNMP Trap-PDU */ -char *GenericTrap[] = { +const char *GenericTrap[] = { "coldStart", "warmStart", "linkDown", @@ -199,10 +212,10 @@ char *GenericTrap[] = { "authenticationFailure", "egpNeighborLoss", "enterpriseSpecific" -#define GT_ENTERPRISE 7 +#define GT_ENTERPRISE 6 }; #define DECODE_GenericTrap(t) \ - ( t >= 0 && t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \ + ( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \ ? GenericTrap[t] \ : (snprintf(buf, sizeof(buf), "gt=%d", t), buf)) @@ -213,8 +226,8 @@ char *GenericTrap[] = { */ #define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */ struct { - char *name; - char **Id; + const char *name; + const char **Id; int numIDs; } Class[] = { defineCLASS(Universal), @@ -232,7 +245,7 @@ struct { /* * defined forms for ASN.1 types */ -char *Form[] = { +const char *Form[] = { "Primitive", #define PRIMITIVE 0 "Constructed", @@ -244,7 +257,7 @@ char *Form[] = { * This is stored as a general-order tree. */ struct obj { - char *desc; /* name of object */ + const char *desc; /* name of object */ u_char oid; /* sub-id following parent */ u_char type; /* object type (unused) */ struct obj *child, *next; /* child and next sibling pointers */ @@ -266,9 +279,9 @@ struct obj { * private enterprises tree, and the experimental tree. */ struct obj_abrev { - char *prefix; /* prefix for this abrev */ + const char *prefix; /* prefix for this abrev */ struct obj *node; /* pointer into object table */ - char *oid; /* ASN.1 encoded OID */ + const char *oid; /* ASN.1 encoded OID */ } obj_abrev_list[] = { #ifndef NO_ABREV_MIB /* .iso.org.dod.internet.mgmt.mib */ @@ -347,7 +360,7 @@ struct be { /* * SNMP versions recognized by this module */ -char *SnmpVersion[] = { +const char *SnmpVersion[] = { "SNMPv1", #define SNMP_VERSION_1 0 "SNMPv2c", @@ -381,13 +394,6 @@ char *SnmpVersion[] = { #define ASN_ID_EXT 0x1f /* extension ID in tag field */ -/* - * truncated==1 means the packet was complete, but we don't have all of - * it to decode. - */ -static int truncated; -#define ifNotTruncated if (truncated) fputs("[|snmp]", stdout); else - /* * This decodes the next ASN.1 object in the stream pointed to by "p" * (and of real-length "len") and stores the intermediate data in the @@ -405,9 +411,10 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) elem->asnlen = 0; elem->type = BE_ANY; if (len < 1) { - ifNotTruncated fputs("[nothing to parse]", stdout); + fputs("[nothing to parse]", stdout); return -1; } + TCHECK(*p); /* * it would be nice to use a bit field, but you can't depend on them. @@ -431,52 +438,66 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) p++; len--; hdr = 1; /* extended tag field */ if (id == ASN_ID_EXT) { - for (id = 0; *p & ASN_BIT8 && len > 0; len--, hdr++, p++) + /* + * The ID follows, as a sequence of octets with the + * 8th bit set and the remaining 7 bits being + * the next 7 bits of the value, terminated with + * an octet with the 8th bit not set. + * + * First, assemble all the octets with the 8th + * bit set. XXX - this doesn't handle a value + * that won't fit in 32 bits. + */ + for (id = 0; *p & ASN_BIT8; len--, hdr++, p++) { + if (len < 1) { + fputs("[Xtagfield?]", stdout); + return -1; + } + TCHECK(*p); id = (id << 7) | (*p & ~ASN_BIT8); - if (len == 0 && *p & ASN_BIT8) { - ifNotTruncated fputs("[Xtagfield?]", stdout); + } + if (len < 1) { + fputs("[Xtagfield?]", stdout); return -1; } + TCHECK(*p); elem->id = id = (id << 7) | *p; --len; ++hdr; ++p; } if (len < 1) { - ifNotTruncated fputs("[no asnlen]", stdout); + fputs("[no asnlen]", stdout); return -1; } + TCHECK(*p); elem->asnlen = *p; p++; len--; hdr++; if (elem->asnlen & ASN_BIT8) { - int noct = elem->asnlen % ASN_BIT8; + u_int32_t noct = elem->asnlen % ASN_BIT8; elem->asnlen = 0; if (len < noct) { - ifNotTruncated printf("[asnlen? %d<%d]", len, noct); + printf("[asnlen? %d<%d]", len, noct); return -1; } + TCHECK2(*p, noct); for (; noct-- > 0; len--, hdr++) elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++; } if (len < elem->asnlen) { - if (!truncated) { - printf("[len%dasnlen); - return -1; - } - /* maybe should check at least 4? */ - elem->asnlen = len; + printf("[len%dasnlen); + return -1; } if (form >= sizeof(Form)/sizeof(Form[0])) { - ifNotTruncated printf("[form?%d]", form); + printf("[form?%d]", form); return -1; } if (class >= sizeof(Class)/sizeof(Class[0])) { - ifNotTruncated printf("[class?%c/%d]", *Form[form], class); + printf("[class?%c/%d]", *Form[form], class); return -1; } if ((int)id >= Class[class].numIDs) { - ifNotTruncated printf("[id?%c/%s/%d]", *Form[form], - Class[class].name, id); + printf("[id?%c/%s/%d]", *Form[form], Class[class].name, id); return -1; } @@ -495,6 +516,7 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) elem->type = BE_INT; data = 0; + TCHECK2(*p, elem->asnlen); if (*p & ASN_BIT8) /* negative */ data = -1; for (i = elem->asnlen; i-- > 0; p++) @@ -533,6 +555,7 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) case GAUGE: case TIMETICKS: { register u_int32_t data; + TCHECK2(*p, elem->asnlen); elem->type = BE_UNS; data = 0; for (i = elem->asnlen; i-- > 0; p++) @@ -543,10 +566,11 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) case COUNTER64: { register u_int32_t high, low; + TCHECK2(*p, elem->asnlen); elem->type = BE_UNS64; high = 0, low = 0; for (i = elem->asnlen; i-- > 0; p++) { - high = (high << 8) | + high = (high << 8) | ((low & 0xFF000000) >> 24); low = (low << 8) | *p; } @@ -584,10 +608,11 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) break; default: - elem->type = BE_OCTET; - elem->data.raw = (caddr_t)p; printf("[P/%s/%s]", Class[class].name, Class[class].Id[id]); + TCHECK2(*p, elem->asnlen); + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; break; } break; @@ -626,6 +651,10 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) p += elem->asnlen; len -= elem->asnlen; return elem->asnlen + hdr; + +trunc: + fputs("[|snmp]", stdout); + return -1; } /* @@ -633,16 +662,17 @@ asn1_parse(register const u_char *p, u_int len, struct be *elem) * This used to be an integral part of asn1_parse() before the intermediate * BE form was added. */ -static void +static int asn1_print(struct be *elem) { u_char *p = (u_char *)elem->data.raw; u_int32_t asnlen = elem->asnlen; - int i; + u_int32_t i; switch (elem->type) { case BE_OCTET: + TCHECK2(*p, asnlen); for (i = asnlen; i-- > 0; p++) printf("_%.2x", *p); break; @@ -651,13 +681,14 @@ asn1_print(struct be *elem) break; case BE_OID: { - int o = 0, first = -1, i = asnlen; + int o = 0, first = -1, i = asnlen; if (!sflag && !nflag && asnlen > 2) { struct obj_abrev *a = &obj_abrev_list[0]; + size_t a_len = strlen(a->oid); for (; a->node; a++) { - if (!memcmp(a->oid, (char *)p, - strlen(a->oid))) { + TCHECK2(*p, a_len); + if (memcmp(a->oid, (char *)p, a_len) == 0) { objp = a->node->child; i -= strlen(a->oid); p += strlen(a->oid); @@ -669,19 +700,24 @@ asn1_print(struct be *elem) } for (; !sflag && i-- > 0; p++) { + TCHECK(*p); o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8); if (*p & ASN_LONGLEN) continue; - + /* * first subitem encodes two items with 1st*OIDMUX+2nd + * (see X.690:1997 clause 8.19 for the details) */ if (first < 0) { + int s; if (!nflag) objp = mibroot; first = 0; - OBJ_PRINT(o/OIDMUX, first); - o %= OIDMUX; + s = o / OIDMUX; + if (s > 2) s = 2; + OBJ_PRINT(s, first); + o -= s * OIDMUX; } OBJ_PRINT(o, first); if (--first < 0) @@ -708,7 +744,7 @@ asn1_print(struct be *elem) break; } d = elem->data.uns64.high * 4294967296.0; /* 2^32 */ - if (elem->data.uns64.high <= 0x1fffff) { + if (elem->data.uns64.high <= 0x1fffff) { d += elem->data.uns64.low; #if 0 /*is looks illegal, but what is the intention?*/ printf("%.f", d); @@ -744,12 +780,16 @@ asn1_print(struct be *elem) case BE_STR: { register int printable = 1, first = 1; const u_char *p = elem->data.str; + TCHECK2(*p, asnlen); for (i = asnlen; printable && i-- > 0; p++) printable = isprint(*p) || isspace(*p); p = elem->data.str; if (printable) { putchar('"'); - (void)fn_print(p, p + asnlen); + if (fn_printn(p, asnlen, snapend)) { + putchar('"'); + goto trunc; + } putchar('"'); } else for (i = asnlen; i-- > 0; p++) { @@ -766,7 +806,8 @@ asn1_print(struct be *elem) case BE_INETADDR: if (asnlen != ASNLEN_INETADDR) printf("[inetaddr len!=%d]", ASNLEN_INETADDR); - for (i = asnlen; i-- > 0; p++) { + TCHECK2(*p, asnlen); + for (i = asnlen; i-- != 0; p++) { printf((i == asnlen-1) ? "%u" : ".%u", *p); } break; @@ -790,6 +831,11 @@ asn1_print(struct be *elem) fputs("[be!?]", stdout); break; } + return 0; + +trunc: + fputs("[|snmp]", stdout); + return -1; } #ifdef notdef @@ -812,7 +858,8 @@ asn1_decode(u_char *p, u_int length) i = asn1_parse(p, length, &elem); if (i >= 0) { fputs(" ", stdout); - asn1_print(&elem); + if (asn1_print(&elem) < 0) + return; if (elem.type == BE_SEQ || elem.type == BE_PDU) { fputs(" {", stdout); asn1_decode(elem.data.raw, elem.asnlen); @@ -848,33 +895,43 @@ static struct smi2be smi2betab[] = { { SMI_BASETYPE_UNKNOWN, BE_NONE } }; -static void smi_decode_oid(struct be *elem, unsigned int *oid, - unsigned int oidsize, unsigned int *oidlen) +static int +smi_decode_oid(struct be *elem, unsigned int *oid, + unsigned int oidsize, unsigned int *oidlen) { u_char *p = (u_char *)elem->data.raw; u_int32_t asnlen = elem->asnlen; int o = 0, first = -1, i = asnlen; for (*oidlen = 0; sflag && i-- > 0; p++) { + TCHECK(*p); o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8); if (*p & ASN_LONGLEN) continue; - + /* * first subitem encodes two items with 1st*OIDMUX+2nd + * (see X.690:1997 clause 8.19 for the details) */ if (first < 0) { first = 0; if (*oidlen < oidsize) { - oid[(*oidlen)++] = o/OIDMUX; + oid[*oidlen] = o / OIDMUX; + if (oid[*oidlen] > 2) oid[*oidlen] = 2; } - o %= OIDMUX; + o -= oid[*oidlen] * OIDMUX; + if (*oidlen < oidsize) (*oidlen)++; } if (*oidlen < oidsize) { - oid[(*oidlen)++] = o; + oid[(*oidlen)++] = o; } o = 0; } + return 0; + +trunc: + fputs("[|snmp]", stdout); + return -1; } static int smi_check_type(SmiBasetype basetype, int be) @@ -894,7 +951,7 @@ static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange, struct be *elem) { int ok = 1; - + switch (smiType->basetype) { case SMI_BASETYPE_OBJECTIDENTIFIER: case SMI_BASETYPE_OCTETSTRING: @@ -911,12 +968,12 @@ static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange, ok = (elem->data.integer >= smiRange->minValue.value.integer32 && elem->data.integer <= smiRange->maxValue.value.integer32); break; - + case SMI_BASETYPE_UNSIGNED32: ok = (elem->data.uns >= smiRange->minValue.value.unsigned32 && elem->data.uns <= smiRange->maxValue.value.unsigned32); break; - + case SMI_BASETYPE_UNSIGNED64: /* XXX */ break; @@ -931,6 +988,10 @@ static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange, case SMI_BASETYPE_UNKNOWN: ok = 1; break; + + default: + ok = 0; + break; } return ok; @@ -963,16 +1024,19 @@ static int smi_check_range(SmiType *smiType, struct be *elem) return ok; } -static SmiNode *smi_print_variable(struct be *elem) +static SmiNode *smi_print_variable(struct be *elem, int *status) { unsigned int oid[128], oidlen; SmiNode *smiNode = NULL; - int i; + unsigned int i; - smi_decode_oid(elem, oid, sizeof(oid)/sizeof(unsigned int), &oidlen); + *status = smi_decode_oid(elem, oid, sizeof(oid)/sizeof(unsigned int), + &oidlen); + if (*status < 0) + return NULL; smiNode = smiGetNodeByOID(oidlen, oid); if (! smiNode) { - asn1_print(elem); + *status = asn1_print(elem); return NULL; } if (vflag) { @@ -985,27 +1049,27 @@ static SmiNode *smi_print_variable(struct be *elem) printf(".%u", oid[i]); } } + *status = 0; return smiNode; } -static void smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem) +static int +smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem) { - unsigned int oid[128], oidlen; + unsigned int i, oid[128], oidlen; SmiType *smiType; SmiNamedNumber *nn; - int i, done = 0; + int done = 0; if (! smiNode || ! (smiNode->nodekind & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) { - asn1_print(elem); - return; + return asn1_print(elem); } if (elem->type == BE_NOSUCHOBJECT || elem->type == BE_NOSUCHINST || elem->type == BE_ENDOFMIBVIEW) { - asn1_print(elem); - return; + return asn1_print(elem); } if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) { @@ -1027,8 +1091,7 @@ static void smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem) smiType = smiGetNodeType(smiNode); if (! smiType) { - asn1_print(elem); - return; + return asn1_print(elem); } if (! smi_check_type(smiType->basetype, elem->type)) { @@ -1046,7 +1109,7 @@ static void smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem) /* apply display hints (integer, octetstring) */ /* convert instance identifier to index type values */ - + switch (elem->type) { case BE_OID: if (smiType->basetype == SMI_BASETYPE_BITS) { @@ -1063,7 +1126,7 @@ static void smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem) } fputs(smiNode->name, stdout); if (smiNode->oidlen < oidlen) { - for (i = smiNode->oidlen; + for (i = smiNode->oidlen; i < oidlen; i++) { printf(".%u", oid[i]); } @@ -1091,8 +1154,9 @@ static void smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem) } if (! done) { - asn1_print(elem); + return asn1_print(elem); } + return 0; } #endif @@ -1140,6 +1204,7 @@ varbind_print(u_char pduid, const u_char *np, u_int length) #ifdef LIBSMI SmiNode *smiNode = NULL; #endif + int status; /* Sequence of varBind */ if ((count = asn1_parse(np, length, &elem)) < 0) @@ -1149,7 +1214,7 @@ varbind_print(u_char pduid, const u_char *np, u_int length) asn1_print(&elem); return; } - if (count < length) + if ((u_int)count < length) printf("[%d extra after SEQ of varbind]", length - count); /* descend */ length = elem.asnlen; @@ -1184,16 +1249,18 @@ varbind_print(u_char pduid, const u_char *np, u_int length) return; } #ifdef LIBSMI - smiNode = smi_print_variable(&elem); + smiNode = smi_print_variable(&elem, &status); #else - asn1_print(&elem); + status = asn1_print(&elem); #endif + if (status < 0) + return; length -= count; np += count; if (pduid != GETREQ && pduid != GETNEXTREQ && pduid != GETBULKREQ) - fputs("=", stdout); + fputs("=", stdout); /* objVal (ANY) */ if ((count = asn1_parse(np, length, &elem)) < 0) @@ -1202,16 +1269,19 @@ varbind_print(u_char pduid, const u_char *np, u_int length) || pduid == GETBULKREQ) { if (elem.type != BE_NULL) { fputs("[objVal!=NULL]", stdout); - asn1_print(&elem); + if (asn1_print(&elem) < 0) + return; } } else { if (elem.type != BE_NULL) { #ifdef LIBSMI - smi_print_value(smiNode, pduid, &elem); + status = smi_print_value(smiNode, pduid, &elem); #else - asn1_print(&elem); + status = asn1_print(&elem); #endif } + if (status < 0) + return; } length = vblength; np = vbend; @@ -1223,7 +1293,7 @@ varbind_print(u_char pduid, const u_char *np, u_int length) * GetBulk, Inform, V2Trap, and Report */ static void -snmppdu_print(u_char pduid, const u_char *np, u_int length) +snmppdu_print(u_short pduid, const u_char *np, u_int length) { struct be elem; int count = 0, error; @@ -1253,13 +1323,13 @@ snmppdu_print(u_char pduid, const u_char *np, u_int length) if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT) && elem.data.integer != 0) { - char errbuf[10]; + char errbuf[20]; printf("[errorStatus(%s)!=0]", DECODE_ErrorStatus(elem.data.integer)); } else if (pduid == GETBULKREQ) { printf(" N=%d", elem.data.integer); } else if (elem.data.integer != 0) { - char errbuf[10]; + char errbuf[20]; printf(" %s", DECODE_ErrorStatus(elem.data.integer)); error = elem.data.integer; } @@ -1318,7 +1388,8 @@ trappdu_print(const u_char *np, u_int length) asn1_print(&elem); return; } - asn1_print(&elem); + if (asn1_print(&elem) < 0) + return; length -= count; np += count; @@ -1332,7 +1403,8 @@ trappdu_print(const u_char *np, u_int length) asn1_print(&elem); return; } - asn1_print(&elem); + if (asn1_print(&elem) < 0) + return; length -= count; np += count; @@ -1346,7 +1418,7 @@ trappdu_print(const u_char *np, u_int length) } generic = elem.data.integer; { - char buf[10]; + char buf[20]; printf(" %s", DECODE_GenericTrap(generic)); } length -= count; @@ -1378,7 +1450,8 @@ trappdu_print(const u_char *np, u_int length) asn1_print(&elem); return; } - asn1_print(&elem); + if (asn1_print(&elem) < 0) + return; length -= count; np += count; @@ -1402,19 +1475,20 @@ pdu_print(const u_char *np, u_int length, int version) fputs("[no PDU]", stdout); return; } - if (count < length) + if ((u_int)count < length) printf("[%d extra after PDU]", length - count); if (vflag) { fputs("{ ", stdout); } - asn1_print(&pdu); + if (asn1_print(&pdu) < 0) + return; fputs(" ", stdout); /* descend into PDU */ length = pdu.asnlen; np = (u_char *)pdu.data.raw; if (version == SNMP_VERSION_1 && - (pdu.id == GETBULKREQ || pdu.id == INFORMREQ || + (pdu.id == GETBULKREQ || pdu.id == INFORMREQ || pdu.id == V2TRAP || pdu.id == REPORT)) { printf("[v2 PDU in v1 message]"); return; @@ -1442,7 +1516,7 @@ pdu_print(const u_char *np, u_int length, int version) } if (vflag) { - fputs("} ", stdout); + fputs(" } ", stdout); } } @@ -1517,8 +1591,9 @@ community_print(const u_char *np, u_int length, int version) return; } /* default community */ - if (strncmp((char *)elem.data.str, DEF_COMMUNITY, - sizeof(DEF_COMMUNITY) - 1)) + if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 && + strncmp((char *)elem.data.str, DEF_COMMUNITY, + sizeof(DEF_COMMUNITY) - 1) == 0)) /* ! "public" */ printf("C=%.*s ", (int)elem.asnlen, elem.data.str); length -= count; @@ -1566,7 +1641,7 @@ usm_print(const u_char *np, u_int length) asn1_print(&elem); return; } - if (vflag) + if (vflag) printf("B=%d ", elem.data.integer); length -= count; np += count; @@ -1579,7 +1654,7 @@ usm_print(const u_char *np, u_int length) asn1_print(&elem); return; } - if (vflag) + if (vflag) printf("T=%d ", elem.data.integer); length -= count; np += count; @@ -1619,7 +1694,7 @@ usm_print(const u_char *np, u_int length) length -= count; np += count; - if (count < length) + if ((u_int)count < length) printf("[%d extra after usm SEQ]", length - count); } @@ -1686,7 +1761,7 @@ v3msg_print(const u_char *np, u_int length) return; } flags = elem.data.str[0]; - if (flags != 0x00 && flags != 0x01 && flags != 0x03 + if (flags != 0x00 && flags != 0x01 && flags != 0x03 && flags != 0x04 && flags != 0x05 && flags != 0x07) { printf("[msgFlags=0x%02X]", flags); return; @@ -1712,7 +1787,7 @@ v3msg_print(const u_char *np, u_int length) length -= count; np += count; - if (count < length) + if ((u_int)count < length) printf("[%d extra after message SEQ]", length - count); if (vflag) { @@ -1770,14 +1845,6 @@ snmp_print(const u_char *np, u_int length) int count = 0; int version = 0; - truncated = 0; - - /* truncated packet? */ - if (np + length > snapend) { - truncated = 1; - length = snapend - np; - } - putchar(' '); /* initial Sequence */ @@ -1788,7 +1855,7 @@ snmp_print(const u_char *np, u_int length) asn1_print(&elem); return; } - if (count < length) + if ((u_int)count < length) printf("[%d extra after iSEQ]", length - count); /* descend */ length = elem.asnlen;