diff -u /tmp/tcpdump-3.4a6/interface.h ./interface.h
--- /tmp/tcpdump-3.4a6/interface.h	Wed May 28 21:54:45 1997
+++ ./interface.h	Sun Feb 22 11:05:27 1998
@@ -52,6 +52,7 @@
 #define PT_RPC		3	/* Remote Procedure Call */
 #define PT_RTP		4	/* Real-Time Applications protocol */
 #define PT_RTCP		5	/* Real-Time Applications control protocol */
+#define PT_SNMP		6	/* Simple Network Management Protocol */
 
 #ifndef min
 #define min(a,b) ((a)>(b)?(b):(a))
diff -u /tmp/tcpdump-3.4a6/mib.h ./mib.h
--- /tmp/tcpdump-3.4a6/mib.h	Fri Jan 14 04:11:41 1994
+++ ./mib.h	Sun Feb 22 11:20:05 1998
@@ -1217,6 +1217,202 @@
 	"snmp", 11, 0,
 	&_snmpEnableAuthTraps_obj, &_transmission_obj
 },
+_usmMIBCompliances_obj = {
+	"usmMIBCompliances", 1, 0,
+	NULL, NULL
+},
+_usmMIBGroups_obj = {
+	"usmMIBGroups", 2, 0,
+	NULL, &_usmMIBCompliances_obj
+},
+_usmUserEngineID_obj = {
+	"usmUserEngineID", 1, 0,
+	NULL, NULL
+},
+_usmUserName_obj = {
+	"usmUserName", 2, 0,
+	NULL, &_usmUserEngineID_obj
+},
+_usmUserSecurityName_obj = {
+	"usmUserSecurityName", 3, 0,
+	NULL, &_usmUserName_obj
+},
+_usmUserCloneFrom_obj = {
+	"usmUserCloneFrom", 4, 0,
+	NULL, &_usmUserSecurityName_obj
+},
+_usmUserAuthProtocol_obj = {
+	"usmUserAuthProtocol", 5, 0,
+	NULL, &_usmUserCloneFrom_obj
+},
+_usmUserAuthKeyChange_obj = {
+	"usmUserAuthKeyChange", 6, 0,
+	NULL, &_usmUserAuthProtocol_obj
+},
+_usmUserOwnAuthKeyChange_obj = {
+	"usmUserOwnAuthKeyChange", 7, 0,
+	NULL, &_usmUserAuthKeyChange_obj
+},
+_usmUserPrivProtocol_obj = {
+	"usmUserPrivProtocol", 8, 0,
+	NULL, &_usmUserOwnAuthKeyChange_obj
+},
+_usmUserPrivKeyChange_obj = {
+	"usmUserPrivKeyChange", 9, 0,
+	NULL, &_usmUserPrivProtocol_obj
+},
+_usmUserOwnPrivKeyChange_obj = {
+	"usmUserOwnPrivKeyChange", 10, 0,
+	NULL, &_usmUserPrivKeyChange_obj
+},
+_usmUserPublic_obj = {
+	"usmUserPublic", 11, 0,
+	NULL, &_usmUserOwnPrivKeyChange_obj
+},
+_usmUserStorageType_obj = {
+	"usmUserStorageType", 12, 0,
+	NULL, &_usmUserPublic_obj
+},
+_usmUserStatus_obj = {
+	"usmUserStatus", 13, 0,
+	NULL, &_usmUserStorageType_obj
+},
+_usmUserEntry_obj = {
+	"usmUserEntry", 1, 0,
+	&_usmUserStatus_obj, NULL
+},
+_usmUserSpinLock_obj = {
+	"usmUserSpinLock", 1, 0,
+	NULL, NULL
+},
+_usmUserTable_obj = {
+	"usmUserTable", 2, 0,
+	&_usmUserEntry_obj, &_usmUserSpinLock_obj
+},
+_usmStatsUnsupportedSecLevels_obj = {
+	"usmStatsUnsupportedSecLevels", 1, 0,
+	NULL, NULL
+},
+_usmStatsNotInTimeWindows_obj = {
+	"usmStatsNotInTimeWindows", 2, 0,
+	NULL, &_usmStatsUnsupportedSecLevels_obj
+},
+_usmStatsUnknownUserNames_obj = {
+	"usmStatsUnknownUserNames", 3, 0,
+	NULL, &_usmStatsNotInTimeWindows_obj
+},
+_usmStatsUnknownEngineIDs_obj = {
+	"usmStatsUnknownEngineIDs", 4, 0,
+	NULL, &_usmStatsUnknownUserNames_obj
+},
+_usmStatsWrongDigests_obj = {
+	"usmStatsWrongDigests", 5, 0,
+	NULL, &_usmStatsUnknownEngineIDs_obj
+},
+_usmStatsDecryptionErrors_obj = {
+	"usmStatsDecryptionErrors", 6, 0,
+	NULL, &_usmStatsWrongDigests_obj
+},
+_usmStats_obj = {
+	"usmStats", 1, 0,
+	&_usmStatsDecryptionErrors_obj, NULL
+},
+_usmUser_obj = {
+	"usmUser", 2, 0,
+	&_usmUserTable_obj, &_usmStats_obj
+},
+_usmMIBObjects_obj = {
+	"usmMIBObjects", 1, 0,
+	&_usmUser_obj, NULL
+},
+_usmMIBConformance_obj = {
+	"usmMIBConformance", 2, 0,
+	&_usmMIBGroups_obj, &_usmMIBObjects_obj
+},
+_snmpMPDMIBCompliances_obj = {
+	"snmpMPDMIBCompliances", 1, 0,
+	NULL, NULL
+},
+_snmpMPDMIBGroups_obj = {
+	"snmpMPDMIBGroups", 2, 0,
+	NULL, &_snmpMPDMIBCompliances_obj
+},
+_snmpUnknownSecurityModels_obj = {
+	"snmpUnknownSecurityModels", 1, 0,
+	NULL, NULL
+},
+_snmpInvalidMsgs_obj = {
+	"snmpInvalidMsgs", 2, 0,
+	NULL, &_snmpUnknownSecurityModels_obj
+},
+_snmpUnknownPDUHandlers_obj = {
+	"snmpUnknownPDUHandlers", 3, 0,
+	NULL, &_snmpInvalidMsgs_obj
+},
+_snmpMPDStats_obj = {
+	"snmpMPDStats", 1, 0,
+	&_snmpUnknownPDUHandlers_obj, NULL
+},
+_snmpMPDAdmin_obj = {
+	"snmpMPDAdmin", 1, 0,
+	NULL, NULL
+},
+_snmpMPDMIBObjects_obj = {
+	"snmpMPDMIBObjects", 2, 0,
+	&_snmpMPDStats_obj, &_snmpMPDAdmin_obj
+},
+_snmpMPDMIBConformance_obj = {
+	"snmpMPDMIBConformance", 3, 0,
+	&_snmpMPDMIBGroups_obj, &_snmpMPDMIBObjects_obj
+},
+_snmpEngineID_obj = {
+	"snmpEngineID", 1, 0,
+	NULL, NULL
+},
+_snmpEngineBoots_obj = {
+	"snmpEngineBoots", 2, 0,
+	NULL, &_snmpEngineID_obj
+},
+_snmpEngineTime_obj = {
+	"snmpEngineTime", 3, 0,
+	NULL, &_snmpEngineBoots_obj
+},
+_snmpEngineMaxMessageSize_obj = {
+	"snmpEngineMaxMessageSize", 4, 0,
+	NULL, &_snmpEngineTime_obj
+},
+_snmpEngine_obj = {
+	"snmpEngine", 1, 0,
+	&_snmpEngineMaxMessageSize_obj, NULL
+},
+_snmpFrameworkAdmin_obj = {
+	"snmpFrameworkAdmin", 1, 0,
+	NULL, NULL
+},
+_snmpFrameworkMIBObjects_obj = {
+	"snmpFrameworkMIBObjects", 2, 0,
+	&_snmpEngine_obj, &_snmpFrameworkAdmin_obj
+},
+_snmpFrameworkMIBConformance_obj = {
+	"snmpFrameworkMIBConformance", 3, 0,
+	NULL, &_snmpFrameworkMIBObjects_obj
+},
+_snmpFrameworkMIB_obj = {
+	"snmpFrameworkMIB", 10, 0,
+	&_snmpFrameworkMIBConformance_obj, NULL
+},
+_snmpMPDMIB_obj = {
+	"snmpMPDMIB", 11, 0,
+	&_snmpMPDMIBConformance_obj, &_snmpFrameworkMIB_obj
+},
+_snmpUsmMIB_obj = {
+	"snmpUsmMIB", 15, 0,
+	&_usmMIBConformance_obj, &_snmpMPDMIB_obj
+},
+_snmpModules_obj = {
+	"snmpModules", 3, 0,
+	&_snmpUsmMIB_obj, NULL
+},
 _mib_obj = {
 	"mib", 1, 0,
 	&_snmp_obj, NULL
@@ -1237,9 +1433,17 @@
 	"private", 4, 0,
 	&_enterprises_obj, &_experimental_obj
 },
