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;

Reply via email to