On Mon, Apr 28, 2014 at 14:20 +0200, Mike Belopuhov wrote: > This adds ktable code from bgpd to fetch, store and perform lookups > in multiple routing tables. Currently it doesn't do anything useful > but it's a prerequisite for any future work in this direction. > > OK to get this in? >
Any objections? > diff --git usr.sbin/snmpd/kroute.c usr.sbin/snmpd/kroute.c > index e157b25..e19f924 100644 > --- usr.sbin/snmpd/kroute.c > +++ usr.sbin/snmpd/kroute.c > @@ -45,10 +45,13 @@ > > #include "snmpd.h" > > extern struct snmpd *env; > > +struct ktable **krt; > +u_int krt_size; > + > struct { > struct event ks_ev; > u_long ks_iflastchange; > u_long ks_nroutes; /* 4 billions enough? */ > int ks_fd; > @@ -77,24 +80,32 @@ struct kif_node { > > int kroute_compare(struct kroute_node *, struct kroute_node *); > int kroute6_compare(struct kroute6_node *, struct kroute6_node *); > int kif_compare(struct kif_node *, struct kif_node *); > > -struct kroute_node *kroute_find(in_addr_t, u_int8_t, u_int8_t); > +void ktable_init(void); > +int ktable_new(u_int, u_int); > +void ktable_free(u_int); > +int ktable_exists(u_int, u_int *); > +struct ktable *ktable_get(u_int); > +int ktable_update(u_int); > + > +struct kroute_node *kroute_find(struct ktable *, in_addr_t, u_int8_t, > + u_int8_t); > struct kroute_node *kroute_matchgw(struct kroute_node *, > struct sockaddr_in *); > -int kroute_insert(struct kroute_node *); > -int kroute_remove(struct kroute_node *); > -void kroute_clear(void); > +int kroute_insert(struct ktable *, struct kroute_node *); > +int kroute_remove(struct ktable *, struct kroute_node *); > +void kroute_clear(struct ktable *); > > -struct kroute6_node *kroute6_find(const struct in6_addr *, u_int8_t, > - u_int8_t); > +struct kroute6_node *kroute6_find(struct ktable *, const struct in6_addr *, > + u_int8_t, u_int8_t); > 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); > +int kroute6_insert(struct ktable *, struct kroute6_node *); > +int kroute6_remove(struct ktable *, struct kroute6_node *); > +void kroute6_clear(struct ktable *); > > 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 *); > > @@ -121,23 +132,21 @@ void if_newaddr(u_short, struct sockaddr *, > struct sockaddr *, > struct sockaddr *); > void if_deladdr(u_short, struct sockaddr *, struct sockaddr *, > struct sockaddr *); > void if_announce(void *); > > -int fetchtable(void); > +int fetchtable(struct ktable *); > int fetchifs(u_short); > -int fetcharp(void); > +int fetcharp(struct ktable *); > void dispatch_rtmsg(int, short, void *); > int rtmsg_process(char *, int); > -int dispatch_rtmsg_addr(struct rt_msghdr *, > +int dispatch_rtmsg_addr(struct ktable *, struct rt_msghdr *, > struct sockaddr *[RTAX_MAX]); > > -RB_HEAD(kroute_tree, kroute_node) krt; > RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare) > RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare) > > -RB_HEAD(kroute6_tree, kroute6_node) krt6; > RB_PROTOTYPE(kroute6_tree, kroute6_node, entry, kroute6_compare) > RB_GENERATE(kroute6_tree, kroute6_node, entry, kroute6_compare) > > RB_HEAD(kif_tree, kif_node) kit; > RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare) > @@ -149,10 +158,11 @@ RB_GENERATE(ka_tree, kif_addr, node, ka_compare) > > void > kr_init(void) > { > int opt = 0, rcvbuf, default_rcvbuf; > + unsigned int tid = RTABLE_ANY; > socklen_t optlen; > > if ((kr_state.ks_ifd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) > fatal("kr_init: ioctl socket"); > > @@ -179,31 +189,166 @@ kr_init(void) > setsockopt(kr_state.ks_fd, SOL_SOCKET, SO_RCVBUF, > &rcvbuf, sizeof(rcvbuf)) == -1 && errno == ENOBUFS; > rcvbuf /= 2) > ; /* nothing */ > > - RB_INIT(&krt); > - RB_INIT(&krt6); > + if (setsockopt(kr_state.ks_fd, AF_ROUTE, ROUTE_TABLEFILTER, &tid, > + sizeof(tid)) == -1) > + log_warn("kr_init: setsockopt AF_ROUTE ROUTE_TABLEFILTER"); > + > RB_INIT(&kit); > RB_INIT(&kat); > > if (fetchifs(0) == -1) > fatalx("kr_init fetchifs"); > - if (fetchtable() == -1) > - fatalx("kr_init fetchtable"); > - if (fetcharp() == -1) > - fatalx("kr_init fetcharp"); > + > + ktable_init(); > > event_set(&kr_state.ks_ev, kr_state.ks_fd, EV_READ | EV_PERSIST, > dispatch_rtmsg, NULL); > event_add(&kr_state.ks_ev, NULL); > } > > void > +ktable_init(void) > +{ > + u_int i; > + > + for (i = 0; i < RT_TABLEID_MAX; i++) > + if (ktable_exists(i, NULL)) > + ktable_update(i); > +} > + > +int > +ktable_new(u_int rtableid, u_int rdomid) > +{ > + struct ktable **xkrt; > + struct ktable *kt; > + size_t newsize, oldsize; > + > + /* resize index table if needed */ > + if (rtableid >= krt_size) { > + oldsize = sizeof(struct ktable *) * krt_size; > + newsize = sizeof(struct ktable *) * (rtableid + 1); > + if ((xkrt = realloc(krt, newsize)) == NULL) { > + log_warn("ktable_new"); > + return (-1); > + } > + krt = xkrt; > + krt_size = rtableid + 1; > + bzero((char *)krt + oldsize, newsize - oldsize); > + } > + > + if (krt[rtableid]) > + fatalx("ktable_new: table already exists."); > + > + /* allocate new element */ > + kt = krt[rtableid] = calloc(1, sizeof(struct ktable)); > + if (kt == NULL) { > + log_warn("ktable_new"); > + return (-1); > + } > + > + /* initialize structure ... */ > + RB_INIT(&kt->krt); > + RB_INIT(&kt->krt6); > + kt->rtableid = rtableid; > + kt->rdomain = rdomid; > + > + /* ... and load it */ > + if (fetchtable(kt) == -1) > + return (-1); > + /* load arp information */ > + if (fetcharp(kt) == -1) > + return (-1); > + > + log_debug("new ktable for rtableid %d", rtableid); > + return (0); > +} > + > +void > +ktable_free(u_int rtableid) > +{ > + struct ktable *kt; > + > + if ((kt = ktable_get(rtableid)) == NULL) > + return; > + > + log_debug("freeing ktable rtableid %u", kt->rtableid); > + kroute_clear(kt); > + kroute6_clear(kt); > + > + krt[kt->rtableid] = NULL; > + free(kt); > +} > + > +struct ktable * > +ktable_get(u_int rtableid) > +{ > + if (rtableid >= krt_size) > + return (NULL); > + return (krt[rtableid]); > +} > + > +int > +ktable_update(u_int rtableid) > +{ > + struct ktable *kt; > + u_int rdomid; > + > + if (!ktable_exists(rtableid, &rdomid)) > + fatalx("King Bula lost a table"); /* may not happen */ > + > + if (rdomid != rtableid) { > + if (ktable_get(rdomid) == NULL && > + ktable_new(rdomid, rdomid) != 0) > + return (-1); > + } > + > + kt = ktable_get(rtableid); > + if (kt == NULL) { > + if (ktable_new(rtableid, rdomid)) > + return (-1); > + } > + return (0); > +} > + > +int > +ktable_exists(u_int rtableid, u_int *rdomid) > +{ > + size_t len; > + struct rt_tableinfo info; > + int mib[6]; > + > + mib[0] = CTL_NET; > + mib[1] = AF_ROUTE; > + mib[2] = 0; > + mib[3] = 0; > + mib[4] = NET_RT_TABLE; > + mib[5] = rtableid; > + > + len = sizeof(info); > + if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) { > + if (errno == ENOENT) > + /* table nonexistent */ > + return (0); > + log_warn("sysctl"); > + /* must return 0 so that the table is considered non-existent */ > + return (0); > + } > + if (rdomid) > + *rdomid = info.rti_domainid; > + return (1); > +} > + > +void > kr_shutdown(void) > { > - kroute_clear(); > + u_int i; > + > + for (i = krt_size; i > 0; i--) > + ktable_free(i - 1); > kif_clear(); > } > > u_int > kr_ifnumber(void) > @@ -301,28 +446,29 @@ ka_compare(struct kif_addr *a, struct kif_addr *b) > return (memcmp(&a->addr.sa, &b->addr.sa, a->addr.sa.sa_len)); > } > > /* tree management */ > struct kroute_node * > -kroute_find(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio) > +kroute_find(struct ktable *kt, in_addr_t prefix, u_int8_t prefixlen, > + u_int8_t prio) > { > struct kroute_node s; > struct kroute_node *kn, *tmp; > > s.r.prefix.s_addr = prefix; > s.r.prefixlen = prefixlen; > s.r.priority = prio; > > - kn = RB_FIND(kroute_tree, &krt, &s); > + kn = RB_FIND(kroute_tree, &kt->krt, &s); > if (kn && prio == RTP_ANY) { > - tmp = RB_PREV(kroute_tree, &krt, kn); > + tmp = RB_PREV(kroute_tree, &kt->krt, kn); > while (tmp) { > if (kroute_compare(&s, tmp) == 0) > kn = tmp; > else > break; > - tmp = RB_PREV(kroute_tree, &krt, kn); > + tmp = RB_PREV(kroute_tree, &kt->krt, kn); > } > } > return (kn); > } > > @@ -345,15 +491,15 @@ kroute_matchgw(struct kroute_node *kr, struct > sockaddr_in *sa_in) > > return (NULL); > } > > int > -kroute_insert(struct kroute_node *kr) > +kroute_insert(struct ktable *kt, struct kroute_node *kr) > { > struct kroute_node *krm; > > - if ((krm = RB_INSERT(kroute_tree, &krt, kr)) != NULL) { > + if ((krm = RB_INSERT(kroute_tree, &kt->krt, kr)) != NULL) { > /* multipath route, add at end of list */ > while (krm->next != NULL) > krm = krm->next; > krm->next = kr; > kr->next = NULL; /* to be sure */ > @@ -362,29 +508,30 @@ kroute_insert(struct kroute_node *kr) > kr_state.ks_nroutes++; > return (0); > } > > int > -kroute_remove(struct kroute_node *kr) > +kroute_remove(struct ktable *kt, struct kroute_node *kr) > { > struct kroute_node *krm; > > - if ((krm = RB_FIND(kroute_tree, &krt, kr)) == NULL) { > + if ((krm = RB_FIND(kroute_tree, &kt->krt, kr)) == NULL) { > log_warnx("kroute_remove failed to find %s/%u", > inet_ntoa(kr->r.prefix), kr->r.prefixlen); > return (-1); > } > > if (krm == kr) { > /* head element */ > - if (RB_REMOVE(kroute_tree, &krt, kr) == NULL) { > + if (RB_REMOVE(kroute_tree, &kt->krt, kr) == NULL) { > log_warnx("kroute_remove failed for %s/%u", > inet_ntoa(kr->r.prefix), kr->r.prefixlen); > return (-1); > } > if (kr->next != NULL) { > - if (RB_INSERT(kroute_tree, &krt, kr->next) != NULL) { > + if (RB_INSERT(kroute_tree, &kt->krt, kr->next) > + != NULL) { > log_warnx("kroute_remove failed to add %s/%u", > inet_ntoa(kr->r.prefix), kr->r.prefixlen); > return (-1); > } > } > @@ -405,37 +552,38 @@ kroute_remove(struct kroute_node *kr) > free(kr); > return (0); > } > > void > -kroute_clear(void) > +kroute_clear(struct ktable *kt) > { > struct kroute_node *kr; > > - while ((kr = RB_MIN(kroute_tree, &krt)) != NULL) > - kroute_remove(kr); > + while ((kr = RB_MIN(kroute_tree, &kt->krt)) != NULL) > + kroute_remove(kt, kr); > } > > struct kroute6_node * > -kroute6_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t > prio) > +kroute6_find(struct ktable *kt, const struct in6_addr *prefix, > + u_int8_t prefixlen, u_int8_t prio) > { > struct kroute6_node s; > struct kroute6_node *kn6, *tmp; > > memcpy(&s.r.prefix, prefix, sizeof(struct in6_addr)); > s.r.prefixlen = prefixlen; > s.r.priority = prio; > > - kn6 = RB_FIND(kroute6_tree, &krt6, &s); > + kn6 = RB_FIND(kroute6_tree, &kt->krt6, &s); > if (kn6 && prio == RTP_ANY) { > - tmp = RB_PREV(kroute6_tree, &krt6, kn6); > + tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); > while (tmp) { > if (kroute6_compare(&s, tmp) == 0) > kn6 = tmp; > else > break; > - tmp = RB_PREV(kroute6_tree, &krt6, kn6); > + tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); > } > } > return (kn6); > } > > @@ -458,15 +606,15 @@ kroute6_matchgw(struct kroute6_node *kr, struct > sockaddr_in6 *sa_in6) > > return (NULL); > } > > int > -kroute6_insert(struct kroute6_node *kr) > +kroute6_insert(struct ktable *kt, struct kroute6_node *kr) > { > struct kroute6_node *krm; > > - if ((krm = RB_INSERT(kroute6_tree, &krt6, kr)) != NULL) { > + if ((krm = RB_INSERT(kroute6_tree, &kt->krt6, kr)) != NULL) { > /* multipath route, add at end of list */ > while (krm->next != NULL) > krm = krm->next; > krm->next = kr; > kr->next = NULL; /* to be sure */ > @@ -475,29 +623,30 @@ kroute6_insert(struct kroute6_node *kr) > kr_state.ks_nroutes++; > return (0); > } > > int > -kroute6_remove(struct kroute6_node *kr) > +kroute6_remove(struct ktable *kt, struct kroute6_node *kr) > { > struct kroute6_node *krm; > > - if ((krm = RB_FIND(kroute6_tree, &krt6, kr)) == NULL) { > + if ((krm = RB_FIND(kroute6_tree, &kt->krt6, kr)) == NULL) { > log_warnx("kroute6_remove failed for %s/%u", > log_in6addr(&kr->r.prefix), kr->r.prefixlen); > return (-1); > } > > if (krm == kr) { > /* head element */ > - if (RB_REMOVE(kroute6_tree, &krt6, kr) == NULL) { > + if (RB_REMOVE(kroute6_tree, &kt->krt6, kr) == NULL) { > log_warnx("kroute6_remove failed for %s/%u", > log_in6addr(&kr->r.prefix), kr->r.prefixlen); > return (-1); > } > if (kr->next != NULL) { > - if (RB_INSERT(kroute6_tree, &krt6, kr->next) != NULL) { > + if (RB_INSERT(kroute6_tree, &kt->krt6, kr->next) != > + NULL) { > log_warnx("kroute6_remove failed to add %s/%u", > log_in6addr(&kr->r.prefix), > kr->r.prefixlen); > return (-1); > } > @@ -519,16 +668,16 @@ kroute6_remove(struct kroute6_node *kr) > free(kr); > return (0); > } > > void > -kroute6_clear(void) > +kroute6_clear(struct ktable *kt) > { > struct kroute6_node *kr; > > - while ((kr = RB_MIN(kroute6_tree, &krt6)) != NULL) > - kroute6_remove(kr); > + while ((kr = RB_MIN(kroute6_tree, &kt->krt6)) != NULL) > + kroute6_remove(kt, kr); > } > > static inline int > karp_compare(struct kif_arp *a, struct kif_arp *b) > { > @@ -1021,22 +1170,20 @@ 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; > } > } > > int > -fetchtable(void) > +fetchtable(struct ktable *kt) > { > int mib[7]; > size_t len; > char *buf; > int rv; > @@ -1045,22 +1192,27 @@ fetchtable(void) > mib[1] = AF_ROUTE; > mib[2] = 0; > mib[3] = AF_INET; > mib[4] = NET_RT_DUMP; > mib[5] = 0; > - mib[6] = 0; /* rtableid */ > + mib[6] = kt->rtableid; > > if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { > + if (kt->rtableid != 0 && errno == EINVAL) > + /* table nonexistent */ > + return (0); > log_warn("sysctl"); > return (-1); > } > + if (len == 0) > + return (0); > if ((buf = malloc(len)) == NULL) { > log_warn("fetchtable"); > return (-1); > } > if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { > - log_warn("sysctl"); > + log_warn("sysctl2"); > free(buf); > return (-1); > } > > rv = rtmsg_process(buf, len); > @@ -1103,11 +1255,11 @@ fetchifs(u_short if_index) > > return (rv); > } > > int > -fetcharp(void) > +fetcharp(struct ktable *kt) > { > size_t len; > int mib[7]; > char *buf; > int rv; > @@ -1116,11 +1268,11 @@ fetcharp(void) > mib[1] = AF_ROUTE; > mib[2] = 0; > mib[3] = AF_INET; > mib[4] = NET_RT_FLAGS; > mib[5] = RTF_LLINFO; > - mib[6] = 0; > + mib[6] = kt->rtableid; > > if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { > log_warn("sysctl"); > return (-1); > } > @@ -1164,10 +1316,11 @@ dispatch_rtmsg(int fd, short event, void *arg) > } > > int > rtmsg_process(char *buf, int len) > { > + struct ktable *kt; > struct rt_msghdr *rtm; > struct if_msghdr ifm; > struct ifa_msghdr *ifam; > struct sockaddr *sa, *rti_info[RTAX_MAX]; > int offset; > @@ -1189,11 +1342,14 @@ rtmsg_process(char *buf, int len) > case RTM_DELETE: > case RTM_RESOLVE: > if (rtm->rtm_errno) /* failed attempts */ > continue; > > - if (dispatch_rtmsg_addr(rtm, rti_info) == -1) > + if ((kt = ktable_get(rtm->rtm_tableid)) == NULL) > + continue; > + > + if (dispatch_rtmsg_addr(kt, rtm, rti_info) == -1) > return (-1); > break; > case RTM_IFINFO: > memcpy(&ifm, next, sizeof(ifm)); > if_change(ifm.ifm_index, ifm.ifm_flags, &ifm.ifm_data, > @@ -1228,11 +1384,12 @@ rtmsg_process(char *buf, int len) > > return (offset); > } > > int > -dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr > *rti_info[RTAX_MAX]) > +dispatch_rtmsg_addr(struct ktable *kt, 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; > @@ -1319,11 +1476,11 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct > sockaddr *rti_info[RTAX_MAX]) > /* 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, > + if ((kr = kroute_find(kt, psa_in->sin_addr.s_addr, > prefixlen, prio)) == NULL) > return (0); > > if (mpath) > /* get the correct route */ > @@ -1331,17 +1488,17 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct > sockaddr *rti_info[RTAX_MAX]) > log_warnx("dispatch_rtmsg[delete] " > "mpath route not found"); > return (0); > } > > - if (kroute_remove(kr) == -1) > + if (kroute_remove(kt, kr) == -1) > return (-1); > break; > case AF_INET6: > sa_in6 = (struct sockaddr_in6 *)sa; > - if ((kr6 = kroute6_find(&psa_in6->sin6_addr, prefixlen, > - prio)) == NULL) > + if ((kr6 = kroute6_find(kt, &psa_in6->sin6_addr, > + prefixlen, prio)) == NULL) > return (0); > > if (mpath) > /* get the correct route */ > if ((kr6 = kroute6_matchgw(kr6, sa_in6)) == > @@ -1349,11 +1506,11 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct > sockaddr *rti_info[RTAX_MAX]) > log_warnx("dispatch_rtmsg[delete] " > "IPv6 mpath route not found"); > return (0); > } > > - if (kroute6_remove(kr6) == -1) > + if (kroute6_remove(kt, kr6) == -1) > return (-1); > break; > } > return (0); > } > @@ -1398,11 +1555,11 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct > sockaddr *rti_info[RTAX_MAX]) > } > > switch (psa->sa_family) { > case AF_INET: > sa_in = (struct sockaddr_in *)sa; > - if ((kr = kroute_find(psa_in->sin_addr.s_addr, prefixlen, > + if ((kr = kroute_find(kt, psa_in->sin_addr.s_addr, prefixlen, > prio)) != NULL) { > /* get the correct route */ > if (mpath && rtm->rtm_type == RTM_CHANGE && > (kr = kroute_matchgw(kr, sa_in)) == NULL) { > log_warnx("dispatch_rtmsg[change] " > @@ -1435,16 +1592,16 @@ add4: > kr->r.flags = flags; > kr->r.if_index = ifindex; > kr->r.ticks = smi_getticks(); > kr->r.priority = prio; > > - kroute_insert(kr); > + kroute_insert(kt, kr); > } > break; > case AF_INET6: > sa_in6 = (struct sockaddr_in6 *)sa; > - if ((kr6 = kroute6_find(&psa_in6->sin6_addr, prefixlen, > + if ((kr6 = kroute6_find(kt, &psa_in6->sin6_addr, prefixlen, > prio)) != NULL) { > /* get the correct route */ > if (mpath && rtm->rtm_type == RTM_CHANGE && > (kr6 = kroute6_matchgw(kr6, sa_in6)) == > NULL) { > @@ -1485,11 +1642,11 @@ add6: > kr6->r.flags = flags; > kr6->r.if_index = ifindex; > kr6->r.ticks = smi_getticks(); > kr6->r.priority = prio; > > - kroute6_insert(kr6); > + kroute6_insert(kt, kr6); > } > break; > } > > return (0); > @@ -1497,23 +1654,29 @@ add6: > > struct kroute * > kroute_first(void) > { > struct kroute_node *kn; > + struct ktable *kt; > > - kn = RB_MIN(kroute_tree, &krt); > + if ((kt = ktable_get(0)) == NULL) > + return (NULL); > + kn = RB_MIN(kroute_tree, &kt->krt); > return (&kn->r); > } > > struct kroute * > kroute_getaddr(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio, int next) > { > struct kroute_node *kn; > + struct ktable *kt; > > - kn = kroute_find(prefix, prefixlen, prio); > + if ((kt = ktable_get(0)) == NULL) > + return (NULL); > + kn = kroute_find(kt, prefix, prefixlen, prio); > if (kn != NULL && next) > - kn = RB_NEXT(kroute_tree, &krt, kn); > + kn = RB_NEXT(kroute_tree, &kt->krt, kn); > if (kn != NULL) > return (&kn->r); > else > return (NULL); > } > diff --git usr.sbin/snmpd/snmpd.h usr.sbin/snmpd/snmpd.h > index 048ef79..61bc749 100644 > --- usr.sbin/snmpd/snmpd.h > +++ usr.sbin/snmpd/snmpd.h > @@ -186,10 +186,22 @@ extern struct ctl_connlist ctl_conns; > > /* > * kroute > */ > > +struct kroute_node; > +struct kroute6_node; > +RB_HEAD(kroute_tree, kroute_node); > +RB_HEAD(kroute6_tree, kroute6_node); > + > +struct ktable { > + struct kroute_tree krt; > + struct kroute6_tree krt6; > + u_int rtableid; > + u_int rdomain; > +}; > + > union kaddr { > struct sockaddr sa; > struct sockaddr_in sin; > struct sockaddr_in6 sin6; > struct sockaddr_dl sdl;