/* * dump-sizes.c -- * * Operations to compute and dump SNMPv3 PDU sizes. * * Copyright (c) 2003 J. Schoenwaelder, International University Bremen. * * See the file "COPYING" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * @(#) $Id: dump-sizes.c 8090 2008-04-18 12:56:29Z strauss $ */ #include #include #include #ifdef HAVE_WIN_H #include "win.h" #endif #include "smi.h" #include "smidump.h" static int silent = 0; static int detail = 0; /* * help functions */ #define m_abs(a) ((a) < 0 ? -(a) : (a)) typedef struct WellKnowType { char *module; char *name; int max; int mean; int min; } WellKnowType; static WellKnowType specialTypes[] = { { "SNMPv2-TC", "PhysAddress", 65535, 6, 0 }, { "INET-ADDRESS-MIB", "InetAddress", 255, 4, 0 }, { "IANATn3270eTC-MIB", "IANATn3270eAddress", 255, 4, 0 }, { NULL, NULL, 0, 0, 0 } }; typedef enum len_type { len_min, len_mean, len_max } len_type; static SmiInteger32 getAbsMinEnum(SmiType *smiType) { SmiNamedNumber *nn; SmiInteger32 min = SMI_BASETYPE_INTEGER32_MAX; for (nn = smiGetFirstNamedNumber(smiType); nn; nn = smiGetNextNamedNumber(nn)) { if (abs(nn->value.value.integer32) < min) { min = abs(nn->value.value.integer32); } } return min; } static SmiInteger32 getAbsMaxEnum(SmiType *smiType) { SmiNamedNumber *nn; SmiInteger32 max = 0; for (nn = smiGetFirstNamedNumber(smiType); nn; nn = smiGetNextNamedNumber(nn)) { if (abs(nn->value.value.integer32) > max) { max = abs(nn->value.value.integer32); } } return max; } static SmiInteger32 getAbsMinInteger32(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiInteger32 min = SMI_BASETYPE_INTEGER32_MAX; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getAbsMinInteger32(parent) : 0; } for (; range; range = smiGetNextRange(range)) { if (abs(range->minValue.value.integer32) < min) { min = abs(range->minValue.value.integer32); } } return min; } static SmiInteger32 getAbsMaxInteger32(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiInteger32 max = SMI_BASETYPE_INTEGER32_MIN; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getAbsMaxInteger32(parent) : SMI_BASETYPE_INTEGER32_MAX; } for (; range; range = smiGetNextRange(range)) { if (abs(range->maxValue.value.integer32) > max) { max = abs(range->maxValue.value.integer32); } } return max; } static SmiUnsigned32 getMinUnsigned32(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiInteger32 min = 0xffffffff; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getMinUnsigned32(parent) : 0; } for (; range; range = smiGetNextRange(range)) { if (range->minValue.value.unsigned32 < min) { min = range->minValue.value.unsigned32; } } return min; } static SmiUnsigned32 getMaxUnsigned32(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiUnsigned32 max = 0; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getMaxUnsigned32(parent) : 0xffffffff; } for (; range; range = smiGetNextRange(range)) { if (range->maxValue.value.unsigned32 > max) { max = range->maxValue.value.unsigned32; } } return max; } static SmiInteger64 getAbsMinInteger64(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiInteger64 min = SMI_BASETYPE_INTEGER64_MAX; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getAbsMinInteger64(parent) : min; } for (; range; range = smiGetNextRange(range)) { if (m_abs(range->minValue.value.integer64) < min) { min = m_abs(range->minValue.value.integer64); } } return min; } static SmiInteger64 getAbsMaxInteger64(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiInteger64 max = SMI_BASETYPE_INTEGER64_MIN; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getAbsMaxInteger64(parent) : max; } for (; range; range = smiGetNextRange(range)) { if (m_abs(range->maxValue.value.integer64) > max) { max = m_abs(range->maxValue.value.integer64); } } return max; } static SmiUnsigned64 getMinUnsigned64(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiInteger64 min = SMI_BASETYPE_UNSIGNED64_MAX; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getMinUnsigned64(parent) : min; } for (; range; range = smiGetNextRange(range)) { if (range->minValue.value.unsigned64 < min) { min = range->minValue.value.unsigned64; } } return min; } static SmiUnsigned64 getMaxUnsigned64(SmiType *smiType) { SmiType *parent; SmiRange *range; SmiUnsigned64 max = SMI_BASETYPE_UNSIGNED64_MIN; range = smiGetFirstRange(smiType); if (! range) { parent = smiGetParentType(smiType); return parent ? getMaxUnsigned64(parent) : max; } for (; range; range = smiGetNextRange(range)) { if (range->maxValue.value.unsigned64 > max) { max = range->maxValue.value.unsigned64; } } return max; } static int ber_len_length(int length) { int len; if (length < 0x80) { return 1; } for (len = 0; length > 0; len++) { length >>= 8; } return len; } static int ber_len_subid(SmiSubid subid) { int len = 0; do { subid >>= 7; len++; } while (subid > 0); return len; } static int ber_len_oid(const SmiSubid *oid, unsigned int oidlen) { int len = 0; int i; len += ber_len_subid(oid[1] + oid[0] * 40); for (i = 2; i < oidlen; i++) { len += ber_len_subid(oid[i]); } len += ber_len_length(len); /* length */ len += 1; /* tag */ return len; } static int ber_len_int32(const SmiInteger32 value) { SmiInteger32 val = value; unsigned char ch, sign; int lim; int len = 0; if (val < 0) { lim = -1; sign = 0x80; } else { lim = 0; sign = 0x00; } do { ch = (unsigned char) val; val >>= 8; len++; } while ((val != lim) || (unsigned char) (ch & 0x80) != sign); len += ber_len_length(len); /* length */ len += 1; /* tag */ return len; } static int ber_len_uint32(const SmiUnsigned32 value) { SmiUnsigned32 val = value; unsigned char ch; int len = 0; do { ch = (unsigned char) val; val >>= 8; len++; } while ((val != 0) || (ch & 0x80) != 0x00); len += ber_len_length(len); /* length */ len += 1; /* tag */ return len; } static int ber_len_int64(const SmiInteger64 value) { SmiInteger64 val = value; unsigned char ch, sign; int lim; int len = 0; if (val < 0) { lim = -1; sign = 0x80; } else { lim = 0; sign = 0x00; } do { ch = (unsigned char) val; val >>= 8; len++; } while ((val != lim) || (unsigned char) (ch & 0x80) != sign); len += ber_len_length(len); /* length */ len += 1; /* tag */ return len; } static int ber_len_uint64(const SmiUnsigned64 value) { SmiUnsigned64 val = value; unsigned char ch; int len = 0; do { ch = (unsigned char) val; val >>= 8; len++; } while ((val != 0) || (ch & 0x80) != 0x00); len += ber_len_length(len); /* length */ len += 1; /* tag */ return len; } static int ber_len_val_oid(SmiType *smiType, len_type flags) { SmiSubid oid[128]; unsigned int oidlen = sizeof(oid)/sizeof(oid[0]); int i; switch (flags) { case len_max: oid[0] = 2; for (i = 1; i < 128; i++) { oid[i] = 4294967295UL; } break; case len_mean: /* see Aiko's measurements */ for (oidlen = 0; oidlen < 15; oidlen++) { oid[oidlen] = 1; } break; case len_min: oid[0] = oid[1] = 0, oidlen = 2; break; } return ber_len_oid(oid, oidlen); } static int ber_len_val_octs(SmiType *smiType, len_type flags) { int len = 0; SmiModule *smiModule; smiModule = smiGetTypeModule(smiType); if (smiModule && smiModule->name && smiType->name) { int i; for (i = 0; specialTypes[i].module; i++) { if (strcmp(specialTypes[i].module, smiModule->name) == 0 && (strcmp(specialTypes[i].name, smiType->name) == 0)) { break; } } if (specialTypes[i].module) { switch (flags) { case len_max: return specialTypes[i].max; break; case len_mean: return specialTypes[i].mean; break; case len_min: return specialTypes[i].min; break; } } } switch (flags) { case len_max: len = smiGetMaxSize(smiType); break; case len_mean: len = (smiGetMaxSize(smiType) + smiGetMinSize(smiType)) / 2; break; case len_min: len = smiGetMinSize(smiType); break; } return len; } static int ber_len_val_bits(SmiType *smiType, len_type flags) { int len = 0; switch (flags) { case len_max: len = smiGetMaxSize(smiType); break; case len_mean: len = (smiGetMaxSize(smiType) + smiGetMinSize(smiType)) / 2; break; case len_min: len = smiGetMinSize(smiType); break; } return len; } static int ber_len_val_enum(SmiType *smiType, len_type flags) { SmiInteger32 val = 0; switch (flags) { case len_max: val = getAbsMaxEnum(smiType); break; case len_mean: val = (getAbsMaxEnum(smiType) + getAbsMinEnum(smiType)) / 2; break; case len_min: val = getAbsMinEnum(smiType); break; } return ber_len_int32(val); } static int ber_len_val_int32(SmiType *smiType, len_type flags) { SmiInteger32 val = 0; switch (flags) { case len_max: val = getAbsMaxInteger32(smiType); break; case len_mean: val = (getAbsMaxInteger32(smiType) + getAbsMinInteger32(smiType)) / 2; break; case len_min: val = getAbsMinInteger32(smiType); break; } return ber_len_int32(val); } static int ber_len_val_uint32(SmiType *smiType, len_type flags) { SmiUnsigned32 val = 0; switch (flags) { case len_max: val = getMaxUnsigned32(smiType); break; case len_mean: val = (getMaxUnsigned32(smiType) + getMinUnsigned32(smiType)) / 2; break; case len_min: val = getMinUnsigned32(smiType); break; } return ber_len_uint32(val); } static int ber_len_val_int64(SmiType *smiType, len_type flags) { SmiInteger64 val = 0; switch (flags) { case len_max: val = getAbsMaxInteger64(smiType); break; case len_mean: val = (getAbsMaxInteger64(smiType) + getAbsMinInteger64(smiType)) / 2; break; case len_min: val = getAbsMinInteger64(smiType); break; } return ber_len_int64(val); } static int ber_len_val_uint64(SmiType *smiType, len_type flags) { SmiUnsigned64 val = 0; switch (flags) { case len_max: val = getMaxUnsigned64(smiType); break; case len_mean: val = (getMaxUnsigned64(smiType) + getMinUnsigned64(smiType)) / 2; break; case len_min: val = getMinUnsigned64(smiType); break; } return ber_len_uint64(val); } static int ber_len_val(SmiType *smiType, len_type flags) { int len = 0; switch (smiType->basetype) { case SMI_BASETYPE_OBJECTIDENTIFIER: len = ber_len_val_oid(smiType, flags); break; case SMI_BASETYPE_OCTETSTRING: len = ber_len_val_octs(smiType, flags); break; case SMI_BASETYPE_BITS: len = ber_len_val_bits(smiType, flags); break; case SMI_BASETYPE_ENUM: len = ber_len_val_enum(smiType, flags); break; case SMI_BASETYPE_INTEGER32: len = ber_len_val_int32(smiType, flags); break; case SMI_BASETYPE_UNSIGNED32: len = ber_len_val_uint32(smiType, flags); break; case SMI_BASETYPE_INTEGER64: len = ber_len_val_int64(smiType, flags); break; case SMI_BASETYPE_UNSIGNED64: len = ber_len_val_uint64(smiType, flags); break; default: break; } return len; } static void append_index(SmiSubid *oid, unsigned int *oidlen, SmiNode *indexNode, len_type flags) { SmiInteger32 int32 = 0; SmiUnsigned32 uint32 = 0; SmiType *indexType; SmiModule *indexModule; int i, len = 0; if (! indexNode) return; indexType = smiGetNodeType(indexNode); if (! indexType) return; indexModule = smiGetTypeModule(indexType); switch (indexType->basetype) { case SMI_BASETYPE_OBJECTIDENTIFIER: switch (flags) { case len_max: len = 128 - *oidlen; if (indexNode->implied) len--; break; case len_mean: len = 16; break; case len_min: len = 2; break; } if (! indexNode->implied && *oidlen < 128) { oid[(*oidlen)++] = len; } for (i = 0; i < len && *oidlen < 128; i++) { switch (flags) { case len_max: if (i == 0) { oid[(*oidlen)++] = 2; } else { oid[(*oidlen)++] = 4294967295UL; } break; case len_mean: oid[(*oidlen)++] = i + 1; break; case len_min: oid[(*oidlen)++] = 0; break; } } break; case SMI_BASETYPE_OCTETSTRING: case SMI_BASETYPE_BITS: switch (flags) { case len_max: len = smiGetMaxSize(indexType); break; case len_mean: len = (smiGetMaxSize(indexType) + smiGetMinSize(indexType) / 2); break; case len_min: len = smiGetMinSize(indexType); break; } if (indexModule && indexModule->name && indexType->name) { int i; for (i = 0; specialTypes[i].module; i++) { if (strcmp(specialTypes[i].module, indexModule->name) == 0 && (strcmp(specialTypes[i].name, indexType->name) == 0)) { break; } } if (specialTypes[i].module) { switch (flags) { case len_max: len = specialTypes[i].max; break; case len_mean: len = specialTypes[i].mean; break; case len_min: len = specialTypes[i].min; break; } } } if (! indexNode->implied && *oidlen < 128) { oid[(*oidlen)++] = len; } for (i = 0; i < len && *oidlen < 128; i++) { switch (flags) { case len_max: oid[(*oidlen)++] = 255; break; case len_mean: if (i == 0) { oid[(*oidlen)++] = 1; } else { oid[(*oidlen)++] = (i%2) ? 85 : 170; } break; case len_min: oid[(*oidlen)++] = 0; break; } } break; case SMI_BASETYPE_ENUM: switch (flags) { case len_max: int32 = getAbsMaxEnum(indexType); break; case len_mean: int32 = (getAbsMaxEnum(indexType) - getAbsMinEnum(indexType)) / 2; break; case len_min: int32 = getAbsMinEnum(indexType); break; } if (*oidlen < 128) { oid[(*oidlen)++] = int32; } break; case SMI_BASETYPE_INTEGER32: switch (flags) { case len_max: int32 = getAbsMaxInteger32(indexType); break; case len_mean: int32 = (getAbsMaxInteger32(indexType) + getAbsMinInteger32(indexType)) / 2; break; case len_min: int32 = getAbsMinInteger32(indexType); break; } if (*oidlen < 128) { oid[(*oidlen)++] = int32; } break; case SMI_BASETYPE_UNSIGNED32: switch (flags) { case len_max: uint32 = getMaxUnsigned32(indexType); break; case len_mean: uint32 = (getMaxUnsigned32(indexType) + getMinUnsigned32(indexType)) / 2; break; case len_min: uint32 = getMinUnsigned32(indexType); break; } if (*oidlen < 128) { oid[(*oidlen)++] = uint32; } break; case SMI_BASETYPE_UNKNOWN: case SMI_BASETYPE_INTEGER64: case SMI_BASETYPE_UNSIGNED64: case SMI_BASETYPE_FLOAT32: case SMI_BASETYPE_FLOAT64: case SMI_BASETYPE_FLOAT128: case SMI_BASETYPE_POINTER: /* should never really get here */ break; } } #undef DUMP_OID static int ber_len_varbind(SmiNode *smiNode, len_type flags) { SmiNode *row; SmiSubid oid[128]; unsigned int oidlen = sizeof(oid)/sizeof(oid[0]); int len = 0; #ifdef DUMP_OID int x; #endif switch (smiNode->nodekind) { case SMI_NODEKIND_SCALAR: for (oidlen = 0; oidlen < smiNode->oidlen; oidlen++) { oid[oidlen] = smiNode->oid[oidlen]; } oid[oidlen++] = 0; break; case SMI_NODEKIND_COLUMN: for (oidlen = 0; oidlen < smiNode->oidlen; oidlen++) { oid[oidlen] = smiNode->oid[oidlen]; } row = smiGetParentNode(smiNode); if (row) { SmiNode *indexNode = NULL, *iNode; SmiElement *smiElement; switch (row->indexkind) { case SMI_INDEX_INDEX: case SMI_INDEX_REORDER: indexNode = row; break; case SMI_INDEX_EXPAND: /* TODO: we have to do more work here! */ break; case SMI_INDEX_AUGMENT: case SMI_INDEX_SPARSE: indexNode = smiGetRelatedNode(row); break; case SMI_INDEX_UNKNOWN: break; } if (indexNode) { for (smiElement = smiGetFirstElement(indexNode); smiElement; smiElement = smiGetNextElement(smiElement)) { iNode = smiGetElementNode(smiElement); append_index(oid, &oidlen, iNode, flags); } } } break; default: return 0; } #ifdef DUMP_OID fprintf(stderr, "%-32s\t", smiNode->name); for (x = 0; x < oidlen; x++) { fprintf(stderr, ".%u", oid[x]); } fprintf(stderr, "\n"); #endif len += ber_len_oid(oid, oidlen); len += ber_len_val(smiGetNodeType(smiNode), flags); len += ber_len_length(len) + 1; return len; } static int isGroup(SmiNode *smiNode) { SmiNode *childNode; if (smiNode->nodekind == SMI_NODEKIND_ROW) { return 1; } for (childNode = smiGetFirstChildNode(smiNode); childNode; childNode = smiGetNextChildNode(childNode)) { if (childNode->nodekind == SMI_NODEKIND_SCALAR && childNode->access > SMI_ACCESS_NOTIFY) { return 1; } } return 0; } static void dumpSizeOfPDU(FILE *f, SmiModule *smiModule, SmiNode *smiNode) { SmiNode *child; int worst = 0; int best = 0; int avg = 0; int b, w, a, n = 0; for (child = smiGetFirstChildNode(smiNode); child; child = smiGetNextChildNode(child)) { if (child->access == SMI_ACCESS_READ_WRITE || child->access == SMI_ACCESS_READ_ONLY) { b = ber_len_varbind(child, len_min); a = ber_len_varbind(child, len_mean); w = ber_len_varbind(child, len_max); best += b, worst += w, avg += a, n++; } } /* varbind list sequence length and tag */ best += ber_len_length(best) + 1; avg += ber_len_length(avg) + 1; worst += ber_len_length(worst) + 1; /* request-id as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(1073741824); worst += ber_len_int32(-214783648); /* error-status as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(0); worst += ber_len_int32(18); /* error-index as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(0); worst += ber_len_int32(n-1); /* PDU sequence length and tag */ best += ber_len_length(best) + 1; avg += ber_len_length(avg) + 1; worst += ber_len_length(worst) + 1; fprintf(f, "%-23s %-23s \t%d\t[%d..%d]\n", smiModule->name, smiNode->name, avg, best, worst); if (detail) { for (child = smiGetFirstChildNode(smiNode); child; child = smiGetNextChildNode(child)) { if (child->access == SMI_ACCESS_READ_WRITE || child->access == SMI_ACCESS_READ_ONLY) { b = ber_len_varbind(child, len_min); a = ber_len_varbind(child, len_mean); w = ber_len_varbind(child, len_max); fprintf(f, "%-23s %-23s \t%d\t[%d..%d]\n", "", child->name, a, b, w); } } } } static void dumpSizeOfCreatePDU(FILE *f, SmiModule *smiModule, SmiNode *smiNode, int ignoreDefaultColumns) { SmiNode *child; SmiType *childType; SmiModule *childTypeModule; int worst = 0; int best = 0; int avg = 0; int b, w, a, n = 0; int isRowStatus; for (child = smiGetFirstChildNode(smiNode); child; child = smiGetNextChildNode(child)) { if (child->access == SMI_ACCESS_READ_WRITE) { /* Ensure RowStatus columns are present even if they * have a default value. */ childType = smiGetNodeType(child); childTypeModule = childType ? smiGetTypeModule(childType) : NULL; isRowStatus = (childType && childType->name && childTypeModule && childTypeModule->name) ? (strcmp(childType->name, "RowStatus") == 0 && strcmp(childTypeModule->name, "SNMPv2-TC") == 0) : 0; /* xxx at least one PDU must be present xxx */ if (ignoreDefaultColumns && child->value.basetype != SMI_BASETYPE_UNKNOWN && !isRowStatus) { continue; } b = ber_len_varbind(child, len_min); a = ber_len_varbind(child, len_mean); w = ber_len_varbind(child, len_max); #if 0 fprintf(f, " %-32s\t[%d..%d] | %d\n", child->name, b, w, a); #endif best += b, worst += w, avg += a, n++; } } /* varbind list sequence length and tag */ best += ber_len_length(best) + 1; avg += ber_len_length(avg) + 1; worst += ber_len_length(worst) + 1; /* request-id as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(1073741824); worst += ber_len_int32(-214783648); /* error-status as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(0); worst += ber_len_int32(18); /* error-index as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(0); worst += ber_len_int32(n-1); /* PDU sequence length and tag */ best += ber_len_length(best) + 1; avg += ber_len_length(avg) + 1; worst += ber_len_length(worst) + 1; fprintf(f, "%-23s %-23s \t%d\t[%d..%d]\n", smiModule->name, smiNode->name, avg, best, worst); } static void dumpSizeOfNotificationPDU(FILE *f, SmiModule *smiModule, SmiNode *smiNode) { SmiElement *smiElement; SmiNode *varNode; int worst = 0; int best = 0; int avg = 0; int w, b, a; int len = 0; static const SmiSubid snmpTrapOid0[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; static const int snmpTrapOid0Len = sizeof(snmpTrapOid0) / sizeof(SmiSubid); b = 15, w = 19, a = 18; best += b, worst += w, avg += a; len += ber_len_oid(smiNode->oid, smiNode->oidlen); len += ber_len_oid(snmpTrapOid0, snmpTrapOid0Len); len += ber_len_length(len) + 1; b = len, w = len, a = len; best += b, worst += w, avg += a; for (smiElement = smiGetFirstElement(smiNode); smiElement; smiElement = smiGetNextElement(smiElement)) { varNode = smiGetElementNode(smiElement); if (! varNode) continue; b = ber_len_varbind(varNode, len_min); a = ber_len_varbind(varNode, len_mean); w = ber_len_varbind(varNode, len_max); best += b, worst += w, avg += a; } /* varbind list sequence length and tag */ best += ber_len_length(best) + 1; avg += ber_len_length(avg) + 1; worst += ber_len_length(worst) + 1; /* request-id as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(1073741824); worst += ber_len_int32(-214783648); /* error-status as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(0); worst += ber_len_int32(18); /* error-index as defined in RFC 3416 */ best += ber_len_int32(0); avg += ber_len_int32(0); worst += ber_len_int32(0); /* PDU sequence length and tag */ best += ber_len_length(best) + 1; avg += ber_len_length(avg) + 1; worst += ber_len_length(worst) + 1; fprintf(f, "%-23s %-23s \t%d\t[%d..%d]\n", smiModule->name, smiNode->name, avg, best, worst); if (detail) { b = 15, w = 19, a = 18; fprintf(f, "%-23s %-23s \t%d\t[%d..%d]\n", "", "sysUpTime", a, b, w); len = 0; len += ber_len_oid(smiNode->oid, smiNode->oidlen); len += ber_len_oid(snmpTrapOid0, snmpTrapOid0Len); len += ber_len_length(len) + 1; b = len, w = len, a = len; fprintf(f, "%-23s %-23s \t%d\t[%d..%d]\n", "", "snmpTrapOID", a, b, w); for (smiElement = smiGetFirstElement(smiNode); smiElement; smiElement = smiGetNextElement(smiElement)) { varNode = smiGetElementNode(smiElement); if (! varNode) continue; b = ber_len_varbind(varNode, len_min); a = ber_len_varbind(varNode, len_mean); w = ber_len_varbind(varNode, len_max); fprintf(f, "%-23s %-23s \t%d\t[%d..%d]\n", "", varNode->name, a, b, w); } } } static void dumpGroupPduSizes(FILE *f, SmiModule *smiModule) { SmiNode *smiNode; for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY); smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) { if (isGroup(smiNode)) { dumpSizeOfPDU(f, smiModule, smiNode); } } } static void dumpFullRowCreatePduSizes(FILE *f, SmiModule *smiModule) { SmiNode *smiNode; for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ROW); smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ROW)) { if (smiNode->create) { dumpSizeOfCreatePDU(f, smiModule, smiNode, 0); } } } static void dumpSmallRowCreatePduSizes(FILE *f, SmiModule *smiModule) { SmiNode *smiNode; for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ROW); smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ROW)) { if (smiNode->create) { dumpSizeOfCreatePDU(f, smiModule, smiNode, 1); } } } static void dumpNotificationPduSizes(FILE *f, SmiModule *smiModule) { SmiNode *smiNode; for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_NOTIFICATION); smiNode; smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_NOTIFICATION)) { dumpSizeOfNotificationPDU(f, smiModule, smiNode); } } static void dumpSizes(int modc, SmiModule **modv, int flags, char *output) { int i; FILE *f = stdout; silent = (flags & SMIDUMP_FLAG_SILENT); if (output) { f = fopen(output, "w"); if (!f) { fprintf(stderr, "smidump: cannot open %s for writing: ", output); perror(NULL); exit(1); } } if (flags & SMIDUMP_FLAG_UNITE) { if (! silent) { int pos = 8888; fprintf(f, "# united module PDU sizes (generated by smidump " SMI_VERSION_STRING ")\n"); fprintf(f, "#\n# smidump -u -f sizes"); for (i = 0; i < modc; i++) { int len = strlen(modv[i]->name); if (pos + len > 70) { fprintf(f, " \\\n#\t"), pos = 8; } fprintf(f, "%s ", modv[i]->name); pos += len + 1; } fprintf(f, "%s\n", (pos == 8) ? "" : "\n"); } fprintf(f, "\n# size of PDUs for groups and rows:\n\n"); for (i = 0; i < modc; i++) { dumpGroupPduSizes(f, modv[i]); } fprintf(f, "\n# size of one-shot row creation PDUs including columns with default values:\n\n"); for (i = 0; i < modc; i++) { dumpFullRowCreatePduSizes(f, modv[i]); } fprintf(f, "\n# size of one-shot row creation PDUs excluding columns with default values:\n\n"); for (i = 0; i < modc; i++) { dumpSmallRowCreatePduSizes(f, modv[i]); } fprintf(f, "\n# size of notification PDUs:\n\n"); for (i = 0; i < modc; i++) { dumpNotificationPduSizes(f, modv[i]); } } else { for (i = 0; i < modc; i++) { if (! silent) { fprintf(f, "# %s module PDU sizes (generated by smidump " SMI_VERSION_STRING ")\n\n", modv[i]->name); } fprintf(f, "\n# size of PDUs for groups and rows:\n\n"); dumpGroupPduSizes(f, modv[i]); fprintf(f, "\n# size of one-shot row creation PDUs including columns with default values:\n\n"); dumpFullRowCreatePduSizes(f, modv[i]); fprintf(f, "\n# size of one-shot row creation PDUs excluding columns with default values:\n\n"); dumpSmallRowCreatePduSizes(f, modv[i]); fprintf(f, "\n# size of notification PDUs:\n\n"); dumpNotificationPduSizes(f, modv[i]); } } if (fflush(f) || ferror(f)) { perror("smidump: write error"); exit(1); } if (output) { fclose(f); } } void initSizes() { static SmidumpDriverOption opt[] = { { "variables", OPT_FLAG, &detail, 0, "show detailed information the sizes of variables"}, { 0, OPT_END, 0, 0 } }; static SmidumpDriver driver = { "sizes", dumpSizes, SMI_FLAG_NODESCR, 0, "RFC 3416 PDU sizes excluding message / transport headers", opt, NULL }; smidumpRegisterDriver(&driver); }