* Input a Neighbor Solicitation Message. * * Based on RFC 2461 * Based on RFC 2462 (duplicate address detection) */
| 115 | * Based on RFC 2462 (duplicate address detection) |
| 116 | */ |
| 117 | void |
| 118 | nd6_ns_input(struct mbuf *m, int off, int icmp6len) |
| 119 | { |
| 120 | struct ifnet *ifp; |
| 121 | struct ip6_hdr *ip6; |
| 122 | struct nd_neighbor_solicit *nd_ns; |
| 123 | struct in6_addr daddr6, myaddr6, saddr6, taddr6; |
| 124 | struct ifaddr *ifa; |
| 125 | struct sockaddr_dl proxydl; |
| 126 | union nd_opts ndopts; |
| 127 | char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; |
| 128 | char *lladdr; |
| 129 | int anycast, lladdrlen, proxy, rflag, tentative, tlladdr; |
| 130 | |
| 131 | ifa = NULL; |
| 132 | |
| 133 | /* RFC 6980: Nodes MUST silently ignore fragments */ |
| 134 | if(m->m_flags & M_FRAGMENTED) |
| 135 | goto freeit; |
| 136 | |
| 137 | ifp = m->m_pkthdr.rcvif; |
| 138 | ip6 = mtod(m, struct ip6_hdr *); |
| 139 | if (__predict_false(ip6->ip6_hlim != 255)) { |
| 140 | ICMP6STAT_INC(icp6s_invlhlim); |
| 141 | nd6log((LOG_ERR, |
| 142 | "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n", |
| 143 | ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src), |
| 144 | ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp))); |
| 145 | goto bads; |
| 146 | } |
| 147 | |
| 148 | if (m->m_len < off + icmp6len) { |
| 149 | m = m_pullup(m, off + icmp6len); |
| 150 | if (m == NULL) { |
| 151 | IP6STAT_INC(ip6s_exthdrtoolong); |
| 152 | return; |
| 153 | } |
| 154 | } |
| 155 | ip6 = mtod(m, struct ip6_hdr *); |
| 156 | nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off); |
| 157 | |
| 158 | saddr6 = ip6->ip6_src; |
| 159 | daddr6 = ip6->ip6_dst; |
| 160 | taddr6 = nd_ns->nd_ns_target; |
| 161 | if (in6_setscope(&taddr6, ifp, NULL) != 0) |
| 162 | goto bad; |
| 163 | |
| 164 | rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0; |
| 165 | if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif) |
| 166 | rflag = 0; |
| 167 | |
| 168 | if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { |
| 169 | /* dst has to be a solicited node multicast address. */ |
| 170 | if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL && |
| 171 | /* don't check ifindex portion */ |
| 172 | daddr6.s6_addr32[1] == 0 && |
| 173 | daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE && |
| 174 | daddr6.s6_addr8[12] == 0xff) { |
no test coverage detected