diff options
Diffstat (limited to 'freebsd/sys/netinet6/nd6_nbr.c')
-rw-r--r-- | freebsd/sys/netinet6/nd6_nbr.c | 128 |
1 files changed, 68 insertions, 60 deletions
diff --git a/freebsd/sys/netinet6/nd6_nbr.c b/freebsd/sys/netinet6/nd6_nbr.c index 49810020..634eea06 100644 --- a/freebsd/sys/netinet6/nd6_nbr.c +++ b/freebsd/sys/netinet6/nd6_nbr.c @@ -122,53 +122,53 @@ VNET_DEFINE_STATIC(int, dad_maxtry) = 15; /* max # of *tries* to void nd6_ns_input(struct mbuf *m, int off, int icmp6len) { - struct ifnet *ifp = m->m_pkthdr.rcvif; - struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); + struct ifnet *ifp; + struct ip6_hdr *ip6; struct nd_neighbor_solicit *nd_ns; - struct in6_addr saddr6 = ip6->ip6_src; - struct in6_addr daddr6 = ip6->ip6_dst; - struct in6_addr taddr6; - struct in6_addr myaddr6; - char *lladdr = NULL; - struct ifaddr *ifa = NULL; - int lladdrlen = 0; - int anycast = 0, proxy = 0, tentative = 0; - int tlladdr; - int rflag; - union nd_opts ndopts; + struct in6_addr daddr6, myaddr6, saddr6, taddr6; + struct ifaddr *ifa; struct sockaddr_dl proxydl; + union nd_opts ndopts; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; + char *lladdr; + int anycast, lladdrlen, proxy, rflag, tentative, tlladdr; + + ifa = NULL; /* RFC 6980: Nodes MUST silently ignore fragments */ if(m->m_flags & M_FRAGMENTED) goto freeit; - rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0; - if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif) - rflag = 0; -#ifndef PULLDOWN_TEST - IP6_EXTHDR_CHECK(m, off, icmp6len,); - nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off); -#else - IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len); - if (nd_ns == NULL) { - ICMP6STAT_INC(icp6s_tooshort); - return; - } -#endif - ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */ - taddr6 = nd_ns->nd_ns_target; - if (in6_setscope(&taddr6, ifp, NULL) != 0) - goto bad; - + ifp = m->m_pkthdr.rcvif; + ip6 = mtod(m, struct ip6_hdr *); if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n", ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src), ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp))); - goto bad; + goto bads; } + if (m->m_len < off + icmp6len) { + m = m_pullup(m, off + icmp6len); + if (m == NULL) { + IP6STAT_INC(ip6s_exthdrtoolong); + return; + } + } + ip6 = mtod(m, struct ip6_hdr *); + nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off); + + saddr6 = ip6->ip6_src; + daddr6 = ip6->ip6_dst; + taddr6 = nd_ns->nd_ns_target; + if (in6_setscope(&taddr6, ifp, NULL) != 0) + goto bad; + + rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0; + if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif) + rflag = 0; + if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { /* dst has to be a solicited node multicast address. */ if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL && @@ -216,6 +216,8 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) goto freeit; } + lladdr = NULL; + lladdrlen = 0; if (ndopts.nd_opts_src_lladdr) { lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1); lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3; @@ -255,6 +257,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); /* (2) check. */ + proxy = 0; if (ifa == NULL) { struct sockaddr_dl rt_gateway; struct rt_addrinfo info; @@ -381,6 +384,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len) ip6_sprintf(ip6bufs, &daddr6))); nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(ip6bufs, &taddr6))); + bads: ICMP6STAT_INC(icp6s_badns); if (ifa != NULL) ifa_free(ifa); @@ -615,32 +619,32 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *saddr6, void nd6_na_input(struct mbuf *m, int off, int icmp6len) { - struct ifnet *ifp = m->m_pkthdr.rcvif; - struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); - struct nd_neighbor_advert *nd_na; - struct in6_addr daddr6 = ip6->ip6_dst; - struct in6_addr taddr6; - int flags; - int is_router; - int is_solicited; - int is_override; - char *lladdr = NULL; - int lladdrlen = 0; - int checklink = 0; + struct ifnet *ifp; + struct ip6_hdr *ip6; struct ifaddr *ifa; - struct llentry *ln = NULL; - union nd_opts ndopts; - struct mbuf *chain = NULL; + struct llentry *ln; + struct mbuf *chain; + struct nd_neighbor_advert *nd_na; + struct in6_addr daddr6, taddr6; struct sockaddr_in6 sin6; + union nd_opts ndopts; u_char linkhdr[LLE_MAX_LINKHDR]; - size_t linkhdrsize; - int lladdr_off; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; + char *lladdr; + size_t linkhdrsize; + int flags, is_override, is_router, is_solicited; + int lladdr_off, lladdrlen, checklink; + + chain = NULL; + ln = NULL; + checklink = 0; /* RFC 6980: Nodes MUST silently ignore fragments */ if(m->m_flags & M_FRAGMENTED) goto freeit; + ifp = m->m_pkthdr.rcvif; + ip6 = mtod(m, struct ip6_hdr *); if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n", @@ -649,22 +653,20 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) goto bad; } -#ifndef PULLDOWN_TEST - IP6_EXTHDR_CHECK(m, off, icmp6len,); - nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off); -#else - IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len); - if (nd_na == NULL) { - ICMP6STAT_INC(icp6s_tooshort); - return; + if (m->m_len < off + icmp6len) { + m = m_pullup(m, off + icmp6len); + if (m == NULL) { + IP6STAT_INC(ip6s_exthdrtoolong); + return; + } } -#endif + ip6 = mtod(m, struct ip6_hdr *); + nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off); flags = nd_na->nd_na_flags_reserved; is_router = ((flags & ND_NA_FLAG_ROUTER) != 0); is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0); is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0); - memset(&sin6, 0, sizeof(sin6)); taddr6 = nd_na->nd_na_target; if (in6_setscope(&taddr6, ifp, NULL)) @@ -676,6 +678,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) ip6_sprintf(ip6bufs, &taddr6))); goto bad; } + + daddr6 = ip6->ip6_dst; if (IN6_IS_ADDR_MULTICAST(&daddr6)) if (is_solicited) { nd6log((LOG_ERR, @@ -692,6 +696,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) goto freeit; } + lladdr = NULL; + lladdrlen = 0; if (ndopts.nd_opts_tgt_lladdr) { lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; @@ -889,8 +895,10 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) * rt->rt_flags &= ~RTF_REJECT; */ ln->la_asked = 0; - if (ln->la_hold != NULL) + if (ln->la_hold != NULL) { + memset(&sin6, 0, sizeof(sin6)); nd6_grab_holdchain(ln, &chain, &sin6); + } freeit: if (ln != NULL) LLE_WUNLOCK(ln); |