NDOize SNMP decoder
diff --git a/interface.h b/interface.h
index d73c925..6ca6a60 100644
--- a/interface.h
+++ b/interface.h
@@ -183,7 +183,6 @@
 extern u_int ppp_hdlc_if_print(const struct pcap_pkthdr *, const u_char *);
 extern u_int ppp_bsdos_if_print(const struct pcap_pkthdr *, const u_char *);
 extern u_int prism_if_print(const struct pcap_pkthdr *, const u_char *);
-extern void snmp_print(const u_char *, u_int);
 extern void tcp_print(const u_char *, u_int, const u_char *, int);
 extern void timed_print(const u_char *);
 extern void rx_print(register const u_char *, int, int, int, u_char *);
diff --git a/netdissect.h b/netdissect.h
index f1543b7..a8876a1 100644
--- a/netdissect.h
+++ b/netdissect.h
@@ -496,6 +496,7 @@
 extern u_int juniper_ppp_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *);
 extern u_int juniper_frelay_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *);
 extern u_int juniper_chdlc_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *);
+extern void snmp_print(netdissect_options *, const u_char *, u_int);
 
 /* stuff that has not yet been rototiled */
 
@@ -523,7 +524,6 @@
 extern void ppp_bsdos_if_print(u_char *,
 			       const struct pcap_pkthdr *, const u_char *);
 
-extern void snmp_print(netdissect_options *,const u_char *, u_int);
 extern void tcp_print(netdissect_options *,const u_char *, u_int,
 		      const u_char *, int);
 extern void timed_print(netdissect_options *,const u_char *, u_int);
diff --git a/print-atm.c b/print-atm.c
index 09bbb8e..528bf2c 100644
--- a/print-atm.c
+++ b/print-atm.c
@@ -312,7 +312,7 @@
 
 		case VCI_ILMIC:
 			ND_PRINT((ndo, "ilmi: "));
-			snmp_print(p, length);
+			snmp_print(ndo, p, length);
 			return;
 		}
 	}
diff --git a/print-snmp.c b/print-snmp.c
index 6f57c2f..bb01d73 100644
--- a/print-snmp.c
+++ b/print-snmp.c
@@ -56,6 +56,7 @@
  #	@(#)snmp.awk.x	1.1 (LANL) 1/15/90
  */
 
+#define NETDISSECT_REWORKED
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -311,10 +312,10 @@
 		} while ((objp = objp->next) != NULL); \
 	} \
 	if (objp) { \
-		printf(suppressdot?"%s":".%s", objp->desc); \
+		ND_PRINT((ndo, suppressdot?"%s":".%s", objp->desc)); \
 		objp = objp->child; \
 	} else \
-		printf(suppressdot?"%u":".%u", (o)); \
+		ND_PRINT((ndo, suppressdot?"%u":".%u", (o))); \
 }
 
 /*
@@ -399,7 +400,8 @@
  * O/w, this returns the number of bytes parsed from "p".
  */
 static int
-asn1_parse(register const u_char *p, u_int len, struct be *elem)
+asn1_parse(netdissect_options *ndo,
+           register const u_char *p, u_int len, struct be *elem)
 {
 	u_char form, class, id;
 	int i, hdr;
@@ -407,10 +409,10 @@
 	elem->asnlen = 0;
 	elem->type = BE_ANY;
 	if (len < 1) {
-		fputs("[nothing to parse]", stdout);
+		ND_PRINT((ndo, "[nothing to parse]"));
 		return -1;
 	}
-	TCHECK(*p);
+	ND_TCHECK(*p);
 
 	/*
 	 * it would be nice to use a bit field, but you can't depend on them.
@@ -446,54 +448,54 @@
 		 */
 		for (id = 0; *p & ASN_BIT8; len--, hdr++, p++) {
 			if (len < 1) {
-				fputs("[Xtagfield?]", stdout);
+				ND_PRINT((ndo, "[Xtagfield?]"));
 				return -1;
 			}
-			TCHECK(*p);
+			ND_TCHECK(*p);
 			id = (id << 7) | (*p & ~ASN_BIT8);
 		}
 		if (len < 1) {
-			fputs("[Xtagfield?]", stdout);
+			ND_PRINT((ndo, "[Xtagfield?]"));
 			return -1;
 		}
-		TCHECK(*p);
+		ND_TCHECK(*p);
 		elem->id = id = (id << 7) | *p;
 		--len;
 		++hdr;
 		++p;
 	}
 	if (len < 1) {
-		fputs("[no asnlen]", stdout);
+		ND_PRINT((ndo, "[no asnlen]"));
 		return -1;
 	}
-	TCHECK(*p);
+	ND_TCHECK(*p);
 	elem->asnlen = *p;
 	p++; len--; hdr++;
 	if (elem->asnlen & ASN_BIT8) {
 		u_int32_t noct = elem->asnlen % ASN_BIT8;
 		elem->asnlen = 0;
 		if (len < noct) {
-			printf("[asnlen? %d<%d]", len, noct);
+			ND_PRINT((ndo, "[asnlen? %d<%d]", len, noct));
 			return -1;
 		}
-		TCHECK2(*p, noct);
+		ND_TCHECK2(*p, noct);
 		for (; noct-- > 0; len--, hdr++)
 			elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++;
 	}
 	if (len < elem->asnlen) {
-		printf("[len%d<asnlen%u]", len, elem->asnlen);
+		ND_PRINT((ndo, "[len%d<asnlen%u]", len, elem->asnlen));
 		return -1;
 	}
 	if (form >= sizeof(Form)/sizeof(Form[0])) {
-		printf("[form?%d]", form);
+		ND_PRINT((ndo, "[form?%d]", form));
 		return -1;
 	}
 	if (class >= sizeof(Class)/sizeof(Class[0])) {
-		printf("[class?%c/%d]", *Form[form], class);
+		ND_PRINT((ndo, "[class?%c/%d]", *Form[form], class));
 		return -1;
 	}
 	if ((int)id >= Class[class].numIDs) {
-		printf("[id?%c/%s/%d]", *Form[form], Class[class].name, id);
+		ND_PRINT((ndo, "[id?%c/%s/%d]", *Form[form], Class[class].name, id));
 		return -1;
 	}
 
