summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2017-11-03 14:28:58 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2017-11-03 14:28:58 +0000
commit74b5e028be722ade5f0409e1251475665b799368 (patch)
treea0f107936fc0f6815afb8e8e3833dc3e7548db12
parent46f68c1628fa702f0777e59dfeb70caa728f6fbc (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.c27
-rw-r--r--sys/netinet6/nd6.h5
-rw-r--r--sys/netinet6/nd6_rtr.c173
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);
}