Add an MIB2_IP6 in addition to the MIB2_IP loop.

This gets IPv6 routes.
This commit is contained in:
david 2011-09-29 22:23:16 +00:00
parent 293a073c92
commit 399942d759

View file

@ -326,13 +326,11 @@ int
route_loop(route_t *r, route_handler callback, void *arg)
{
struct route_entry entry;
struct sockaddr_in sin;
struct strbuf msg;
struct T_optmgmt_req *tor;
struct T_optmgmt_ack *toa;
struct T_error_ack *tea;
struct opthdr *opt;
mib2_ipRouteEntry_t *rt, *rtend;
u_char buf[8192];
int flags, rc, rtable, ret;
@ -360,6 +358,8 @@ route_loop(route_t *r, route_handler callback, void *arg)
msg.maxlen = sizeof(buf);
for (;;) {
mib2_ipRouteEntry_t *rt, *rtend;
flags = 0;
if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0)
return (-1);
@ -386,6 +386,8 @@ route_loop(route_t *r, route_handler callback, void *arg)
flags = 0;
do {
struct sockaddr_in sin;
rc = getmsg(r->ip_fd, NULL, &msg, &flags);
if (rc != 0 && rc != MOREDATA)
@ -423,6 +425,96 @@ route_loop(route_t *r, route_handler callback, void *arg)
}
} while (rc == MOREDATA);
}
tor = (struct T_optmgmt_req *)buf;
toa = (struct T_optmgmt_ack *)buf;
tea = (struct T_error_ack *)buf;
tor->PRIM_type = T_OPTMGMT_REQ;
tor->OPT_offset = sizeof(*tor);
tor->OPT_length = sizeof(*opt);
tor->MGMT_flags = T_CURRENT;
opt = (struct opthdr *)(tor + 1);
opt->level = MIB2_IP6;
opt->name = opt->len = 0;
msg.maxlen = sizeof(buf);
msg.len = sizeof(*tor) + sizeof(*opt);
msg.buf = buf;
if (putmsg(r->ip_fd, &msg, NULL, 0) < 0)
return (-1);
opt = (struct opthdr *)(toa + 1);
msg.maxlen = sizeof(buf);
for (;;) {
mib2_ipv6RouteEntry_t *rt, *rtend;
flags = 0;
if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0)
return (-1);
/* See if we're finished. */
if (rc == 0 &&
msg.len >= sizeof(*toa) &&
toa->PRIM_type == T_OPTMGMT_ACK &&
toa->MGMT_flags == T_SUCCESS && opt->len == 0)
break;
if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK)
return (-1);
if (rc != MOREDATA || msg.len < (int)sizeof(*toa) ||
toa->PRIM_type != T_OPTMGMT_ACK ||
toa->MGMT_flags != T_SUCCESS)
return (-1);
rtable = (opt->level == MIB2_IP6 && opt->name == MIB2_IP6_ROUTE);
msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*rt));
msg.len = 0;
flags = 0;
do {
struct sockaddr_in6 sin6;
rc = getmsg(r->ip_fd, NULL, &msg, &flags);
if (rc != 0 && rc != MOREDATA)
return (-1);
if (!rtable)
continue;
rt = (mib2_ipv6RouteEntry_t *)msg.buf;
rtend = (mib2_ipv6RouteEntry_t *)(msg.buf + msg.len);
sin6.sin6_family = AF_INET6;
for ( ; rt < rtend; rt++) {
if ((rt->ipv6RouteInfo.re_ire_type &
(IRE_BROADCAST|IRE_ROUTE_REDIRECT|
IRE_LOCAL|IRE_ROUTE)) != 0 ||
memcmp(&rt->ipv6RouteNextHop, IP6_ADDR_UNSPEC, IP6_ADDR_LEN) == 0)
continue;
sin6.sin6_addr = rt->ipv6RouteNextHop;
addr_ston((struct sockaddr *)&sin6,
&entry.route_gw);
sin6.sin6_addr = rt->ipv6RouteDest;
addr_ston((struct sockaddr *)&sin6,
&entry.route_dst);
entry.route_dst.addr_bits = rt->ipv6RoutePfxLength;
if ((ret = callback(&entry, arg)) != 0)
return (ret);
}
} while (rc == MOREDATA);
}
return (0);
}
#elif defined(HAVE_NET_RADIX_H)