From db5359d69a9ec06842730b8af2a30072a38b5aa1 Mon Sep 17 00:00:00 2001 From: hrs Date: Tue, 4 Dec 2012 17:12:23 +0000 Subject: - Fix LOR in sa6_recoverscope() in rt_msg2()[1]. - Check V_deembed_scopeid before checking if sa_family == AF_INET6. - Fix scope id handing in route(8)[2] and ifconfig(8). Reported by: rpaulo[1], Mateusz Guzik[1], peter[2] --- sbin/ifconfig/af_inet6.c | 5 ++-- sbin/route/route.c | 10 +++++++ sys/net/rtsock.c | 71 ++++++++++++++++++++++-------------------------- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c index a9ad867..5911a94 100644 --- a/sbin/ifconfig/af_inet6.c +++ b/sbin/ifconfig/af_inet6.c @@ -251,8 +251,9 @@ in6_status(int s __unused, const struct ifaddrs *ifa) if ((flags6 & IN6_IFF_TEMPORARY) != 0) printf("temporary "); - if (sin->sin6_scope_id) - printf("scopeid 0x%x ", sin->sin6_scope_id); + if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id) + printf("scopeid 0x%x ", + ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id); if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { printf("pltime "); diff --git a/sbin/route/route.c b/sbin/route/route.c index 107c66f..b63ce63 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -1208,6 +1208,16 @@ getaddr(int which, char *str, struct hostent **hpp) exit(1); } memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6)); +#ifdef __KAME__ + if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr) || + IN6_IS_ADDR_MC_NODELOCAL(&su->sin6.sin6_addr)) && + su->sin6.sin6_scope_id) { + *(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] = + htons(su->sin6.sin6_scope_id); + su->sin6.sin6_scope_id = 0; + } +#endif freeaddrinfo(res); if (q != NULL) *q++ = '/'; diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 1ff6bca..d1bf200 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -804,28 +804,31 @@ route_output(struct mbuf *m, struct socket *so) } info.rti_info[RTAX_DST] = rt_key(rt); #ifdef INET6 - switch (rt_key(rt)->sa_family) { - case AF_INET6: - if (V_deembed_scopeid == 0) + if (V_deembed_scopeid) { + switch (rt_key(rt)->sa_family) { + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&ss_dst; + bcopy(rt_key(rt), sin6, sizeof(*sin6)); + if (sa6_recoverscope(sin6) == 0) + info.rti_info[RTAX_DST] = + (struct sockaddr *)sin6; break; - sin6 = (struct sockaddr_in6 *)&ss_dst; - bcopy(rt_key(rt), sin6, sizeof(*sin6)); - if (sa6_recoverscope(sin6) == 0) - info.rti_info[RTAX_DST] = - (struct sockaddr *)sin6; - break; + } } #endif info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; #ifdef INET6 - switch (rt->rt_gateway->sa_family) { - case AF_INET6: - sin6 = (struct sockaddr_in6 *)&ss_gw; - bcopy(rt->rt_gateway, sin6, sizeof(*sin6)); - if (sa6_recoverscope(sin6) == 0) - info.rti_info[RTAX_GATEWAY] = - (struct sockaddr *)sin6; - break; + if (V_deembed_scopeid) { + switch (rt->rt_gateway->sa_family) { + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&ss_gw; + bcopy(rt->rt_gateway, sin6, + sizeof(*sin6)); + if (sa6_recoverscope(sin6) == 0) + info.rti_info[RTAX_GATEWAY] = + (struct sockaddr *)sin6; + break; + } } #endif info.rti_info[RTAX_NETMASK] = rt_mask(rt); @@ -1130,15 +1133,11 @@ rt_msg1(int type, struct rt_addrinfo *rtinfo) rtinfo->rti_addrs |= (1 << i); dlen = SA_SIZE(sa); #ifdef INET6 - switch (sa->sa_family) { - case AF_INET6: - if (V_deembed_scopeid == 0) - break; + if (V_deembed_scopeid && sa->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)&ss; bcopy(sa, sin6, sizeof(*sin6)); if (sa6_recoverscope(sin6) == 0) sa = (struct sockaddr *)sin6; - break; } #endif m_copyback(m, len, dlen, (caddr_t)sa); @@ -1219,15 +1218,11 @@ again: rtinfo->rti_addrs |= (1 << i); dlen = SA_SIZE(sa); #ifdef INET6 - switch (sa->sa_family) { - case AF_INET6: - if (V_deembed_scopeid == 0) - break; + if (V_deembed_scopeid && sa->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)&ss; bcopy(sa, sin6, sizeof(*sin6)); if (sa6_recoverscope(sin6) == 0) sa = (struct sockaddr *)sin6; - break; } #endif if (cp) { @@ -1594,18 +1589,16 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; } #ifdef INET6 - for (i = 0; i < RTAX_MAX; i++) { - if (info.rti_info[i] == NULL) - continue; - switch (info.rti_info[i]->sa_family) { - case AF_INET6: - if (V_deembed_scopeid == 0) - break; + if (V_deembed_scopeid) { + for (i = 0; i < RTAX_MAX; i++) { + if (info.rti_info[i] == NULL) + continue; + if (info.rti_info[i]->sa_family != AF_INET6) + continue; sin6 = (struct sockaddr_in6 *)&ss[i]; bcopy(info.rti_info[i], sin6, sizeof(*sin6)); if (sa6_recoverscope(sin6) == 0) info.rti_info[i] = (struct sockaddr *)sin6; - break; } } #endif @@ -1811,7 +1804,7 @@ sysctl_iflist(int af, struct walkarg *w) int len, error = 0; bzero((caddr_t)&info, sizeof(info)); - IFNET_RLOCK(); + IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; @@ -1856,7 +1849,7 @@ sysctl_iflist(int af, struct walkarg *w) done: if (ifp != NULL) IF_ADDR_RUNLOCK(ifp); - IFNET_RUNLOCK(); + IFNET_RUNLOCK_NOSLEEP(); return (error); } @@ -1870,7 +1863,7 @@ sysctl_ifmalist(int af, struct walkarg *w) struct ifaddr *ifa; bzero((caddr_t)&info, sizeof(info)); - IFNET_RLOCK(); + IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; @@ -1905,7 +1898,7 @@ sysctl_ifmalist(int af, struct walkarg *w) IF_ADDR_RUNLOCK(ifp); } done: - IFNET_RUNLOCK(); + IFNET_RUNLOCK_NOSLEEP(); return (error); } -- cgit v1.1