+_security_obj = {
+	"security", 5, 0,
+	NULL, &_private_obj
+},
+_snmpV2_obj = {
+	"snmpV2", 6, 0,
+	&_snmpModules_obj, &_security_obj
+},
 _internet_obj = {
 	"internet", 1, 0,
-	&_private_obj, NULL
+	&_snmpV2_obj, NULL
 },
 _dod_obj = {
 	"dod", 6, 0,
diff -u /tmp/tcpdump-3.4a6/print-snmp.c ./print-snmp.c
--- /tmp/tcpdump-3.4a6/print-snmp.c	Sun Jun 15 22:20:28 1997
+++ ./print-snmp.c	Sun Feb 22 11:23:00 1998
@@ -94,7 +94,11 @@
 #define GAUGE 2
 	"TimeTicks",
 #define TIMETICKS 3
-	"Opaque"
+	"Opaque",
+#define OPAQUE 4
+	"C-5",
+	"Counter64"
+#define COUNTER64 6
 };
 
 /*
@@ -109,8 +113,28 @@
 #define GETRESP 2
 	"SetRequest",
 #define SETREQ 3
-	"Trap"
+	"Trap",
 #define TRAP 4
+	"GetBulk",
+#define GETBULKREQ 5
+	"Inform",
+#define INFORMREQ 6
+	"V2Trap",
+#define V2TRAP 7
+	"Report"
+#define REPORT 8
+};
+
+/*
+ * Context-specific ASN.1 types for the SNMP Exceptions and their tags
+ */
+char *Exceptions[] = {
+	"noSuchObject",
+#define NOSUCHOBJECT 0
+	"noSuchInstance",
+#define NOSUCHINSTANCE 1
+	"endOfMibView",
+#define ENDOFMIBVIEW 2
 };
 
 /*
@@ -130,10 +154,23 @@
 	"noSuchName",
 	"badValue",
 	"readOnly",
-	"genErr"
+	"genErr",
+	"noAccess",
+	"wrongType",
+	"wrongLength",
+	"wrongEncoding",
+	"wrongValue",
+	"noCreation",
+	"inconsistentValue",
+	"resourceUnavailable",
+	"commitFailed",
+	"undoFailed",
+	"authorizationError",
+	"notWritable",
+	"inconsistentName"
 };
 #define DECODE_ErrorStatus(e) \
-	( e >= 0 && e <= sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
+	( e >= 0 && e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
 	? ErrorStatus[e] : (sprintf(errbuf, "err=%u", e), errbuf))
 
 /*
@@ -150,7 +187,7 @@
 #define GT_ENTERPRISE 7
 };
 #define DECODE_GenericTrap(t) \
-	( t >= 0 && t <= sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
+	( t >= 0 && t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
 	? GenericTrap[t] : (sprintf(buf, "gt=%d", t), buf))
 
 /*
@@ -172,6 +209,8 @@
 #define	CONTEXT		2
 	defineCLASS(Private),
 #define	PRIVATE		3
+	defineCLASS(Exceptions),
+#define EXCEPTIONS	4
 };
 
 /*
@@ -227,6 +266,10 @@
 	/* .iso.org.dod.internet.experimental */
 	{ "X:",	&_experimental_obj,	"\53\6\1\3" },
 #endif
