print-snmp.c

来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,905 行 · 第 1/3 页

C
1,905
字号
		case CONTEXT:			elem->type = BE_PDU;			elem->data.raw = (caddr_t)p;			break;		default:			elem->type = BE_OCTET;			elem->data.raw = (caddr_t)p;			printf("C/%s/%s",				Class[class].name, Class[class].Id[id]);			break;		}		break;	}	p += elem->asnlen;	len -= elem->asnlen;	return elem->asnlen + hdr;trunc:	fputs("[|snmp]", stdout);	return -1;}/* * Display the ASN.1 object represented by the BE object. * This used to be an integral part of asn1_parse() before the intermediate * BE form was added. */static intasn1_print(struct be *elem){	u_char *p = (u_char *)elem->data.raw;	u_int32_t asnlen = elem->asnlen;	u_int32_t i;	switch (elem->type) {	case BE_OCTET:		TCHECK2(*p, asnlen);		for (i = asnlen; i-- > 0; p++)			printf("_%.2x", *p);		break;	case BE_NULL:		break;	case BE_OID: {		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++) {				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);					first = 1;					break;				}			}		}		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;				s = o / OIDMUX;				if (s > 2) s = 2;				OBJ_PRINT(s, first);				o -= s * OIDMUX;			}			OBJ_PRINT(o, first);			if (--first < 0)				first = 0;			o = 0;		}		break;	}	case BE_INT:		printf("%d", elem->data.integer);		break;	case BE_UNS:		printf("%u", 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;#if 0 /*is looks illegal, but what is the intention?*/			printf("%.f", d);#else			printf("%f", d);#endif			break;		}		d += (elem->data.uns64.low & 0xfffff000);#if 0 /*is looks illegal, but what is the intention?*/		snprintf(first, sizeof(first), "%.f", d);#else		snprintf(first, sizeof(first), "%f", d);#endif		snprintf(last, sizeof(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;		TCHECK2(*p, asnlen);		for (i = asnlen; printable && i-- > 0; p++)			printable = isprint(*p) || isspace(*p);		p = elem->data.str;		if (printable) {			putchar('"');			if (fn_printn(p, asnlen, snapend)) {				putchar('"');				goto trunc;			}			putchar('"');		} else			for (i = asnlen; i-- > 0; p++) {				printf(first ? "%.2x" : "_%.2x", *p);				first = 0;			}		break;	}	case BE_SEQ:		printf("Seq(%u)", elem->asnlen);		break;	case BE_INETADDR:		if (asnlen != ASNLEN_INETADDR)			printf("[inetaddr len!=%d]", ASNLEN_INETADDR);		TCHECK2(*p, asnlen);		for (i = asnlen; i-- != 0; p++) {			printf((i == asnlen-1) ? "%u" : ".%u", *p);		}		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);		break;	case BE_ANY:		fputs("[BE_ANY!?]", stdout);		break;	default:		fputs("[be!?]", stdout);		break;	}	return 0;trunc:	fputs("[|snmp]", stdout);	return -1;}#ifdef notdef/* * This is a brute force ASN.1 printer: recurses to dump an entire structure. * This will work for any ASN.1 stream, not just an SNMP PDU. * * By adding newlines and spaces at the correct places, this would print in * Rose-Normal-Form. * * This is not currently used. */static voidasn1_decode(u_char *p, u_int length){	struct be elem;	int i = 0;	while (i >= 0 && length > 0) {		i = asn1_parse(p, length, &elem);		if (i >= 0) {			fputs(" ", stdout);			if (asn1_print(&elem) < 0)				return;			if (elem.type == BE_SEQ || elem.type == BE_PDU) {				fputs(" {", stdout);				asn1_decode(elem.data.raw, elem.asnlen);				fputs(" }", stdout);			}			length -= i;			p += i;		}	}}#endif#ifdef LIBSMIstruct smi2be {    SmiBasetype basetype;    int be;};static struct smi2be smi2betab[] = {    { SMI_BASETYPE_INTEGER32,		BE_INT },    { SMI_BASETYPE_OCTETSTRING,		BE_STR },    { SMI_BASETYPE_OCTETSTRING,		BE_INETADDR },    { SMI_BASETYPE_OBJECTIDENTIFIER,	BE_OID },    { SMI_BASETYPE_UNSIGNED32,		BE_UNS },    { SMI_BASETYPE_INTEGER64,		BE_NONE },    { SMI_BASETYPE_UNSIGNED64,		BE_UNS64 },    { SMI_BASETYPE_FLOAT32,		BE_NONE },    { SMI_BASETYPE_FLOAT64,		BE_NONE },    { SMI_BASETYPE_FLOAT128,		BE_NONE },    { SMI_BASETYPE_ENUM,		BE_INT },    { SMI_BASETYPE_BITS,		BE_STR },    { SMI_BASETYPE_UNKNOWN,		BE_NONE }};static intsmi_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;			    if (oid[*oidlen] > 2) oid[*oidlen] = 2;			}			o -= oid[*oidlen] * OIDMUX;			if (*oidlen < oidsize) (*oidlen)++;		}		if (*oidlen < oidsize) {			oid[(*oidlen)++] = o;		}		o = 0;	}	return 0;trunc:	fputs("[|snmp]", stdout);	return -1;}static int smi_check_type(SmiBasetype basetype, int be){    int i;    for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) {	if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) {	    return 1;	}    }    return 0;}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:	if (smiRange->minValue.value.unsigned32	    == smiRange->maxValue.value.unsigned32) {	    ok = (elem->asnlen == smiRange->minValue.value.unsigned32);	} else {	    ok = (elem->asnlen >= smiRange->minValue.value.unsigned32		  && elem->asnlen <= smiRange->maxValue.value.unsigned32);	}	break;    case SMI_BASETYPE_INTEGER32:	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;	/* case SMI_BASETYPE_INTEGER64: SMIng */	/* case SMI_BASETYPE_FLOAT32: SMIng */	/* case SMI_BASETYPE_FLOAT64: SMIng */	/* case SMI_BASETYPE_FLOAT128: SMIng */    case SMI_BASETYPE_ENUM:    case SMI_BASETYPE_BITS:    case SMI_BASETYPE_UNKNOWN:	ok = 1;	break;    default:	ok = 0;	break;    }    return ok;}static int smi_check_range(SmiType *smiType, struct be *elem){        SmiRange *smiRange;	int ok = 1;	for (smiRange = smiGetFirstRange(smiType);	     smiRange;	     smiRange = smiGetNextRange(smiRange)) {	    ok = smi_check_a_range(smiType, smiRange, elem);	    if (ok) {		break;	    }	}	if (ok) {	    SmiType *parentType;	    parentType = smiGetParentType(smiType);	    if (parentType) {		ok = smi_check_range(parentType, elem);	    }	}	return ok;}static SmiNode *smi_print_variable(struct be *elem, int *status){	unsigned int oid[128], oidlen;	SmiNode *smiNode = NULL;	unsigned int i;	*status = smi_decode_oid(elem, oid, sizeof(oid)/sizeof(unsigned int),	    &oidlen);	if (*status < 0)		return NULL;	smiNode = smiGetNodeByOID(oidlen, oid);	if (! smiNode) {		*status = asn1_print(elem);		return NULL;	}	if (vflag) {		fputs(smiGetNodeModule(smiNode)->name, stdout);		fputs("::", stdout);	}	fputs(smiNode->name, stdout);	if (smiNode->oidlen < oidlen) {	        for (i = smiNode->oidlen; i < oidlen; i++) {		        printf(".%u", oid[i]);		}	}	*status = 0;	return smiNode;}static intsmi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem){	unsigned int i, oid[128], oidlen;	SmiType *smiType;	SmiNamedNumber *nn;	int done = 0;	if (! smiNode || ! (smiNode->nodekind			    & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {	    return asn1_print(elem);	}	if (elem->type == BE_NOSUCHOBJECT	    || elem->type == BE_NOSUCHINST	    || elem->type == BE_ENDOFMIBVIEW) {	    return asn1_print(elem);	}	if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {	    fputs("[notNotifyable]", stdout);	}	if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {	    fputs("[notReadable]", stdout);	}	if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {	    fputs("[notWritable]", stdout);	}	if (RESPONSE_CLASS(pduid)	    && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {	    fputs("[noAccess]", stdout);	}	smiType = smiGetNodeType(smiNode);	if (! smiType) {	    return asn1_print(elem);	}	if (! smi_check_type(smiType->basetype, elem->type)) {	    fputs("[wrongType]", stdout);	}	if (! smi_check_range(smiType, elem)) {	    fputs("[outOfRange]", stdout);	}	/* resolve bits to named bits */	/* check whether instance identifier is valid */	/* apply display hints (integer, octetstring) */	/* convert instance identifier to index type values */	switch (elem->type) {	case BE_OID:	        if (smiType->basetype == SMI_BASETYPE_BITS) {		        /* print bit labels */		} else {		        smi_decode_oid(elem, oid,				       sizeof(oid)/sizeof(unsigned int),				       &oidlen);			smiNode = smiGetNodeByOID(oidlen, oid);			if (smiNode) {			        if (vflag) {					fputs(smiGetNodeModule(smiNode)->name, stdout);					fputs("::", stdout);				}				fputs(smiNode->name, stdout);				if (smiNode->oidlen < oidlen) {				        for (i = smiNode->oidlen;					     i < oidlen; i++) {					        printf(".%u", oid[i]);					}				}				done++;			}		}		break;	case BE_INT:	        if (smiType->basetype == SMI_BASETYPE_ENUM) {		        for (nn = smiGetFirstNamedNumber(smiType);			     nn;			     nn = smiGetNextNamedNumber(nn)) {			         if (nn->value.value.integer32				     == elem->data.integer) {				         fputs(nn->name, stdout);					 printf("(%d)", elem->data.integer);					 done++;					 break;				}			}		}		break;	}	if (! done) {		return asn1_print(elem);	}	return 0;}#endif/* * General SNMP header *	SEQUENCE { *		version INTEGER {version-1(0)}, *		community OCTET STRING, *		data ANY	-- PDUs *	} * PDUs for all but Trap: (see rfc1157 from page 15 on) *	SEQUENCE { *		request-id INTEGER, *		error-status INTEGER, *		error-index INTEGER, *		varbindlist SEQUENCE OF *			SEQUENCE { *				name ObjectName, *				value ObjectValue *			} *	} * PDU for Trap: *	SEQUENCE { *		enterprise OBJECT IDENTIFIER, *		agent-addr NetworkAddress, *		generic-trap INTEGER, *		specific-trap INTEGER, *		time-stamp TimeTicks, *		varbindlist SEQUENCE OF *			SEQUENCE { *				name ObjectName, *				value ObjectValue *			} *	} *//* * Decode SNMP varBind */static voidvarbind_print(u_char pduid, const u_char *np, u_int length){	struct be elem;	int count = 0, ind;#ifdef LIBSMI	SmiNode *smiNode = NULL;#endif	int status;	/* Sequence of varBind */	if ((count = asn1_parse(np, length, &elem)) < 0)		return;	if (elem.type != BE_SEQ) {		fputs("[!SEQ of varbind]", stdout);		asn1_print(&elem);		return;	}	if ((u_int)count < length)		printf("[%d extra after SEQ of varbind]", length - count);	/* descend */	length = elem.asnlen;	np = (u_char *)elem.data.raw;	for (ind = 1; length > 0; ind++) {		const u_char *vbend;		u_int vblength;		fputs(" ", stdout);		/* Sequence */		if ((count = asn1_parse(np, length, &elem)) < 0)			return;		if (elem.type != BE_SEQ) {			fputs("[!varbind]", stdout);			asn1_print(&elem);			return;		}		vbend = np + count;		vblength = length - count;		/* descend */		length = elem.asnlen;		np = (u_char *)elem.data.raw;		/* objName (OID) */		if ((count = asn1_parse(np, length, &elem)) < 0)			return;		if (elem.type != BE_OID) {			fputs("[objName!=OID]", stdout);			asn1_print(&elem);			return;		}#ifdef LIBSMI		smiNode = smi_print_variable(&elem, &status);#else		status = asn1_print(&elem);#endif		if (status < 0)			return;		length -= count;		np += count;		if (pduid != GETREQ && pduid != GETNEXTREQ		    && pduid != GETBULKREQ)			fputs("=", stdout);		/* objVal (ANY) */		if ((count = asn1_parse(np, length, &elem)) < 0)			return;		if (pduid == GETREQ || pduid == GETNEXTREQ		    || pduid == GETBULKREQ) {			if (elem.type != BE_NULL) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?