From f4d1af37ddeedade34d3da50938b4ff46c639458 Mon Sep 17 00:00:00 2001 From: mikeb Date: Tue, 7 Jan 2014 17:07:45 +0000 Subject: [PATCH] Propagate an rdomain number to the nd6_lookup independently from the ifp pointer which can be NULL. This prevents a crash reported by David Hill . OK bluhm --- sys/netinet/tcp_input.c | 5 +++-- sys/netinet6/icmp6.c | 4 ++-- sys/netinet6/in6_src.c | 5 +++-- sys/netinet6/nd6.c | 26 +++++++++++++++----------- sys/netinet6/nd6.h | 6 +++--- sys/netinet6/nd6_nbr.c | 4 ++-- sys/netinet6/nd6_rtr.c | 10 ++++++---- 7 files changed, 34 insertions(+), 26 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index d9b274a437e..65f6804d54f 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.269 2013/10/20 11:03:01 phessler Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.270 2014/01/07 17:07:45 mikeb Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -148,7 +148,8 @@ struct timeval tcp_ackdrop_ppslim_last; do { \ if (tp && tp->t_inpcb && (tp->t_inpcb->inp_flags & INP_IPV6) && \ tp->t_inpcb->inp_route6.ro_rt) { \ - nd6_nud_hint(tp->t_inpcb->inp_route6.ro_rt, NULL, 0); \ + nd6_nud_hint(tp->t_inpcb->inp_route6.ro_rt, NULL, 0, \ + tp->t_inpcb->inp_rtableid); \ } \ } while (0) #else diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 8173cb55b6b..0160e2ff484 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: icmp6.c,v 1.137 2013/12/20 02:04:08 krw Exp $ */ +/* $OpenBSD: icmp6.c,v 1.138 2014/01/07 17:07:46 mikeb Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* @@ -2503,7 +2503,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) struct nd_opt_hdr *nd_opt; char *lladdr; - rt_nexthop = nd6_lookup(nexthop, 0, ifp); + rt_nexthop = nd6_lookup(nexthop, 0, ifp, ifp->if_rdomain); if (!rt_nexthop) goto nolladdropt; len = sizeof(*nd_opt) + ifp->if_addrlen; diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index 8569db45f08..7ec305abbc7 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_src.c,v 1.36 2013/11/11 09:15:35 mpi Exp $ */ +/* $OpenBSD: in6_src.c,v 1.37 2014/01/07 17:07:46 mikeb Exp $ */ /* $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $ */ /* @@ -228,7 +228,8 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, if (opts && opts->ip6po_nexthop) { sin6_next = satosin6(opts->ip6po_nexthop); - rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL); + rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL, + rtableid); if (rt) { ia6 = in6_ifawithscope(rt->rt_ifp, dst, rtableid); diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index cb08b2fce5a..92b0dbcbfeb 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.c,v 1.105 2013/11/11 09:15:35 mpi Exp $ */ +/* $OpenBSD: nd6.c,v 1.106 2014/01/07 17:07:46 mikeb Exp $ */ /* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */ /* @@ -637,7 +637,8 @@ nd6_purge(struct ifnet *ifp) } struct rtentry * -nd6_lookup(struct in6_addr *addr6, int create, struct ifnet *ifp) +nd6_lookup(struct in6_addr *addr6, int create, struct ifnet *ifp, + u_int rtableid) { struct rtentry *rt; struct sockaddr_in6 sin6; @@ -647,7 +648,7 @@ nd6_lookup(struct in6_addr *addr6, int create, struct ifnet *ifp) sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; - rt = rtalloc1(sin6tosa(&sin6), create, ifp->if_rdomain); + rt = rtalloc1(sin6tosa(&sin6), create, rtableid); if (rt && (rt->rt_flags & RTF_LLINFO) == 0) { /* * This is the case for the default route. @@ -690,7 +691,7 @@ nd6_lookup(struct in6_addr *addr6, int create, struct ifnet *ifp) info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = sin6tosa(&all1_sa); if ((e = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, - &rt, ifp->if_rdomain)) != 0) { + &rt, rtableid)) != 0) { #if 0 char ip[INET6_ADDRSTRLEN]; log(LOG_ERR, @@ -779,7 +780,8 @@ nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp) * Even if the address matches none of our addresses, it might be * in the neighbor cache. */ - if ((rt = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL) + if ((rt = nd6_lookup(&addr->sin6_addr, 0, ifp, + ifp->if_rdomain)) != NULL) return (1); return (0); @@ -902,7 +904,8 @@ nd6_free(struct rtentry *rt, int gc) * XXX cost-effective methods? */ void -nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force) +nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force, + u_int rtableid) { struct llinfo_nd6 *ln; @@ -913,7 +916,7 @@ nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force) if (!rt) { if (!dst6) return; - if (!(rt = nd6_lookup(dst6, 0, NULL))) + if (!(rt = nd6_lookup(dst6, 0, NULL, rtableid))) return; } @@ -1321,7 +1324,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) } s = splsoftnet(); - if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL || + if ((rt = nd6_lookup(&nb_addr, 0, ifp, ifp->if_rdomain)) == NULL || (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) { error = EINVAL; splx(s); @@ -1378,7 +1381,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, * description on it in NS section (RFC 2461 7.2.3). */ - rt = nd6_lookup(from, 0, ifp); + rt = nd6_lookup(from, 0, ifp, ifp->if_rdomain); if (!rt) { #if 0 /* nothing must be done if there's no lladdr */ @@ -1386,7 +1389,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, return NULL; #endif - rt = nd6_lookup(from, RT_REPORT, ifp); + rt = nd6_lookup(from, RT_REPORT, ifp, ifp->if_rdomain); is_newentry = 1; } else { /* do nothing if static ndp is set */ @@ -1698,7 +1701,8 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0, * it is tolerable, because this should be a rare case. */ if (nd6_is_addr_neighbor(dst, ifp) && - (rt = nd6_lookup(&dst->sin6_addr, RT_REPORT, ifp)) != NULL) + (rt = nd6_lookup(&dst->sin6_addr, RT_REPORT, ifp, + ifp->if_rdomain)) != NULL) ln = (struct llinfo_nd6 *)rt->rt_llinfo; } if (!ln || !rt) { diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index c2db89055f7..de300d99d96 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.h,v 1.35 2013/10/25 02:54:42 deraadt Exp $ */ +/* $OpenBSD: nd6.h,v 1.36 2014/01/07 17:07:46 mikeb Exp $ */ /* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */ /* @@ -259,12 +259,12 @@ int nd6_is_addr_neighbor(struct sockaddr_in6 *, struct ifnet *); void nd6_option_init(void *, int, union nd_opts *); struct nd_opt_hdr *nd6_option(union nd_opts *); int nd6_options(union nd_opts *); -struct rtentry *nd6_lookup(struct in6_addr *, int, struct ifnet *); +struct rtentry *nd6_lookup(struct in6_addr *, int, struct ifnet *, u_int); void nd6_setmtu(struct ifnet *); void nd6_llinfo_settimer(struct llinfo_nd6 *, long); void nd6_timer(void *); void nd6_purge(struct ifnet *); -void nd6_nud_hint(struct rtentry *, struct in6_addr *, int); +void nd6_nud_hint(struct rtentry *, struct in6_addr *, int, u_int); int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *, struct sockaddr *, u_char *); void nd6_rtrequest(int, struct rtentry *); diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index f8e82ef910a..b45c56b49d0 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6_nbr.c,v 1.72 2013/11/19 09:00:43 mpi Exp $ */ +/* $OpenBSD: nd6_nbr.c,v 1.73 2014/01/07 17:07:46 mikeb Exp $ */ /* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */ /* @@ -681,7 +681,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) * If no neighbor cache entry is found, NA SHOULD silently be * discarded. */ - rt = nd6_lookup(&taddr6, 0, ifp); + rt = nd6_lookup(&taddr6, 0, ifp, ifp->if_rdomain); if ((rt == NULL) || ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) || ((sdl = SDL(rt->rt_gateway)) == NULL)) diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 80c75d7a6bc..2b0d123f792 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6_rtr.c,v 1.74 2013/11/11 09:15:35 mpi Exp $ */ +/* $OpenBSD: nd6_rtr.c,v 1.75 2014/01/07 17:07:46 mikeb Exp $ */ /* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */ /* @@ -669,7 +669,8 @@ defrouter_select(void) */ TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) { if (!selected_dr && - (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) && + (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp, + dr->ifp->if_rdomain)) && (ln = (struct llinfo_nd6 *)rt->rt_llinfo) && ND6_IS_LLINFO_PROBREACH(ln)) { selected_dr = dr; @@ -697,7 +698,8 @@ defrouter_select(void) else selected_dr = TAILQ_NEXT(installed_dr, dr_entry); } else if (installed_dr && - (rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) && + (rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp, + installed_dr->ifp->if_rdomain)) && (ln = (struct llinfo_nd6 *)rt->rt_llinfo) && ND6_IS_LLINFO_PROBREACH(ln) && rtpref(selected_dr) <= rtpref(installed_dr)) { @@ -1398,7 +1400,7 @@ find_pfxlist_reachable_router(struct nd_prefix *pr) LIST_FOREACH(pfxrtr, &pr->ndpr_advrtrs, pfr_entry) { if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0, - pfxrtr->router->ifp)) && + pfxrtr->router->ifp, pfxrtr->router->ifp->if_rdomain)) && (ln = (struct llinfo_nd6 *)rt->rt_llinfo) && ND6_IS_LLINFO_PROBREACH(ln)) break; /* found */ -- 2.20.1