+#ifndef NO_ABBREV_SNMPMODS
+	/* .iso.org.dod.internet.snmpV2.snmpModules */
+        { "S:", &_snmpModules_obj,      "\53\6\1\6\3" },
+#endif
 	{ 0,0,0 }
 };
 
@@ -260,6 +303,10 @@
 		int32_t integer;
 		u_int32_t uns;
 		const u_char *str;
+	        struct {
+		        u_int32_t high;
+		        u_int32_t low;
+		} uns64;
 	} data;
 	u_short id;
 	u_char form, class;		/* tag info */
@@ -275,13 +322,30 @@
 #define BE_SEQ		7
 #define BE_INETADDR	8
 #define BE_PDU		9
+#define BE_UNS64	10
+#define BE_NOSUCHOBJECT	128
+#define BE_NOSUCHINST	129
+#define BE_ENDOFMIBVIEW	130
+};
+
+/*
+ * SNMP versions recognized by this module
+ */
+char *SnmpVersion[] = {
+	"SNMPv1",
+#define SNMP_VERSION_1	0
+	"SNMPv2c",
+#define SNMP_VERSION_2	1
+	"SNMPv2u",
+#define SNMP_VERSION_2U	2
+	"SNMPv3"
+#define SNMP_VERSION_3	3
 };
 
 /*
  * Defaults for SNMP PDU components
  */
 #define DEF_COMMUNITY "public"
