Hi,
With some help from blambert@ and thorough testing by sthen@, I was
able to get this working fairly well. There are some rough edges
however, namely the rdomain kludge and the need for an RTM_DELETE
notification, but apart from that it seems to be doing the right
thing.
The ARP part of the kroute builds sorted ARP lists hanging off of
the interface nodes in the interface R/B tree. There's fetcharp()
that fetches and updates ARP entries on all interfaces within an
rdomain and kernel notifications arriving at the routing socket
that add or remove entries. When interface goes away its ARP list
gets purged.
The MIB part iterates over all interfaces and all ARP entries and
calls mib_physaddr for each one of them that completes filling all
node's fields.
OK?
diff --git usr.sbin/snmpd/kroute.c usr.sbin/snmpd/kroute.c
index 1ed4d17..7c0989b 100644
--- usr.sbin/snmpd/kroute.c
+++ usr.sbin/snmpd/kroute.c
@@ -45,10 +45,12 @@
#include "snmpd.h"
extern struct snmpd *env;
+u_short snmpd_rtableid;
+
struct {
struct event ks_ev;
u_long ks_iflastchange;
u_long ks_nroutes; /* 4 billions enough? */
int ks_fd;
@@ -69,10 +71,11 @@ struct kroute6_node {
};
struct kif_node {
RB_ENTRY(kif_node) entry;
TAILQ_HEAD(, kif_addr) addrs;
+ TAILQ_HEAD(, kif_arp) arps;
struct kif k;
};
int kroute_compare(struct kroute_node *, struct kroute_node *);
int kroute6_compare(struct kroute6_node *, struct kroute6_node *);
@@ -91,10 +94,14 @@ struct kroute6_node *kroute6_matchgw(struct kroute6_node *,
struct sockaddr_in6 *);
int kroute6_insert(struct kroute6_node *);
int kroute6_remove(struct kroute6_node *);
void kroute6_clear(void);
+struct kif_arp *karp_find(struct sockaddr *, u_short);
+int karp_insert(struct kif_node *, struct kif_arp *);
+int karp_remove(struct kif_node *, struct kif_arp *);
+
struct kif_node *kif_find(u_short);
struct kif_node *kif_insert(u_short);
int kif_remove(struct kif_node *);
void kif_clear(void);
struct kif *kif_update(u_short, int, struct if_data *,
@@ -118,10 +125,11 @@ void if_deladdr(u_short, struct sockaddr *,
struct sockaddr *,
struct sockaddr *);
void if_announce(void *);
int fetchtable(void);
int fetchifs(u_short);
+int fetcharp(void);
void dispatch_rtmsg(int, short, void *);
int rtmsg_process(char *, int);
int dispatch_rtmsg_addr(struct rt_msghdr *,
struct sockaddr *[RTAX_MAX]);
@@ -145,10 +153,12 @@ void
kr_init(void)
{
int opt = 0, rcvbuf, default_rcvbuf;
socklen_t optlen;
+ snmpd_rtableid = getrtable();
+
if ((kr_state.ks_ifd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
fatal("kr_init: ioctl socket");
if ((kr_state.ks_fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1)
fatal("kr_init: route socket");
@@ -182,10 +192,12 @@ kr_init(void)
if (fetchifs(0) == -1)
fatalx("kr_init fetchifs");
if (fetchtable() == -1)
fatalx("kr_init fetchtable");
+ if (fetcharp() == -1)
+ fatalx("kr_init fetcharp");
event_set(&kr_state.ks_ev, kr_state.ks_fd, EV_READ | EV_PERSIST,
dispatch_rtmsg, NULL);
event_add(&kr_state.ks_ev, NULL);
}
@@ -519,10 +531,126 @@ kroute6_clear(void)
while ((kr = RB_MIN(kroute6_tree, &krt6)) != NULL)
kroute6_remove(kr);
}
+static inline int
+karp_compare(struct kif_arp *a, struct kif_arp *b)
+{
+ /* Interface indices are assumed equal */
+ if (ntohl(a->addr.sin.sin_addr.s_addr) >
+ ntohl(b->addr.sin.sin_addr.s_addr))
+ return (1);
+ if (ntohl(a->addr.sin.sin_addr.s_addr) <
+ ntohl(b->addr.sin.sin_addr.s_addr))
+ return (-1);
+ return (0);
+}
+
+static inline struct kif_arp *
+karp_search(struct kif_arp *s, struct kif_node *kn)
+{
+ struct kif_arp *ka;
+
+ TAILQ_FOREACH(ka, &kn->arps, entry) {
+ switch (karp_compare(s, ka)) {
+ case 0: /* found */
+ return (ka);
+ case -1: /* s < ka, end the search */
+ return (NULL);
+ }
+ }
+ /* looped throught the whole list and didn't find */
+ return (NULL);
+}
+
+struct kif_arp *
+karp_find(struct sockaddr *sa, u_short ifindex)
+{
+ struct kif_node *kn;
+ struct kif_arp *ka = NULL, s;
+
+ memcpy(&s.addr.sa, sa, sa->sa_len);
+
+ if (ifindex > 0 && (kn = kif_find(ifindex)) == NULL)
+ return (NULL);
+
+ if (ifindex == 0) {
+ /*
+ * We do this manually, because we want to handle zero
+ * ifindex special case differently from kif_find, in
+ * particular it means that we have to look for the
+ * address on all available interfaces.
+ */
+ RB_FOREACH(kn, kif_tree, &kit) {
+ if ((ka = karp_search(&s, kn)) != NULL)
+ break;
+ }
+ } else {
+ if ((kn = kif_find(ifindex)) == NULL)
+ return (NULL);
+ ka = karp_search(&s, kn);
+ }
+ return (ka);
+}
+
+int
+karp_insert(struct kif_node *kn, struct kif_arp *ka)
+{
+ struct kif_arp *pivot;
+
+ if (ka->if_index == 0)
+ return (-1);
+ if (!kn && (kn = kif_find(ka->if_index)) == NULL)
+ return (-1);
+ /* Put entry on the list in the ascending lexical order */
+ TAILQ_FOREACH(pivot, &kn->arps, entry) {
+ switch (karp_compare(ka, pivot)) {
+ case 0: /* collision */
+ return (-1);
+ case -1: /* ka < pivot */
+ TAILQ_INSERT_BEFORE(pivot, ka, entry);
+ return (0);
+ }
+ }
+ /* ka is larger than any other element on the list */
+ TAILQ_INSERT_TAIL(&kn->arps, ka, entry);
+ return (0);
+}
+
+int
+karp_remove(struct kif_node *kn, struct kif_arp *ka)
+{
+ if (ka->if_index == 0)
+ return (-1);
+ if (!kn && (kn = kif_find(ka->if_index)) == NULL)
+ return (-1);
+ TAILQ_REMOVE(&kn->arps, ka, entry);
+ free(ka);
+ return (0);
+}
+
+struct kif_arp *
+karp_first(u_short ifindex)
+{
+ struct kif_node *kn;
+
+ if ((kn = kif_find(ifindex)) == NULL)
+ return (NULL);
+ return (TAILQ_FIRST(&kn->arps));
+}
+
+struct kif_arp *
+karp_getaddr(struct sockaddr *sa, u_short ifindex, int next)
+{
+ struct kif_arp *ka;
+
+ if ((ka = karp_find(sa, ifindex)) == NULL)
+ return (NULL);
+ return (next ? TAILQ_NEXT(ka, entry) : ka);
+}
+
struct kif_node *
kif_find(u_short if_index)
{
struct kif_node s;
@@ -570,10 +698,11 @@ kif_insert(u_short if_index)
if ((kif = calloc(1, sizeof(struct kif_node))) == NULL)
return (NULL);
kif->k.if_index = if_index;
TAILQ_INIT(&kif->addrs);
+ TAILQ_INIT(&kif->arps);
if (RB_INSERT(kif_tree, &kit, kif) != NULL)
fatalx("kif_insert: RB_INSERT");
kr_state.ks_nkif++;
@@ -584,20 +713,24 @@ kif_insert(u_short if_index)
int
kif_remove(struct kif_node *kif)
{
struct kif_addr *ka;
+ struct kif_arp *kr;
if (RB_REMOVE(kif_tree, &kit, kif) == NULL) {
log_warnx("RB_REMOVE(kif_tree, &kit, kif)");
return (-1);
}
while ((ka = TAILQ_FIRST(&kif->addrs)) != NULL) {
TAILQ_REMOVE(&kif->addrs, ka, entry);
ka_remove(ka);
}
+ while ((kr = TAILQ_FIRST(&kif->arps)) != NULL) {
+ karp_remove(kif, kr);
+ }
free(kif);
kr_state.ks_nkif--;
kr_state.ks_iflastchange = smi_getticks();
@@ -895,10 +1028,12 @@ if_announce(void *msg)
switch (ifan->ifan_what) {
case IFAN_ARRIVAL:
kif = kif_insert(ifan->ifan_index);
strlcpy(kif->k.if_name, ifan->ifan_name,
sizeof(kif->k.if_name));
+ /* Update the ARP table */
+ fetcharp();
break;
case IFAN_DEPARTURE:
kif = kif_find(ifan->ifan_index);
kif_remove(kif);
break;
@@ -974,10 +1109,49 @@ fetchifs(u_short if_index)
free(buf);
return (rv);
}
+int
+fetcharp(void)
+{
+ size_t len;
+ int mib[7];
+ char *buf;
+ int rv;
+
+ mib[0] = CTL_NET;
+ mib[1] = AF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET;
+ mib[4] = NET_RT_FLAGS;
+ mib[5] = RTF_LLINFO;
+ mib[6] = snmpd_rtableid;
+
+ if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) {
+ log_warn("sysctl");
+ return (-1);
+ }
+ /* Empty table? */
+ if (len == 0)
+ return (0);
+ if ((buf = malloc(len)) == NULL) {
+ log_warn("fetcharp");
+ return (-1);
+ }
+ if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) {
+ log_warn("sysctl");
+ free(buf);
+ return (-1);
+ }
+
+ rv = rtmsg_process(buf, len);
+ free(buf);
+
+ return (rv);
+}
+
/* ARGSUSED */
void
dispatch_rtmsg(int fd, short event, void *arg)
{
char buf[RT_BUF_SIZE];
@@ -1018,14 +1192,13 @@ rtmsg_process(char *buf, int len)
switch (rtm->rtm_type) {
case RTM_ADD:
case RTM_GET:
case RTM_CHANGE:
case RTM_DELETE:
+ case RTM_RESOLVE:
if (rtm->rtm_errno) /* failed attempts */
continue;
- if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
- continue;
if (dispatch_rtmsg_addr(rtm, rti_info) == -1)
return (-1);
break;
case RTM_IFINFO:
@@ -1067,12 +1240,14 @@ int
dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX])
{
struct sockaddr *sa, *psa;
struct sockaddr_in *sa_in, *psa_in = NULL;
struct sockaddr_in6 *sa_in6, *psa_in6 = NULL;
+ struct sockaddr_dl *sa_dl;
struct kroute_node *kr;
struct kroute6_node *kr6;
+ struct kif_arp *ka;
int flags, mpath = 0;
u_int16_t ifindex;
u_int8_t prefixlen;
u_int8_t prio;
@@ -1129,16 +1304,33 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct
sockaddr *rti_info[RTAX_MAX])
if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
switch (sa->sa_family) {
case AF_LINK:
flags |= F_CONNECTED;
ifindex = rtm->rtm_index;
- sa = NULL;
mpath = 0; /* link local stuff can't be mpath */
break;
}
if (rtm->rtm_type == RTM_DELETE) {
+ if (sa != NULL && sa->sa_family == AF_LINK &&
+ (rtm->rtm_flags & RTF_HOST) &&
+ psa->sa_family == AF_INET) {
+ if (rtm->rtm_tableid != snmpd_rtableid)
+ return (0);
+ if ((ka = karp_find(psa, ifindex)) == NULL)
+ return (0);
+ if (karp_remove(NULL, ka) == -1)
+ return (-1);
+ return (0);
+ } else if (sa == NULL && (rtm->rtm_flags & RTF_HOST) &&
+ psa->sa_family == AF_INET) {
+ if (rtm->rtm_tableid != snmpd_rtableid)
+ return (0);
+ if ((ka = karp_find(psa, ifindex)) != NULL)
+ karp_remove(NULL, ka);
+ /* Continue to the route section below */
+ }
switch (psa->sa_family) {
case AF_INET:
sa_in = (struct sockaddr_in *)sa;
if ((kr = kroute_find(psa_in->sin_addr.s_addr,
prefixlen, prio)) == NULL)
@@ -1178,10 +1370,52 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct
sockaddr *rti_info[RTAX_MAX])
}
if (sa == NULL && !(flags & F_CONNECTED))
return (0);
+ /* Add or update an ARP entry */
+ if ((rtm->rtm_flags & RTF_LLINFO) && (rtm->rtm_flags & RTF_HOST) &&
+ sa != NULL && sa->sa_family == AF_LINK &&
+ psa->sa_family == AF_INET) {
+ if (rtm->rtm_tableid != snmpd_rtableid)
+ return (0);
+ sa_dl = (struct sockaddr_dl *)sa;
+ /* ignore incomplete entries */
+ if (!sa_dl->sdl_alen)
+ return (0);
+ /* ignore entries that do not specify an interface */
+ if (ifindex == 0)
+ return (0);
+ if ((ka = karp_find(psa, ifindex)) != NULL) {
+ memcpy(&ka->target.sdl, sa_dl, sa_dl->sdl_len);
+ /* save static/permanent flags */
+ if (rtm->rtm_rmx.rmx_expire == 0 ||
+ rtm->rtm_flags & RTF_PERMANENT_ARP)
+ flags |= F_STATIC;
+ ka->flags = flags;
+ } else {
+ if ((ka = calloc(1, sizeof(struct kif_arp))) == NULL) {
+ log_warn("dispatch_rtmsg");
+ return (-1);
+ }
+ memcpy(&ka->addr.sa, psa, psa->sa_len);
+ memcpy(&ka->target.sdl, sa_dl, sa_dl->sdl_len);
+ /* save static/permanent flags */
+ if (rtm->rtm_rmx.rmx_expire == 0 ||
+ rtm->rtm_flags & RTF_PERMANENT_ARP)
+ flags |= F_STATIC;
+ ka->flags = flags;
+ ka->if_index = ifindex;
+ if (karp_insert(NULL, ka)) {
+ free(ka);
+ log_warnx("dispatch_rtmsg: failed to insert");
+ return (-1);
+ }
+ }
+ return (0);
+ }
+
switch (psa->sa_family) {
case AF_INET:
sa_in = (struct sockaddr_in *)sa;
if ((kr = kroute_find(psa_in->sin_addr.s_addr, prefixlen,
prio)) != NULL) {
diff --git usr.sbin/snmpd/mib.c usr.sbin/snmpd/mib.c
index e124a03..c284472 100644
--- usr.sbin/snmpd/mib.c
+++ usr.sbin/snmpd/mib.c
@@ -2928,10 +2928,13 @@ int mib_ipfragfails(struct oid *, struct ber_oid *,
struct ber_element **);
int mib_iproutingdiscards(struct oid *, struct ber_oid *,
struct ber_element **);
int mib_ipaddr(struct oid *, struct ber_oid *, struct ber_element **);
struct ber_oid *
mib_ipaddrtable(struct oid *, struct ber_oid *, struct ber_oid *);
+int mib_physaddr(struct oid *, struct ber_oid *, struct ber_element **);
+struct ber_oid *
+ mib_physaddrtable(struct oid *, struct ber_oid *, struct ber_oid *);
static struct oid ip_mib[] = {
{ MIB(ipMIB), OID_MIB },
{ MIB(ipForwarding), OID_RD, mib_ipforwarding },
{ MIB(ipDefaultTTL), OID_RD, mib_ipdefaultttl },
@@ -2963,15 +2966,19 @@ static struct oid ip_mib[] = {
mib_ipaddrtable },
{ MIB(ipAdEntBcastAddr), OID_TRD, mib_ipaddr, NULL,
mib_ipaddrtable },
{ MIB(ipAdEntReasmMaxSize), OID_TRD, mib_ipaddr, NULL,
mib_ipaddrtable },
+ { MIB(ipNetToMediaIfIndex), OID_TRD, mib_physaddr, NULL,
+ mib_physaddrtable },
+ { MIB(ipNetToMediaPhysAddress), OID_TRD, mib_physaddr, NULL,
+ mib_physaddrtable },
+ { MIB(ipNetToMediaNetAddress), OID_TRD, mib_physaddr, NULL,
+ mib_physaddrtable },
+ { MIB(ipNetToMediaType), OID_TRD, mib_physaddr, NULL,
+ mib_physaddrtable },
#ifdef notyet
- { MIB(ipNetToMediaIfIndex) },
- { MIB(ipNetToMediaPhysAddress) },
- { MIB(ipNetToMediaNetAddress) },
- { MIB(ipNetToMediaType) },
{ MIB(ipRoutingDiscards) },
#endif
{ MIBEND }
};
@@ -3256,10 +3263,153 @@ mib_ipaddr(struct oid *oid, struct ber_oid *o, struct
ber_element **elm)
}
return (0);
}
+struct ber_oid *
+mib_physaddrtable(struct oid *oid, struct ber_oid *o, struct ber_oid *no)
+{
+ struct sockaddr_in addr;
+ struct oid a, b;
+ struct kif *kif;
+ struct kif_arp *ka;
+ u_int32_t id, idx = 0;
+
+ bcopy(&oid->o_id, no, sizeof(*no));
+ id = oid->o_oidlen - 1;
+
+ if (o->bo_n >= oid->o_oidlen) {
+ /*
+ * Compare the requested and the matched OID to see
+ * if we have to iterate to the next element.
+ */
+ bzero(&a, sizeof(a));
+ bcopy(o, &a.o_id, sizeof(struct ber_oid));
+ bzero(&b, sizeof(b));
+ bcopy(&oid->o_id, &b.o_id, sizeof(struct ber_oid));
+ b.o_oidlen--;
+ b.o_flags |= OID_TABLE;
+ if (smi_oid_cmp(&a, &b) == 0) {
+ o->bo_id[id] = oid->o_oid[id];
+ bcopy(o, no, sizeof(*no));
+ }
+ }
+
+ if (o->bo_n > OIDIDX_ipNetToMedia + 1)
+ idx = o->bo_id[OIDIDX_ipNetToMedia + 1];
+
+ bzero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_len = sizeof(addr);
+ if (o->bo_n > OIDIDX_ipNetToMedia + 2)
+ mps_decodeinaddr(no, &addr.sin_addr, OIDIDX_ipNetToMedia + 2);
+
+ if ((kif = kr_getif(idx)) == NULL) {
+ /* No configured interfaces */
+ if (idx == 0)
+ return (NULL);
+ /*
+ * It may happen that an interface with a specific index
+ * does not exist or has been removed. Jump to the next
+ * available interface.
+ */
+ kif = kr_getif(0);
+ nextif:
+ for (; kif != NULL; kif = kr_getnextif(kif->if_index))
+ if (kif->if_index > idx &&
+ (ka = karp_first(kif->if_index)) != NULL)
+ break;
+ if (kif == NULL) {
+ /* No more interfaces with addresses on them */
+ o->bo_id[OIDIDX_ipNetToMedia + 1] = 0;
+ mps_encodeinaddr(no, NULL, OIDIDX_ipNetToMedia + 2);
+ smi_oidlen(o);
+ return (NULL);
+ }
+ } else {
+ if (idx == 0 || addr.sin_addr.s_addr == 0)
+ ka = karp_first(kif->if_index);
+ else
+ ka = karp_getaddr((struct sockaddr *)&addr, idx, 1);
+ if (ka == NULL) {
+ /* Try next interface */
+ goto nextif;
+ }
+ }
+ idx = kif->if_index;
+
+ no->bo_id[OIDIDX_ipNetToMedia + 1] = idx;
+ /* Encode real IPv4 address */
+ memcpy(&addr, &ka->addr.sin, ka->addr.sin.sin_len);
+ mps_encodeinaddr(no, &addr.sin_addr, OIDIDX_ipNetToMedia + 2);
+
+ smi_oidlen(o);
+ return (no);
+}
+
+int
+mib_physaddr(struct oid *oid, struct ber_oid *o, struct ber_element **elm)
+{
+ struct ber_element *ber = *elm;
+ struct sockaddr_in addr;
+ struct kif_arp *ka;
+ u_int32_t val, idx = 0;
+
+ idx = o->bo_id[OIDIDX_ipNetToMedia + 1];
+ if (idx == 0) {
+ /* Strip invalid interface index and fail */
+ o->bo_n = OIDIDX_ipNetToMedia + 1;
+ return (1);
+ }
+
+ /* Get the IP address */
+ bzero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_len = sizeof(addr);
+
+ if (mps_decodeinaddr(o, &addr.sin_addr,
+ OIDIDX_ipNetToMedia + 2) == -1) {
+ /* Strip invalid address and fail */
+ o->bo_n = OIDIDX_ipNetToMedia + 2;
+ return (1);
+ }
+ if ((ka = karp_getaddr((struct sockaddr *)&addr, idx, 0)) == NULL)
+ return (1);
+
+ /* write OID */
+ ber = ber_add_oid(ber, o);
+
+ switch (o->bo_id[OIDIDX_ipNetToMedia]) {
+ case 1: /* ipNetToMediaIfIndex */
+ ber = ber_add_integer(ber, ka->if_index);
+ break;
+ case 2: /* ipNetToMediaPhysAddress */
+ if (bcmp(LLADDR(&ka->target.sdl), ether_zeroaddr,
+ sizeof(ether_zeroaddr)) == 0)
+ ber = ber_add_nstring(ber, ether_zeroaddr,
+ sizeof(ether_zeroaddr));
+ else
+ ber = ber_add_nstring(ber, LLADDR(&ka->target.sdl),
+ ka->target.sdl.sdl_alen);
+ break;
+ case 3: /* ipNetToMediaNetAddress */
+ val = addr.sin_addr.s_addr;
+ ber = ber_add_nstring(ber, (char *)&val, sizeof(u_int32_t));
+ ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_IPADDR);
+ break;
+ case 4: /* ipNetToMediaType */
+ if (ka->flags & F_STATIC)
+ ber = ber_add_integer(ber, 4); /* static */
+ else
+ ber = ber_add_integer(ber, 3); /* dynamic */
+ break;
+ default:
+ return (-1);
+ }
+ return (0);
+}
+
/*
* Defined in IP-FORWARD-MIB.txt (rfc4292)
*/
int mib_ipfnroutes(struct oid *, struct ber_oid *, struct ber_element **);
diff --git usr.sbin/snmpd/mib.h usr.sbin/snmpd/mib.h
index 2551adb..4017508 100644
--- usr.sbin/snmpd/mib.h
+++ usr.sbin/snmpd/mib.h
@@ -324,10 +324,11 @@
#define MIB_ipAdEntNetMask MIB_ipAddrEntry, 3
#define MIB_ipAdEntBcastAddr MIB_ipAddrEntry, 4
#define MIB_ipAdEntReasmMaxSize MIB_ipAddrEntry, 5
#define MIB_ipNetToMediaTable MIB_ipMIB, 22
#define MIB_ipNetToMediaEntry MIB_ipNetToMediaTable, 1
+#define OIDIDX_ipNetToMedia 9
#define MIB_ipNetToMediaIfIndex MIB_ipNetToMediaEntry, 1
#define MIB_ipNetToMediaPhysAddress MIB_ipNetToMediaEntry, 2
#define MIB_ipNetToMediaNetAddress MIB_ipNetToMediaEntry, 3
#define MIB_ipNetToMediaType MIB_ipNetToMediaEntry, 4
#define MIB_ipRoutingDiscards MIB_ipMIB, 23
@@ -1283,11 +1284,10 @@
{ MIBDECL(ipNetToMediaEntry) }, \
{ MIBDECL(ipNetToMediaIfIndex) }, \
{ MIBDECL(ipNetToMediaPhysAddress) }, \
{ MIBDECL(ipNetToMediaNetAddress) }, \
{ MIBDECL(ipNetToMediaType) }, \
- { MIBDECL(ipNetToMediaType) }, \
\
{ MIBDECL(ipfMIB) }, \
{ MIBDECL(ipfInetCidrRouteNumber) }, \
{ MIBDECL(ipfInetCidrRouteTable) }, \
{ MIBDECL(ipfInetCidrRouteEntry) }, \
diff --git usr.sbin/snmpd/snmpd.h usr.sbin/snmpd/snmpd.h
index 95244c4..bd5eae9 100644
--- usr.sbin/snmpd/snmpd.h
+++ usr.sbin/snmpd/snmpd.h
@@ -20,10 +20,11 @@
#ifndef _SNMPD_H
#define _SNMPD_H
#include <netinet/in.h>
#include <netinet/if_ether.h>
+#include <net/if_dl.h>
#include <net/pfvar.h>
#include <net/route.h>
#include "ber.h"
#include <snmp.h>
@@ -173,10 +174,11 @@ extern struct ctl_connlist ctl_conns;
union kaddr {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
+ struct sockaddr_dl sdl;
char pad[32];
};
struct kroute {
struct in_addr prefix;
@@ -206,10 +208,19 @@ struct kif_addr {
TAILQ_ENTRY(kif_addr) entry;
RB_ENTRY(kif_addr) node;
};
+struct kif_arp {
+ u_short flags;
+ u_short if_index;
+ union kaddr addr;
+ union kaddr target;
+
+ TAILQ_ENTRY(kif_arp) entry;
+};
+
struct kif {
char if_name[IF_NAMESIZE];
char if_descr[IFDESCRSIZE];
u_int8_t if_lladdr[ETHER_ADDR_LEN];
struct if_data if_data;
@@ -538,10 +549,13 @@ struct kif_addr *kr_getaddr(struct sockaddr *);
struct kif_addr *kr_getnextaddr(struct sockaddr *);
struct kroute *kroute_first(void);
struct kroute *kroute_getaddr(in_addr_t, u_int8_t, u_int8_t, int);
+struct kif_arp *karp_first(u_short);
+struct kif_arp *karp_getaddr(struct sockaddr *, u_short, int);
+
/* snmpe.c */
pid_t snmpe(struct privsep *, struct privsep_proc *);
void snmpe_shutdown(struct privsep *, struct privsep_proc *);
/* trap.c */