@@ -512,7 +514,7 @@
 				elem->type = BE_INT;
 				data = 0;
 
-				TCHECK2(*p, elem->asnlen);
+				ND_TCHECK2(*p, elem->asnlen);
 				if (*p & ASN_BIT8)	/* negative */
 					data = -1;
 				for (i = elem->asnlen; i-- > 0; p++)
@@ -534,8 +536,7 @@
 			default:
 				elem->type = BE_OCTET;
 				elem->data.raw = (caddr_t)p;
-				printf("[P/U/%s]",
-					Class[class].Id[id]);
+				ND_PRINT((ndo, "[P/U/%s]", Class[class].Id[id]));
 				break;
 			}
 			break;
@@ -551,7 +552,7 @@
 			case GAUGE:
 			case TIMETICKS: {
 				register u_int32_t data;
-				TCHECK2(*p, elem->asnlen);
+				ND_TCHECK2(*p, elem->asnlen);
 				elem->type = BE_UNS;
 				data = 0;
 				for (i = elem->asnlen; i-- > 0; p++)
@@ -562,7 +563,7 @@
 
 			case COUNTER64: {
 				register u_int32_t high, low;
-				TCHECK2(*p, elem->asnlen);
+				ND_TCHECK2(*p, elem->asnlen);
 			        elem->type = BE_UNS64;
 				high = 0, low = 0;
 				for (i = elem->asnlen; i-- > 0; p++) {
@@ -578,8 +579,8 @@
 			default:
 				elem->type = BE_OCTET;
 				elem->data.raw = (caddr_t)p;
-				printf("[P/A/%s]",
-					Class[class].Id[id]);
+				ND_PRINT((ndo, "[P/A/%s]",
+					Class[class].Id[id]));
 				break;
 			}
 			break;
@@ -604,9 +605,8 @@
 			break;
 
 		default:
-			printf("[P/%s/%s]",
-				Class[class].name, Class[class].Id[id]);
-			TCHECK2(*p, elem->asnlen);
+			ND_PRINT((ndo, "[P/%s/%s]", Class[class].name, Class[class].Id[id]));
+			ND_TCHECK2(*p, elem->asnlen);
 			elem->type = BE_OCTET;
 			elem->data.raw = (caddr_t)p;
 			break;
@@ -625,7 +625,7 @@
 			default:
 				elem->type = BE_OCTET;
 				elem->data.raw = (caddr_t)p;
-				printf("C/U/%s", Class[class].Id[id]);
+				ND_PRINT((ndo, "C/U/%s", Class[class].Id[id]));
 				break;
 			}
 			break;
@@ -638,8 +638,7 @@
 		default:
 			elem->type = BE_OCTET;
 			elem->data.raw = (caddr_t)p;
-			printf("C/%s/%s",
-				Class[class].name, Class[class].Id[id]);
+			ND_PRINT((ndo, "C/%s/%s", Class[class].name, Class[class].Id[id]));
 			break;
 		}
 		break;
@@ -649,7 +648,7 @@
 	return elem->asnlen + hdr;
 
 trunc:
-	printf("%s", tstr);
+	ND_PRINT((ndo, "%s", tstr));
 	return -1;
 }
 
@@ -659,7 +658,8 @@
  * BE form was added.
  */
 static int
