From owner-svn-src-all@FreeBSD.ORG Thu May 8 11:56:07 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 27BC7592; Thu, 8 May 2014 11:56:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 13AE439D; Thu, 8 May 2014 11:56:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s48Bu6KL076442; Thu, 8 May 2014 11:56:06 GMT (envelope-from melifaro@svn.freebsd.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s48Bu6fo076440; Thu, 8 May 2014 11:56:06 GMT (envelope-from melifaro@svn.freebsd.org) Message-Id: <201405081156.s48Bu6fo076440@svn.freebsd.org> From: "Alexander V. Chernikov" Date: Thu, 8 May 2014 11:56:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r265666 - in head: sbin/route sys/net X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 May 2014 11:56:07 -0000 Author: melifaro Date: Thu May 8 11:56:06 2014 New Revision: 265666 URL: http://svnweb.freebsd.org/changeset/base/265666 Log: Fix incorrect netmasks being passed via rtsock. Since radix has been ignoring sa_family in passed sockaddrs, no one ever has bothered filling valid sa_family in netmasks. Additionally, radix adjusts sa_len field in every netmask not to compare zero bytes at all. This leads us to rt_mask with sa_family of AF_UNSPEC (-1) and arbitrary sa_len field (0 for default route, for example). However, rtsock have been passing that rt_mask intact for ages, requiring all rtsock consumers to make ther own local hacks. We even have unfixed on in base: do `route -n monitor` in one window and issue `route -n get addr` for some directly-connected address. You will probably see the following: got message of size 304 on Thu May 8 15:06:06 2014 RTM_GET: Report Metrics: len 304, pid: 30493, seq 1, errno 0, flags: locks: inits: sockaddrs: 10.0.0.0 link#1 (255) ffff ffff ff em0:8.0.27.c5.29.d4 10.0.0.92 _________________^^^^^^^^^^^^^^^^^^ after the change: got message of size 312 on Thu May 8 15:44:07 2014 RTM_GET: Report Metrics: len 312, pid: 2895, seq 1, errno 0, flags: locks: inits: sockaddrs: 10.0.0.0 link#1 255.255.255.0 em0:8.0.27.c5.29.d4 10.0.0.92 _________________^^^^^^^^^^^^^^^^^^ Sponsored by: Yandex LLC MFC after: 1 month Modified: head/sbin/route/route.c head/sys/net/rtsock.c Modified: head/sbin/route/route.c ============================================================================== --- head/sbin/route/route.c Thu May 8 08:37:32 2014 (r265665) +++ head/sbin/route/route.c Thu May 8 11:56:06 2014 (r265666) @@ -1727,8 +1727,6 @@ print_getmsg(struct rt_msghdr *rtm, int (sp[RTAX_IFP]->sa_family != AF_LINK || ((struct sockaddr_dl *)(void *)sp[RTAX_IFP])->sdl_nlen == 0)) sp[RTAX_IFP] = NULL; - if (sp[RTAX_DST] && sp[RTAX_NETMASK]) - sp[RTAX_NETMASK]->sa_family = sp[RTAX_DST]->sa_family; /* XXX */ if (sp[RTAX_DST]) (void)printf("destination: %s\n", routename(sp[RTAX_DST])); if (sp[RTAX_NETMASK]) Modified: head/sys/net/rtsock.c ============================================================================== --- head/sys/net/rtsock.c Thu May 8 08:37:32 2014 (r265665) +++ head/sys/net/rtsock.c Thu May 8 11:56:06 2014 (r265666) @@ -162,6 +162,8 @@ static int sysctl_ifmalist(int af, struc static int route_output(struct mbuf *m, struct socket *so); static void rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out); static void rt_dispatch(struct mbuf *, sa_family_t); +static struct sockaddr *rtsock_fix_netmask(struct sockaddr *dst, + struct sockaddr *smask, struct sockaddr_storage *dmask); static struct netisr_handler rtsock_nh = { .nh_name = "rtsock", @@ -520,8 +522,8 @@ route_output(struct mbuf *m, struct sock struct rtentry *rt = NULL; struct radix_node_head *rnh; struct rt_addrinfo info; -#ifdef INET6 struct sockaddr_storage ss; +#ifdef INET6 struct sockaddr_in6 *sin6; int i, rti_need_deembed = 0; #endif @@ -784,7 +786,8 @@ report: } info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; - info.rti_info[RTAX_NETMASK] = rt_mask(rt); + info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), + rt_mask(rt), &ss); info.rti_info[RTAX_GENMASK] = 0; if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { ifp = rt->rt_ifp; @@ -967,6 +970,25 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, str } /* + * Fill in @dmask with valid netmask leaving original @smask + * intact. Mostly used with radix netmasks. + */ +static struct sockaddr * +rtsock_fix_netmask(struct sockaddr *dst, struct sockaddr *smask, + struct sockaddr_storage *dmask) +{ + if (dst == NULL || smask == NULL) + return (NULL); + + memset(dmask, 0, dst->sa_len); + memcpy(dmask, smask, smask->sa_len); + dmask->ss_len = dst->sa_len; + dmask->ss_family = dst->sa_family; + + return ((struct sockaddr *)dmask); +} + +/* * Used by the routing socket. */ static struct mbuf * @@ -1247,6 +1269,7 @@ rtsock_addrmsg(int cmd, struct ifaddr *i struct mbuf *m; struct ifa_msghdr *ifam; struct ifnet *ifp = ifa->ifa_ifp; + struct sockaddr_storage ss; if (V_route_cb.any_count == 0) return (0); @@ -1256,7 +1279,8 @@ rtsock_addrmsg(int cmd, struct ifaddr *i bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr; - info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; + info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask( + info.rti_info[RTAX_IFP], ifa->ifa_netmask, &ss); info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; if ((m = rt_msg1(ncmd, &info)) == NULL) return (ENOBUFS); @@ -1295,13 +1319,14 @@ rtsock_routemsg(int cmd, struct ifnet *i struct sockaddr *sa; struct mbuf *m; struct rt_msghdr *rtm; + struct sockaddr_storage ss; if (V_route_cb.any_count == 0) return (0); bzero((caddr_t)&info, sizeof(info)); - info.rti_info[RTAX_NETMASK] = rt_mask(rt); info.rti_info[RTAX_DST] = sa = rt_key(rt); + info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(sa, rt_mask(rt), &ss); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; if ((m = rt_msg1(cmd, &info)) == NULL) return (ENOBUFS); @@ -1473,6 +1498,7 @@ sysctl_dumpentry(struct radix_node *rn, struct rtentry *rt = (struct rtentry *)rn; int error = 0, size; struct rt_addrinfo info; + struct sockaddr_storage ss; if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) return 0; @@ -1483,7 +1509,8 @@ sysctl_dumpentry(struct radix_node *rn, bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; - info.rti_info[RTAX_NETMASK] = rt_mask(rt); + info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), + rt_mask(rt), &ss); info.rti_info[RTAX_GENMASK] = 0; if (rt->rt_ifp) { info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr; @@ -1659,6 +1686,7 @@ sysctl_iflist(int af, struct walkarg *w) struct ifaddr *ifa; struct rt_addrinfo info; int len, error = 0; + struct sockaddr_storage ss; bzero((caddr_t)&info, sizeof(info)); IFNET_RLOCK_NOSLEEP(); @@ -1687,7 +1715,8 @@ sysctl_iflist(int af, struct walkarg *w) ifa->ifa_addr) != 0) continue; info.rti_info[RTAX_IFA] = ifa->ifa_addr; - info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; + info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask( + ifa->ifa_addr, ifa->ifa_netmask, &ss); info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; error = rtsock_msg_buffer(RTM_NEWADDR, &info, w, &len); if (error != 0) @@ -1704,8 +1733,9 @@ sysctl_iflist(int af, struct walkarg *w) } } IF_ADDR_RUNLOCK(ifp); - info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = - info.rti_info[RTAX_BRD] = NULL; + info.rti_info[RTAX_IFA] = NULL; + info.rti_info[RTAX_NETMASK] = NULL; + info.rti_info[RTAX_BRD] = NULL; } done: if (ifp != NULL)