-#define DEF_VERSION 0
 
 /*
  * constants for ASN.1 decoding
@@ -325,7 +389,7 @@
 	elem->asnlen = 0;
 	elem->type = BE_ANY;
 	if (len < 1) {
-		ifNotTruncated puts("[nothing to parse], stdout");
+		ifNotTruncated fputs("[nothing to parse]", stdout);
 		return -1;
 	}
 
@@ -471,6 +535,20 @@
 				break;
 			}
 
+			case COUNTER64: {
+				register u_int32_t high, low;
+			        elem->type = BE_UNS64;
+				high = 0, low = 0;
+				for (i = elem->asnlen; i-- > 0; p++) {
+				        high = (high << 8) | 
+					    ((low & 0xFF000000) >> 24);
+					low = (low << 8) | *p;
+				}
+				elem->data.uns64.high = high;
+				elem->data.uns64.low = low;
+				break;
+			}
+
 			default:
 				elem->type = BE_OCTET;
 				elem->data.raw = (caddr_t)p;
@@ -480,6 +558,25 @@
 			}
 			break;
 
+		case CONTEXT:
+			switch (id) {
+			case NOSUCHOBJECT:
+				elem->type = BE_NOSUCHOBJECT;
+				elem->data.raw = NULL;
+				break;
+
+			case NOSUCHINSTANCE:
+				elem->type = BE_NOSUCHINST;
+				elem->data.raw = NULL;
+				break;
+
+			case ENDOFMIBVIEW:
+				elem->type = BE_ENDOFMIBVIEW;
+				elem->data.raw = NULL;
+				break;
+			}
+			break;
+
 		default:
 			elem->type = BE_OCTET;
 			elem->data.raw = (caddr_t)p;
@@ -595,6 +692,39 @@
 		printf("%d", elem->data.uns);
 		break;
 
+	case BE_UNS64: {	/* idea borrowed from by Marshall Rose */
+	        double d;
+		int j, carry;
+		char *cpf, *cpl, last[6], first[30];
+		if (elem->data.uns64.high == 0) {
+		        printf("%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;
+			printf("%.f", d);
+			break;
+		}
+		d += (elem->data.uns64.low & 0xfffff000);
+		sprintf(first, "%.f", d);
+		sprintf(last, "%5.5d", elem->data.uns64.low & 0xfff);
+		for (carry = 0, cpf = first+strlen(first)-1, cpl = last+4;
+		     cpl >= last;
+		     cpf--, cpl--) {
+		        j = carry + (*cpf - '0') + (*cpl - '0');
+			if (j > 9) {
+			        j -= 10;
+				carry = 1;
+			} else {
+			        carry = 0;
+		        }
+			*cpf = j + '0';
+		}
+		fputs(first, stdout);
+		break;
+	}
+
 	case BE_STR: {
 		register int printable = 1, first = 1;
 		const u_char *p = elem->data.str;
@@ -630,6 +760,12 @@
 		break;
 	}
 
