diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2017-11-03 14:28:58 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2017-11-03 14:28:58 +0000 |
commit | 74b5e028be722ade5f0409e1251475665b799368 (patch) | |
tree | a0f107936fc0f6815afb8e8e3833dc3e7548db12 | |
parent | 46f68c1628fa702f0777e59dfeb70caa728f6fbc (diff) |
We are processing Router Solicitation / Advertisement messages only
for the Source Link-layer Address Options.
Merge nd6_rs_input() and nd6_ra_input() into one generic function that
does just that.
input & OK mpi
-rw-r--r-- | sys/netinet6/icmp6.c | 27 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 5 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 173 |
3 files changed, 63 insertions, 142 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 421280690c9..9567e5cc4fd 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: icmp6.c,v 1.219 2017/10/18 17:01:14 bluhm Exp $ */ +/* $OpenBSD: icmp6.c,v 1.220 2017/11/03 14:28:57 florian Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* @@ -637,32 +637,23 @@ icmp6_input(struct mbuf **mp, int *offp, int proto, int af) break; case ND_ROUTER_SOLICIT: - if (code != 0) - goto badcode; - if (icmp6len < sizeof(struct nd_router_solicit)) - goto badlen; - if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { - /* give up local */ - nd6_rs_input(m, off, icmp6len); - m = NULL; - goto freeit; - } - nd6_rs_input(n, off, icmp6len); - /* m stays. */ - break; - case ND_ROUTER_ADVERT: if (code != 0) goto badcode; - if (icmp6len < sizeof(struct nd_router_advert)) + if ((icmp6->icmp6_type == ND_ROUTER_SOLICIT && icmp6len < + sizeof(struct nd_router_solicit)) || + (icmp6->icmp6_type == ND_ROUTER_ADVERT && icmp6len < + sizeof(struct nd_router_advert))) goto badlen; + if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { /* give up local */ - nd6_ra_input(m, off, icmp6len); + nd6_rtr_cache(m, off, icmp6len, + icmp6->icmp6_type); m = NULL; goto freeit; } - nd6_ra_input(n, off, icmp6len); + nd6_rtr_cache(n, off, icmp6len, icmp6->icmp6_type); /* m stays. */ break; diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index fa63806d040..06fb3a49927 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.h,v 1.72 2017/08/09 14:36:00 florian Exp $ */ +/* $OpenBSD: nd6.h,v 1.73 2017/11/03 14:28:57 florian Exp $ */ /* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */ /* @@ -192,9 +192,8 @@ void nd6_ns_output(struct ifnet *, struct in6_addr *, caddr_t nd6_ifptomac(struct ifnet *); void nd6_dad_start(struct ifaddr *); void nd6_dad_stop(struct ifaddr *); -void nd6_ra_input(struct mbuf *, int, int); -void nd6_rs_input(struct mbuf *, int, int); +void nd6_rtr_cache(struct mbuf *, int, int, int); int in6_ifdel(struct ifnet *, struct in6_addr *); void rt6_flush(struct in6_addr *, struct ifnet *); diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 51772d5814e..b00762619cd 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6_rtr.c,v 1.164 2017/08/09 06:21:04 florian Exp $ */ +/* $OpenBSD: nd6_rtr.c,v 1.165 2017/11/03 14:28:57 florian Exp $ */ /* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */ /* @@ -60,111 +60,15 @@ int rt6_deleteroute(struct rtentry *, void *, unsigned int); /* - * Receive Router Solicitation Message - just for routers. - * Router solicitation/advertisement is mostly managed by userland program - * (rtadvd) so here we have no function like nd6_ra_output(). - * - * Based on RFC 2461 + * Process Source Link-layer Address Options from + * Router Solicitation / Advertisement Messages. */ void -nd6_rs_input(struct mbuf *m, int off, int icmp6len) +nd6_rtr_cache(struct mbuf *m, int off, int icmp6len, int icmp6_type) { struct ifnet *ifp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_router_solicit *nd_rs; - struct in6_addr saddr6 = ip6->ip6_src; -#if 0 - struct in6_addr daddr6 = ip6->ip6_dst; -#endif - char *lladdr = NULL; - int lladdrlen = 0; -#if 0 - struct sockaddr_dl *sdl = NULL; - struct llinfo_nd6 *ln = NULL; - struct rtentry *rt = NULL; - int is_newentry; -#endif - union nd_opts ndopts; - char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; - - /* If I'm not a router, ignore it. XXX - too restrictive? */ - if (!ip6_forwarding) - goto freeit; - - /* Sanity checks */ - if (ip6->ip6_hlim != 255) { - nd6log((LOG_ERR, - "nd6_rs_input: invalid hlim (%d) from %s to %s on %u\n", - ip6->ip6_hlim, - inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)), - inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)), - m->m_pkthdr.ph_ifidx)); - goto bad; - } - - /* - * Don't update the neighbor cache, if src = ::. - * This indicates that the src has no IP address assigned yet. - */ - if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) - goto freeit; - - IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len); - if (nd_rs == NULL) { - icmp6stat_inc(icp6s_tooshort); - return; - } - - icmp6len -= sizeof(*nd_rs); - nd6_option_init(nd_rs + 1, icmp6len, &ndopts); - if (nd6_options(&ndopts) < 0) { - nd6log((LOG_INFO, - "nd6_rs_input: invalid ND option, ignored\n")); - /* nd6_options have incremented stats */ - goto freeit; - } - - if (ndopts.nd_opts_src_lladdr) { - lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1); - lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3; - } - - ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp == NULL) - goto freeit; - - if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { - nd6log((LOG_INFO, - "nd6_rs_input: lladdrlen mismatch for %s " - "(if %d, RS packet %d)\n", - inet_ntop(AF_INET6, &saddr6, src, sizeof(src)), - ifp->if_addrlen, lladdrlen - 2)); - if_put(ifp); - goto bad; - } - - nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0); - if_put(ifp); - - freeit: - m_freem(m); - return; - - bad: - icmp6stat_inc(icp6s_badrs); - m_freem(m); -} - -/* - * Receive Router Advertisement Message. - * - * Based on RFC 2461 - */ -void -nd6_ra_input(struct mbuf *m, int off, int icmp6len) -{ - struct ifnet *ifp; - struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_router_advert *nd_ra; struct in6_addr saddr6 = ip6->ip6_src; char *lladdr = NULL; @@ -172,35 +76,62 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len) union nd_opts ndopts; char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; + KASSERT(icmp6_type == ND_ROUTER_SOLICIT || icmp6_type == + ND_ROUTER_ADVERT); + /* Sanity checks */ if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, - "nd6_ra_input: invalid hlim (%d) from %s to %s on %u\n", - ip6->ip6_hlim, + "%s: invalid hlim (%d) from %s to %s on %u\n", + __func__, ip6->ip6_hlim, inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)), inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)), m->m_pkthdr.ph_ifidx)); goto bad; } - if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) { - nd6log((LOG_ERR, - "nd6_ra_input: src %s is not link-local\n", - inet_ntop(AF_INET6, &saddr6, src, sizeof(src)))); - goto bad; - } - - IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len); - if (nd_ra == NULL) { - icmp6stat_inc(icp6s_tooshort); - return; + switch (icmp6_type) { + case ND_ROUTER_SOLICIT: + /* + * Don't update the neighbor cache, if src = ::. + * This indicates that the src has no IP address assigned yet. + */ + if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) + goto freeit; + + IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, + icmp6len); + if (nd_rs == NULL) { + icmp6stat_inc(icp6s_tooshort); + return; + } + + icmp6len -= sizeof(*nd_rs); + nd6_option_init(nd_rs + 1, icmp6len, &ndopts); + break; + case ND_ROUTER_ADVERT: + if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) { + nd6log((LOG_ERR, + "%s: src %s is not link-local\n", __func__, + inet_ntop(AF_INET6, &saddr6, src, sizeof(src)))); + goto bad; + } + + IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, + icmp6len); + if (nd_ra == NULL) { + icmp6stat_inc(icp6s_tooshort); + return; + } + + icmp6len -= sizeof(*nd_ra); + nd6_option_init(nd_ra + 1, icmp6len, &ndopts); + break; } - icmp6len -= sizeof(*nd_ra); - nd6_option_init(nd_ra + 1, icmp6len, &ndopts); if (nd6_options(&ndopts) < 0) { nd6log((LOG_INFO, - "nd6_ra_input: invalid ND option, ignored\n")); + "%s: invalid ND option, ignored\n", __func__)); /* nd6_options have incremented stats */ goto freeit; } @@ -216,15 +147,14 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len) if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { nd6log((LOG_INFO, - "nd6_ra_input: lladdrlen mismatch for %s " - "(if %d, RA packet %d)\n", - inet_ntop(AF_INET6, &saddr6, src, sizeof(src)), + "%s: lladdrlen mismatch for %s (if %d, RA/RS packet %d)\n", + __func__, inet_ntop(AF_INET6, &saddr6, src, sizeof(src)), ifp->if_addrlen, lladdrlen - 2)); if_put(ifp); goto bad; } - nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0); + nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, icmp6_type, 0); if_put(ifp); freeit: @@ -232,7 +162,8 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len) return; bad: - icmp6stat_inc(icp6s_badra); + icmp6stat_inc(icmp6_type == ND_ROUTER_SOLICIT ? icp6s_badrs : + icp6s_badra); m_freem(m); } |