diff options
author | melifaro <melifaro@FreeBSD.org> | 2014-01-04 22:25:26 +0000 |
---|---|---|
committer | melifaro <melifaro@FreeBSD.org> | 2014-01-04 22:25:26 +0000 |
commit | f85abe95558065229851d77464b1b080e8b7388a (patch) | |
tree | 30ad6ec1053ace25e1f08c9626c9844194354f00 /sys/net/rtsock.c | |
parent | b03757c0c6594aac65b51957fe1b1c9f55f84fe5 (diff) | |
download | FreeBSD-src-f85abe95558065229851d77464b1b080e8b7388a.zip FreeBSD-src-f85abe95558065229851d77464b1b080e8b7388a.tar.gz |
Change semantics for rnh_lookup() function: now
it performs exact match search, regardless of netmask existance.
This simplifies most of rnh_lookup() consumers.
Fix panic triggered by deleting non-existent host route.
PR: kern/185092
Submitted by: Nikolay Denev <ndenev at gmail.com>
MFC after: 1 month
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r-- | sys/net/rtsock.c | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index e7d1d99..50b7f0d 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -727,10 +727,24 @@ route_output(struct mbuf *m, struct socket *so) info.rti_info[RTAX_DST]->sa_family); if (rnh == NULL) senderr(EAFNOSUPPORT); + RADIX_NODE_HEAD_RLOCK(rnh); - rt = (struct rtentry *) rnh->rnh_lookup(info.rti_info[RTAX_DST], - info.rti_info[RTAX_NETMASK], rnh); - if (rt == NULL) { /* XXX looks bogus */ + + if (info.rti_info[RTAX_NETMASK] == NULL && + rtm->rtm_type == RTM_GET) { + /* + * Provide logest prefix match for + * address lookup (no mask). + * 'route -n get addr' + */ + rt = (struct rtentry *) rnh->rnh_matchaddr( + info.rti_info[RTAX_DST], rnh); + } else + rt = (struct rtentry *) rnh->rnh_lookup( + info.rti_info[RTAX_DST], + info.rti_info[RTAX_NETMASK], rnh); + + if (rt == NULL) { RADIX_NODE_HEAD_RUNLOCK(rnh); senderr(ESRCH); } @@ -787,25 +801,6 @@ route_output(struct mbuf *m, struct socket *so) RT_ADDREF(rt); RADIX_NODE_HEAD_RUNLOCK(rnh); - /* - * Fix for PR: 82974 - * - * RTM_CHANGE/LOCK need a perfect match, rn_lookup() - * returns a perfect match in case a netmask is - * specified. For host routes only a longest prefix - * match is returned so it is necessary to compare the - * existence of the netmask. If both have a netmask - * rnh_lookup() did a perfect match and if none of them - * have a netmask both are host routes which is also a - * perfect match. - */ - - if (rtm->rtm_type != RTM_GET && - (!rt_mask(rt) != !info.rti_info[RTAX_NETMASK])) { - RT_UNLOCK(rt); - senderr(ESRCH); - } - switch(rtm->rtm_type) { case RTM_GET: |