nd6_nbr.c (61965) | nd6_nbr.c (62587) |
---|---|
1/* $FreeBSD: head/sys/netinet6/nd6_nbr.c 62587 2000-07-04 16:35:15Z itojun $ */ 2/* $KAME: nd6_nbr.c,v 1.37 2000/06/04 12:46:13 itojun Exp $ */ 3 |
|
1/* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. | 4/* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. |
28 * 29 * $FreeBSD: head/sys/netinet6/nd6_nbr.c 61965 2000-06-22 19:04:41Z ume $ | |
30 */ 31 | 31 */ 32 |
33#include "opt_inet.h" 34#include "opt_inet6.h" |
|
32#include "opt_ipsec.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/malloc.h> 37#include <sys/mbuf.h> 38#include <sys/socket.h> 39#include <sys/sockio.h> --- 6 unchanged lines hidden (view full) --- 46#include <net/if.h> 47#include <net/if_types.h> 48#include <net/if_dl.h> 49#include <net/route.h> 50 51#include <netinet/in.h> 52#include <netinet/in_var.h> 53#include <netinet6/in6_var.h> | 35#include "opt_ipsec.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/malloc.h> 40#include <sys/mbuf.h> 41#include <sys/socket.h> 42#include <sys/sockio.h> --- 6 unchanged lines hidden (view full) --- 49#include <net/if.h> 50#include <net/if_types.h> 51#include <net/if_dl.h> 52#include <net/route.h> 53 54#include <netinet/in.h> 55#include <netinet/in_var.h> 56#include <netinet6/in6_var.h> |
54#include <netinet6/ip6.h> | 57#include |
55#include <netinet6/ip6_var.h> 56#include <netinet6/nd6.h> | 58#include <netinet6/ip6_var.h> 59#include <netinet6/nd6.h> |
57#include <netinet6/icmp6.h> | 60#include |
58 | 61 |
62#ifdef IPSEC 63#include <netinet6/ipsec.h> 64#ifdef INET6 65#include <netinet6/ipsec6.h> 66#endif 67#endif 68 |
|
59#include <net/net_osdep.h> 60 | 69#include <net/net_osdep.h> 70 |
61#define SDL(s) ((struct sockaddr_dl *)s) | 71#define SDL(s) ((struct sockaddr_dl *)s) |
62 | 72 |
63struct dadq; 64static struct dadq *nd6_dad_find __P((struct ifaddr *)); 65static void nd6_dad_timer __P((struct ifaddr *)); 66static void nd6_dad_ns_input __P((struct ifaddr *)); 67static void nd6_dad_na_input __P((struct ifaddr *)); | 73struct dadq; 74static struct dadq *nd6_dad_find __P((struct ifaddr *)); 75static void nd6_dad_timer __P((struct ifaddr *)); 76static void nd6_dad_ns_output __P((struct dadq *, struct ifaddr *)); 77static void nd6_dad_ns_input __P((struct ifaddr *)); 78static void nd6_dad_na_input __P((struct ifaddr *)); |
68 | 79 |
69/* ignore NS in DAD - specwise incorrect, */ 70int dad_ignore_ns = 0; | 80static int dad_ignore_ns = 0; /* ignore NS in DAD - specwise incorrect*/ 81static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */ |
71 72/* 73 * Input an Neighbor Solicitation Message. 74 * 75 * Based on RFC 2461 76 * Based on RFC 2462 (duplicated address detection) | 82 83/* 84 * Input an Neighbor Solicitation Message. 85 * 86 * Based on RFC 2461 87 * Based on RFC 2462 (duplicated address detection) |
77 * 78 * XXX proxy advertisement | |
79 */ 80void 81nd6_ns_input(m, off, icmp6len) 82 struct mbuf *m; 83 int off, icmp6len; 84{ 85 struct ifnet *ifp = m->m_pkthdr.rcvif; 86 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); | 88 */ 89void 90nd6_ns_input(m, off, icmp6len) 91 struct mbuf *m; 92 int off, icmp6len; 93{ 94 struct ifnet *ifp = m->m_pkthdr.rcvif; 95 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); |
87 struct nd_neighbor_solicit *nd_ns 88 = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off); | 96 struct nd_neighbor_solicit *nd_ns; |
89 struct in6_addr saddr6 = ip6->ip6_src; 90 struct in6_addr daddr6 = ip6->ip6_dst; | 97 struct in6_addr saddr6 = ip6->ip6_src; 98 struct in6_addr daddr6 = ip6->ip6_dst; |
91 struct in6_addr taddr6 = nd_ns->nd_ns_target; | 99 struct in6_addr taddr6; |
92 struct in6_addr myaddr6; 93 char *lladdr = NULL; 94 struct ifaddr *ifa; 95 int lladdrlen = 0; 96 int anycast = 0, proxy = 0, tentative = 0; 97 int tlladdr; 98 union nd_opts ndopts; | 100 struct in6_addr myaddr6; 101 char *lladdr = NULL; 102 struct ifaddr *ifa; 103 int lladdrlen = 0; 104 int anycast = 0, proxy = 0, tentative = 0; 105 int tlladdr; 106 union nd_opts ndopts; |
107 struct sockaddr_dl *proxydl = NULL; |
|
99 100 if (ip6->ip6_hlim != 255) { 101 log(LOG_ERR, 102 "nd6_ns_input: invalid hlim %d\n", ip6->ip6_hlim); | 108 109 if (ip6->ip6_hlim != 255) { 110 log(LOG_ERR, 111 "nd6_ns_input: invalid hlim %d\n", ip6->ip6_hlim); |
103 return; | 112 goto freeit; |
104 } 105 106 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { 107 /* dst has to be solicited node multicast address. */ 108 if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL 109 /*don't check ifindex portion*/ 110 && daddr6.s6_addr32[1] == 0 111 && daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE 112 && daddr6.s6_addr8[12] == 0xff) { 113 ; /*good*/ 114 } else { 115 log(LOG_INFO, "nd6_ns_input: bad DAD packet " 116 "(wrong ip6 dst)\n"); 117 goto bad; 118 } 119 } 120 | 113 } 114 115 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { 116 /* dst has to be solicited node multicast address. */ 117 if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL 118 /*don't check ifindex portion*/ 119 && daddr6.s6_addr32[1] == 0 120 && daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE 121 && daddr6.s6_addr8[12] == 0xff) { 122 ; /*good*/ 123 } else { 124 log(LOG_INFO, "nd6_ns_input: bad DAD packet " 125 "(wrong ip6 dst)\n"); 126 goto bad; 127 } 128 } 129 |
130#ifndef PULLDOWN_TEST 131 IP6_EXTHDR_CHECK(m, off, icmp6len,); 132 nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off); 133#else 134 IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len); 135 if (nd_ns == NULL) { 136 icmp6stat.icp6s_tooshort++; 137 return; 138 } 139#endif 140 taddr6 = nd_ns->nd_ns_target; 141 |
|
121 if (IN6_IS_ADDR_MULTICAST(&taddr6)) { 122 log(LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"); 123 goto bad; 124 } 125 126 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6)) 127 taddr6.s6_addr16[1] = htons(ifp->if_index); 128 --- 20 unchanged lines hidden (view full) --- 149 * (RFC 2461 7.2.4) 150 * 151 * NS IP dst is unicast/anycast MUST NOT add 152 * NS IP dst is solicited-node multicast MUST add 153 * 154 * In implementation, we add target link-layer address by default. 155 * We do not add one in MUST NOT cases. 156 */ | 142 if (IN6_IS_ADDR_MULTICAST(&taddr6)) { 143 log(LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"); 144 goto bad; 145 } 146 147 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6)) 148 taddr6.s6_addr16[1] = htons(ifp->if_index); 149 --- 20 unchanged lines hidden (view full) --- 170 * (RFC 2461 7.2.4) 171 * 172 * NS IP dst is unicast/anycast MUST NOT add 173 * NS IP dst is solicited-node multicast MUST add 174 * 175 * In implementation, we add target link-layer address by default. 176 * We do not add one in MUST NOT cases. 177 */ |
178#if 0 /* too much! */ 179 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &daddr6); 180 if (ifa && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)) 181 tlladdr = 0; 182 else 183#endif |
|
157 if (!IN6_IS_ADDR_MULTICAST(&daddr6)) 158 tlladdr = 0; 159 else 160 tlladdr = 1; 161 162 /* 163 * Target address (taddr6) must be either: 164 * (1) Valid unicast/anycast address for my receiving interface, 165 * (2) Unicast address for which I'm offering proxy service, or 166 * (3) "tentative" address on which DAD is being performed. 167 */ 168 /* (1) and (3) check. */ 169 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); 170 171 /* (2) check. */ | 184 if (!IN6_IS_ADDR_MULTICAST(&daddr6)) 185 tlladdr = 0; 186 else 187 tlladdr = 1; 188 189 /* 190 * Target address (taddr6) must be either: 191 * (1) Valid unicast/anycast address for my receiving interface, 192 * (2) Unicast address for which I'm offering proxy service, or 193 * (3) "tentative" address on which DAD is being performed. 194 */ 195 /* (1) and (3) check. */ 196 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); 197 198 /* (2) check. */ |
172 if (!ifa && nd6_proxyall) { | 199 if (!ifa) { |
173 struct rtentry *rt; 174 struct sockaddr_in6 tsin6; 175 176 bzero(&tsin6, sizeof tsin6); 177 tsin6.sin6_len = sizeof(struct sockaddr_in6); 178 tsin6.sin6_family = AF_INET6; 179 tsin6.sin6_addr = taddr6; 180 181 rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0); | 200 struct rtentry *rt; 201 struct sockaddr_in6 tsin6; 202 203 bzero(&tsin6, sizeof tsin6); 204 tsin6.sin6_len = sizeof(struct sockaddr_in6); 205 tsin6.sin6_family = AF_INET6; 206 tsin6.sin6_addr = taddr6; 207 208 rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0); |
182 if (rt && rt->rt_ifp != ifp) { | 209 if (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 && 210 rt->rt_gateway->sa_family == AF_LINK) { |
183 /* | 211 /* |
184 * search link local addr for ifp, and use it for 185 * proxy NA. | 212 * proxy NDP for single entry |
186 */ | 213 */ |
187 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp); 188 if (ifa) | 214 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 215 IN6_IFF_NOTREADY|IN6_IFF_ANYCAST); 216 if (ifa) { |
189 proxy = 1; | 217 proxy = 1; |
218 proxydl = SDL(rt->rt_gateway); 219 } |
|
190 } | 220 } |
191 rtfree(rt); | 221 if (rt) 222 rtfree(rt); |
192 } 193 if (!ifa) { 194 /* 195 * We've got a NS packet, and we don't have that adddress 196 * assigned for us. We MUST silently ignore it. 197 * See RFC2461 7.2.3. 198 */ | 223 } 224 if (!ifa) { 225 /* 226 * We've got a NS packet, and we don't have that adddress 227 * assigned for us. We MUST silently ignore it. 228 * See RFC2461 7.2.3. 229 */ |
199 return; | 230 goto freeit; |
200 } 201 myaddr6 = *IFA_IN6(ifa); 202 anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST; 203 tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE; 204 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED) | 231 } 232 myaddr6 = *IFA_IN6(ifa); 233 anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST; 234 tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE; 235 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED) |
205 return; | 236 goto freeit; |
206 207 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 208 log(LOG_INFO, 209 "nd6_ns_input: lladdrlen mismatch for %s " 210 "(if %d, NS packet %d)\n", 211 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2); 212 } 213 214 if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) { 215 log(LOG_INFO, 216 "nd6_ns_input: duplicate IP6 address %s\n", 217 ip6_sprintf(&saddr6)); | 237 238 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 239 log(LOG_INFO, 240 "nd6_ns_input: lladdrlen mismatch for %s " 241 "(if %d, NS packet %d)\n", 242 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2); 243 } 244 245 if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) { 246 log(LOG_INFO, 247 "nd6_ns_input: duplicate IP6 address %s\n", 248 ip6_sprintf(&saddr6)); |
218 return; | 249 goto freeit; |
219 } 220 221 /* 222 * We have neighbor solicitation packet, with target address equals to 223 * one of my tentative address. 224 * 225 * src addr how to process? 226 * --- --- --- 9 unchanged lines hidden (view full) --- 236 * duplicated address detection. 237 * 238 * If not, the packet is for addess resolution; 239 * silently ignore it. 240 */ 241 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) 242 nd6_dad_ns_input(ifa); 243 | 250 } 251 252 /* 253 * We have neighbor solicitation packet, with target address equals to 254 * one of my tentative address. 255 * 256 * src addr how to process? 257 * --- --- --- 9 unchanged lines hidden (view full) --- 267 * duplicated address detection. 268 * 269 * If not, the packet is for addess resolution; 270 * silently ignore it. 271 */ 272 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) 273 nd6_dad_ns_input(ifa); 274 |
244 return; | 275 goto freeit; |
245 } 246 247 /* 248 * If the source address is unspecified address, entries must not 249 * be created or updated. 250 * It looks that sender is performing DAD. Output NA toward 251 * all-node multicast address, to tell the sender that I'm using 252 * the address. 253 * S bit ("solicited") must be zero. 254 */ 255 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { 256 saddr6 = in6addr_linklocal_allnodes; 257 saddr6.s6_addr16[1] = htons(ifp->if_index); 258 nd6_na_output(ifp, &saddr6, &taddr6, 259 ((anycast || proxy || !tlladdr) 260 ? 0 : ND_NA_FLAG_OVERRIDE) 261 | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0), | 276 } 277 278 /* 279 * If the source address is unspecified address, entries must not 280 * be created or updated. 281 * It looks that sender is performing DAD. Output NA toward 282 * all-node multicast address, to tell the sender that I'm using 283 * the address. 284 * S bit ("solicited") must be zero. 285 */ 286 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { 287 saddr6 = in6addr_linklocal_allnodes; 288 saddr6.s6_addr16[1] = htons(ifp->if_index); 289 nd6_na_output(ifp, &saddr6, &taddr6, 290 ((anycast || proxy || !tlladdr) 291 ? 0 : ND_NA_FLAG_OVERRIDE) 292 | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0), |
262 tlladdr); 263 return; | 293 tlladdr, (struct sockaddr *)proxydl); 294 goto freeit; |
264 } 265 266 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0); 267 268 nd6_na_output(ifp, &saddr6, &taddr6, 269 ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) 270 | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) 271 | ND_NA_FLAG_SOLICITED, | 295 } 296 297 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0); 298 299 nd6_na_output(ifp, &saddr6, &taddr6, 300 ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) 301 | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) 302 | ND_NA_FLAG_SOLICITED, |
272 tlladdr); | 303 tlladdr, (struct sockaddr *)proxydl); 304 freeit: 305 m_freem(m); |
273 return; 274 275 bad: 276 log(LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6)); 277 log(LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6)); 278 log(LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6)); | 306 return; 307 308 bad: 309 log(LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6)); 310 log(LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6)); 311 log(LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6)); |
279 return; | 312 m_freem(m); |
280} 281 282/* 283 * Output an Neighbor Solicitation Message. Caller specifies: 284 * - ICMP6 header source IP6 address 285 * - ND6 header target IP6 address 286 * - ND6 header source datalink address 287 * --- 8 unchanged lines hidden (view full) --- 296 int dad; /* duplicated address detection */ 297{ 298 struct mbuf *m; 299 struct ip6_hdr *ip6; 300 struct nd_neighbor_solicit *nd_ns; 301 struct in6_ifaddr *ia = NULL; 302 struct ip6_moptions im6o; 303 int icmp6len; | 313} 314 315/* 316 * Output an Neighbor Solicitation Message. Caller specifies: 317 * - ICMP6 header source IP6 address 318 * - ND6 header target IP6 address 319 * - ND6 header source datalink address 320 * --- 8 unchanged lines hidden (view full) --- 329 int dad; /* duplicated address detection */ 330{ 331 struct mbuf *m; 332 struct ip6_hdr *ip6; 333 struct nd_neighbor_solicit *nd_ns; 334 struct in6_ifaddr *ia = NULL; 335 struct ip6_moptions im6o; 336 int icmp6len; |
337 int maxlen; |
|
304 caddr_t mac; 305 struct ifnet *outif = NULL; 306 307 if (IN6_IS_ADDR_MULTICAST(taddr6)) 308 return; 309 | 338 caddr_t mac; 339 struct ifnet *outif = NULL; 340 341 if (IN6_IS_ADDR_MULTICAST(taddr6)) 342 return; 343 |
310 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) | 344 /* estimate the size of message */ 345 maxlen = sizeof(*ip6) + sizeof(*nd_ns); 346 maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7; 347 if (max_linkhdr + maxlen >= MCLBYTES) { 348#ifdef DIAGNOSTIC 349 printf("nd6_ns_output: max_linkhdr + maxlen >= MCLBYTES " 350 "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES); 351#endif |
311 return; | 352 return; |
353 } |
|
312 | 354 |
355 MGETHDR(m, M_DONTWAIT, MT_DATA); 356 if (m && max_linkhdr + maxlen >= MHLEN) { 357 MCLGET(m, M_DONTWAIT); 358 if ((m->m_flags & M_EXT) == 0) { 359 m_free(m); 360 m = NULL; 361 } 362 } 363 if (m == NULL) 364 return; 365 |
|
313 if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) { 314 m->m_flags |= M_MCAST; 315 im6o.im6o_multicast_ifp = ifp; 316 im6o.im6o_multicast_hlim = 255; 317 im6o.im6o_multicast_loop = 0; 318 } 319 320 icmp6len = sizeof(*nd_ns); 321 m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len; | 366 if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) { 367 m->m_flags |= M_MCAST; 368 im6o.im6o_multicast_ifp = ifp; 369 im6o.im6o_multicast_hlim = 255; 370 im6o.im6o_multicast_loop = 0; 371 } 372 373 icmp6len = sizeof(*nd_ns); 374 m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len; |
322 MH_ALIGN(m, m->m_len + 16); /* 1+1+6 is enought. but just in case */ | 375 m->m_data += max_linkhdr; /*or MH_ALIGN() equivalent?*/ |
323 324 /* fill neighbor solicitation packet */ 325 ip6 = mtod(m, struct ip6_hdr *); 326 ip6->ip6_flow = 0; | 376 377 /* fill neighbor solicitation packet */ 378 ip6 = mtod(m, struct ip6_hdr *); 379 ip6->ip6_flow = 0; |
327 ip6->ip6_vfc = IPV6_VERSION; | 380 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 381 ip6->ip6_vfc |= IPV6_VERSION; |
328 /* ip6->ip6_plen will be set later */ 329 ip6->ip6_nxt = IPPROTO_ICMPV6; 330 ip6->ip6_hlim = 255; 331 if (daddr6) 332 ip6->ip6_dst = *daddr6; 333 else { 334 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; 335 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); 336 ip6->ip6_dst.s6_addr32[1] = 0; 337 ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE; 338 ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3]; 339 ip6->ip6_dst.s6_addr8[12] = 0xff; 340 } 341 if (!dad) { | 382 /* ip6->ip6_plen will be set later */ 383 ip6->ip6_nxt = IPPROTO_ICMPV6; 384 ip6->ip6_hlim = 255; 385 if (daddr6) 386 ip6->ip6_dst = *daddr6; 387 else { 388 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; 389 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); 390 ip6->ip6_dst.s6_addr32[1] = 0; 391 ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE; 392 ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3]; 393 ip6->ip6_dst.s6_addr8[12] = 0xff; 394 } 395 if (!dad) { |
342 /* spec-wise correct, scope match */ | 396#if 0 /* KAME way, exact address scope match */ |
343 /* | 397 /* |
398 * Select a source whose scope is the same as that of the dest. 399 * Typically, the dest is link-local solicitation multicast 400 * (i.e. neighbor discovery) or link-local/global unicast 401 * (i.e. neighbor un-reachability detection). 402 */ 403 ia = in6_ifawithifp(ifp, &ip6->ip6_dst); 404 if (ia == NULL) { 405 m_freem(m); 406 return; 407 } 408 ip6->ip6_src = ia->ia_addr.sin6_addr; 409#else /* spec-wise correct */ 410 /* |
|
344 * RFC2461 7.2.2: 345 * "If the source address of the packet prompting the 346 * solicitation is the same as one of the addresses assigned 347 * to the outgoing interface, that address SHOULD be placed 348 * in the IP Source Address of the outgoing solicitation. 349 * Otherwise, any one of the addresses assigned to the 350 * interface should be used." 351 * --- 20 unchanged lines hidden (view full) --- 372 else { 373 ia = in6_ifawithifp(ifp, &ip6->ip6_dst); 374 if (ia == NULL) { 375 m_freem(m); /*XXX*/ 376 return; 377 } 378 ip6->ip6_src = ia->ia_addr.sin6_addr; 379 } | 411 * RFC2461 7.2.2: 412 * "If the source address of the packet prompting the 413 * solicitation is the same as one of the addresses assigned 414 * to the outgoing interface, that address SHOULD be placed 415 * in the IP Source Address of the outgoing solicitation. 416 * Otherwise, any one of the addresses assigned to the 417 * interface should be used." 418 * --- 20 unchanged lines hidden (view full) --- 439 else { 440 ia = in6_ifawithifp(ifp, &ip6->ip6_dst); 441 if (ia == NULL) { 442 m_freem(m); /*XXX*/ 443 return; 444 } 445 ip6->ip6_src = ia->ia_addr.sin6_addr; 446 } |
447#endif |
|
380 } else { 381 /* 382 * Source address for DAD packet must always be IPv6 383 * unspecified address. (0::0) 384 */ 385 bzero(&ip6->ip6_src, sizeof(ip6->ip6_src)); 386 } 387 nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1); --- 32 unchanged lines hidden (view full) --- 420 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen); 421 } 422 423 ip6->ip6_plen = htons((u_short)icmp6len); 424 nd_ns->nd_ns_cksum = 0; 425 nd_ns->nd_ns_cksum 426 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len); 427 | 448 } else { 449 /* 450 * Source address for DAD packet must always be IPv6 451 * unspecified address. (0::0) 452 */ 453 bzero(&ip6->ip6_src, sizeof(ip6->ip6_src)); 454 } 455 nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1); --- 32 unchanged lines hidden (view full) --- 488 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen); 489 } 490 491 ip6->ip6_plen = htons((u_short)icmp6len); 492 nd_ns->nd_ns_cksum = 0; 493 nd_ns->nd_ns_cksum 494 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len); 495 |
496#ifdef IPSEC 497 /* Don't lookup socket */ 498 ipsec_setsocket(m, NULL); 499#endif |
|
428 ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif); 429 if (outif) { 430 icmp6_ifstat_inc(outif, ifs6_out_msg); 431 icmp6_ifstat_inc(outif, ifs6_out_neighborsolicit); 432 } 433 icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++; 434} 435 436/* 437 * Neighbor advertisement input handling. 438 * 439 * Based on RFC 2461 440 * Based on RFC 2462 (duplicated address detection) | 500 ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif); 501 if (outif) { 502 icmp6_ifstat_inc(outif, ifs6_out_msg); 503 icmp6_ifstat_inc(outif, ifs6_out_neighborsolicit); 504 } 505 icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++; 506} 507 508/* 509 * Neighbor advertisement input handling. 510 * 511 * Based on RFC 2461 512 * Based on RFC 2462 (duplicated address detection) |
513 * 514 * the following items are not implemented yet: 515 * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD) 516 * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD) |
|
441 */ 442void 443nd6_na_input(m, off, icmp6len) 444 struct mbuf *m; 445 int off, icmp6len; 446{ 447 struct ifnet *ifp = m->m_pkthdr.rcvif; 448 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); | 517 */ 518void 519nd6_na_input(m, off, icmp6len) 520 struct mbuf *m; 521 int off, icmp6len; 522{ 523 struct ifnet *ifp = m->m_pkthdr.rcvif; 524 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); |
449 struct nd_neighbor_advert *nd_na 450 = (struct nd_neighbor_advert *)((caddr_t)ip6 + off); | 525 struct nd_neighbor_advert *nd_na; 526#if 0 527 struct in6_addr saddr6 = ip6->ip6_src; 528#endif |
451 struct in6_addr daddr6 = ip6->ip6_dst; | 529 struct in6_addr daddr6 = ip6->ip6_dst; |
452 struct in6_addr taddr6 = nd_na->nd_na_target; 453 int flags = nd_na->nd_na_flags_reserved; 454 int is_router = ((flags & ND_NA_FLAG_ROUTER) != 0); 455 int is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0); 456 int is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0); | 530 struct in6_addr taddr6; 531 int flags; 532 int is_router; 533 int is_solicited; 534 int is_override; |
457 char *lladdr = NULL; 458 int lladdrlen = 0; 459 struct ifaddr *ifa; 460 struct llinfo_nd6 *ln; 461 struct rtentry *rt; 462 struct sockaddr_dl *sdl; 463 union nd_opts ndopts; 464 465 if (ip6->ip6_hlim != 255) { 466 log(LOG_ERR, 467 "nd6_na_input: invalid hlim %d\n", ip6->ip6_hlim); | 535 char *lladdr = NULL; 536 int lladdrlen = 0; 537 struct ifaddr *ifa; 538 struct llinfo_nd6 *ln; 539 struct rtentry *rt; 540 struct sockaddr_dl *sdl; 541 union nd_opts ndopts; 542 543 if (ip6->ip6_hlim != 255) { 544 log(LOG_ERR, 545 "nd6_na_input: invalid hlim %d\n", ip6->ip6_hlim); |
546 goto freeit; 547 } 548 549#ifndef PULLDOWN_TEST 550 IP6_EXTHDR_CHECK(m, off, icmp6len,); 551 nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off); 552#else 553 IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len); 554 if (nd_na == NULL) { 555 icmp6stat.icp6s_tooshort++; |
|
468 return; 469 } | 556 return; 557 } |
558#endif 559 taddr6 = nd_na->nd_na_target; 560 flags = nd_na->nd_na_flags_reserved; 561 is_router = ((flags & ND_NA_FLAG_ROUTER) != 0); 562 is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0); 563 is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0); |
|
470 471 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6)) 472 taddr6.s6_addr16[1] = htons(ifp->if_index); 473 474 if (IN6_IS_ADDR_MULTICAST(&taddr6)) { 475 log(LOG_ERR, 476 "nd6_na_input: invalid target address %s\n", 477 ip6_sprintf(&taddr6)); | 564 565 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6)) 566 taddr6.s6_addr16[1] = htons(ifp->if_index); 567 568 if (IN6_IS_ADDR_MULTICAST(&taddr6)) { 569 log(LOG_ERR, 570 "nd6_na_input: invalid target address %s\n", 571 ip6_sprintf(&taddr6)); |
478 return; | 572 goto freeit; |
479 } 480 if (IN6_IS_ADDR_MULTICAST(&daddr6)) 481 if (is_solicited) { 482 log(LOG_ERR, 483 "nd6_na_input: a solicited adv is multicasted\n"); | 573 } 574 if (IN6_IS_ADDR_MULTICAST(&daddr6)) 575 if (is_solicited) { 576 log(LOG_ERR, 577 "nd6_na_input: a solicited adv is multicasted\n"); |
484 return; | 578 goto freeit; |
485 } 486 487 icmp6len -= sizeof(*nd_na); 488 nd6_option_init(nd_na + 1, icmp6len, &ndopts); 489 if (nd6_options(&ndopts) < 0) { 490 log(LOG_INFO, "nd6_na_input: invalid ND option, ignored\n"); | 579 } 580 581 icmp6len -= sizeof(*nd_na); 582 nd6_option_init(nd_na + 1, icmp6len, &ndopts); 583 if (nd6_options(&ndopts) < 0) { 584 log(LOG_INFO, "nd6_na_input: invalid ND option, ignored\n"); |
491 return; | 585 goto freeit; |
492 } 493 494 if (ndopts.nd_opts_tgt_lladdr) { 495 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 496 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 497 } 498 499 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); --- 5 unchanged lines hidden (view full) --- 505 * already using the same address as mine. This indicates DAD failure. 506 * This is defined in RFC 2462. 507 * 508 * Otherwise, process as defined in RFC 2461. 509 */ 510 if (ifa 511 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) { 512 nd6_dad_na_input(ifa); | 586 } 587 588 if (ndopts.nd_opts_tgt_lladdr) { 589 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 590 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 591 } 592 593 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); --- 5 unchanged lines hidden (view full) --- 599 * already using the same address as mine. This indicates DAD failure. 600 * This is defined in RFC 2462. 601 * 602 * Otherwise, process as defined in RFC 2461. 603 */ 604 if (ifa 605 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) { 606 nd6_dad_na_input(ifa); |
513 return; | 607 goto freeit; |
514 } 515 516 /* Just for safety, maybe unnecessery. */ 517 if (ifa) { 518 log(LOG_ERR, 519 "nd6_na_input: duplicate IP6 address %s\n", 520 ip6_sprintf(&taddr6)); | 608 } 609 610 /* Just for safety, maybe unnecessery. */ 611 if (ifa) { 612 log(LOG_ERR, 613 "nd6_na_input: duplicate IP6 address %s\n", 614 ip6_sprintf(&taddr6)); |
521 return; | 615 goto freeit; |
522 } 523 524 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 525 log(LOG_INFO, 526 "nd6_na_input: lladdrlen mismatch for %s " 527 "(if %d, NA packet %d)\n", 528 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2); 529 } 530 531 /* 532 * If no neighbor cache entry is found, NA SHOULD silently be discarded. 533 */ 534 rt = nd6_lookup(&taddr6, 0, ifp); 535 if ((rt == NULL) || 536 ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) || 537 ((sdl = SDL(rt->rt_gateway)) == NULL)) | 616 } 617 618 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 619 log(LOG_INFO, 620 "nd6_na_input: lladdrlen mismatch for %s " 621 "(if %d, NA packet %d)\n", 622 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2); 623 } 624 625 /* 626 * If no neighbor cache entry is found, NA SHOULD silently be discarded. 627 */ 628 rt = nd6_lookup(&taddr6, 0, ifp); 629 if ((rt == NULL) || 630 ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) || 631 ((sdl = SDL(rt->rt_gateway)) == NULL)) |
538 return; | 632 goto freeit; |
539 540 if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { 541 /* 542 * If the link-layer has address, and no lladdr option came, 543 * discard the packet. 544 */ 545 if (ifp->if_addrlen && !lladdr) | 633 634 if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { 635 /* 636 * If the link-layer has address, and no lladdr option came, 637 * discard the packet. 638 */ 639 if (ifp->if_addrlen && !lladdr) |
546 return; | 640 goto freeit; |
547 548 /* 549 * Record link-layer address, and update the state. 550 */ 551 sdl->sdl_alen = ifp->if_addrlen; 552 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); 553 if (is_solicited) { 554 ln->ln_state = ND6_LLINFO_REACHABLE; | 641 642 /* 643 * Record link-layer address, and update the state. 644 */ 645 sdl->sdl_alen = ifp->if_addrlen; 646 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); 647 if (is_solicited) { 648 ln->ln_state = ND6_LLINFO_REACHABLE; |
649 ln->ln_byhint = 0; |
|
555 if (ln->ln_expire) 556 ln->ln_expire = time_second + 557 nd_ifinfo[rt->rt_ifp->if_index].reachable; 558 } else 559 ln->ln_state = ND6_LLINFO_STALE; 560 ln->ln_router = is_router; 561 } else { 562 int llchange; --- 34 unchanged lines hidden (view full) --- 597 */ 598 if (!is_override && (lladdr && llchange)) { /* (1) */ 599 /* 600 * If state is REACHABLE, make it STALE. 601 * no other updates should be done. 602 */ 603 if (ln->ln_state == ND6_LLINFO_REACHABLE) 604 ln->ln_state = ND6_LLINFO_STALE; | 650 if (ln->ln_expire) 651 ln->ln_expire = time_second + 652 nd_ifinfo[rt->rt_ifp->if_index].reachable; 653 } else 654 ln->ln_state = ND6_LLINFO_STALE; 655 ln->ln_router = is_router; 656 } else { 657 int llchange; --- 34 unchanged lines hidden (view full) --- 692 */ 693 if (!is_override && (lladdr && llchange)) { /* (1) */ 694 /* 695 * If state is REACHABLE, make it STALE. 696 * no other updates should be done. 697 */ 698 if (ln->ln_state == ND6_LLINFO_REACHABLE) 699 ln->ln_state = ND6_LLINFO_STALE; |
605 return; | 700 goto freeit; |
606 } else if (is_override /* (2a) */ 607 || (!is_override && (lladdr && !llchange)) /* (2b) */ 608 || !lladdr) { /* (2c) */ 609 /* 610 * Update link-local address, if any. 611 */ 612 if (lladdr) { 613 sdl->sdl_alen = ifp->if_addrlen; 614 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); 615 } 616 617 /* 618 * If solicited, make the state REACHABLE. 619 * If not solicited and the link-layer address was 620 * changed, make it STALE. 621 */ 622 if (is_solicited) { 623 ln->ln_state = ND6_LLINFO_REACHABLE; | 701 } else if (is_override /* (2a) */ 702 || (!is_override && (lladdr && !llchange)) /* (2b) */ 703 || !lladdr) { /* (2c) */ 704 /* 705 * Update link-local address, if any. 706 */ 707 if (lladdr) { 708 sdl->sdl_alen = ifp->if_addrlen; 709 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen); 710 } 711 712 /* 713 * If solicited, make the state REACHABLE. 714 * If not solicited and the link-layer address was 715 * changed, make it STALE. 716 */ 717 if (is_solicited) { 718 ln->ln_state = ND6_LLINFO_REACHABLE; |
719 ln->ln_byhint = 0; |
|
624 if (ln->ln_expire) { 625 ln->ln_expire = time_second + 626 nd_ifinfo[ifp->if_index].reachable; 627 } 628 } else { 629 if (lladdr && llchange) 630 ln->ln_state = ND6_LLINFO_STALE; 631 } --- 26 unchanged lines hidden (view full) --- 658 } 659 splx(s); 660 } 661 ln->ln_router = is_router; 662 } 663 rt->rt_flags &= ~RTF_REJECT; 664 ln->ln_asked = 0; 665 if (ln->ln_hold) { | 720 if (ln->ln_expire) { 721 ln->ln_expire = time_second + 722 nd_ifinfo[ifp->if_index].reachable; 723 } 724 } else { 725 if (lladdr && llchange) 726 ln->ln_state = ND6_LLINFO_STALE; 727 } --- 26 unchanged lines hidden (view full) --- 754 } 755 splx(s); 756 } 757 ln->ln_router = is_router; 758 } 759 rt->rt_flags &= ~RTF_REJECT; 760 ln->ln_asked = 0; 761 if (ln->ln_hold) { |
666 nd6_output(ifp, ln->ln_hold, | 762#ifdef OLDIP6OUTPUT 763 (*ifp->if_output)(ifp, ln->ln_hold, rt_key(rt), rt); 764#else 765 /* 766 * we assume ifp is not a p2p here, so just set the 2nd 767 * argument as the 1st one. 768 */ 769 nd6_output(ifp, ifp, ln->ln_hold, |
667 (struct sockaddr_in6 *)rt_key(rt), rt); | 770 (struct sockaddr_in6 *)rt_key(rt), rt); |
771#endif |
|
668 ln->ln_hold = 0; 669 } | 772 ln->ln_hold = 0; 773 } |
774 775 freeit: 776 m_freem(m); |
|
670} 671 672/* 673 * Neighbor advertisement output handling. 674 * 675 * Based on RFC 2461 676 * | 777} 778 779/* 780 * Neighbor advertisement output handling. 781 * 782 * Based on RFC 2461 783 * |
677 * XXX NA delay for anycast address is not implemented yet 678 * (RFC 2461 7.2.7) 679 * XXX proxy advertisement? | 784 * the following items are not implemented yet: 785 * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD) 786 * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD) |
680 */ 681void | 787 */ 788void |
682nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr) | 789nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0) |
683 struct ifnet *ifp; 684 struct in6_addr *daddr6, *taddr6; 685 u_long flags; | 790 struct ifnet *ifp; 791 struct in6_addr *daddr6, *taddr6; 792 u_long flags; |
686 int tlladdr; /* 1 if include target link-layer address */ | 793 int tlladdr; /* 1 if include target link-layer address */ 794 struct sockaddr *sdl0; /* sockaddr_dl (= proxy NA) or NULL */ |
687{ 688 struct mbuf *m; 689 struct ip6_hdr *ip6; 690 struct nd_neighbor_advert *nd_na; 691 struct in6_ifaddr *ia = NULL; 692 struct ip6_moptions im6o; 693 int icmp6len; | 795{ 796 struct mbuf *m; 797 struct ip6_hdr *ip6; 798 struct nd_neighbor_advert *nd_na; 799 struct in6_ifaddr *ia = NULL; 800 struct ip6_moptions im6o; 801 int icmp6len; |
802 int maxlen; |
|
694 caddr_t mac; | 803 caddr_t mac; |
695 struct ifnet *outif; 696 697 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) | 804 struct ifnet *outif = NULL; 805 806 /* estimate the size of message */ 807 maxlen = sizeof(*ip6) + sizeof(*nd_na); 808 maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7; 809 if (max_linkhdr + maxlen >= MCLBYTES) { 810#ifdef DIAGNOSTIC 811 printf("nd6_na_output: max_linkhdr + maxlen >= MCLBYTES " 812 "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES); 813#endif |
698 return; | 814 return; |
815 } |
|
699 | 816 |
817 MGETHDR(m, M_DONTWAIT, MT_DATA); 818 if (m && max_linkhdr + maxlen >= MHLEN) { 819 MCLGET(m, M_DONTWAIT); 820 if ((m->m_flags & M_EXT) == 0) { 821 m_free(m); 822 m = NULL; 823 } 824 } 825 if (m == NULL) 826 return; 827 |
|
700 if (IN6_IS_ADDR_MULTICAST(daddr6)) { 701 m->m_flags |= M_MCAST; 702 im6o.im6o_multicast_ifp = ifp; 703 im6o.im6o_multicast_hlim = 255; 704 im6o.im6o_multicast_loop = 0; 705 } 706 707 icmp6len = sizeof(*nd_na); 708 m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len; | 828 if (IN6_IS_ADDR_MULTICAST(daddr6)) { 829 m->m_flags |= M_MCAST; 830 im6o.im6o_multicast_ifp = ifp; 831 im6o.im6o_multicast_hlim = 255; 832 im6o.im6o_multicast_loop = 0; 833 } 834 835 icmp6len = sizeof(*nd_na); 836 m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len; |
709 MH_ALIGN(m, m->m_len + 16); /* 1+1+6 is enough. but just in case */ | 837 m->m_data += max_linkhdr; /*or MH_ALIGN() equivalent?*/ |
710 711 /* fill neighbor advertisement packet */ 712 ip6 = mtod(m, struct ip6_hdr *); 713 ip6->ip6_flow = 0; | 838 839 /* fill neighbor advertisement packet */ 840 ip6 = mtod(m, struct ip6_hdr *); 841 ip6->ip6_flow = 0; |
714 ip6->ip6_vfc = IPV6_VERSION; | 842 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 843 ip6->ip6_vfc |= IPV6_VERSION; |
715 ip6->ip6_nxt = IPPROTO_ICMPV6; 716 ip6->ip6_hlim = 255; 717 if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) { 718 /* reply to DAD */ 719 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; 720 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); 721 ip6->ip6_dst.s6_addr32[1] = 0; 722 ip6->ip6_dst.s6_addr32[2] = 0; --- 19 unchanged lines hidden (view full) --- 742 nd_na->nd_na_target.s6_addr16[1] = 0; 743 744 /* 745 * "tlladdr" indicates NS's condition for adding tlladdr or not. 746 * see nd6_ns_input() for details. 747 * Basically, if NS packet is sent to unicast/anycast addr, 748 * target lladdr option SHOULD NOT be included. 749 */ | 844 ip6->ip6_nxt = IPPROTO_ICMPV6; 845 ip6->ip6_hlim = 255; 846 if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) { 847 /* reply to DAD */ 848 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; 849 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); 850 ip6->ip6_dst.s6_addr32[1] = 0; 851 ip6->ip6_dst.s6_addr32[2] = 0; --- 19 unchanged lines hidden (view full) --- 871 nd_na->nd_na_target.s6_addr16[1] = 0; 872 873 /* 874 * "tlladdr" indicates NS's condition for adding tlladdr or not. 875 * see nd6_ns_input() for details. 876 * Basically, if NS packet is sent to unicast/anycast addr, 877 * target lladdr option SHOULD NOT be included. 878 */ |
750 if (tlladdr && (mac = nd6_ifptomac(ifp))) { | 879 if (tlladdr) { 880 mac = NULL; 881 /* 882 * sdl0 != NULL indicates proxy NA. If we do proxy, use 883 * lladdr in sdl0. If we are not proxying (sending NA for 884 * my address) use lladdr configured for the interface. 885 */ 886 if (sdl0 == NULL) 887 mac = nd6_ifptomac(ifp); 888 else if (sdl0->sa_family == AF_LINK) { 889 struct sockaddr_dl *sdl; 890 sdl = (struct sockaddr_dl *)sdl0; 891 if (sdl->sdl_alen == ifp->if_addrlen) 892 mac = LLADDR(sdl); 893 } 894 } 895 if (tlladdr && mac) { |
751 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen; 752 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1); 753 754 /* roundup to 8 bytes alignment! */ 755 optlen = (optlen + 7) & ~7; 756 757 m->m_pkthdr.len += optlen; 758 m->m_len += optlen; --- 7 unchanged lines hidden (view full) --- 766 767 ip6->ip6_plen = htons((u_short)icmp6len); 768 nd_na->nd_na_flags_reserved = flags; 769 nd_na->nd_na_cksum = 0; 770 nd_na->nd_na_cksum = 771 in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len); 772 773#ifdef IPSEC | 896 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen; 897 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1); 898 899 /* roundup to 8 bytes alignment! */ 900 optlen = (optlen + 7) & ~7; 901 902 m->m_pkthdr.len += optlen; 903 m->m_len += optlen; --- 7 unchanged lines hidden (view full) --- 911 912 ip6->ip6_plen = htons((u_short)icmp6len); 913 nd_na->nd_na_flags_reserved = flags; 914 nd_na->nd_na_cksum = 0; 915 nd_na->nd_na_cksum = 916 in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len); 917 918#ifdef IPSEC |
774 m->m_pkthdr.rcvif = NULL; 775#endif /*IPSEC*/ | 919 /* Don't lookup socket */ 920 ipsec_setsocket(m, NULL); 921#endif |
776 ip6_output(m, NULL, NULL, 0, &im6o, &outif); 777 if (outif) { 778 icmp6_ifstat_inc(outif, ifs6_out_msg); 779 icmp6_ifstat_inc(outif, ifs6_out_neighboradvert); 780 } 781 icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++; 782} 783 --- 12 unchanged lines hidden (view full) --- 796 } 797} 798 799TAILQ_HEAD(dadq_head, dadq); 800struct dadq { 801 TAILQ_ENTRY(dadq) dad_list; 802 struct ifaddr *dad_ifa; 803 int dad_count; /* max NS to send */ | 922 ip6_output(m, NULL, NULL, 0, &im6o, &outif); 923 if (outif) { 924 icmp6_ifstat_inc(outif, ifs6_out_msg); 925 icmp6_ifstat_inc(outif, ifs6_out_neighboradvert); 926 } 927 icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++; 928} 929 --- 12 unchanged lines hidden (view full) --- 942 } 943} 944 945TAILQ_HEAD(dadq_head, dadq); 946struct dadq { 947 TAILQ_ENTRY(dadq) dad_list; 948 struct ifaddr *dad_ifa; 949 int dad_count; /* max NS to send */ |
950 int dad_ns_tcount; /* # of trials to send NS */ |
|
804 int dad_ns_ocount; /* NS sent so far */ 805 int dad_ns_icount; 806 int dad_na_icount; 807 struct callout_handle dad_timer; 808}; 809 810static struct dadq_head dadq; 811 812static struct dadq * 813nd6_dad_find(ifa) 814 struct ifaddr *ifa; 815{ 816 struct dadq *dp; 817 | 951 int dad_ns_ocount; /* NS sent so far */ 952 int dad_ns_icount; 953 int dad_na_icount; 954 struct callout_handle dad_timer; 955}; 956 957static struct dadq_head dadq; 958 959static struct dadq * 960nd6_dad_find(ifa) 961 struct ifaddr *ifa; 962{ 963 struct dadq *dp; 964 |
818 TAILQ_FOREACH(dp, &dadq, dad_list) { | 965 for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) { |
819 if (dp->dad_ifa == ifa) 820 return dp; 821 } 822 return NULL; 823} 824 825/* 826 * Start Duplicated Address Detection (DAD) for specified interface address. --- 14 unchanged lines hidden (view full) --- 841 842 /* 843 * If we don't need DAD, don't do it. 844 * There are several cases: 845 * - DAD is disabled (ip6_dad_count == 0) 846 * - the interface address is anycast 847 */ 848 if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) { | 966 if (dp->dad_ifa == ifa) 967 return dp; 968 } 969 return NULL; 970} 971 972/* 973 * Start Duplicated Address Detection (DAD) for specified interface address. --- 14 unchanged lines hidden (view full) --- 988 989 /* 990 * If we don't need DAD, don't do it. 991 * There are several cases: 992 * - DAD is disabled (ip6_dad_count == 0) 993 * - the interface address is anycast 994 */ 995 if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) { |
849 printf("nd6_dad_start: called with non-tentative address " | 996 log(LOG_DEBUG, 997 "nd6_dad_start: called with non-tentative address " |
850 "%s(%s)\n", 851 ip6_sprintf(&ia->ia_addr.sin6_addr), 852 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 853 return; 854 } 855 if (ia->ia6_flags & IN6_IFF_ANYCAST) { 856 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 857 return; --- 8 unchanged lines hidden (view full) --- 866 return; 867 if (nd6_dad_find(ifa) != NULL) { 868 /* DAD already in progress */ 869 return; 870 } 871 872 dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT); 873 if (dp == NULL) { | 998 "%s(%s)\n", 999 ip6_sprintf(&ia->ia_addr.sin6_addr), 1000 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1001 return; 1002 } 1003 if (ia->ia6_flags & IN6_IFF_ANYCAST) { 1004 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 1005 return; --- 8 unchanged lines hidden (view full) --- 1014 return; 1015 if (nd6_dad_find(ifa) != NULL) { 1016 /* DAD already in progress */ 1017 return; 1018 } 1019 1020 dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT); 1021 if (dp == NULL) { |
874 printf("nd6_dad_start: memory allocation failed for " | 1022 log(LOG_ERR, "nd6_dad_start: memory allocation failed for " |
875 "%s(%s)\n", 876 ip6_sprintf(&ia->ia_addr.sin6_addr), 877 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 878 return; 879 } 880 bzero(dp, sizeof(*dp)); 881 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list); 882 883#ifdef ND6_DEBUG | 1023 "%s(%s)\n", 1024 ip6_sprintf(&ia->ia_addr.sin6_addr), 1025 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1026 return; 1027 } 1028 bzero(dp, sizeof(*dp)); 1029 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list); 1030 1031#ifdef ND6_DEBUG |
884 printf("%s: starting DAD for %s\n", if_name(ifa->ifa_ifp), | 1032 log(LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp), |
885 ip6_sprintf(&ia->ia_addr.sin6_addr)); 886#endif 887 888 /* 889 * Send NS packet for DAD, ip6_dad_count times. 890 * Note that we must delay the first transmission, if this is the 891 * first packet to be sent from the interface after interface 892 * (re)initialization. 893 */ 894 dp->dad_ifa = ifa; 895 ifa->ifa_refcnt++; /*just for safety*/ 896 dp->dad_count = ip6_dad_count; 897 dp->dad_ns_icount = dp->dad_na_icount = 0; | 1033 ip6_sprintf(&ia->ia_addr.sin6_addr)); 1034#endif 1035 1036 /* 1037 * Send NS packet for DAD, ip6_dad_count times. 1038 * Note that we must delay the first transmission, if this is the 1039 * first packet to be sent from the interface after interface 1040 * (re)initialization. 1041 */ 1042 dp->dad_ifa = ifa; 1043 ifa->ifa_refcnt++; /*just for safety*/ 1044 dp->dad_count = ip6_dad_count; 1045 dp->dad_ns_icount = dp->dad_na_icount = 0; |
898 dp->dad_ns_ocount = 0; | 1046 dp->dad_ns_ocount = dp->dad_ns_tcount = 0; |
899 if (!tick) { | 1047 if (!tick) { |
900 dp->dad_ns_ocount++; 901 nd6_ns_output(ifa->ifa_ifp, NULL, &ia->ia_addr.sin6_addr, 902 NULL, 1); | 1048 nd6_dad_ns_output(dp, ifa); |
903 dp->dad_timer = 904 timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, 905 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000); 906 } else { 907 int ntick; 908 909 if (*tick == 0) 910 ntick = random() % (MAX_RTR_SOLICITATION_DELAY * hz); --- 13 unchanged lines hidden (view full) --- 924 int s; 925 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 926 struct dadq *dp; 927 928 s = splnet(); /*XXX*/ 929 930 /* Sanity check */ 931 if (ia == NULL) { | 1049 dp->dad_timer = 1050 timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, 1051 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000); 1052 } else { 1053 int ntick; 1054 1055 if (*tick == 0) 1056 ntick = random() % (MAX_RTR_SOLICITATION_DELAY * hz); --- 13 unchanged lines hidden (view full) --- 1070 int s; 1071 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 1072 struct dadq *dp; 1073 1074 s = splnet(); /*XXX*/ 1075 1076 /* Sanity check */ 1077 if (ia == NULL) { |
932 printf("nd6_dad_timer: called with null parameter\n"); | 1078 log(LOG_ERR, "nd6_dad_timer: called with null parameter\n"); |
933 goto done; 934 } 935 dp = nd6_dad_find(ifa); 936 if (dp == NULL) { | 1079 goto done; 1080 } 1081 dp = nd6_dad_find(ifa); 1082 if (dp == NULL) { |
937 printf("nd6_dad_timer: DAD structure not found\n"); | 1083 log(LOG_ERR, "nd6_dad_timer: DAD structure not found\n"); |
938 goto done; 939 } 940 if (ia->ia6_flags & IN6_IFF_DUPLICATED) { | 1084 goto done; 1085 } 1086 if (ia->ia6_flags & IN6_IFF_DUPLICATED) { |
941 printf("nd6_dad_timer: called with duplicated address " | 1087 log(LOG_ERR, "nd6_dad_timer: called with duplicated address " |
942 "%s(%s)\n", 943 ip6_sprintf(&ia->ia_addr.sin6_addr), 944 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 945 goto done; 946 } 947 if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) { | 1088 "%s(%s)\n", 1089 ip6_sprintf(&ia->ia_addr.sin6_addr), 1090 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1091 goto done; 1092 } 1093 if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) { |
948 printf("nd6_dad_timer: called with non-tentative address " | 1094 log(LOG_ERR, "nd6_dad_timer: called with non-tentative address " |
949 "%s(%s)\n", 950 ip6_sprintf(&ia->ia_addr.sin6_addr), 951 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 952 goto done; 953 } 954 | 1095 "%s(%s)\n", 1096 ip6_sprintf(&ia->ia_addr.sin6_addr), 1097 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1098 goto done; 1099 } 1100 |
1101 /* timeouted with IFF_{RUNNING,UP} check */ 1102 if (dp->dad_ns_tcount > dad_maxtry) { 1103 log(LOG_ERR, "%s: could not run DAD, driver problem?\n", 1104 if_name(ifa->ifa_ifp)); 1105 1106 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list); 1107 free(dp, M_IP6NDP); 1108 dp = NULL; 1109 IFAFREE(ifa); 1110 goto done; 1111 } 1112 |
|
955 /* Need more checks? */ 956 if (dp->dad_ns_ocount < dp->dad_count) { 957 /* 958 * We have more NS to go. Send NS packet for DAD. 959 */ | 1113 /* Need more checks? */ 1114 if (dp->dad_ns_ocount < dp->dad_count) { 1115 /* 1116 * We have more NS to go. Send NS packet for DAD. 1117 */ |
960 dp->dad_ns_ocount++; 961 nd6_ns_output(ifa->ifa_ifp, NULL, &ia->ia_addr.sin6_addr, 962 NULL, 1); | 1118 nd6_dad_ns_output(dp, ifa); |
963 dp->dad_timer = 964 timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, 965 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000); 966 } else { 967 /* 968 * We have transmitted sufficient number of DAD packets. 969 * See what we've got. 970 */ --- 5 unchanged lines hidden (view full) --- 976 /* 977 * the check is in nd6_dad_na_input(), 978 * but just in case 979 */ 980 duplicate++; 981 } 982 983 if (dp->dad_ns_icount) { | 1119 dp->dad_timer = 1120 timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, 1121 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000); 1122 } else { 1123 /* 1124 * We have transmitted sufficient number of DAD packets. 1125 * See what we've got. 1126 */ --- 5 unchanged lines hidden (view full) --- 1132 /* 1133 * the check is in nd6_dad_na_input(), 1134 * but just in case 1135 */ 1136 duplicate++; 1137 } 1138 1139 if (dp->dad_ns_icount) { |
1140#if 0 /*heuristics*/ 1141 /* 1142 * if 1143 * - we have sent many(?) DAD NS, and 1144 * - the number of NS we sent equals to the 1145 * number of NS we've got, and 1146 * - we've got no NA 1147 * we may have a faulty network card/driver which 1148 * loops back multicasts to myself. 1149 */ 1150 if (3 < dp->dad_count 1151 && dp->dad_ns_icount == dp->dad_count 1152 && dp->dad_na_icount == 0) { 1153 log(LOG_INFO, "DAD questionable for %s(%s): " 1154 "network card loops back multicast?\n", 1155 ip6_sprintf(&ia->ia_addr.sin6_addr), 1156 if_name(ifa->ifa_ifp)); 1157 /* XXX consider it a duplicate or not? */ 1158 /* duplicate++; */ 1159 } else { 1160 /* We've seen NS, means DAD has failed. */ 1161 duplicate++; 1162 } 1163#else |
|
984 /* We've seen NS, means DAD has failed. */ 985 duplicate++; | 1164 /* We've seen NS, means DAD has failed. */ 1165 duplicate++; |
1166#endif |
|
986 } 987 988 if (duplicate) { 989 /* (*dp) will be freed in nd6_dad_duplicated() */ 990 dp = NULL; 991 nd6_dad_duplicated(ifa); 992 } else { 993 /* 994 * We are done with DAD. No NA came, no NS came. 995 * duplicated address found. 996 */ 997 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 998 999#ifdef ND6_DEBUG | 1167 } 1168 1169 if (duplicate) { 1170 /* (*dp) will be freed in nd6_dad_duplicated() */ 1171 dp = NULL; 1172 nd6_dad_duplicated(ifa); 1173 } else { 1174 /* 1175 * We are done with DAD. No NA came, no NS came. 1176 * duplicated address found. 1177 */ 1178 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 1179 1180#ifdef ND6_DEBUG |
1000 printf("%s: DAD complete for %s - no duplicates " 1001 "found\n", if_name(ifa->ifa_ifp), | 1181 log(LOG_INFO, 1182 "%s: DAD complete for %s - no duplicates found\n", 1183 if_name(ifa->ifa_ifp), |
1002 ip6_sprintf(&ia->ia_addr.sin6_addr)); 1003#endif 1004 1005 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list); 1006 free(dp, M_IP6NDP); 1007 dp = NULL; | 1184 ip6_sprintf(&ia->ia_addr.sin6_addr)); 1185#endif 1186 1187 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list); 1188 free(dp, M_IP6NDP); 1189 dp = NULL; |
1008 ifa->ifa_refcnt--; | 1190 IFAFREE(ifa); |
1009 } 1010 } 1011 1012done: 1013 splx(s); 1014} 1015 1016void 1017nd6_dad_duplicated(ifa) 1018 struct ifaddr *ifa; 1019{ 1020 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 1021 struct dadq *dp; 1022 1023 dp = nd6_dad_find(ifa); 1024 if (dp == NULL) { | 1191 } 1192 } 1193 1194done: 1195 splx(s); 1196} 1197 1198void 1199nd6_dad_duplicated(ifa) 1200 struct ifaddr *ifa; 1201{ 1202 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 1203 struct dadq *dp; 1204 1205 dp = nd6_dad_find(ifa); 1206 if (dp == NULL) { |
1025 printf("nd6_dad_duplicated: DAD structure not found\n"); | 1207 log(LOG_ERR, "nd6_dad_duplicated: DAD structure not found\n"); |
1026 return; 1027 } 1028 1029 log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: %d NS, " 1030 "%d NA\n", if_name(ifa->ifa_ifp), 1031 ip6_sprintf(&ia->ia_addr.sin6_addr), 1032 dp->dad_ns_icount, dp->dad_na_icount); 1033 1034 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 1035 ia->ia6_flags |= IN6_IFF_DUPLICATED; 1036 1037 /* We are done with DAD, with duplicated address found. (failure) */ 1038 untimeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa | 1208 return; 1209 } 1210 1211 log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: %d NS, " 1212 "%d NA\n", if_name(ifa->ifa_ifp), 1213 ip6_sprintf(&ia->ia_addr.sin6_addr), 1214 dp->dad_ns_icount, dp->dad_na_icount); 1215 1216 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 1217 ia->ia6_flags |= IN6_IFF_DUPLICATED; 1218 1219 /* We are done with DAD, with duplicated address found. (failure) */ 1220 untimeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa |
1039 , dp->dad_timer); | 1221 , dp->dad_timer 1222 ); |
1040 | 1223 |
1041 printf("%s: DAD complete for %s - duplicate found\n", | 1224 log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n", |
1042 if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr)); | 1225 if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr)); |
1043 printf("%s: manual intervention required\n", if_name(ifa->ifa_ifp)); | 1226 log(LOG_ERR, "%s: manual intervention required\n", 1227 if_name(ifa->ifa_ifp)); |
1044 1045 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list); 1046 free(dp, M_IP6NDP); 1047 dp = NULL; | 1228 1229 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list); 1230 free(dp, M_IP6NDP); 1231 dp = NULL; |
1048 ifa->ifa_refcnt--; | 1232 IFAFREE(ifa); |
1049} 1050 | 1233} 1234 |
1051void | 1235static void 1236nd6_dad_ns_output(dp, ifa) 1237 struct dadq *dp; 1238 struct ifaddr *ifa; 1239{ 1240 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 1241 struct ifnet *ifp = ifa->ifa_ifp; 1242 1243 dp->dad_ns_tcount++; 1244 if ((ifp->if_flags & IFF_UP) == 0) { 1245#if 0 1246 printf("%s: interface down?\n", if_name(ifp)); 1247#endif 1248 return; 1249 } 1250 if ((ifp->if_flags & IFF_RUNNING) == 0) { 1251#if 0 1252 printf("%s: interface not running?\n", if_name(ifp)); 1253#endif 1254 return; 1255 } 1256 1257 dp->dad_ns_ocount++; 1258 nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL, 1); 1259} 1260 1261static void |
1052nd6_dad_ns_input(ifa) 1053 struct ifaddr *ifa; 1054{ 1055 struct in6_ifaddr *ia; 1056 struct ifnet *ifp; 1057 struct in6_addr *taddr6; 1058 struct dadq *dp; 1059 int duplicate; --- 38 unchanged lines hidden (view full) --- 1098 * not sure if I got a duplicate. 1099 * increment ns count and see what happens. 1100 */ 1101 if (dp) 1102 dp->dad_ns_icount++; 1103 } 1104} 1105 | 1262nd6_dad_ns_input(ifa) 1263 struct ifaddr *ifa; 1264{ 1265 struct in6_ifaddr *ia; 1266 struct ifnet *ifp; 1267 struct in6_addr *taddr6; 1268 struct dadq *dp; 1269 int duplicate; --- 38 unchanged lines hidden (view full) --- 1308 * not sure if I got a duplicate. 1309 * increment ns count and see what happens. 1310 */ 1311 if (dp) 1312 dp->dad_ns_icount++; 1313 } 1314} 1315 |
1106void | 1316static void |
1107nd6_dad_na_input(ifa) 1108 struct ifaddr *ifa; 1109{ 1110 struct dadq *dp; 1111 1112 if (!ifa) 1113 panic("ifa == NULL in nd6_dad_na_input"); 1114 1115 dp = nd6_dad_find(ifa); 1116 if (dp) 1117 dp->dad_na_icount++; 1118 1119 /* remove the address. */ 1120 nd6_dad_duplicated(ifa); 1121} | 1317nd6_dad_na_input(ifa) 1318 struct ifaddr *ifa; 1319{ 1320 struct dadq *dp; 1321 1322 if (!ifa) 1323 panic("ifa == NULL in nd6_dad_na_input"); 1324 1325 dp = nd6_dad_find(ifa); 1326 if (dp) 1327 dp->dad_na_icount++; 1328 1329 /* remove the address. */ 1330 nd6_dad_duplicated(ifa); 1331} |