+	case BE_NOSUCHOBJECT:
+	case BE_NOSUCHINST:
+	case BE_ENDOFMIBVIEW:
+	        printf("[%s]", Class[EXCEPTIONS].Id[elem->id]);
+		break;
+
 	case BE_PDU:
 		printf("%s(%u)",
 			Class[CONTEXT].Id[elem->id], elem->asnlen);
@@ -768,13 +904,15 @@
 		length -= count;
 		np += count;
 
-		if (pduid != GETREQ && pduid != GETNEXTREQ && !error)
+		if (pduid != GETREQ && pduid != GETNEXTREQ
+		    && pduid != GETBULKREQ && !error)
 				fputs("=", stdout);
 
 		/* objVal (ANY) */
 		if ((count = asn1_parse(np, length, &elem)) < 0)
 			return;
-		if (pduid == GETREQ || pduid == GETNEXTREQ) {
+		if (pduid == GETREQ || pduid == GETNEXTREQ
+		    || pduid == GETBULKREQ) {
 			if (elem.type != BE_NULL) {
 				fputs("[objVal!=NULL]", stdout);
 				asn1_print(&elem);
@@ -791,7 +929,8 @@
 }
 
 /*
- * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest
+ * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
+ * GetBulk, Inform, V2Trap, and Report
  */
 static void
 snmppdu_print(u_char pduid, const u_char *np, u_int length)
@@ -820,11 +959,14 @@
 		return;
 	}
 	error = 0;
-	if ((pduid == GETREQ || pduid == GETNEXTREQ)
+	if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
+	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
 	    && elem.data.integer != 0) {
 		char errbuf[10];
 		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];
 		printf(" %s", DECODE_ErrorStatus(elem.data.integer));
@@ -841,9 +983,12 @@
 		asn1_print(&elem);
 		return;
 	}
-	if ((pduid == GETREQ || pduid == GETNEXTREQ)
+	if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
+	    || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
 	    && elem.data.integer != 0)
 		printf("[errorIndex(%d)!=0]", elem.data.integer);
