On 02/11/17(Thu) 23:25, Florian Obser wrote:
> 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.
Ok, but I'd suggest a different name: nd6_rtr_cache().
I'd also suggest you look at killing the others functions in this file,
I doubt they are still in use since you introduced slaacd(8) (:
>
> OK?
>
> diff --git netinet6/icmp6.c netinet6/icmp6.c
> index 421280690c9..b5e12169584 100644
> --- netinet6/icmp6.c
> +++ netinet6/icmp6.c
> @@ -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_cache_from_rtr_input(m, off, icmp6len,
> + icmp6->icmp6_type);
> m = NULL;
> goto freeit;
> }
> - nd6_ra_input(n, off, icmp6len);
> + nd6_cache_from_rtr_input(n, off, icmp6len, icmp6->icmp6_type);
> /* m stays. */
> break;
>
> diff --git netinet6/nd6.h netinet6/nd6.h
> index fa63806d040..ce273321a25 100644
> --- netinet6/nd6.h
> +++ netinet6/nd6.h
> @@ -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_cache_from_rtr_input(struct mbuf *, int, int, int);
>
> int in6_ifdel(struct ifnet *, struct in6_addr *);
> void rt6_flush(struct in6_addr *, struct ifnet *);
> diff --git netinet6/nd6_rtr.c netinet6/nd6_rtr.c
> index 51772d5814e..18397b8267b 100644
> --- netinet6/nd6_rtr.c
> +++ netinet6/nd6_rtr.c
> @@ -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_cache_from_rtr_input(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);
> }
>
>
> --
> I'm not entirely sure you are real.
>