mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-04 12:52:15 +00:00
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:<UP,DONE,PINNED> locks: inits: sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA> 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:<UP,DONE,PINNED> locks: inits: sockaddrs: <DST,GATEWAY,NETMASK,IFP,IFA> 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
This commit is contained in:
parent
f0736f4cec
commit
3deb3649d5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=265666
@ -1727,8 +1727,6 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib)
|
||||
(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])
|
||||
|
@ -162,6 +162,8 @@ static int sysctl_ifmalist(int af, struct walkarg *w);
|
||||
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 socket *so)
|
||||
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 @@ route_output(struct mbuf *m, struct socket *so)
|
||||
}
|
||||
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;
|
||||
@ -966,6 +969,25 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@ -1247,6 +1269,7 @@ rtsock_addrmsg(int cmd, struct ifaddr *ifa, int fibnum)
|
||||
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 *ifa, int fibnum)
|
||||
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 *ifp, int error, struct rtentry *rt,
|
||||
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, void *vw)
|
||||
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, void *vw)
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user