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 */

Reply via email to