-asn1_print(struct be *elem)
+asn1_print(netdissect_options *ndo,
+           struct be *elem)
 {
 	u_char *p = (u_char *)elem->data.raw;
 	u_int32_t asnlen = elem->asnlen;
@@ -668,9 +668,9 @@
 	switch (elem->type) {
 
 	case BE_OCTET:
-		TCHECK2(*p, asnlen);
+		ND_TCHECK2(*p, asnlen);
 		for (i = asnlen; i-- > 0; p++)
-			printf("_%.2x", *p);
+			ND_PRINT((ndo, "_%.2x", *p));
 		break;
 
 	case BE_NULL:
@@ -679,24 +679,24 @@
 	case BE_OID: {
 		int o = 0, first = -1, i = asnlen;
 
-		if (!sflag && !nflag && asnlen > 2) {
+		if (!ndo->ndo_sflag && !ndo->ndo_nflag && asnlen > 2) {
 			const struct obj_abrev *a = &obj_abrev_list[0];
 			size_t a_len = strlen(a->oid);
 			for (; a->node; a++) {
-				TCHECK2(*p, a_len);
+				ND_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);
-					fputs(a->prefix, stdout);
+					ND_PRINT((ndo, "%s", a->prefix));
 					first = 1;
 					break;
 				}
 			}
 		}
 
-		for (; !sflag && i-- > 0; p++) {
-			TCHECK(*p);
+		for (; !ndo->ndo_sflag && i-- > 0; p++) {
+			ND_TCHECK(*p);
 			o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
 			if (*p & ASN_LONGLEN)
 			        continue;
@@ -707,7 +707,7 @@
 			 */
 			if (first < 0) {
 			        int s;
-				if (!nflag)
+				if (!ndo->ndo_nflag)
 					objp = mibroot;
 				first = 0;
 				s = o / OIDMUX;
@@ -724,11 +724,11 @@
 	}
 
 	case BE_INT:
-		printf("%d", elem->data.integer);
+		ND_PRINT((ndo, "%d", elem->data.integer));
 		break;
 
 	case BE_UNS:
-		printf("%u", elem->data.uns);
+		ND_PRINT((ndo, "%u", elem->data.uns));
 		break;
 
 	case BE_UNS64: {	/* idea borrowed from by Marshall Rose */
@@ -736,16 +736,16 @@
 		int j, carry;
 		char *cpf, *cpl, last[6], first[30];
 		if (elem->data.uns64.high == 0) {
-		        printf("%u", elem->data.uns64.low);
-		        break;
+			ND_PRINT((ndo, "%u", elem->data.uns64.low));
+			break;
 		}
 		d = elem->data.uns64.high * 4294967296.0;	/* 2^32 */
 		if (elem->data.uns64.high <= 0x1fffff) {
 		        d += elem->data.uns64.low;
 #if 0 /*is looks illegal, but what is the intention?*/
-			printf("%.f", d);
+			ND_PRINT((ndo, "%.f", d));
 #else
-			printf("%f", d);
+			ND_PRINT((ndo, "%f", d));
 #endif
 			break;
 		}
@@ -769,68 +769,67 @@
 		        }
 			*cpf = j + '0';
 		}
-		fputs(first, stdout);
+		ND_PRINT((ndo, "%s", first));
 		break;
 	}
 
 	case BE_STR: {
 		register int printable = 1, first = 1;
 		const u_char *p = elem->data.str;
-		TCHECK2(*p, asnlen);
+		ND_TCHECK2(*p, asnlen);
 		for (i = asnlen; printable && i-- > 0; p++)
 			printable = ND_ISPRINT(*p);
 		p = elem->data.str;
 		if (printable) {
-			putchar('"');
-			if (fn_printn(p, asnlen, snapend)) {
-				putchar('"');
+			ND_PRINT((ndo, "\""));
+			if (fn_printn(p, asnlen, ndo->ndo_snapend)) {
+				ND_PRINT((ndo, "\""));
 				goto trunc;
 			}
-			putchar('"');
+			ND_PRINT((ndo, "\""));
 		} else
 			for (i = asnlen; i-- > 0; p++) {
-				printf(first ? "%.2x" : "_%.2x", *p);
+				ND_PRINT((ndo, first ? "%.2x" : "_%.2x", *p));
 				first = 0;
 			}
 		break;
 	}
 
 	case BE_SEQ:
-		printf("Seq(%u)", elem->asnlen);
+		ND_PRINT((ndo, "Seq(%u)", elem->asnlen));
 		break;
 
 	case BE_INETADDR:
 		if (asnlen != ASNLEN_INETADDR)
-			printf("[inetaddr len!=%d]", ASNLEN_INETADDR);
-		TCHECK2(*p, asnlen);
+			ND_PRINT((ndo, "[inetaddr len!=%d]", ASNLEN_INETADDR));
+		ND_TCHECK2(*p, asnlen);
 		for (i = asnlen; i-- != 0; p++) {
-			printf((i == asnlen-1) ? "%u" : ".%u", *p);
+			ND_PRINT((ndo, (i == asnlen-1) ? "%u" : ".%u", *p));
 		}
 		break;
 
 	case BE_NOSUCHOBJECT:
 	case BE_NOSUCHINST:
 	case BE_ENDOFMIBVIEW:
-	        printf("[%s]", Class[EXCEPTIONS].Id[elem->id]);
+		ND_PRINT((ndo, "[%s]", Class[EXCEPTIONS].Id[elem->id]));
 		break;
 
 	case BE_PDU:
-		printf("%s(%u)",
-			Class[CONTEXT].Id[elem->id], elem->asnlen);
+		ND_PRINT((ndo, "%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen));
 		break;
 
 	case BE_ANY:
-		fputs("[BE_ANY!?]", stdout);
+		ND_PRINT((ndo, "[BE_ANY!?]"));
 		break;
 
 	default:
-		fputs("[be!?]", stdout);
+		ND_PRINT((ndo, "[be!?]"));
 		break;
 	}
 	return 0;
 
 trunc:
-	printf("%s", tstr);
+	ND_PRINT((ndo, "%s", tstr));
 	return -1;
 }
 
@@ -851,15 +850,15 @@
 	int i = 0;
 
 	while (i >= 0 && length > 0) {
-		i = asn1_parse(p, length, &elem);
+		i = asn1_parse(ndo, p, length, &elem);
 		if (i >= 0) {
-			fputs(" ", stdout);
-			if (asn1_print(&elem) < 0)
+			ND_PRINT((ndo, " "));
+			if (asn1_print(ndo, &elem) < 0)
 				return;
 			if (elem.type == BE_SEQ || elem.type == BE_PDU) {
-				fputs(" {", stdout);
+				ND_PRINT((ndo, " {"));
 				asn1_decode(elem.data.raw, elem.asnlen);
-				fputs(" }", stdout);
+				ND_PRINT((ndo, " }"));
 			}
 			length -= i;
 			p += i;
@@ -899,8 +898,8 @@
 	u_int32_t asnlen = elem->asnlen;
 	int o = 0, first = -1, i = asnlen;
 
-	for (*oidlen = 0; sflag && i-- > 0; p++) {
-		TCHECK(*p);
+	for (*oidlen = 0; ndo->ndo_sflag && i-- > 0; p++) {
+		ND_TCHECK(*p);
 	        o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
 		if (*p & ASN_LONGLEN)
 		    continue;
@@ -926,7 +925,7 @@
 	return 0;
 
 trunc:
-	printf("%s", tstr);
+	ND_PRINT((ndo, "%s", tstr));
 	return -1;
 }
 
@@ -1032,17 +1031,16 @@
 		return NULL;
 	smiNode = smiGetNodeByOID(oidlen, oid);
 	if (! smiNode) {
-		*status = asn1_print(elem);
+		*status = asn1_print(ndo, elem);
 		return NULL;
 	}
-	if (vflag) {
-		fputs(smiGetNodeModule(smiNode)->name, stdout);
-		fputs("::", stdout);
+	if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "%s::", smiGetNodeModule(smiNode)->name));
 	}
-	fputs(smiNode->name, stdout);
+	ND_PRINT((ndo, "%s", smiNode->name));
 	if (smiNode->oidlen < oidlen) {
-	        for (i = smiNode->oidlen; i < oidlen; i++) {
-		        printf(".%u", oid[i]);
+		for (i = smiNode->oidlen; i < oidlen; i++) {
+			ND_PRINT((ndo, ".%u", oid[i]));
 		}
 	}
 	*status = 0;
@@ -1059,43 +1057,43 @@
 
 	if (! smiNode || ! (smiNode->nodekind
 			    & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
-	    return asn1_print(elem);
+	    return asn1_print(ndo, elem);
 	}
 
 	if (elem->type == BE_NOSUCHOBJECT
 	    || elem->type == BE_NOSUCHINST
 	    || elem->type == BE_ENDOFMIBVIEW) {
-	    return asn1_print(elem);
+	    return asn1_print(ndo, elem);
 	}
 
 	if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
-	    fputs("[notNotifyable]", stdout);
+	    ND_PRINT((ndo, "[notNotifyable]"));
 	}
 
 	if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
-	    fputs("[notReadable]", stdout);
+	    ND_PRINT((ndo, "[notReadable]"));
 	}
 
 	if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {
-	    fputs("[notWritable]", stdout);
+	    ND_PRINT((ndo, "[notWritable]"));
 	}
 
 	if (RESPONSE_CLASS(pduid)
 	    && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {
-	    fputs("[noAccess]", stdout);
+	    ND_PRINT((ndo, "[noAccess]"));
 	}
 
 	smiType = smiGetNodeType(smiNode);
 	if (! smiType) {
-	    return asn1_print(elem);
+	    return asn1_print(ndo, elem);
 	}
 
 	if (! smi_check_type(smiType->basetype, elem->type)) {
-	    fputs("[wrongType]", stdout);
+	    ND_PRINT((ndo, "[wrongType]"));
 	}
 
 	if (! smi_check_range(smiType, elem)) {
-	    fputs("[outOfRange]", stdout);
+	    ND_PRINT((ndo, "[outOfRange]"));
 	}
 
 	/* resolve bits to named bits */
@@ -1116,15 +1114,14 @@
 				       &oidlen);
 			smiNode = smiGetNodeByOID(oidlen, oid);
 			if (smiNode) {
-			        if (vflag) {
-					fputs(smiGetNodeModule(smiNode)->name, stdout);
-					fputs("::", stdout);
+			        if (ndo->ndo_vflag) {
+					ND_PRINT((ndo, "%s::", smiGetNodeModule(smiNode)->name));
 				}
-				fputs(smiNode->name, stdout);
+				ND_PRINT((ndo, "%s", smiNode->name));
 				if (smiNode->oidlen < oidlen) {
 				        for (i = smiNode->oidlen;
 					     i < oidlen; i++) {
-					        printf(".%u", oid[i]);
+					        ND_PRINT((ndo, ".%u", oid[i]));
 					}
 				}
 				done++;
@@ -1139,8 +1136,8 @@
 			     nn = smiGetNextNamedNumber(nn)) {
 			         if (nn->value.value.integer32
 				     == elem->data.integer) {
-				         fputs(nn->name, stdout);
-					 printf("(%d)", elem->data.integer);
+				         ND_PRINT((ndo, "%s", nn->name));
+					 ND_PRINT((ndo, "(%d)", elem->data.integer));
 					 done++;
 					 break;
 				}
@@ -1150,7 +1147,7 @@
 	}
 
 	if (! done) {
-		return asn1_print(elem);
+		return asn1_print(ndo, elem);
 	}
 	return 0;
 }
@@ -1193,7 +1190,8 @@
  * Decode SNMP varBind
  */
 static void
-varbind_print(u_char pduid, const u_char *np, u_int length)
+varbind_print(netdissect_options *ndo,
+              u_char pduid, const u_char *np, u_int length)
 {
 	struct be elem;
 	int count = 0, ind;
@@ -1203,15 +1201,15 @@
 	int status;
 
 	/* Sequence of varBind */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_SEQ) {
-		fputs("[!SEQ of varbind]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[!SEQ of varbind]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	if ((u_int)count < length)
-		printf("[%d extra after SEQ of varbind]", length - count);
+		ND_PRINT((ndo, "[%d extra after SEQ of varbind]", length - count));
 	/* descend */
 	length = elem.asnlen;
 	np = (u_char *)elem.data.raw;
@@ -1220,14 +1218,14 @@
 		const u_char *vbend;
 		u_int vblength;
 
-		fputs(" ", stdout);
+		ND_PRINT((ndo, " "));
 
 		/* Sequence */
-		if ((count = asn1_parse(np, length, &elem)) < 0)
+		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 			return;
 		if (elem.type != BE_SEQ) {
-			fputs("[!varbind]", stdout);
-			asn1_print(&elem);
+			ND_PRINT((ndo, "[!varbind]"));
+			asn1_print(ndo, &elem);
 			return;
 		}
 		vbend = np + count;
@@ -1237,17 +1235,17 @@
 		np = (u_char *)elem.data.raw;
 
 		/* objName (OID) */
-		if ((count = asn1_parse(np, length, &elem)) < 0)
+		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 			return;
 		if (elem.type != BE_OID) {
-			fputs("[objName!=OID]", stdout);
-			asn1_print(&elem);
+			ND_PRINT((ndo, "[objName!=OID]"));
+			asn1_print(ndo, &elem);
 			return;
 		}
 #ifdef LIBSMI
 		smiNode = smi_print_variable(&elem, &status);
 #else
-		status = asn1_print(&elem);
+		status = asn1_print(ndo, &elem);
 #endif
 		if (status < 0)
 			return;
@@ -1256,16 +1254,16 @@
 
 		if (pduid != GETREQ && pduid != GETNEXTREQ
 		    && pduid != GETBULKREQ)
-			fputs("=", stdout);
+			ND_PRINT((ndo, "="));
 
 		/* objVal (ANY) */
-		if ((count = asn1_parse(np, length, &elem)) < 0)
+		if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 			return;
 		if (pduid == GETREQ || pduid == GETNEXTREQ
 		    || pduid == GETBULKREQ) {
 			if (elem.type != BE_NULL) {
-				fputs("[objVal!=NULL]", stdout);
-				if (asn1_print(&elem) < 0)
+				ND_PRINT((ndo, "[objVal!=NULL]"));
+				if (asn1_print(ndo, &elem) < 0)
 					return;
 			}
 		} else {
@@ -1273,7 +1271,7 @@
 #ifdef LIBSMI
 				status = smi_print_value(smiNode, pduid, &elem);
 #else
-				status = asn1_print(&elem);
+				status = asn1_print(ndo, &elem);
 #endif
 			}
 			if (status < 0)
@@ -1289,30 +1287,31 @@
  * GetBulk, Inform, V2Trap, and Report
  */
 static void
-snmppdu_print(u_short pduid, const u_char *np, u_int length)
+snmppdu_print(netdissect_options *ndo,
+              u_short pduid, const u_char *np, u_int length)
 {
 	struct be elem;
 	int count = 0, error;
 
 	/* reqId (Integer) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[reqId!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[reqId!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
-	if (vflag)
-		printf("R=%d ", elem.data.integer);
+	if (ndo->ndo_vflag)
+		ND_PRINT((ndo, "R=%d ", elem.data.integer));
 	length -= count;
 	np += count;
 
 	/* errorStatus (Integer) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[errorStatus!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[errorStatus!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	error = 0;
@@ -1320,48 +1319,47 @@
 	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
 	    && elem.data.integer != 0) {
 		char errbuf[20];
-		printf("[errorStatus(%s)!=0]",
-			DECODE_ErrorStatus(elem.data.integer));
+		ND_PRINT((ndo, "[errorStatus(%s)!=0]",
+			DECODE_ErrorStatus(elem.data.integer)));
 	} else if (pduid == GETBULKREQ) {
-	        printf(" N=%d", elem.data.integer);
+		ND_PRINT((ndo, " N=%d", elem.data.integer));
 	} else if (elem.data.integer != 0) {
 		char errbuf[20];
-		printf(" %s", DECODE_ErrorStatus(elem.data.integer));
+		ND_PRINT((ndo, " %s", DECODE_ErrorStatus(elem.data.integer)));
 		error = elem.data.integer;
 	}
 	length -= count;
 	np += count;
 
 	/* errorIndex (Integer) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[errorIndex!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[errorIndex!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
 	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
 	    && elem.data.integer != 0)
-		printf("[errorIndex(%d)!=0]", elem.data.integer);
+		ND_PRINT((ndo, "[errorIndex(%d)!=0]", elem.data.integer));
 	else if (pduid == GETBULKREQ)
-	        printf(" M=%d", elem.data.integer);
+		ND_PRINT((ndo, " M=%d", elem.data.integer));
 	else if (elem.data.integer != 0) {
 		if (!error)
-			printf("[errorIndex(%d) w/o errorStatus]",
-				elem.data.integer);
+			ND_PRINT((ndo, "[errorIndex(%d) w/o errorStatus]", elem.data.integer));
 		else {
-			printf("@%d", elem.data.integer);
+			ND_PRINT((ndo, "@%d", elem.data.integer));
 			error = elem.data.integer;
 		}
 	} else if (error) {
-		fputs("[errorIndex==0]", stdout);
+		ND_PRINT((ndo, "[errorIndex==0]"));
 		error = 0;
 	}
 	length -= count;
 	np += count;
 
-	varbind_print(pduid, np, length);
+	varbind_print(ndo, pduid, np, length);
 	return;
 }
 
@@ -1369,89 +1367,90 @@
  * Decode SNMP Trap PDU
  */
 static void
-trappdu_print(const u_char *np, u_int length)
+trappdu_print(netdissect_options *ndo,
+              const u_char *np, u_int length)
 {
 	struct be elem;
 	int count = 0, generic;
 
-	putchar(' ');
+	ND_PRINT((ndo, " "));
 
 	/* enterprise (oid) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_OID) {
-		fputs("[enterprise!=OID]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[enterprise!=OID]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
-	if (asn1_print(&elem) < 0)
+	if (asn1_print(ndo, &elem) < 0)
 		return;
 	length -= count;
 	np += count;
 
-	putchar(' ');
+	ND_PRINT((ndo, " "));
 
 	/* agent-addr (inetaddr) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INETADDR) {
-		fputs("[agent-addr!=INETADDR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[agent-addr!=INETADDR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
-	if (asn1_print(&elem) < 0)
+	if (asn1_print(ndo, &elem) < 0)
 		return;
 	length -= count;
 	np += count;
 
 	/* generic-trap (Integer) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[generic-trap!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[generic-trap!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	generic = elem.data.integer;
 	{
 		char buf[20];
-		printf(" %s", DECODE_GenericTrap(generic));
+		ND_PRINT((ndo, " %s", DECODE_GenericTrap(generic)));
 	}
 	length -= count;
 	np += count;
 
 	/* specific-trap (Integer) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[specific-trap!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[specific-trap!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	if (generic != GT_ENTERPRISE) {
 		if (elem.data.integer != 0)
-			printf("[specific-trap(%d)!=0]", elem.data.integer);
+			ND_PRINT((ndo, "[specific-trap(%d)!=0]", elem.data.integer));
 	} else
-		printf(" s=%d", elem.data.integer);
+		ND_PRINT((ndo, " s=%d", elem.data.integer));
 	length -= count;
 	np += count;
 
-	putchar(' ');
+	ND_PRINT((ndo, " "));
 
 	/* time-stamp (TimeTicks) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_UNS) {			/* XXX */
-		fputs("[time-stamp!=TIMETICKS]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[time-stamp!=TIMETICKS]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
-	if (asn1_print(&elem) < 0)
+	if (asn1_print(ndo, &elem) < 0)
 		return;
 	length -= count;
 	np += count;
 
-	varbind_print (TRAP, np, length);
+	varbind_print(ndo, TRAP, np, length);
 	return;
 }
 
@@ -1459,26 +1458,27 @@
  * Decode arbitrary SNMP PDUs.
  */
 static void
-pdu_print(const u_char *np, u_int length, int version)
+pdu_print(netdissect_options *ndo,
+          const u_char *np, u_int length, int version)
 {
 	struct be pdu;
 	int count = 0;
 
 	/* PDU (Context) */
-	if ((count = asn1_parse(np, length, &pdu)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &pdu)) < 0)
 		return;
 	if (pdu.type != BE_PDU) {
-		fputs("[no PDU]", stdout);
+		ND_PRINT((ndo, "[no PDU]"));
 		return;
 	}
 	if ((u_int)count < length)
-		printf("[%d extra after PDU]", length - count);
-	if (vflag) {
-		fputs("{ ", stdout);
+		ND_PRINT((ndo, "[%d extra after PDU]", length - count));
+	if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "{ "));
 	}
-	if (asn1_print(&pdu) < 0)
+	if (asn1_print(ndo, &pdu) < 0)
 		return;
-	fputs(" ", stdout);
+	ND_PRINT((ndo, " "));
 	/* descend into PDU */
 	length = pdu.asnlen;
 	np = (u_char *)pdu.data.raw;
@@ -1486,18 +1486,18 @@
 	if (version == SNMP_VERSION_1 &&
 	    (pdu.id == GETBULKREQ || pdu.id == INFORMREQ ||
 	     pdu.id == V2TRAP || pdu.id == REPORT)) {
-	        printf("[v2 PDU in v1 message]");
+	        ND_PRINT((ndo, "[v2 PDU in v1 message]"));
 		return;
 	}
 
 	if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
-	        printf("[v1 PDU in v2 message]");
+		ND_PRINT((ndo, "[v1 PDU in v2 message]"));
 		return;
 	}
 
 	switch (pdu.id) {
 	case TRAP:
-		trappdu_print(np, length);
+		trappdu_print(ndo, np, length);
 		break;
 	case GETREQ:
 	case GETNEXTREQ:
@@ -1507,12 +1507,12 @@
 	case INFORMREQ:
 	case V2TRAP:
 	case REPORT:
-		snmppdu_print(pdu.id, np, length);
+		snmppdu_print(ndo, pdu.id, np, length);
 		break;
 	}
 
-	if (vflag) {
-		fputs(" } ", stdout);
+	if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, " } "));
 	}
 }
 
@@ -1520,70 +1520,72 @@
  * Decode a scoped SNMP PDU.
  */
 static void
-scopedpdu_print(const u_char *np, u_int length, int version)
+scopedpdu_print(netdissect_options *ndo,
+                const u_char *np, u_int length, int version)
 {
 	struct be elem;
 	int i, count = 0;
 
 	/* Sequence */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_SEQ) {
-		fputs("[!scoped PDU]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[!scoped PDU]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length = elem.asnlen;
 	np = (u_char *)elem.data.raw;
 
 	/* contextEngineID (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[contextEngineID!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[contextEngineID!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
 	np += count;
 
-	fputs("E= ", stdout);
+	ND_PRINT((ndo, "E= "));
 	for (i = 0; i < (int)elem.asnlen; i++) {
-            printf("0x%02X", elem.data.str[i]);
-        }
-	fputs(" ", stdout);
+		ND_PRINT((ndo, "0x%02X", elem.data.str[i]));
+	}
+	ND_PRINT((ndo, " "));
 
 	/* contextName (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[contextName!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[contextName!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
 	np += count;
 
-	printf("C=%.*s ", (int)elem.asnlen, elem.data.str);
+	ND_PRINT((ndo, "C=%.*s ", (int)elem.asnlen, elem.data.str));
 
-	pdu_print(np, length, version);
+	pdu_print(ndo, np, length, version);
 }
 
 /*
  * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
  */
 static void
-community_print(const u_char *np, u_int length, int version)
+community_print(netdissect_options *ndo,
+                const u_char *np, u_int length, int version)
 {
 	struct be elem;
 	int count = 0;
 
 	/* Community (String) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[comm!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[comm!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	/* default community */
@@ -1591,114 +1593,116 @@
 	    strncmp((char *)elem.data.str, DEF_COMMUNITY,
 	            sizeof(DEF_COMMUNITY) - 1) == 0))
 		/* ! "public" */
-		printf("C=%.*s ", (int)elem.asnlen, elem.data.str);
+		ND_PRINT((ndo, "C=%.*s ", (int)elem.asnlen, elem.data.str));
 	length -= count;
 	np += count;
 
-	pdu_print(np, length, version);
+	pdu_print(ndo, np, length, version);
 }
 
 /*
  * Decode SNMPv3 User-based Security Message Header (SNMPv3)
  */
 static void
-usm_print(const u_char *np, u_int length)
+usm_print(netdissect_options *ndo,
+          const u_char *np, u_int length)
 {
         struct be elem;
 	int count = 0;
 
 	/* Sequence */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_SEQ) {
-		fputs("[!usm]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[!usm]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length = elem.asnlen;
 	np = (u_char *)elem.data.raw;
 
 	/* msgAuthoritativeEngineID (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[msgAuthoritativeEngineID!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgAuthoritativeEngineID!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
 	np += count;
 
 	/* msgAuthoritativeEngineBoots (INTEGER) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[msgAuthoritativeEngineBoots!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgAuthoritativeEngineBoots!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
-	if (vflag)
-	        printf("B=%d ", elem.data.integer);
+	if (ndo->ndo_vflag)
+		ND_PRINT((ndo, "B=%d ", elem.data.integer));
 	length -= count;
 	np += count;
 
 	/* msgAuthoritativeEngineTime (INTEGER) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[msgAuthoritativeEngineTime!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgAuthoritativeEngineTime!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
-	if (vflag)
-	        printf("T=%d ", elem.data.integer);
+	if (ndo->ndo_vflag)
+		ND_PRINT((ndo, "T=%d ", elem.data.integer));
 	length -= count;
 	np += count;
 
 	/* msgUserName (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[msgUserName!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgUserName!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
         np += count;
 
-	printf("U=%.*s ", (int)elem.asnlen, elem.data.str);
+	ND_PRINT((ndo, "U=%.*s ", (int)elem.asnlen, elem.data.str));
 
 	/* msgAuthenticationParameters (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[msgAuthenticationParameters!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgAuthenticationParameters!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
         np += count;
 
 	/* msgPrivacyParameters (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[msgPrivacyParameters!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgPrivacyParameters!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
         np += count;
 
 	if ((u_int)count < length)
-		printf("[%d extra after usm SEQ]", length - count);
+		ND_PRINT((ndo, "[%d extra after usm SEQ]", length - count));
 }
 
 /*
  * Decode SNMPv3 Message Header (SNMPv3)
  */
 static void
-v3msg_print(const u_char *np, u_int length)
+v3msg_print(netdissect_options *ndo,
+            const u_char *np, u_int length)
 {
 	struct be elem;
 	int count = 0;
@@ -1708,75 +1712,74 @@
 	int xlength = length;
 
 	/* Sequence */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_SEQ) {
-		fputs("[!message]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[!message]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length = elem.asnlen;
 	np = (u_char *)elem.data.raw;
 
-	if (vflag) {
-		fputs("{ ", stdout);
+	if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "{ "));
 	}
 
 	/* msgID (INTEGER) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[msgID!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgID!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
 	np += count;
 
 	/* msgMaxSize (INTEGER) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[msgMaxSize!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgMaxSize!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
 	np += count;
 
 	/* msgFlags (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[msgFlags!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgFlags!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	if (elem.asnlen != 1) {
-	        printf("[msgFlags size %d]", elem.asnlen);
+		ND_PRINT((ndo, "[msgFlags size %d]", elem.asnlen));
 		return;
 	}
 	flags = elem.data.str[0];
 	if (flags != 0x00 && flags != 0x01 && flags != 0x03
 	    && flags != 0x04 && flags != 0x05 && flags != 0x07) {
-		printf("[msgFlags=0x%02X]", flags);
+		ND_PRINT((ndo, "[msgFlags=0x%02X]", flags));
 		return;
 	}
 	length -= count;
 	np += count;
 
-	fputs("F=", stdout);
-	if (flags & 0x01) fputs("a", stdout);
-	if (flags & 0x02) fputs("p", stdout);
-	if (flags & 0x04) fputs("r", stdout);
-	fputs(" ", stdout);
+	ND_PRINT((ndo, "F=%s%s%s ",
+	          flags & 0x01 ? "a" : "",
+	          flags & 0x02 ? "p" : "",
+	          flags & 0x04 ? "r" : ""));
 
 	/* msgSecurityModel (INTEGER) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[msgSecurityModel!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgSecurityModel!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	model = elem.data.integer;
@@ -1784,18 +1787,18 @@
 	np += count;
 
 	if ((u_int)count < length)
-		printf("[%d extra after message SEQ]", length - count);
+		ND_PRINT((ndo, "[%d extra after message SEQ]", length - count));
 
-	if (vflag) {
-		fputs("} ", stdout);
+	if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "} "));
 	}
 
 	if (model == 3) {
-	    if (vflag) {
-		fputs("{ USM ", stdout);
+	    if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "{ USM "));
 	    }
 	} else {
-	    printf("[security model %d]", model);
+	    ND_PRINT((ndo, "[security model %d]", model));
             return;
 	}
 
@@ -1803,31 +1806,31 @@
 	length = xlength - (np - xnp);
 
 	/* msgSecurityParameters (OCTET STRING) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_STR) {
-		fputs("[msgSecurityParameters!=STR]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[msgSecurityParameters!=STR]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	length -= count;
 	np += count;
 
 	if (model == 3) {
-	    usm_print(elem.data.str, elem.asnlen);
-	    if (vflag) {
-		fputs("} ", stdout);
+	    usm_print(ndo, elem.data.str, elem.asnlen);
+	    if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "} "));
 	    }
 	}
 
-	if (vflag) {
-	    fputs("{ ScopedPDU ", stdout);
+	if (ndo->ndo_vflag) {
+	    ND_PRINT((ndo, "{ ScopedPDU "));
 	}
 
-	scopedpdu_print(np, length, 3);
+	scopedpdu_print(ndo, np, length, 3);
 
-	if (vflag) {
-		fputs("} ", stdout);
+	if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "} "));
 	}
 }
 
@@ -1835,34 +1838,35 @@
  * Decode SNMP header and pass on to PDU printing routines
  */
 void
-snmp_print(const u_char *np, u_int length)
+snmp_print(netdissect_options *ndo,
+           const u_char *np, u_int length)
 {
 	struct be elem;
 	int count = 0;
 	int version = 0;
 
-	putchar(' ');
+	ND_PRINT((ndo, " "));
 
 	/* initial Sequence */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_SEQ) {
-		fputs("[!init SEQ]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[!init SEQ]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 	if ((u_int)count < length)
-		printf("[%d extra after iSEQ]", length - count);
+		ND_PRINT((ndo, "[%d extra after iSEQ]", length - count));
 	/* descend */
 	length = elem.asnlen;
 	np = (u_char *)elem.data.raw;
 
 	/* Version (INTEGER) */
-	if ((count = asn1_parse(np, length, &elem)) < 0)
+	if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
 		return;
 	if (elem.type != BE_INT) {
-		fputs("[version!=INT]", stdout);
-		asn1_print(&elem);
+		ND_PRINT((ndo, "[version!=INT]"));
+		asn1_print(ndo, &elem);
 		return;
 	}
 
@@ -1870,11 +1874,11 @@
 	case SNMP_VERSION_1:
 	case SNMP_VERSION_2:
 	case SNMP_VERSION_3:
-	        if (vflag)
-		        printf("{ %s ", SnmpVersion[elem.data.integer]);
+		if (ndo->ndo_vflag)
+			ND_PRINT((ndo, "{ %s ", SnmpVersion[elem.data.integer]));
 		break;
 	default:
-	        printf("[version = %d]", elem.data.integer);
+	        ND_PRINT((ndo, "[version = %d]", elem.data.integer));
 		return;
 	}
 	version = elem.data.integer;
@@ -1884,17 +1888,17 @@
 	switch (version) {
 	case SNMP_VERSION_1:
         case SNMP_VERSION_2:
-		community_print(np, length, version);
+		community_print(ndo, np, length, version);
 		break;
 	case SNMP_VERSION_3:
-		v3msg_print(np, length);
+		v3msg_print(ndo, np, length);
 		break;
 	default:
-	        printf("[version = %d]", elem.data.integer);
+		ND_PRINT((ndo, "[version = %d]", elem.data.integer));
 		break;
 	}
 
-	if (vflag) {
-		fputs("} ", stdout);
+	if (ndo->ndo_vflag) {
+		ND_PRINT((ndo, "} "));
 	}
 }
diff --git a/print-udp.c b/print-udp.c
index 5d2d83c..4b0a481 100644
--- a/print-udp.c
+++ b/print-udp.c
@@ -437,7 +437,7 @@
 
 		case PT_SNMP:
 			udpipaddr_print(ndo, ip, sport, dport);
-			snmp_print((const u_char *)(up + 1), length);
+			snmp_print(ndo, (const u_char *)(up + 1), length);
 			break;
 
 		case PT_CNFP:
@@ -591,7 +591,7 @@
 			isakmp_print(ndo, (const u_char *)(up + 1), length, bp2);
 #endif
 		else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT))
-			snmp_print((const u_char *)(up + 1), length);
+			snmp_print(ndo, (const u_char *)(up + 1), length);
 		else if (ISPORT(NTP_PORT))
 			ntp_print(ndo, (const u_char *)(up + 1), length);
 		else if (ISPORT(KERBEROS_PORT) || ISPORT(KERBEROS_SEC_PORT))