summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6/nd6_nbr.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet6/nd6_nbr.c')
-rw-r--r--freebsd/sys/netinet6/nd6_nbr.c128
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);