+	else if (pduid == GETBULKREQ)
+	        printf(" M=%d", elem.data.integer);
 	else if (elem.data.integer != 0) {
 		if (!error)
 			printf("[errorIndex(%d) w/o errorStatus]",
@@ -867,7 +1012,7 @@
  * Decode SNMP Trap PDU
  */
 static void
-trap_print(const u_char *np, u_int length)
+trappdu_print(const u_char *np, u_int length)
 {
 	struct be elem;
 	int count = 0, generic;
@@ -951,53 +1096,119 @@
 }
 
 /*
- * Decode SNMP header and pass on to PDU printing routines
+ * Decode arbitrary SNMP PDUs.
  */
-void
-snmp_print(const u_char *np, u_int length)
+static void
+pdu_print(const u_char *np, u_int length, int version)
 {
-	struct be elem, pdu;
+	struct be pdu;
 	int count = 0;
 
-	truncated = 0;
+	/* PDU (Context) */
+	if ((count = asn1_parse(np, length, &pdu)) < 0)
+		return;
+	if (pdu.type != BE_PDU) {
+		fputs("[no PDU]", stdout);
+		return;
+	}
+	if (count < length)
+		printf("[%d extra after PDU]", length - count);
+	asn1_print(&pdu);
+	/* descend into PDU */
+	length = pdu.asnlen;
+	np = (u_char *)pdu.data.raw;
 
-	/* truncated packet? */
-	if (np + length > snapend) {
-		truncated = 1;
-		length = snapend - np;
+	if (version == SNMP_VERSION_1 &&
+	    (pdu.id == GETBULKREQ || pdu.id == INFORMREQ || 
+	     pdu.id == V2TRAP || pdu.id == REPORT)) {
+	        printf("[v2 PDU in v1 message]");
+		return;
 	}
 
-	putchar(' ');
+	if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
+	        printf("[v1 PDU in v2 message]");
+		return;
+	}
 
-	/* initial Sequence */
+	switch (pdu.id) {
+	case TRAP:
+		trappdu_print(np, length);
+		break;
+	case GETREQ:
+	case GETNEXTREQ:
+	case GETRESP:
+	case SETREQ:
+	case GETBULKREQ:
+	case INFORMREQ:
+	case V2TRAP:
+	case REPORT:
+		snmppdu_print(pdu.id, np, length);
+		break;
+	}
+}
+
+/*
+ * Decode a scoped SNMP PDU.
+ */
+static void
+scopedpdu_print(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)
 		return;
 	if (elem.type != BE_SEQ) {
-		fputs("[!init SEQ]", stdout);
+		fputs("[!scoped PDU]", stdout);
 		asn1_print(&elem);
 		return;
 	}
-	if (count < length)
-		printf("[%d extra after iSEQ]", length - count);
-	/* descend */
 	length = elem.asnlen;
 	np = (u_char *)elem.data.raw;
-	/* Version (Integer) */
+
+	/* contextEngineID (OCTET STRING) */
 	if ((count = asn1_parse(np, length, &elem)) < 0)
 		return;
-	if (elem.type != BE_INT) {
-		fputs("[version!=INT]", stdout);
+	if (elem.type != BE_STR) {
+		fputs("[contextEngineID!=STR]", stdout);
 		asn1_print(&elem);
 		return;
 	}
-	/* only handle version==0 */
-	if (elem.data.integer != DEF_VERSION) {
-		printf("[version(%d)!=0]", elem.data.integer);
+	length -= count;
+	np += count;
+
+	fputs("E= ", stdout);
+	for (i = 0; i < (int)elem.asnlen; i++) {
+            printf("0x%02X", elem.data.str[i]);
+        }
+	fputs(" ", stdout);
+
+	/* contextName (OCTET STRING) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_STR) {
+		fputs("[contextName!=STR]", stdout);
+		asn1_print(&elem);
 		return;
 	}
 	length -= count;
 	np += count;
 
+	printf("C=%.*s ", (int)elem.asnlen, elem.data.str);
+
+	pdu_print(np, length, version);
+}
+
+/*
+ * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
+ */
+static void
+community_print(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)
 		return;
@@ -1014,30 +1225,295 @@
 	length -= count;
 	np += count;
 
-	/* PDU (Context) */
-	if ((count = asn1_parse(np, length, &pdu)) < 0)
+	pdu_print(np, length, version);
+}
+
+/*
+ * Decode SNMPv3 User-based Security Message Header (SNMPv3)
+ */
+static void
+usm_print(const u_char *np, u_int length)
+{
+        struct be elem;
+	int count = 0;
+
+	/* Sequence */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
 		return;
-	if (pdu.type != BE_PDU) {
-		fputs("[no PDU]", stdout);
+	if (elem.type != BE_SEQ) {
+		fputs("[!usm]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length = elem.asnlen;
+	np = (u_char *)elem.data.raw;
+
+	/* msgAuthoritativeEngineID (OCTET STRING) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_STR) {
+		fputs("[msgAuthoritativeEngineID!=STR]", stdout);
+		asn1_print(&elem);
 		return;
 	}
+	length -= count;
+	np += count;
+
+	/* msgAuthoritativeEngineBoots (INTEGER) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_INT) {
+		fputs("[msgAuthoritativeEngineBoots!=INT]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	if (vflag) 
+	        printf("B=%d ", elem.data.integer);
+	length -= count;
+	np += count;
+
+	/* msgAuthoritativeEngineTime (INTEGER) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_INT) {
+		fputs("[msgAuthoritativeEngineTime!=INT]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	if (vflag) 
+	        printf("T=%d ", elem.data.integer);
+	length -= count;
+	np += count;
+
+	/* msgUserName (OCTET STRING) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_STR) {
+		fputs("[msgUserName!=STR]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length -= count;
+        np += count;
+
+	printf("U=%.*s ", (int)elem.asnlen, elem.data.str);
+
+	/* msgAuthenticationParameters (OCTET STRING) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_STR) {
+		fputs("[msgAuthenticationParameters!=STR]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length -= count;
+        np += count;
+
+	/* msgPrivacyParameters (OCTET STRING) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_STR) {
+		fputs("[msgPrivacyParameters!=STR]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length -= count;
+        np += count;
+
 	if (count < length)
-		printf("[%d extra after PDU]", length - count);
-	asn1_print(&pdu);
-	/* descend into PDU */
-	length = pdu.asnlen;
-	np = (u_char *)pdu.data.raw;
+		printf("[%d extra after usm SEQ]", length - count);
+}
 
-	switch (pdu.id) {
-	case TRAP:
-		trap_print(np, length);
+/*
+ * Decode SNMPv3 Message Header (SNMPv3)
+ */
+static void
+v3msg_print(const u_char *np, u_int length)
+{
+	struct be elem;
+	int count = 0;
+	u_char flags;
+	int model;
+	const u_char *xnp = np;
+	int xlength = length;
+
+	/* Sequence */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_SEQ) {
+		fputs("[!message]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length = elem.asnlen;
+	np = (u_char *)elem.data.raw;
+
+	/* msgID (INTEGER) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_INT) {
+		fputs("[msgID!=INT]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length -= count;
+	np += count;
+
+	/* msgMaxSize (INTEGER) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_INT) {
+		fputs("[msgMaxSize!=INT]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length -= count;
+	np += count;
+
+	/* msgFlags (OCTET STRING) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_STR) {
+		fputs("[msgFlags!=STR]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	if (elem.asnlen != 1) {
+	        printf("[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);
+		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);
+
+	/* msgSecurityModel (INTEGER) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_INT) {
+		fputs("[msgSecurityModel!=INT]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	model = elem.data.integer;
+	length -= count;
+	np += count;
+
+	if (count < length)
+		printf("[%d extra after message SEQ]", length - count);
+
+	if (model == 3) {
+	    if (vflag) {
+		fputs("USM ", stdout);
+	    }
+	} else {
+	    printf("[security model %d]", model);
+            return;
+	}
+
+	np = xnp + (np - xnp);
+	length = xlength - (np - xnp);
+
+	/* msgSecurityParameters (OCTET STRING) */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_STR) {
+		fputs("[msgSecurityParameters!=STR]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	length -= count;
+	np += count;
+
+	if (model == 3) {
+	    usm_print(elem.data.str, elem.asnlen);
+	}
+
+	if (vflag) {
+	    fputs("ScopedPDU ", stdout);
+	}
+
+	scopedpdu_print(np, length, 3);
+}
+
+/*
+ * Decode SNMP header and pass on to PDU printing routines
+ */
+void
+snmp_print(const u_char *np, u_int length)
+{
+	struct be elem;
+	int count = 0;
+	int version = 0;
+
+	truncated = 0;
+
+	/* truncated packet? */
+	if (np + length > snapend) {
+		truncated = 1;
+		length = snapend - np;
+	}
+
+	putchar(' ');
+
+	/* initial Sequence */
+	if ((count = asn1_parse(np, length, &elem)) < 0)
+		return;
+	if (elem.type != BE_SEQ) {
+		fputs("[!init SEQ]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+	if (count < length)
+		printf("[%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)
+		return;
+	if (elem.type != BE_INT) {
+		fputs("[version!=INT]", stdout);
+		asn1_print(&elem);
+		return;
+	}
+
+	switch (elem.data.integer) {
+	case SNMP_VERSION_1:
+	case SNMP_VERSION_2:
+	case SNMP_VERSION_3:
+	        if (vflag)
+		        printf("%s ", SnmpVersion[elem.data.integer]);
 		break;
-	case GETREQ:
-	case GETNEXTREQ:
-	case GETRESP:
-	case SETREQ:
-		snmppdu_print(pdu.id, np, length);
+	default:
+	        printf("[version = %d]", elem.data.integer);
+		return;
+	}
+	version = elem.data.integer;
+	length -= count;
+	np += count;
+
+	switch (version) {
+	case SNMP_VERSION_1:
+        case SNMP_VERSION_2:
+		community_print(np, length, version);
+		break;
+	case SNMP_VERSION_3:
+		v3msg_print(np, length);
+		break;
+	default:
+	        printf("[version = %d]", elem.data.integer);
 		break;
 	}
-	return;
 }
diff -u /tmp/tcpdump-3.4a6/print-udp.c ./print-udp.c
--- /tmp/tcpdump-3.4a6/print-udp.c	Mon Jul 28 06:58:57 1997
+++ ./print-udp.c	Sun Feb 22 11:05:28 1998
@@ -374,6 +374,15 @@
 			while (cp < ep)
 				cp = rtcp_print(cp, ep);
 			break;
+
+		case PT_SNMP:
+			(void)printf("%s.%s > %s.%s:",
+                                ipaddr_string(&ip->ip_src),
+                                udpport_string(sport),
+                                ipaddr_string(&ip->ip_dst),
+                                udpport_string(dport));
+			snmp_print((const u_char *)(up + 1), length);
+			break;
 		}
 		return;
 	}
diff -u /tmp/tcpdump-3.4a6/tcpdump.1 ./tcpdump.1
--- /tmp/tcpdump-3.4a6/tcpdump.1	Tue Jul  1 01:32:09 1997
+++ ./tcpdump.1	Sun Feb 22 11:05:28 1998
@@ -185,8 +185,9 @@
 \fBrtp\fR (Real-Time Applications protocol),
 \fBrtcp\fR (Real-Time Applications control protocol),
 \fBvat\fR (Visual Audio Tool),
+\fBwb\fR (distributed White Board),
 and
-\fBwb\fR (distributed White Board).
+\fBsnmp\fR (Simple Network Management Protocol).
 .TP
 .B \-S
 Print absolute, rather than relative, TCP sequence numbers.
diff -u /tmp/tcpdump-3.4a6/tcpdump.c ./tcpdump.c
--- /tmp/tcpdump-3.4a6/tcpdump.c	Sat Oct 18 22:50:17 1997
+++ ./tcpdump.c	Sun Feb 22 11:05:28 1998
@@ -239,6 +239,8 @@
 				packettype = PT_RTP;
 			else if (strcasecmp(optarg, "rtcp") == 0)
 				packettype = PT_RTCP;
+			else if (strcasecmp(optarg, "snmp") == 0)
+				packettype = PT_SNMP;
 			else
 				error("unknown packet type `%s'", optarg);
 			break;
