/* \summary: Simple Network Management Protocol (SNMP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
+#include <limits.h>
#ifdef USE_LIBSMI
#include <smi.h>
#endif
+#include "netdissect-ctype.h"
+
+#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
elem->type = BE_ANY;
if (len < 1) {
ND_PRINT("[nothing to parse]");
- return -1;
+ goto invalid;
}
- ND_TCHECK_1(p);
/*
* it would be nice to use a bit field, but you can't depend on them.
* that won't fit in 32 bits.
*/
id = 0;
- ND_TCHECK_1(p);
while (GET_U_1(p) & ASN_BIT8) {
if (len < 1) {
ND_PRINT("[Xtagfield?]");
- return -1;
+ goto invalid;
}
id = (id << 7) | (GET_U_1(p) & ~ASN_BIT8);
len--;
hdr++;
p++;
- ND_TCHECK_1(p);
}
if (len < 1) {
ND_PRINT("[Xtagfield?]");
- return -1;
+ goto invalid;
}
- ND_TCHECK_1(p);
elem->id = id = (id << 7) | GET_U_1(p);
--len;
++hdr;
}
if (len < 1) {
ND_PRINT("[no asnlen]");
- return -1;
+ goto invalid;
}
- ND_TCHECK_1(p);
elem->asnlen = GET_U_1(p);
p++; len--; hdr++;
if (elem->asnlen & ASN_BIT8) {
elem->asnlen = 0;
if (len < noct) {
ND_PRINT("[asnlen? %d<%d]", len, noct);
- return -1;
+ goto invalid;
}
- ND_TCHECK_LEN(p, noct);
for (; noct != 0; len--, hdr++, noct--) {
elem->asnlen = (elem->asnlen << ASN_SHIFT8) | GET_U_1(p);
p++;
}
if (len < elem->asnlen) {
ND_PRINT("[len%d<asnlen%u]", len, elem->asnlen);
- return -1;
+ goto invalid;
}
if (form >= sizeof(Form)/sizeof(Form[0])) {
ND_PRINT("[form?%d]", form);
- return -1;
+ goto invalid;
}
if (class >= sizeof(Class)/sizeof(Class[0])) {
ND_PRINT("[class?%c/%d]", *Form[form], class);
- return -1;
+ goto invalid;
}
if ((int)id >= Class[class].numIDs) {
ND_PRINT("[id?%c/%s/%d]", *Form[form], Class[class].name, id);
- return -1;
+ goto invalid;
}
ND_TCHECK_LEN(p, elem->asnlen);
break;
case INTEGER: {
- int32_t data;
+ uint32_t data;
elem->type = BE_INT;
data = 0;
if (elem->asnlen == 0) {
ND_PRINT("[asnlen=0]");
- return -1;
+ goto invalid;
}
if (GET_U_1(p) & ASN_BIT8) /* negative */
- data = -1;
+ data = UINT_MAX;
for (i = elem->asnlen; i != 0; p++, i--)
data = (data << ASN_SHIFT8) | GET_U_1(p);
elem->data.integer = data;
len -= elem->asnlen;
return elem->asnlen + hdr;
-trunc:
- nd_print_trunc(ndo);
+invalid:
return -1;
}
-static int
+static void
asn1_print_octets(netdissect_options *ndo, struct be *elem)
{
const u_char *p = (const u_char *)elem->data.raw;
uint32_t asnlen = elem->asnlen;
uint32_t i;
- ND_TCHECK_LEN(p, asnlen);
for (i = asnlen; i != 0; p++, i--)
ND_PRINT("_%.2x", GET_U_1(p));
- return 0;
-
-trunc:
- nd_print_trunc(ndo);
- return -1;
}
-static int
+static void
asn1_print_string(netdissect_options *ndo, struct be *elem)
{
int printable = 1, first = 1;
uint32_t i;
p = elem->data.str;
- ND_TCHECK_LEN(p, asnlen);
for (i = asnlen; printable && i != 0; p++, i--)
- printable = ND_ISPRINT(GET_U_1(p));
+ printable = ND_ASCII_ISPRINT(GET_U_1(p));
p = elem->data.str;
if (printable) {
ND_PRINT("\"");
- if (nd_printn(ndo, p, asnlen, ndo->ndo_snapend)) {
- ND_PRINT("\"");
- goto trunc;
- }
+ nd_printjn(ndo, p, asnlen);
ND_PRINT("\"");
} else {
for (i = asnlen; i != 0; p++, i--) {
first = 0;
}
}
- return 0;
-
-trunc:
- nd_print_trunc(ndo);
- return -1;
}
/*
switch (elem->type) {
case BE_OCTET:
- if (asn1_print_octets(ndo, elem) == -1)
- return -1;
+ asn1_print_octets(ndo, elem);
break;
case BE_NULL:
break;
case BE_OID: {
- int o = 0, first = -1;
+ int first = -1;
+ uint32_t o = 0;
p = (const u_char *)elem->data.raw;
i = asnlen;
for (; a->node; a++) {
if (i < a->oid_len)
continue;
- if (!ND_TTEST_LEN(p, a->oid_len))
- continue;
+ ND_TCHECK_LEN(p, a->oid_len);
if (memcmp(a->oid, p, a->oid_len) == 0) {
objp = a->node->child;
i -= a->oid_len;
}
for (; i != 0; p++, i--) {
- ND_TCHECK_1(p);
o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
if (GET_U_1(p) & ASN_LONGLEN)
continue;
break;
case BE_STR:
- if (asn1_print_string(ndo, elem) == -1)
- return -1;
+ asn1_print_string(ndo, elem);
break;
case BE_SEQ:
if (asnlen != ASNLEN_INETADDR)
ND_PRINT("[inetaddr len!=%d]", ASNLEN_INETADDR);
p = (const u_char *)elem->data.raw;
- ND_TCHECK_LEN(p, asnlen);
for (i = asnlen; i != 0; p++, i--) {
ND_PRINT((i == asnlen) ? "%u" : ".%u", GET_U_1(p));
}
ND_PRINT("[be!?]");
break;
}
+ /* This function now always returns 0. Don't make it void yet, as other
+ * code checks for negative result and this function might need to signal
+ * invalid data later.
+ */
return 0;
-
-trunc:
- nd_print_trunc(ndo);
- return -1;
}
#ifdef notdef
struct be elem;
int i = 0;
- while (i >= 0 && length > 0) {
+ while (i >= 0 && length != 0) {
i = asn1_parse(ndo, p, length, &elem);
if (i >= 0) {
ND_PRINT(" ");
unsigned int firstval;
for (*oidlen = 0; i != 0; p++, i--) {
- ND_TCHECK_1(p);
o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
if (GET_U_1(p) & ASN_LONGLEN)
continue;
o = 0;
}
return 0;
-
-trunc:
- nd_print_trunc(ndo);
- return -1;
}
static int smi_check_type(SmiBasetype basetype, int be)
}
if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
- ND_PRINT("[notNotifyable]");
+ ND_PRINT("[notNotifiable]");
}
if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
u_short pduid, const u_char *np, u_int length)
{
struct be elem;
- int count = 0, ind;
+ int count = 0;
#ifdef USE_LIBSMI
SmiNode *smiNode = NULL;
#endif
length = elem.asnlen;
np = (const u_char *)elem.data.raw;
- for (ind = 1; length > 0; ind++) {
+ while (length) {
const u_char *vbend;
u_int vblength;
np += count;
varbind_print(ndo, pduid, np, length);
- return;
}
/*
np += count;
varbind_print(ndo, TRAP, np, length);
- return;
}
/*
np += count;
ND_PRINT("E=");
- if (asn1_print_octets(ndo, &elem) == -1)
- return;
+ asn1_print_octets(ndo, &elem);
ND_PRINT(" ");
/* contextName (OCTET STRING) */
np += count;
ND_PRINT("C=");
- if (asn1_print_string(ndo, &elem) == -1)
- return;
+ asn1_print_string(ndo, &elem);
ND_PRINT(" ");
pdu_print(ndo, np, length, version);
sizeof(DEF_COMMUNITY) - 1) == 0)) {
/* ! "public" */
ND_PRINT("C=");
- if (asn1_print_string(ndo, &elem) == -1)
- return;
+ asn1_print_string(ndo, &elem);
ND_PRINT(" ");
}
length -= count;
np += count;
ND_PRINT("U=");
- if (asn1_print_string(ndo, &elem) == -1)
- return;
+ asn1_print_string(ndo, &elem);
ND_PRINT(" ");
/* msgAuthenticationParameters (OCTET STRING) */