diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2012-10-01 11:36:56 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2012-10-01 11:36:56 +0000 |
commit | 33bae3ed38b7dab44bf5ed7a6da6af4772428773 (patch) | |
tree | 7924fcd94a7613d88c741b04a9c0313e7bf1c828 /usr.sbin/snmpd | |
parent | 0bdfecfa92bc2adfbcdf936c4065b2fcd08dbad4 (diff) |
Support the 0.0.0.0 and 255.255.255.255 IPv4 addresses in the ipAddrTable.
This fixes an issue which aborted the address traversal / SNMP walk when
an "any"/0.0.0.0 address was configured on an interface. The problem
was found with a pppoe(4) device that is typically configured with 0.0.0.0
on startup.
Found and fix tested by Gerhard Roth
Diffstat (limited to 'usr.sbin/snmpd')
-rw-r--r-- | usr.sbin/snmpd/mib.c | 25 | ||||
-rw-r--r-- | usr.sbin/snmpd/mps.c | 27 | ||||
-rw-r--r-- | usr.sbin/snmpd/snmpd.h | 4 |
3 files changed, 40 insertions, 16 deletions
diff --git a/usr.sbin/snmpd/mib.c b/usr.sbin/snmpd/mib.c index 68ddc7c2f20..d00fb5456c4 100644 --- a/usr.sbin/snmpd/mib.c +++ b/usr.sbin/snmpd/mib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mib.c,v 1.60 2012/09/20 20:11:58 yuo Exp $ */ +/* $OpenBSD: mib.c,v 1.61 2012/10/01 11:36:55 reyk Exp $ */ /* * Copyright (c) 2012 Joel Knight <joel@openbsd.org> @@ -3139,15 +3139,22 @@ mib_ipaddrtable(struct oid *oid, struct ber_oid *o, struct ber_oid *no) } mps_decodeinaddr(no, &addr.sin_addr, OIDIDX_ipAddr + 1); - if (addr.sin_addr.s_addr == INADDR_ANY) + if (o->bo_n <= (OIDIDX_ipAddr + 1)) ka = kr_getaddr(NULL); else ka = kr_getnextaddr((struct sockaddr *)&addr); - if (ka == NULL || ka->addr.sa.sa_family != AF_INET) - addr.sin_addr.s_addr = 0; - else + if (ka == NULL || ka->addr.sa.sa_family != AF_INET) { + /* + * Encode invalid "last address" marker which will tell + * mib_ipaddr() to fail and the SNMP engine to find the + * next OID. + */ + mps_encodeinaddr(no, NULL, OIDIDX_ipAddr + 1); + } else { + /* Encode real IPv4 address */ addr.sin_addr.s_addr = ka->addr.sin.sin_addr.s_addr; - mps_encodeinaddr(no, &addr.sin_addr, OIDIDX_ipAddr + 1); + mps_encodeinaddr(no, &addr.sin_addr, OIDIDX_ipAddr + 1); + } smi_oidlen(o); return (no); @@ -3165,7 +3172,11 @@ mib_ipaddr(struct oid *oid, struct ber_oid *o, struct ber_element **elm) addr.sin_family = AF_INET; addr.sin_len = sizeof(addr); - mps_decodeinaddr(o, &addr.sin_addr, OIDIDX_ipAddr + 1); + if (mps_decodeinaddr(o, &addr.sin_addr, OIDIDX_ipAddr + 1) == -1) { + /* Strip invalid address and fail */ + o->bo_n = OIDIDX_ipAddr + 1; + return (1); + } ka = kr_getaddr((struct sockaddr *)&addr); if (ka == NULL || ka->addr.sa.sa_family != AF_INET) return (1); diff --git a/usr.sbin/snmpd/mps.c b/usr.sbin/snmpd/mps.c index 9f6a4129652..e913b000c5b 100644 --- a/usr.sbin/snmpd/mps.c +++ b/usr.sbin/snmpd/mps.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mps.c,v 1.16 2012/09/17 16:43:59 reyk Exp $ */ +/* $OpenBSD: mps.c,v 1.17 2012/10/01 11:36:55 reyk Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -333,16 +333,23 @@ mps_table(struct oid *oid, struct ber_oid *o, struct ber_oid *no) void mps_encodeinaddr(struct ber_oid *o, struct in_addr *addr, int offset) { - u_int32_t a = htole32(addr->s_addr); + u_int32_t a, i; o->bo_n = offset; - o->bo_id[o->bo_n++] = a & 0xff; - o->bo_id[o->bo_n++] = (a >> 8) & 0xff; - o->bo_id[o->bo_n++] = (a >> 16) & 0xff; - o->bo_id[o->bo_n++] = (a >> 24) & 0xff; + if (addr != NULL) { + a = htole32(addr->s_addr); + o->bo_id[o->bo_n++] = a & 0xff; + o->bo_id[o->bo_n++] = (a >> 8) & 0xff; + o->bo_id[o->bo_n++] = (a >> 16) & 0xff; + o->bo_id[o->bo_n++] = (a >> 24) & 0xff; + } else { + /* Create an invalid "last address" marker (5 bytes) */ + for (i = 0; i < 5; i++) + o->bo_id[o->bo_n++] = 0xff; + } } -void +int mps_decodeinaddr(struct ber_oid *o, struct in_addr *addr, int offset) { u_int32_t a; @@ -352,4 +359,10 @@ mps_decodeinaddr(struct ber_oid *o, struct in_addr *addr, int offset) ((o->bo_id[offset + 2] & 0xff) << 16) | ((o->bo_id[offset + 3] & 0xff) << 24); addr->s_addr = letoh32(a); + + /* Detect invalid address */ + if ((o->bo_n - offset) > 4) + return (-1); + + return (0); } diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index 8f112433353..50c3c6efeae 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.38 2012/09/18 08:29:09 reyk Exp $ */ +/* $OpenBSD: snmpd.h,v 1.39 2012/10/01 11:36:55 reyk Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org> @@ -495,7 +495,7 @@ int mps_setint(struct oid *, struct ber_oid *, int mps_getts(struct oid *, struct ber_oid *, struct ber_element **); void mps_encodeinaddr(struct ber_oid *, struct in_addr *, int); -void mps_decodeinaddr(struct ber_oid *, struct in_addr *, int); +int mps_decodeinaddr(struct ber_oid *, struct in_addr *, int); struct ber_oid *mps_table(struct oid *, struct ber_oid *, struct ber_oid *); /* pf.c */ |