Download raw body.
snmpd: testers wanted: varbind syntax validation
Hello tech@,
I'm not sure in what direction I want to take this diff, but below is an
early attempt at syntax validation for varbinds in snmpd. With this diff
I found the invalid carpGroupDemote INTEGER range for which I just
committed a fix. If you run snmpd on a low risk machine I would be
interested to see what varbinds break and if we can fix them. Since
metrics can change over time, I'm not expecting every failure (assuming
there are) to show up on the first fly-over.
If you connect external metrics via AgentX, make sure you include their
corresponding MIB files via `mib directory` in snmpd.conf, or manually
place them (and their dependencies) inside /usr/share/snmp/mibs.
How will a failure show up? A GENERR will be returned, and a a
"not MIB compliant" line will show up in the log, like:
AgentX(2948596552/1757229136): 780061712 OPENBSD-CARP-MIB::carpGroupDemote.1: not MIB compliant
After this, the AgentX connection is closed. Meaning that if the data
came from snmpd_metrics (spawned by snmpd itself), snmpd_metrics will
exit and take snmpd with it. If it's an external daemon it's dependent
on the daemon; vmd, and relayd should reconnect automatically, other
daemons might behave differently.
martijn@
diff refs/heads/master refs/heads/snmpd/mib_syntax
commit - 8c9ea0ff3fd3788b066415bd61a787c53e6c77b7
commit + 2e6836dc56c30b72cf51908e715184381a0337ee
blob - da9643f9aa602ae007006920d1f162624a0f39f2
blob + 27cd3bda1230b4823b718cdde34de1f91857bbc4
--- usr.sbin/snmpd/application.c
+++ usr.sbin/snmpd/application.c
@@ -1485,6 +1485,13 @@ appl_varbind_valid(struct appl_varbind *varbind,
}
}
+ if (varbind->av_value->be_class == BER_CLASS_UNIVERSAL ||
+ varbind->av_value->be_class == BER_CLASS_APPLICATION || 0) {
+ if (!mib_varbind_valid(&varbind->av_oid, varbind->av_value)) {
+ *errstr = "not MIB compliant";
+ return 0;
+ }
+ }
if (varbind->av_value->be_class == BER_CLASS_UNIVERSAL) {
switch (varbind->av_value->be_type) {
case BER_TYPE_NULL:
blob - fc2a428828de5e9ca1761e25223fc7eeee165e2f
blob + 8c41d11fb48a3821be32387e91bf3b7e21161be6
--- usr.sbin/snmpd/mib.h
+++ usr.sbin/snmpd/mib.h
@@ -34,6 +34,7 @@ void mib_clear(void);
char *mib_oid2string(struct ber_oid *, char *, size_t,
enum mib_oidfmt);
const char *mib_string2oid(const char *, struct ber_oid *);
+int mib_varbind_valid(struct ber_oid *, struct ber_element *);
#define MIBDECL(...) { { MIB_##__VA_ARGS__ }, \
(sizeof((uint32_t []) { MIB_##__VA_ARGS__ }) / sizeof(uint32_t))}, #__VA_ARGS__
blob - eb7a1a1272dbfe1ac06fc5b3aebbde9e3fb65b41
blob + a18d5ceebda51285765cc76ced6a803a3e95cf72
--- usr.sbin/snmpd/mib.y
+++ usr.sbin/snmpd/mib.y
@@ -35,6 +35,7 @@
#include "log.h"
#include "mib.h"
+#include "snmp.h"
/* RFC2578 section 3.1 */
#define DESCRIPTOR_MAX 64
@@ -71,6 +72,45 @@ struct oid_resolved {
size_t bo_n;
};
+struct range {
+ long long start;
+ long long end;
+};
+
+struct ranges {
+ struct range range[20];
+ size_t nranges;
+};
+
+enum type {
+ TYPE_REFERENCE,
+ TYPE_INTEGER,
+ TYPE_OID,
+ TYPE_OSTRING,
+ TYPE_IPADDRESS,
+ TYPE_COUNTER32,
+ TYPE_GAUGE32,
+ TYPE_UNSIGNED32,
+ TYPE_TIMETICKS,
+ TYPE_OPAQUE,
+ TYPE_COUNTER64,
+ TYPE_BITS,
+ TYPE_ENUMERATED,
+ TYPE_SEQUENCEOF
+};
+
+struct syntax {
+ enum type type;
+ union {
+ char reference[DESCRIPTOR_MAX + 1];
+ struct item *refitem;
+ };
+ union {
+ struct ranges ranges;
+ /* TODO support for enumerated */
+ };
+};
+
enum status {
CURRENT,
DEPRECATED,
@@ -92,7 +132,7 @@ struct objectidentity {
};
struct objecttype {
- void *syntax;
+ struct syntax syntax;
char *units;
enum access maxaccess;
enum status status;
@@ -114,7 +154,7 @@ struct textualconvention {
enum status status;
char *description;
char *reference;
- void *syntax;
+ struct syntax syntax;
};
struct item {
@@ -131,7 +171,8 @@ struct item {
IT_OBJECT_GROUP,
IT_NOTIFICATION_GROUP,
IT_MODULE_COMPLIANCE,
- IT_AGENT_CAPABITIES
+ IT_AGENT_CAPABITIES,
+ IT_SEQUENCE
} type;
int resolved;
struct module *module;
@@ -206,19 +247,20 @@ int mib_moduleidentity(const char *, time_t, const c
const char *, const char *, const struct oid_unresolved *);
int mib_objectidentity(const char *, enum status, const char *,
const char *, const struct oid_unresolved *);
-int mib_objecttype(const char *, void *, const char *,
+int mib_objecttype(const char *, struct syntax *, const char *,
enum access, enum status, const char *, const char *,
void *, void *, const struct oid_unresolved *);
int mib_notificationtype(const char *, void *, enum status,
const char *, const char *, const struct oid_unresolved *);
int mib_textualconvetion(const char *, const char *, enum status,
- const char *, const char *, void *);
+ const char *, const char *, const struct syntax *);
int mib_objectgroup(const char *, void *, enum status,
const char *, const char *, const struct oid_unresolved *);
int mib_notificationgroup(const char *, void *, enum status,
const char *, const char *, const struct oid_unresolved *);
int mib_modulecompliance(const char *, enum status, const char *,
const char *, void *, const struct oid_unresolved *);
+int mib_item_sequence(const char *, void *);
struct item *mib_item_find(struct item *, const char *);
struct item *mib_item_parent(struct ber_oid *);
int mib_resolve_oid(struct oid_resolved *,
@@ -272,6 +314,9 @@ typedef union {
char symbollist[SYMBOLS_MAX][DESCRIPTOR_MAX + 1];
struct objidcomponent objidcomponent;
struct oid_unresolved oid;
+ struct syntax syntax;
+ struct range range;
+ struct ranges ranges;
time_t time;
enum status status;
enum access access;
@@ -309,6 +354,7 @@ typedef union {
%token <number> NUMBER
%token <signednumber> SIGNEDNUMBER
%type <string> moduleidentifier smiv2moduleidentifier
+%type <signednumber> value
%type <import> symbolsfrom
%type <symbollist> symbollist
%type <string> descriptor symbol
@@ -318,6 +364,10 @@ typedef union {
%type <time> lastupdated
%type <status> status
%type <access> access
+%type <range> range
+%type <ranges> ranges
+%type <syntax> syntax type integersubtype octetstringsubtype
+%type <syntax> enumeration bits
%%
@@ -561,7 +611,7 @@ assignment : descriptor OBJECT IDENTIFIER PRODUCTION
units = $5[0] == '\0' ? NULL : $5;
reference = $12[0] == '\0' ? NULL : $12;
- if (mib_objecttype($1, NULL, units, $7, $9, $11,
+ if (mib_objecttype($1, &$4, units, $7, $9, $11,
reference, NULL, NULL, &$16) == -1)
YYERROR;
}
@@ -577,6 +627,8 @@ assignment : descriptor OBJECT IDENTIFIER PRODUCTION
YYERROR;
}
| typereference PRODUCTION SEQUENCE '{' entries '}' {
+ if (mib_item_sequence($1, NULL) == -1)
+ YYERROR;
/* Table entry, ignore for now */
}
| typereference PRODUCTION TEXTUALCONVENTION displaypart
@@ -587,7 +639,7 @@ assignment : descriptor OBJECT IDENTIFIER PRODUCTION
reference = $9[0] == '\0' ? NULL : $9;
if (mib_textualconvetion($1, displayhint, $6,
- $8, reference, NULL) == -1)
+ $8, reference, &$11) == -1)
YYERROR;
}
| descriptor MODULECOMPLIANCE STATUS status
@@ -647,12 +699,27 @@ objects : object
object : descriptor
;
-syntax : type
- | SEQUENCE OF typereference
- | integersubtype
- | octetstringsubtype
- | enumeration
- | bits
+syntax : type {
+ $$ = $1;
+ }
+ | SEQUENCE OF typereference {
+ $$ = (struct syntax){};
+ $$.type = TYPE_SEQUENCEOF;
+ strlcpy($$.reference, $3,
+ sizeof($$.reference));
+ }
+ | integersubtype {
+ $$ = $1;
+ }
+ | octetstringsubtype {
+ $$ = $1;
+ }
+ | enumeration {
+ $$ = $1;
+ }
+ | bits {
+ $$ = $1;
+ }
;
unitspart : UNITS TEXT {
@@ -869,34 +936,132 @@ objidcomponent : NUMBER {
}
;
-type : typereference
- | INTEGER
- | OBJECT IDENTIFIER
- | OCTET STRING
- | Integer32
- | IpAddress
- | Counter32
- | Gauge32
- | Unsigned32
- | TimeTicks
- | Opaque
- | Counter64
- | BITS
+type : typereference {
+ $$ = (struct syntax){};
+ $$.type = TYPE_REFERENCE;
+ strlcpy($$.reference, $1, sizeof($$.reference));
+ }
+ | INTEGER {
+ $$ = (struct syntax){
+ .type = TYPE_INTEGER
+ };
+ }
+ | OBJECT IDENTIFIER {
+ $$ = (struct syntax){
+ .type = TYPE_OID
+ };
+ }
+ | OCTET STRING {
+ $$ = (struct syntax){
+ .type = TYPE_OSTRING
+ };
+ }
+ | Integer32 {
+ $$ = (struct syntax){
+ .type = TYPE_INTEGER
+ };
+ }
+ | IpAddress {
+ $$ = (struct syntax){
+ .type = TYPE_IPADDRESS
+ };
+ }
+ | Counter32 {
+ $$ = (struct syntax){
+ .type = TYPE_COUNTER32
+ };
+ }
+ | Gauge32 {
+ $$ = (struct syntax){
+ .type = TYPE_GAUGE32
+ };
+ }
+ | Unsigned32 {
+ $$ = (struct syntax){
+ .type = TYPE_UNSIGNED32
+ };
+ }
+ | TimeTicks {
+ $$ = (struct syntax){
+ .type = TYPE_TIMETICKS
+ };
+ }
+ | Opaque {
+ $$ = (struct syntax){
+ .type = TYPE_OPAQUE
+ };
+ }
+ | Counter64 {
+ $$ = (struct syntax){
+ .type = TYPE_COUNTER64
+ };
+ }
+ | BITS {
+ $$ = (struct syntax){
+ .type = TYPE_BITS
+ };
+ }
;
-integersubtype : INTEGER '(' ranges ')'
- | Integer32 '(' ranges ')'
- | Unsigned32 '(' ranges ')'
- | Gauge32 '(' ranges ')'
- | typereference '(' ranges ')'
+integersubtype : INTEGER '(' ranges ')' {
+ $$ = (struct syntax){
+ .type = TYPE_INTEGER,
+ .ranges = $3
+ };
+ }
+ | Integer32 '(' ranges ')' {
+ $$ = (struct syntax){
+ .type = TYPE_INTEGER,
+ .ranges = $3
+ };
+ }
+ | Unsigned32 '(' ranges ')' {
+ $$ = (struct syntax){
+ .type = TYPE_UNSIGNED32,
+ .ranges = $3
+ };
+ }
+ | Gauge32 '(' ranges ')' {
+ $$ = (struct syntax){
+ .type = TYPE_GAUGE32,
+ .ranges = $3
+ };
+ }
+ | typereference '(' ranges ')' {
+ $$ = (struct syntax){
+ .type = TYPE_REFERENCE,
+ .ranges = $3
+ };
+ strlcpy($$.reference, $1, sizeof($$.reference));
+ }
;
-octetstringsubtype : OCTET STRING '(' SIZE '(' ranges ')' ')'
- | Opaque '(' SIZE '(' ranges ')' ')'
- | typereference '(' SIZE '(' ranges ')' ')'
+octetstringsubtype : OCTET STRING '(' SIZE '(' ranges ')' ')' {
+ $$ = (struct syntax) {
+ .type = TYPE_OSTRING,
+ .ranges = $6
+ };
+ }
+ | Opaque '(' SIZE '(' ranges ')' ')' {
+ $$ = (struct syntax) {
+ .type = TYPE_OPAQUE,
+ .ranges = $5
+ };
+ }
+ | typereference '(' SIZE '(' ranges ')' ')' {
+ $$ = (struct syntax) {
+ .type = TYPE_REFERENCE,
+ .ranges = $5
+ };
+ strlcpy($$.reference, $1, sizeof($$.reference));
+ }
;
-bits : BITS '{' namedbits '}'
+bits : BITS '{' namedbits '}' {
+ $$ = (struct syntax) {
+ .type = TYPE_BITS
+ };
+ }
;
namedbits : namedbit
@@ -906,8 +1071,17 @@ namedbits : namedbit
namedbit : identifier '(' NUMBER ')'
;
-enumeration : INTEGER '{' namednumbers '}'
- | typereference '{' namednumbers '}'
+enumeration : INTEGER '{' namednumbers '}' {
+ $$ = (struct syntax) {
+ .type = TYPE_ENUMERATED,
+ };
+ }
+ | typereference '{' namednumbers '}' {
+ $$ = (struct syntax) {
+ .type = TYPE_ENUMERATED
+ };
+ strlcpy($$.reference, $1, sizeof($$.reference));
+ }
;
namednumbers : namednumber
@@ -918,18 +1092,105 @@ namednumber : identifier '(' NUMBER ')'
| identifier '(' SIGNEDNUMBER ')'
;
-ranges : range '|' ranges
- | range
+ranges : ranges '|' range {
+ size_t i, j;
+ int inserted = 0;
+
+ $$.nranges = $1.nranges;
+ for (i = j = 0; i < $1.nranges; i++, j++) {
+ if (inserted) {
+ $$.range[i] = $1.range[j];
+ continue;
+ }
+ if (($3.start >= $1.range[j].start &&
+ $3.start <= $1.range[j].end) ||
+ ($3.end >= $1.range[j].start &&
+ $3.end <= $1.range[j].end)) {
+ yyerror("Ranges can't overlap");
+ YYERROR;
+ }
+ if ($3.end == $1.range[j].start - 1) {
+ $$.range[i].start = $3.start;
+ $$.range[i].end =
+ $1.range[j].end;
+ inserted = 1;
+ continue;
+ } else if (
+ $3.start == $1.range[j].end + 1) {
+ $$.range[i].start =
+ $1.range[j].start;
+ $$.range[i].end = $3.end;
+ inserted = 1;
+ continue;
+ } else if (
+ $3.start < $1.range[j].start) {
+ if ($$.nranges ==
+ nitems($$.range)) {
+ yyerror(
+ "too many ranges");
+ YYERROR;
+ }
+ $$.range[i] = $3;
+ $$.nranges++;
+ i++;
+ inserted = 1;
+ }
+ $$.range[i] = $1.range[j];
+ }
+ }
+ | range {
+ $$.nranges = 1;
+ $$.range[0] = $1;
+ }
;
-range : value
- | value RANGESEPARATOR value
+range : value {
+ $$.start = $1;
+ $$.end = $1;
+ }
+ | value RANGESEPARATOR value {
+ if ($1 >= $3) {
+ yyerror("invalid range: "
+ "%lld not smaller than %lld",
+ $1, $3);
+ YYERROR;
+ }
+ $$.start = $1;
+ $$.end = $3;
+ }
;
-value : SIGNEDNUMBER
- | NUMBER
- | HSTRING
- | BSTRING
+value : SIGNEDNUMBER {
+ $$ = $1;
+ }
+ | NUMBER {
+ $$ = $1;
+ }
+ | HSTRING {
+ size_t i;
+ int val;
+ char digit;
+
+ $$ = 0;
+ for (i = 1; $1[i] != '\''; i++) {
+ $$ <<= 4;
+ digit = tolower($1[i]);
+ if (digit >= '0' && digit <= '9')
+ val = digit - '0';
+ else if (digit >= 'a' && digit <= 'f')
+ val = digit - 'a' + 10;
+ $$ |= val;
+ }
+ }
+ | BSTRING {
+ size_t i;
+
+ $$ = 0;
+ for (i = 1; $1[i] != '\''; i++) {
+ $$ <<= 1;
+ $$ |= $1[i] - '0';
+ }
+ }
;
access : descriptor {
@@ -1528,7 +1789,7 @@ mib_objectidentity(const char *name, enum status statu
}
int
-mib_objecttype(const char *name, void *syntax, const char *units,
+mib_objecttype(const char *name, struct syntax *syntax, const char *units,
enum access maxaccess, enum status status, const char *description,
const char *reference, void *index, void *defval,
const struct oid_unresolved *oid)
@@ -1539,6 +1800,7 @@ mib_objecttype(const char *name, void *syntax, const c
return -1;
item->objecttype.maxaccess = maxaccess;
+ item->objecttype.syntax = *syntax;
item->objecttype.status = status;
if (mib_item_oid(item, oid) == -1)
return -1;
@@ -1564,13 +1826,18 @@ mib_notificationtype(const char *name, void *objects,
int
mib_textualconvetion(const char *name, const char *displayhint,
enum status status, const char *description, const char *reference,
- void *syntax)
+ const struct syntax *syntax)
{
struct item *item;
if ((item = mib_item(name, IT_TEXTUAL_CONVENTION)) == NULL)
return -1;
item->textualconvention.status = status;
+ if (syntax->reference[0] != '\0') {
+ yyerror("TEXTUAL-CONVENTION SYNTAX can't be typerefence");
+ return -1;
+ }
+ item->textualconvention.syntax = *syntax;
return 0;
}
@@ -1619,6 +1886,16 @@ mib_modulecompliance(const char *name, enum status sta
return 0;
}
+int
+mib_item_sequence(const char *name, void *entries)
+{
+ struct item *item;
+
+ if ((item = mib_item(name, IT_SEQUENCE)) == NULL)
+ return -1;
+ return 0;
+}
+
void
mib_parsefile(const char *path)
{
@@ -1781,11 +2058,175 @@ mib_oid2string(struct ber_oid *oid, char *buf, size_t
return buf;
}
+int
+mib_varbind_valid(struct ber_oid *oid, struct ber_element *value)
+{
+ struct item *item;
+ struct syntax *syntax;
+ long long ival;
+ void *sval;
+ size_t i, slen;
+
+ item = mib_item_parent(oid);
+ if (item == NULL || item->type != IT_OBJECT_TYPE)
+ return 1;
+
+ if (item->objecttype.syntax.type == TYPE_REFERENCE) {
+ if (item->objecttype.syntax.refitem->type == IT_SEQUENCE)
+ return 1;
+ syntax =
+ &item->objecttype.syntax.refitem->textualconvention.syntax;
+ } else
+ syntax = &item->objecttype.syntax;
+
+ switch (syntax->type) {
+ case TYPE_REFERENCE:
+ fatal("%s: can't happen", __func__);
+ case TYPE_INTEGER:
+ case TYPE_ENUMERATED:
+ if (value->be_class != BER_CLASS_UNIVERSAL ||
+ value->be_type != BER_TYPE_INTEGER)
+ return 0;
+ if (ober_get_integer(value, &ival) == -1)
+ return 0;
+ if (ival < INT32_MIN || ival > INT32_MAX)
+ return 0;
+ for (i = 0; i < syntax->ranges.nranges; i++) {
+ if (ival >= syntax->ranges.range[i].start &&
+ ival <= syntax->ranges.range[i].end)
+ break;
+ }
+ if (syntax->ranges.nranges > 0 && i == syntax->ranges.nranges)
+ return 0;
+ return 1;
+ case TYPE_OID:
+ if (value->be_class != BER_CLASS_UNIVERSAL ||
+ value->be_type != BER_TYPE_OBJECT)
+ return 0;
+ return 1;
+ case TYPE_OSTRING:
+ if (value->be_class != BER_CLASS_UNIVERSAL ||
+ value->be_type != BER_TYPE_OCTETSTRING)
+ return 0;
+ if (ober_get_nstring(value, &sval, &slen) == -1)
+ return 0;
+ if (slen > SMI_OCTETSTRING_MAX)
+ return 0;
+ for (i = 0; i < syntax->ranges.nranges; i++) {
+ if (slen >= (size_t)syntax->ranges.range[i].start &&
+ slen <= (size_t)syntax->ranges.range[i].end)
+ break;
+ }
+ if (syntax->ranges.nranges > 0 && i == syntax->ranges.nranges)
+ return 0;
+ return 1;
+ case TYPE_IPADDRESS:
+ if (value->be_class != BER_CLASS_APPLICATION ||
+ value->be_type != SNMP_T_IPADDR)
+ return 0;
+ if (ober_get_nstring(value, &sval, &slen) == -1)
+ return 0;
+ if (slen != 4)
+ return 0;
+ return 1;
+ case TYPE_COUNTER32:
+ if (value->be_class != BER_CLASS_APPLICATION ||
+ value->be_type != SNMP_T_COUNTER32)
+ return 0;
+ if (ober_get_integer(value, &ival) == -1)
+ return 0;
+ if (ival < 0 || ival > UINT32_MAX)
+ return 0;
+ return 1;
+ case TYPE_GAUGE32:
+ case TYPE_UNSIGNED32:
+ if (value->be_class != BER_CLASS_APPLICATION ||
+ value->be_type != SNMP_T_GAUGE32)
+ return 0;
+ if (ober_get_integer(value, &ival) == -1)
+ return 0;
+ if (ival < 0 || ival > UINT32_MAX)
+ return 0;
+ return 1;
+ case TYPE_TIMETICKS:
+ if (value->be_class != BER_CLASS_APPLICATION ||
+ value->be_type != SNMP_T_TIMETICKS)
+ return 0;
+ if (ober_get_integer(value, &ival) == -1)
+ return 0;
+ if (ival < 0 || ival > UINT32_MAX)
+ return 0;
+ return 1;
+ case TYPE_OPAQUE:
+ if (value->be_class != BER_CLASS_APPLICATION ||
+ value->be_type != SNMP_T_OPAQUE)
+ return 0;
+ if (ober_get_nstring(value, &sval, &slen) == -1)
+ return 0;
+ /* No size limit */
+ return 1;
+ case TYPE_COUNTER64:
+ if (value->be_class != BER_CLASS_APPLICATION ||
+ value->be_type != SNMP_T_COUNTER64)
+ return 0;
+ if (ober_get_integer(value, &ival) == -1)
+ return 0;
+ /* 64 bits value, no range check */
+ return 1;
+ case TYPE_BITS:
+ if (value->be_class != BER_CLASS_UNIVERSAL ||
+ value->be_type != BER_TYPE_OCTETSTRING)
+ return 0;
+ if (ober_get_nstring(value, &sval, &slen) == -1)
+ return 0;
+ /* No explicit limit, 128 recommended */
+ return 1;
+ case TYPE_SEQUENCEOF:
+ return 0;
+ }
+}
+
void
mib_defaults(void)
{
struct oid_unresolved oid;
struct item *iso;
+ const struct syntax stdisplay = {
+ .type = TYPE_OSTRING,
+ .ranges.nranges = 1,
+ .ranges.range[0].start = 0,
+ .ranges.range[0].end = 255
+ }, stostring = {
+ .type = TYPE_OSTRING
+ }, stmacaddr = {
+ .type = TYPE_OSTRING,
+ .ranges.nranges = 1,
+ .ranges.range[0].start = 6,
+ .ranges.range[0].end =6
+ }, stenumerated = {
+ .type = TYPE_ENUMERATED
+ }, stmaxint = {
+ .type = TYPE_INTEGER,
+ .ranges.nranges = 1,
+ .ranges.range[0].start = 0,
+ .ranges.range[0].end = 2147483647
+ }, stoid = {
+ .type = TYPE_OID
+ }, sttimestamp = {
+ .type = TYPE_TIMETICKS
+ }, stdateandtime = {
+ .type = TYPE_OSTRING,
+ .ranges.nranges = 2,
+ .ranges.range[0].start = 8,
+ .ranges.range[0].end = 8,
+ .ranges.range[1].start = 11,
+ .ranges.range[1].end = 11
+ }, sttaddress = {
+ .type = TYPE_OSTRING,
+ .ranges.nranges = 1,
+ .ranges.range[0].start = 1,
+ .ranges.range[0].end = 255
+ };
if (!RB_EMPTY(&modulesci))
return;
@@ -1924,37 +2365,37 @@ mib_defaults(void)
exit(1);
if (mib_textualconvetion(
- "DisplayString", "255a", CURRENT, "", NULL, NULL) == -1 ||
+ "DisplayString", "255a", CURRENT, "", NULL, &stdisplay) == -1 ||
mib_textualconvetion(
- "PhysAddress", "1x:", CURRENT, "", NULL, NULL) == -1 ||
+ "PhysAddress", "1x:", CURRENT, "", NULL, &stostring) == -1 ||
mib_textualconvetion(
- "MacAddress", "1x:", CURRENT, "", NULL, NULL) == -1 ||
+ "MacAddress", "1x:", CURRENT, "", NULL, &stmacaddr) == -1 ||
mib_textualconvetion(
- "TruthValue", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "TruthValue", NULL, CURRENT, "", NULL, &stenumerated) == -1 ||
mib_textualconvetion(
- "TestAndIncr", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "TestAndIncr", NULL, CURRENT, "", NULL, &stmaxint) == -1 ||
mib_textualconvetion(
- "AutonomousType", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "AutonomousType", NULL, CURRENT, "", NULL, &stoid) == -1 ||
mib_textualconvetion(
- "InstancePointer", NULL, OBSOLETE, "", NULL, NULL) == -1 ||
+ "InstancePointer", NULL, OBSOLETE, "", NULL, &stoid) == -1 ||
mib_textualconvetion(
- "VariablePointer", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "VariablePointer", NULL, CURRENT, "", NULL, &stoid) == -1 ||
mib_textualconvetion(
- "RowPointer", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "RowPointer", NULL, CURRENT, "", NULL, &stoid) == -1 ||
mib_textualconvetion(
- "RowStatus", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "RowStatus", NULL, CURRENT, "", NULL, &stenumerated) == -1 ||
mib_textualconvetion(
- "TimeStamp", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "TimeStamp", NULL, CURRENT, "", NULL, &sttimestamp) == -1 ||
mib_textualconvetion(
- "TimeInterval", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "TimeInterval", NULL, CURRENT, "", NULL, &stmaxint) == -1 ||
mib_textualconvetion(
- "DateAndTime", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "DateAndTime", NULL, CURRENT, "", NULL, &stdateandtime) == -1 ||
mib_textualconvetion(
- "StorageType", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "StorageType", NULL, CURRENT, "", NULL, &stenumerated) == -1 ||
mib_textualconvetion(
- "TDomain", NULL, CURRENT, "", NULL, NULL) == -1 ||
+ "TDomain", NULL, CURRENT, "", NULL, &stoid) == -1 ||
mib_textualconvetion(
- "TAddress", NULL, CURRENT, "", NULL, NULL) == -1)
+ "TAddress", NULL, CURRENT, "", NULL, &sttaddress) == -1)
exit(1);
RB_INSERT(modulesci, &modulesci, module);
@@ -2104,7 +2545,7 @@ mib_resolve_oid(struct oid_resolved *dst, struct oid_u
int
mib_resolve_item(struct item *item)
{
- struct item *prev;
+ struct item *prev, *typeref;
struct oid_resolved oid;
if (item->resolved)
@@ -2114,7 +2555,8 @@ mib_resolve_item(struct item *item)
if (item->type == IT_MACRO ||
item->type == IT_APPLICATIONSYNTAX ||
- item->type == IT_TEXTUAL_CONVENTION)
+ item->type == IT_TEXTUAL_CONVENTION ||
+ item->type == IT_SEQUENCE)
return 0;
if (mib_resolve_oid(&oid, item->oid_unresolved, item) == -1)
@@ -2122,6 +2564,29 @@ mib_resolve_item(struct item *item)
free(item->oid_unresolved);
item->oid = oid;
+ if (item->type == IT_OBJECT_TYPE) {
+ if (item->objecttype.syntax.reference[0] != '\0') {
+ if ((typeref = mib_item_find(
+ item, item->objecttype.syntax.reference)) == NULL) {
+ log_warnx("%s::%s: OBJECT-TYPE SYNTAX "
+ "reference %s not found",
+ item->module->name, item->name,
+ item->objecttype.syntax.reference);
+ return -1;
+ }
+ if (typeref->type != IT_TEXTUAL_CONVENTION &&
+ typeref->type != IT_SEQUENCE) {
+ log_warnx("%s::%s: OBJECT-TYPE SYNTAX "
+ "reference %s not TEXTUAL-CONVENTION",
+ item->module->name, item->name,
+ item->objecttype.syntax.reference);
+ return -1;
+ }
+ item->objecttype.syntax.refitem = typeref;
+ } else
+ item->objecttype.syntax.refitem = NULL;
+ }
+
if ((prev = RB_INSERT(items, &items, item)) != NULL) {
/* Prioritize an OID derived from a MACRO over a plain OID */
if (prev->type == IT_OID && item->type != IT_OID) {
snmpd: testers wanted: varbind syntax validation