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 + -
显示快捷键?