Index: snmpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v
retrieving revision 1.25
diff -u snmpd.h
--- snmpd.h 6 Jun 2009 18:38:01 -0000 1.25
+++ snmpd.h 18 Dec 2009 12:10:17 -0000
@@ -209,9 +209,9 @@
long long sm_request;
long long sm_error;
-#define sm_nonrepeaters sm_error
long long sm_errorindex;
-#define sm_maxrepetitions sm_errorindex
+ long long sm_nonrepeaters;
+ long long sm_maxrepetitions;
struct ber_element *sm_pdu;
struct ber_element *sm_pduend;
Index: snmpe.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v
retrieving revision 1.24
diff -u snmpe.c
@@ -477,19 +479,95 @@
return (BER_TYPE_OCTETSTRING);
}
+static struct ber_element *
+snmpe_br_maxreps(struct snmp_message *msg, struct ber_element *start_elm,
+ struct ber_oid *start_oid, int len)
+{
+ char buf[BUFSIZ];
+ struct ber_element *a, *b, *c, *d, *first, *last;
+ struct ber_oid oids[SNMPD_MAXVARBINDLEN];
+ int repnum, vb_count, vb_idx = 0;
+
+ msg->sm_errorindex = len;
+ log_debug("snmpe_br_maxreps: maxreps=%d", msg->sm_maxrepetitions);
+
+ /* stuff in the first oid we have already */
+ bcopy(start_oid, oids, sizeof(*start_oid));
+ log_debug("snmpe_br_maxreps: varbind %d, oid %s", vb_idx,
+ smi_oidstring(start_oid, buf, sizeof(buf)));
+
+ vb_idx = 1;
+ a = start_elm;
+
+ /* build a list of oids to iterate over */
+ while ((a != NULL) && (a->be_type != BER_TYPE_EOC)) {
+ msg->sm_errorindex ++;
+ a = a->be_next;
+
+ if (a->be_class != BER_CLASS_UNIVERSAL ||
+ a->be_type != BER_TYPE_SEQUENCE)
+ continue;
+ if ((b = a->be_sub) == NULL)
+ continue;
+ if (ber_get_oid(b, &(oids[vb_idx])) != 0)
+ return NULL;
+ if (oids[vb_idx].bo_n < BER_MIN_OID_LEN ||
+ oids[vb_idx].bo_n > BER_MAX_OID_LEN)
+ return NULL;
+
+ log_debug("snmpe_br_maxreps: varbind %d, oid %s", vb_idx,
+ smi_oidstring(&(oids[vb_idx]), buf, sizeof(buf)));
+ vb_idx ++;
+ }
+ vb_count = vb_idx;
+ log_debug("snmpe_br_maxreps: %d varbinds.", vb_count);
+
+ msg->sm_errorindex = 0;
+ msg->sm_error = SNMP_ERROR_NONE;
+
+ first = last = NULL;
+
+ for (repnum = 0; repnum < msg->sm_maxrepetitions; repnum++) {
+ for(vb_idx=0; vb_idx<vb_count; vb_idx++) {
+ log_debug("snmpe_br_maxreps: varbind %d, repnum %d oid
%s", vb_idx, repnum,
+ smi_oidstring(&(oids[vb_idx]), buf,
sizeof(buf)));
+
+ if (oids[vb_idx].bo_n == 0)
+ continue;
+ c = ber_add_sequence(NULL);
+ d = mps_getnextreq(c, &(oids[vb_idx]));
+ if (d == NULL) {
+ oids[vb_idx].bo_n = 0;
+ continue;
+ }
+ len += ber_calc_len(c);
+ if (len > SNMPD_MAXVARBINDLEN) {
+ log_debug("len > SNMPD_MAXVARBINDLEN: %d>%d",
len, SNMPD_MAXVARBINDLEN);
+ ber_free_elements(c);
+ return first;
+ }
+ if (first == NULL)
+ first = c;
+ else
+ last->be_next = c;
+ last = c;
+ }
+ }
+ return first;
+}
+
int
snmpe_parse(struct sockaddr_storage *ss,
struct ber_element *root, struct snmp_message *msg)
{
struct snmp_stats *stats = &env->sc_stats;
- struct ber_element *a, *b, *c, *d, *e, *f, *next, *last;
+ struct ber_element *a, *b, *c, *d, *next, *last;
const char *errstr = "invalid message";
long long ver, req;
unsigned long type, errval, erridx;
- u_int class, state, i = 0, j = 0;
+ u_int class, state, i = 0;
char *comn, buf[BUFSIZ], host[MAXHOSTNAMELEN];
struct ber_oid o;
- size_t len;
bzero(msg, sizeof(*msg));
@@ -591,6 +671,8 @@
msg->sm_request = req;
msg->sm_error = errval;
msg->sm_errorindex = erridx;
+ msg->sm_nonrepeaters = msg->sm_error;
+ msg->sm_maxrepetitions = msg->sm_errorindex;
print_host(ss, host, sizeof(host));
log_debug("snmpe_parse: %s: SNMPv%d '%s' context %d request %lld",
@@ -599,7 +681,7 @@
errstr = "invalid varbind element";
for (i = 1, a = msg->sm_varbind, last = NULL;
- a != NULL && i < SNMPD_MAXVARBIND; a = next, i++) {
+ a != NULL && i < SNMPD_MAXVARBINDLEN; a = next, i++) {
next = a->be_next;
if (a->be_class != BER_CLASS_UNIVERSAL ||
@@ -647,30 +729,28 @@
msg->sm_error = SNMP_ERROR_READONLY;
goto varfail;
case SNMP_C_GETBULKREQ:
- j = msg->sm_maxrepetitions;
+ msg->sm_error = 0;
msg->sm_errorindex = 0;
- msg->sm_error = SNMP_ERROR_NOSUCHNAME;
- for (d = NULL, len = 0; j > 0; j--) {
- e = ber_add_sequence(NULL);
- if (c == NULL)
- c = e;
- f = mps_getnextreq(e, &o);
- if (f == NULL) {
- ber_free_elements(e);
- if (d == NULL)
- goto varfail;
+ if (msg->sm_nonrepeaters) {
+ log_debug("handling %dth nonrepeater
%s",
+ msg->sm_nonrepeaters,
smi_oidstring(&o, buf, sizeof(buf)));
+ msg->sm_nonrepeaters--;
+ c = ber_add_sequence(NULL);
+ if ((d = mps_getnextreq(c, &o))
!= NULL)
break;
- }
- len += ber_calc_len(e);
- if (len > SNMPD_MAXVARBINDLEN) {
- ber_free_elements(e);
- break;
- }
- if (d != NULL)
- ber_link_elements(d, e);
- d = e;
+ ber_free_elements(c);
+ c = NULL;
+ break; /* ignore error */
}
- msg->sm_error = 0;
+ if (msg->sm_maxrepetitions == 0) {
+ log_debug("error: no nonreps, no
maxreps, oid not expected: %s",
+ smi_oidstring(&o, buf,
sizeof(buf)));
+ msg->sm_error =
SNMP_ERROR_GENERR;
+ goto varfail;
+ }
+ c = snmpe_br_maxreps(msg, a, &o, i);
+ state = 42; /* break inner loop */
+ i = state * SNMPD_MAXVARBINDLEN; /*
break outer loop */
break;
default:
goto varfail;