Deleted Added
full compact
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}