On Mon, Apr 07, 2014 at 04:04:24PM +0200, Mike Belopuhov wrote: > 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?
One nit, one possible improvement inline below. > > 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 */ ^ a random typo appears! > + 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); > +} If I'm following the logic correctly here (ifindex, being unsigned, is either 0 or >0), you check for a non-zero ifindex, perform a lookup via kif_find, and then immediately check for a non-zero ifindex and perform a lookup via kif_find again. If I'm missing something here, please point it out. Other than these, looks good to me. > + > +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 */ >