xref: /freebsd/sys/netinet6/in6.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * Copyright (c) 1982, 1986, 1991, 1993
34  *	The Regents of the University of California.  All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  * 3. All advertising materials mentioning features or use of this software
45  *    must display the following acknowledgement:
46  *	This product includes software developed by the University of
47  *	California, Berkeley and its contributors.
48  * 4. Neither the name of the University nor the names of its contributors
49  *    may be used to endorse or promote products derived from this software
50  *    without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  *
64  *	@(#)in.c	8.2 (Berkeley) 11/15/93
65  */
66 
67 #include <sys/param.h>
68 #include <sys/errno.h>
69 #include <sys/malloc.h>
70 #include <sys/socket.h>
71 #include <sys/socketvar.h>
72 #include <sys/sockio.h>
73 #include <sys/systm.h>
74 #include <sys/proc.h>
75 #include <sys/time.h>
76 #include <sys/kernel.h>
77 #include <sys/syslog.h>
78 
79 #include <net/if.h>
80 #include <net/if_types.h>
81 #include <net/route.h>
82 #include "gif.h"
83 
84 #include <net/if_dl.h>
85 
86 #include <netinet/in.h>
87 #include <netinet/in_var.h>
88 #include <netinet/if_ether.h>
89 
90 #include <netinet6/nd6.h>
91 #include <netinet6/ip6.h>
92 #include <netinet6/ip6_var.h>
93 #include <netinet6/mld6_var.h>
94 #include <netinet6/in6_ifattach.h>
95 #if NGIF > 0
96 #include <net/if_gif.h>
97 #endif
98 
99 #include <net/net_osdep.h>
100 
101 MALLOC_DEFINE(M_IPMADDR, "in6_multi", "internet multicast address");
102 
103 /*
104  * Definitions of some costant IP6 addresses.
105  */
106 const struct	in6_addr in6addr_any = IN6ADDR_ANY_INIT;
107 const struct	in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
108 const struct	in6_addr in6addr_nodelocal_allnodes =
109 	IN6ADDR_NODELOCAL_ALLNODES_INIT;
110 const struct	in6_addr in6addr_linklocal_allnodes =
111 	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
112 const struct	in6_addr in6addr_linklocal_allrouters =
113 	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
114 
115 const struct	in6_addr in6mask0 = IN6MASK0;
116 const struct	in6_addr in6mask32 = IN6MASK32;
117 const struct	in6_addr in6mask64 = IN6MASK64;
118 const struct	in6_addr in6mask96 = IN6MASK96;
119 const struct	in6_addr in6mask128 = IN6MASK128;
120 
121 static int	in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
122 	struct ifnet *, struct proc *));
123 struct	in6_multihead in6_multihead;	/* XXX BSS initialization */
124 
125 /*
126  * Determine whether an IP6 address is in a reserved set of addresses
127  * that may not be forwarded, or whether datagrams to that destination
128  * may be forwarded.
129  */
130 int
131 in6_canforward(src, dst)
132 	struct	in6_addr *src, *dst;
133 {
134 	if (IN6_IS_ADDR_LINKLOCAL(src) ||
135 	   IN6_IS_ADDR_LINKLOCAL(dst) ||
136 	   IN6_IS_ADDR_MULTICAST(dst))
137 		return(0);
138 	return(1);
139 }
140 
141 /*
142  * Check if the loopback entry will be automatically generated.
143  *   if 0 returned, will not be automatically generated.
144  *   if 1 returned, will be automatically generated.
145  */
146 static int
147 in6_is_ifloop_auto(struct ifaddr *ifa)
148 {
149 #define SIN6(s) ((struct sockaddr_in6 *)s)
150 	/*
151 	 * If RTF_CLONING is unset, or (IFF_LOOPBACK | IFF_POINTOPOINT),
152 	 * or netmask is all0 or all1, then cloning will not happen,
153 	 * then we can't rely on its loopback entry generation.
154 	 */
155 	if ((ifa->ifa_flags & RTF_CLONING) == 0 ||
156 	    (ifa->ifa_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) ||
157 	    (SIN6(ifa->ifa_netmask)->sin6_len == sizeof(struct sockaddr_in6)
158 	     &&
159 	     IN6_ARE_ADDR_EQUAL(&SIN6(ifa->ifa_netmask)->sin6_addr,
160 				&in6mask128)) ||
161 	    ((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_len == 0)
162 		return 0;
163 	else
164 		return 1;
165 #undef SIN6
166 }
167 
168 /*
169  * Subroutine for in6_ifaddloop() and in6_ifremloop().
170  * This routine does actual work.
171  */
172 static void
173 in6_ifloop_request(int cmd, struct ifaddr *ifa)
174 {
175 	struct sockaddr_in6 lo_sa;
176 	struct sockaddr_in6 all1_sa;
177 	struct rtentry *nrt = NULL;
178 
179 	bzero(&lo_sa, sizeof(lo_sa));
180 	bzero(&all1_sa, sizeof(all1_sa));
181 	lo_sa.sin6_family = AF_INET6;
182 	lo_sa.sin6_len = sizeof(struct sockaddr_in6);
183 	all1_sa = lo_sa;
184 	lo_sa.sin6_addr = in6addr_loopback;
185 	all1_sa.sin6_addr = in6mask128;
186 
187 	/* So we add or remove static loopback entry, here. */
188 	rtrequest(cmd, ifa->ifa_addr,
189 		  (struct sockaddr *)&lo_sa,
190 		  (struct sockaddr *)&all1_sa,
191 		  RTF_UP|RTF_HOST, &nrt);
192 
193 	/*
194 	 * Make sure rt_ifa be equal to IFA, the second argument of the
195 	 * function.
196 	 * We need this because when we refer rt_ifa->ia6_flags in ip6_input,
197 	 * we assume that the rt_ifa points to the address instead of the
198 	 * loopback address.
199 	 */
200 	if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
201 		nrt->rt_ifa->ifa_refcnt--;
202 		ifa->ifa_refcnt++;
203 		nrt->rt_ifa = ifa;
204 	}
205 	if (nrt)
206 		nrt->rt_refcnt--;
207 }
208 
209 /*
210  * Add ownaddr as loopback rtentry, if necessary(ex. on p2p link).
211  * Because, KAME needs loopback rtentry for ownaddr check in
212  * ip6_input().
213  */
214 static void
215 in6_ifaddloop(struct ifaddr *ifa)
216 {
217 	if (!in6_is_ifloop_auto(ifa)) {
218 		struct rtentry *rt;
219 
220 		/* If there is no loopback entry, allocate one. */
221 		rt = rtalloc1(ifa->ifa_addr, 0, 0);
222 		if (rt == 0 || (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
223 			in6_ifloop_request(RTM_ADD, ifa);
224 		if (rt)
225 			rt->rt_refcnt--;
226 	}
227 }
228 
229 /*
230  * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
231  * if it exists.
232  */
233 static void
234 in6_ifremloop(struct ifaddr *ifa)
235 {
236 	if (!in6_is_ifloop_auto(ifa)) {
237 		struct in6_ifaddr *ia;
238 		int ia_count = 0;
239 
240 		/* If only one ifa for the loopback entry, delete it. */
241 		for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
242 			if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa),
243 					       &ia->ia_addr.sin6_addr)) {
244 				ia_count++;
245 				if (ia_count > 1)
246 					break;
247 			}
248 		}
249 		if (ia_count == 1)
250 			in6_ifloop_request(RTM_DELETE, ifa);
251 	}
252 }
253 
254 /*
255  * Subroutine for in6_ifaddproxy() and in6_ifremproxy().
256  * This routine does actual work.
257  * call in6_addmulti() when cmd == 1.
258  * call in6_delmulti() when cmd == 2.
259  */
260 static int
261 in6_ifproxy_request(int cmd, struct in6_ifaddr *ia)
262 {
263 	int error = 0;
264 
265 	/*
266 	 * If we have an IPv6 dstaddr on adding p2p interface,
267 	 * join dstaddr's solicited multicast on necessary interface.
268 	 */
269 	if ((ia->ia_ifp->if_flags & IFF_POINTOPOINT) &&
270 	    ia->ia_dstaddr.sin6_family == AF_INET6 &&
271 	    !IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
272 		struct in6_ifaddr *ia_lan;
273 
274 		/*
275 		 * TODO: Join only on some specified interfaces by some
276 		 * configuration.
277 		 * Unsolicited Neighbor Advertisements will be also necessary.
278 		 *
279 		 * Now, join on interfaces which meets following.
280 		 *   -IFF_BROADCAST and IFF_MULTICAST
281 		 *    (NBMA is out of scope)
282 		 *   -the prefix value is same as p2p dstaddr
283 		 */
284 		for (ia_lan = in6_ifaddr; ia_lan; ia_lan = ia_lan->ia_next) {
285 			struct in6_addr llsol;
286 
287 			if ((ia_lan->ia_ifp->if_flags &
288 			     (IFF_BROADCAST|IFF_MULTICAST)) !=
289 			    (IFF_BROADCAST|IFF_MULTICAST))
290 				continue;
291 			if (!IN6_ARE_MASKED_ADDR_EQUAL(IA6_IN6(ia),
292 						       IA6_IN6(ia_lan),
293 						       IA6_MASKIN6(ia_lan)))
294 				continue;
295 			if (ia_lan->ia_ifp == ia->ia_ifp)
296 				continue;
297 
298 			/* init llsol */
299 			bzero(&llsol, sizeof(struct in6_addr));
300 			llsol.s6_addr16[0] = htons(0xff02);
301 			llsol.s6_addr16[1] = htons(ia_lan->ia_ifp->if_index);
302 			llsol.s6_addr32[1] = 0;
303 			llsol.s6_addr32[2] = htonl(1);
304 			llsol.s6_addr32[3] =
305 				ia->ia_dstaddr.sin6_addr.s6_addr32[3];
306 			llsol.s6_addr8[12] = 0xff;
307 
308 			if (cmd == 1)
309 				(void)in6_addmulti(&llsol,
310 						   ia_lan->ia_ifp,
311 						   &error);
312 			else if (cmd == 2) {
313 				struct in6_multi *in6m;
314 
315 				IN6_LOOKUP_MULTI(llsol,
316 						 ia_lan->ia_ifp,
317 						 in6m);
318 				if (in6m)
319 					in6_delmulti(in6m);
320 			}
321 		}
322 	}
323 	return error;
324 }
325 
326 static int
327 in6_ifaddproxy(struct in6_ifaddr *ia)
328 {
329 	return(in6_ifproxy_request(1, ia));
330 }
331 
332 static void
333 in6_ifremproxy(struct in6_ifaddr *ia)
334 {
335 	in6_ifproxy_request(2, ia);
336 }
337 
338 int
339 in6_ifindex2scopeid(idx)
340 	int idx;
341 {
342 	struct ifnet *ifp;
343 	struct ifaddr *ifa;
344 	struct sockaddr_in6 *sin6;
345 
346 	if (idx < 0 || if_index < idx)
347 		return -1;
348 	ifp = ifindex2ifnet[idx];
349 
350 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
351 	{
352 		if (ifa->ifa_addr->sa_family != AF_INET6)
353 			continue;
354 		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
355 		if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
356 			return sin6->sin6_scope_id & 0xffff;
357 	}
358 
359 	return -1;
360 }
361 
362 int
363 in6_mask2len(mask)
364 	struct in6_addr *mask;
365 {
366 	int x, y;
367 
368 	for (x = 0; x < sizeof(*mask); x++) {
369 		if (mask->s6_addr8[x] != 0xff)
370 			break;
371 	}
372 	y = 0;
373 	if (x < sizeof(*mask)) {
374 		for (y = 0; y < 8; y++) {
375 			if ((mask->s6_addr8[x] & (0x80 >> y)) == 0)
376 				break;
377 		}
378 	}
379 	return x * 8 + y;
380 }
381 
382 void
383 in6_len2mask(mask, len)
384 	struct in6_addr *mask;
385 	int len;
386 {
387 	int i;
388 
389 	bzero(mask, sizeof(*mask));
390 	for (i = 0; i < len / 8; i++)
391 		mask->s6_addr8[i] = 0xff;
392 	if (len % 8)
393 		mask->s6_addr8[i] = (0xff00 >> (len % 8)) & 0xff;
394 }
395 
396 int	in6_interfaces;		/* number of external internet interfaces */
397 
398 #define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
399 #define ia62ifa(ia6)	((struct ifaddr *)(ia6))
400 
401 int
402 in6_control(so, cmd, data, ifp, p)
403 	struct	socket *so;
404 	u_long cmd;
405 	caddr_t	data;
406 	struct ifnet *ifp;
407 	struct proc *p;
408 {
409 	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
410 	struct	in6_ifaddr *ia, *oia;
411 	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
412 	struct	sockaddr_in6 oldaddr, net;
413 	int	error = 0, hostIsNew, prefixIsNew;
414 	int privileged;
415 
416 	privileged = 0;
417 	if (p == NULL || !suser(p))
418 		privileged++;
419 
420 	/*
421 	 * xxx should prevent processes for link-local addresses?
422 	 */
423 #if NGIF > 0
424 	if (ifp && ifp->if_type == IFT_GIF) {
425 		switch (cmd) {
426 		case SIOCSIFPHYADDR_IN6:
427 			if (!privileged)
428 				return(EPERM);
429 			/*fall through*/
430 		case SIOCGIFPSRCADDR_IN6:
431 		case SIOCGIFPDSTADDR_IN6:
432 			return gif_ioctl(ifp, cmd, data);
433 		}
434 	}
435 #endif
436 
437 	if (ifp == 0)
438 		return(EOPNOTSUPP);
439 
440 	switch (cmd) {
441 	case SIOCSNDFLUSH_IN6:
442 	case SIOCSPFXFLUSH_IN6:
443 	case SIOCSRTRFLUSH_IN6:
444 		if (!privileged)
445 			return(EPERM);
446 		/*fall through*/
447 	case SIOCGIFINFO_IN6:
448 	case SIOCGDRLST_IN6:
449 	case SIOCGPRLST_IN6:
450 	case SIOCGNBRINFO_IN6:
451 		return(nd6_ioctl(cmd, data, ifp));
452 	}
453 
454 	switch (cmd) {
455 	case SIOCSIFPREFIX_IN6:
456 	case SIOCDIFPREFIX_IN6:
457 	case SIOCAIFPREFIX_IN6:
458 	case SIOCCIFPREFIX_IN6:
459 	case SIOCSGIFPREFIX_IN6:
460 		if (!privileged)
461 			return(EPERM);
462 		/*fall through*/
463 	case SIOCGIFPREFIX_IN6:
464 		if (ip6_forwarding == 0)
465 			return(EPERM);
466 		return(in6_prefix_ioctl(so, cmd, data, ifp));
467 	}
468 
469 	switch (cmd) {
470 	case SIOCALIFADDR:
471 	case SIOCDLIFADDR:
472 		if (!privileged)
473 			return(EPERM);
474 		/*fall through*/
475 	case SIOCGLIFADDR:
476 		return in6_lifaddr_ioctl(so, cmd, data, ifp, p);
477 	}
478 
479 	/*
480 	 * Find address for this interface, if it exists.
481 	 */
482 	{
483 
484 		struct sockaddr_in6 *sa6 =
485 			(struct sockaddr_in6 *)&ifra->ifra_addr;
486 
487 		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
488 			if (sa6->sin6_addr.s6_addr16[1] == 0) {
489 				/* interface ID is not embedded by the user */
490 				sa6->sin6_addr.s6_addr16[1] =
491 					htons(ifp->if_index);
492 			} else
493 				if (sa6->sin6_addr.s6_addr16[1] !=
494 				    htons(ifp->if_index))
495 					return(EINVAL);	/* ifid is contradict */
496 			if (sa6->sin6_scope_id) {
497 				if (sa6->sin6_scope_id !=
498 				    (u_int32_t)ifp->if_index)
499 					return(EINVAL);
500 				sa6->sin6_scope_id = 0; /* XXX: good way? */
501 			}
502 		}
503 	}
504  	ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
505 
506 	switch (cmd) {
507 
508 	case SIOCDIFADDR_IN6:
509 		if (ia == 0)
510 			return(EADDRNOTAVAIL);
511 		/* FALLTHROUGH */
512 	case SIOCAIFADDR_IN6:
513 	case SIOCSIFADDR_IN6:
514 	case SIOCSIFNETMASK_IN6:
515 	case SIOCSIFDSTADDR_IN6:
516 		if (!privileged)
517 			return(EPERM);
518 		if (ia == 0) {
519 			ia = (struct in6_ifaddr *)
520 				malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
521 			if (ia == NULL)
522 				return (ENOBUFS);
523 			bzero((caddr_t)ia, sizeof(*ia));
524 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
525 			ia->ia_ifa.ifa_dstaddr
526 				= (struct sockaddr *)&ia->ia_dstaddr;
527 			ia->ia_ifa.ifa_netmask
528 				= (struct sockaddr *)&ia->ia_prefixmask;
529 
530 			ia->ia_ifp = ifp;
531 			if ((oia = in6_ifaddr) != NULL) {
532 				for ( ; oia->ia_next; oia = oia->ia_next)
533 					continue;
534 				oia->ia_next = ia;
535 			} else
536 				in6_ifaddr = ia;
537 			TAILQ_INSERT_TAIL(&ifp->if_addrlist,
538 				(struct ifaddr *)ia, ifa_list);
539 			if ((ifp->if_flags & IFF_LOOPBACK) == 0)
540 				in6_interfaces++;	/*XXX*/
541 		}
542 
543 		if (cmd == SIOCAIFADDR_IN6) {
544 			/* sanity for overflow - beware unsigned */
545 			struct in6_addrlifetime *lt;
546 			lt = &ifra->ifra_lifetime;
547 			if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
548 			 && lt->ia6t_vltime + time_second < time_second) {
549 				return EINVAL;
550 			}
551 			if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
552 			 && lt->ia6t_pltime + time_second < time_second) {
553 				return EINVAL;
554 			}
555 		}
556 		break;
557 
558 	case SIOCGIFADDR_IN6:
559 		/* This interface is basically deprecated. use SIOCGIFCONF. */
560 		/* fall through */
561 	case SIOCGIFAFLAG_IN6:
562 	case SIOCGIFNETMASK_IN6:
563 	case SIOCGIFDSTADDR_IN6:
564 	case SIOCGIFALIFETIME_IN6:
565 		/* must think again about its semantics */
566 		if (ia == 0)
567 			return(EADDRNOTAVAIL);
568 		break;
569 	case SIOCSIFALIFETIME_IN6:
570 	    {
571 		struct in6_addrlifetime *lt;
572 
573 		if (!privileged)
574 			return(EPERM);
575 		if (ia == 0)
576 			return(EADDRNOTAVAIL);
577 		/* sanity for overflow - beware unsigned */
578 		lt = &ifr->ifr_ifru.ifru_lifetime;
579 		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
580 		 && lt->ia6t_vltime + time_second < time_second) {
581 			return EINVAL;
582 		}
583 		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
584 		 && lt->ia6t_pltime + time_second < time_second) {
585 			return EINVAL;
586 		}
587 		break;
588 	    }
589 	}
590 
591 	switch (cmd) {
592 
593 	case SIOCGIFADDR_IN6:
594 		ifr->ifr_addr = ia->ia_addr;
595 		break;
596 
597 	case SIOCGIFDSTADDR_IN6:
598 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
599 			return(EINVAL);
600 		ifr->ifr_dstaddr = ia->ia_dstaddr;
601 		break;
602 
603 	case SIOCGIFNETMASK_IN6:
604 		ifr->ifr_addr = ia->ia_prefixmask;
605 		break;
606 
607 	case SIOCGIFAFLAG_IN6:
608 		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
609 		break;
610 
611 	case SIOCGIFSTAT_IN6:
612 		if (ifp == NULL)
613 			return EINVAL;
614 		if (in6_ifstat == NULL || ifp->if_index >= in6_ifstatmax
615 		 || in6_ifstat[ifp->if_index] == NULL) {
616 			/* return EAFNOSUPPORT? */
617 			bzero(&ifr->ifr_ifru.ifru_stat,
618 				sizeof(ifr->ifr_ifru.ifru_stat));
619 		} else
620 			ifr->ifr_ifru.ifru_stat = *in6_ifstat[ifp->if_index];
621 		break;
622 
623 	case SIOCGIFSTAT_ICMP6:
624 		if (ifp == NULL)
625 			return EINVAL;
626 		if (icmp6_ifstat == NULL || ifp->if_index >= icmp6_ifstatmax ||
627 		    icmp6_ifstat[ifp->if_index] == NULL) {
628 			/* return EAFNOSUPPORT? */
629 			bzero(&ifr->ifr_ifru.ifru_stat,
630 				sizeof(ifr->ifr_ifru.ifru_icmp6stat));
631 		} else
632 			ifr->ifr_ifru.ifru_icmp6stat =
633 				*icmp6_ifstat[ifp->if_index];
634 		break;
635 
636 	case SIOCSIFDSTADDR_IN6:
637 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
638 			return(EINVAL);
639 		oldaddr = ia->ia_dstaddr;
640 		ia->ia_dstaddr = ifr->ifr_dstaddr;
641 
642 		/* link-local index check */
643 		if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
644 			if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] == 0) {
645 				/* interface ID is not embedded by the user */
646 				ia->ia_dstaddr.sin6_addr.s6_addr16[1]
647 					= htons(ifp->if_index);
648 			} else
649 				if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] !=
650 				    htons(ifp->if_index)) {
651 					ia->ia_dstaddr = oldaddr;
652 					return(EINVAL);	/* ifid is contradict */
653 				}
654 		}
655 
656 		if (ifp->if_ioctl && (error = (ifp->if_ioctl)
657 				      (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
658 			ia->ia_dstaddr = oldaddr;
659 			return(error);
660 		}
661 		if (ia->ia_flags & IFA_ROUTE) {
662 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
663 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
664 			ia->ia_ifa.ifa_dstaddr =
665 				(struct sockaddr *)&ia->ia_dstaddr;
666 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
667 		}
668 		break;
669 
670 	case SIOCGIFALIFETIME_IN6:
671 		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
672 		break;
673 
674 	case SIOCSIFALIFETIME_IN6:
675 		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
676 		/* for sanity */
677 		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
678 			ia->ia6_lifetime.ia6t_expire =
679 				time_second + ia->ia6_lifetime.ia6t_vltime;
680 		} else
681 			ia->ia6_lifetime.ia6t_expire = 0;
682 		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
683 			ia->ia6_lifetime.ia6t_preferred =
684 				time_second + ia->ia6_lifetime.ia6t_pltime;
685 		} else
686 			ia->ia6_lifetime.ia6t_preferred = 0;
687 		break;
688 
689 	case SIOCSIFADDR_IN6:
690 		return(in6_ifinit(ifp, ia, &ifr->ifr_addr, 1));
691 
692 	case SIOCSIFNETMASK_IN6:
693 		ia->ia_prefixmask = ifr->ifr_addr;
694 		bzero(&net, sizeof(net));
695 		net.sin6_len = sizeof(struct sockaddr_in6);
696 		net.sin6_family = AF_INET6;
697 		net.sin6_port = htons(0);
698 		net.sin6_flowinfo = htonl(0);
699 		net.sin6_addr.s6_addr32[0]
700 			= ia->ia_addr.sin6_addr.s6_addr32[0] &
701 				ia->ia_prefixmask.sin6_addr.s6_addr32[0];
702 		net.sin6_addr.s6_addr32[1]
703 			= ia->ia_addr.sin6_addr.s6_addr32[1] &
704 				ia->ia_prefixmask.sin6_addr.s6_addr32[1];
705 		net.sin6_addr.s6_addr32[2]
706 			= ia->ia_addr.sin6_addr.s6_addr32[2] &
707 				ia->ia_prefixmask.sin6_addr.s6_addr32[2];
708 		net.sin6_addr.s6_addr32[3]
709 			= ia->ia_addr.sin6_addr.s6_addr32[3] &
710 				ia->ia_prefixmask.sin6_addr.s6_addr32[3];
711 		ia->ia_net = net;
712 		break;
713 
714 	case SIOCAIFADDR_IN6:
715 		prefixIsNew = 0;
716 		hostIsNew = 1;
717 
718 		if (ifra->ifra_addr.sin6_len == 0) {
719 			ifra->ifra_addr = ia->ia_addr;
720 			hostIsNew = 0;
721 		} else if (IN6_ARE_ADDR_EQUAL(&ifra->ifra_addr.sin6_addr,
722 					      &ia->ia_addr.sin6_addr))
723 			hostIsNew = 0;
724 
725 		if (ifra->ifra_prefixmask.sin6_len) {
726 			in6_ifscrub(ifp, ia);
727 			ia->ia_prefixmask = ifra->ifra_prefixmask;
728 			prefixIsNew = 1;
729 		}
730 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
731 		    (ifra->ifra_dstaddr.sin6_family == AF_INET6)) {
732 			in6_ifscrub(ifp, ia);
733 			ia->ia_dstaddr = ifra->ifra_dstaddr;
734 			/* link-local index check: should be a separate function? */
735 			if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) {
736 				if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] == 0) {
737 					/*
738 					 * interface ID is not embedded by
739 					 * the user
740 					 */
741 					ia->ia_dstaddr.sin6_addr.s6_addr16[1]
742 						= htons(ifp->if_index);
743 				} else
744 					if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] !=
745 					    htons(ifp->if_index)) {
746 						ia->ia_dstaddr = oldaddr;
747 						return(EINVAL);	/* ifid is contradict */
748 					}
749 			}
750 			prefixIsNew = 1; /* We lie; but effect's the same */
751 		}
752 		if (ifra->ifra_addr.sin6_family == AF_INET6 &&
753 		    (hostIsNew || prefixIsNew))
754 			error = in6_ifinit(ifp, ia, &ifra->ifra_addr, 0);
755 		if (ifra->ifra_addr.sin6_family == AF_INET6
756 		    && hostIsNew && (ifp->if_flags & IFF_MULTICAST)) {
757 			int error_local = 0;
758 
759 			/*
760 			 * join solicited multicast addr for new host id
761 			 */
762 			struct in6_addr llsol;
763 			bzero(&llsol, sizeof(struct in6_addr));
764 			llsol.s6_addr16[0] = htons(0xff02);
765 			llsol.s6_addr16[1] = htons(ifp->if_index);
766 			llsol.s6_addr32[1] = 0;
767 			llsol.s6_addr32[2] = htonl(1);
768 			llsol.s6_addr32[3] =
769 				ifra->ifra_addr.sin6_addr.s6_addr32[3];
770 			llsol.s6_addr8[12] = 0xff;
771 			(void)in6_addmulti(&llsol, ifp, &error_local);
772 			if (error == 0)
773 				error = error_local;
774 		}
775 		/* Join dstaddr's solicited multicast if necessary. */
776 		if (nd6_proxyall && hostIsNew) {
777 			int error_local;
778 
779 			error_local = in6_ifaddproxy(ia);
780 			if (error == 0)
781 				error = error_local;
782 		}
783 
784 		ia->ia6_flags = ifra->ifra_flags;
785 		ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/*safety*/
786 
787 		ia->ia6_lifetime = ifra->ifra_lifetime;
788 		/* for sanity */
789 		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
790 			ia->ia6_lifetime.ia6t_expire =
791 				time_second + ia->ia6_lifetime.ia6t_vltime;
792 		} else
793 			ia->ia6_lifetime.ia6t_expire = 0;
794 		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
795 			ia->ia6_lifetime.ia6t_preferred =
796 				time_second + ia->ia6_lifetime.ia6t_pltime;
797 		} else
798 			ia->ia6_lifetime.ia6t_preferred = 0;
799 
800 		/*
801 		 * Perform DAD, if needed.
802 		 * XXX It may be of use, if we can administratively
803 		 * disable DAD.
804 		 */
805 		switch (ifp->if_type) {
806 		case IFT_ARCNET:
807 		case IFT_ETHER:
808 		case IFT_FDDI:
809 			ia->ia6_flags |= IN6_IFF_TENTATIVE;
810 			nd6_dad_start((struct ifaddr *)ia, NULL);
811 			break;
812 #ifdef IFT_DUMMY
813 		case IFT_DUMMY:
814 #endif
815 		case IFT_FAITH:
816 		case IFT_GIF:
817 		case IFT_LOOP:
818 		default:
819 			break;
820 		}
821 
822 		if (hostIsNew) {
823 			int iilen;
824 			int error_local = 0;
825 
826 			iilen = (sizeof(ia->ia_prefixmask.sin6_addr) << 3) -
827 				in6_mask2len(&ia->ia_prefixmask.sin6_addr);
828 			error_local = in6_prefix_add_ifid(iilen, ia);
829 			if (error == 0)
830 				error = error_local;
831 		}
832 
833 		return(error);
834 
835 	case SIOCDIFADDR_IN6:
836 		in6_ifscrub(ifp, ia);
837 
838 		if (ifp->if_flags & IFF_MULTICAST) {
839 			/*
840 			 * delete solicited multicast addr for deleting host id
841 			 */
842 			struct in6_multi *in6m;
843 			struct in6_addr llsol;
844 			bzero(&llsol, sizeof(struct in6_addr));
845 			llsol.s6_addr16[0] = htons(0xff02);
846 			llsol.s6_addr16[1] = htons(ifp->if_index);
847 			llsol.s6_addr32[1] = 0;
848 			llsol.s6_addr32[2] = htonl(1);
849 			llsol.s6_addr32[3] =
850 				ia->ia_addr.sin6_addr.s6_addr32[3];
851 			llsol.s6_addr8[12] = 0xff;
852 
853 			IN6_LOOKUP_MULTI(llsol, ifp, in6m);
854 			if (in6m)
855 				in6_delmulti(in6m);
856 		}
857 		/* Leave dstaddr's solicited multicast if necessary. */
858 		if (nd6_proxyall)
859 			in6_ifremproxy(ia);
860 
861 		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
862 		oia = ia;
863 		if (oia == (ia = in6_ifaddr))
864 			in6_ifaddr = ia->ia_next;
865 		else {
866 			while (ia->ia_next && (ia->ia_next != oia))
867 				ia = ia->ia_next;
868 			if (ia->ia_next)
869 				ia->ia_next = oia->ia_next;
870 			else
871 				printf("Didn't unlink in6_ifaddr from list\n");
872 		}
873 		{
874 			int iilen;
875 
876 			iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) -
877 				in6_mask2len(&oia->ia_prefixmask.sin6_addr);
878 			in6_prefix_remove_ifid(iilen, oia);
879 		}
880 		IFAFREE((&oia->ia_ifa));
881 		break;
882 
883 	default:
884 		if (ifp == 0 || ifp->if_ioctl == 0)
885 			return(EOPNOTSUPP);
886 		return((*ifp->if_ioctl)(ifp, cmd, data));
887 	}
888 	return(0);
889 }
890 
891 /*
892  * SIOC[GAD]LIFADDR.
893  *	SIOCGLIFADDR: get first address. (?!?)
894  *	SIOCGLIFADDR with IFLR_PREFIX:
895  *		get first address that matches the specified prefix.
896  *	SIOCALIFADDR: add the specified address.
897  *	SIOCALIFADDR with IFLR_PREFIX:
898  *		add the specified prefix, filling hostid part from
899  *		the first link-local address.  prefixlen must be <= 64.
900  *	SIOCDLIFADDR: delete the specified address.
901  *	SIOCDLIFADDR with IFLR_PREFIX:
902  *		delete the first address that matches the specified prefix.
903  * return values:
904  *	EINVAL on invalid parameters
905  *	EADDRNOTAVAIL on prefix match failed/specified address not found
906  *	other values may be returned from in6_ioctl()
907  *
908  * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
909  * this is to accomodate address naming scheme other than RFC2374,
910  * in the future.
911  * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
912  * address encoding scheme. (see figure on page 8)
913  */
914 static int
915 in6_lifaddr_ioctl(so, cmd, data, ifp, p)
916 	struct socket *so;
917 	u_long cmd;
918 	caddr_t	data;
919 	struct ifnet *ifp;
920 	struct proc *p;
921 {
922 	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
923 	struct ifaddr *ifa;
924 
925 	/* sanity checks */
926 	if (!data || !ifp) {
927 		panic("invalid argument to in6_lifaddr_ioctl");
928 		/*NOTRECHED*/
929 	}
930 
931 	switch (cmd) {
932 	case SIOCGLIFADDR:
933 		/* address must be specified on GET with IFLR_PREFIX */
934 		if ((iflr->flags & IFLR_PREFIX) == 0)
935 			break;
936 		/*FALLTHROUGH*/
937 	case SIOCALIFADDR:
938 	case SIOCDLIFADDR:
939 		/* address must be specified on ADD and DELETE */
940 		if (iflr->addr.ss_family != AF_INET6)
941 			return EINVAL;
942 		if (iflr->addr.ss_len != sizeof(struct sockaddr_in6))
943 			return EINVAL;
944 		/* XXX need improvement */
945 		if (iflr->dstaddr.ss_family
946 		 && iflr->dstaddr.ss_family != AF_INET6)
947 			return EINVAL;
948 		if (iflr->dstaddr.ss_family
949 		 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in6))
950 			return EINVAL;
951 		break;
952 	default: /*shouldn't happen*/
953 		return EOPNOTSUPP;
954 	}
955 	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
956 		return EINVAL;
957 
958 	switch (cmd) {
959 	case SIOCALIFADDR:
960 	    {
961 		struct in6_aliasreq ifra;
962 		struct in6_addr *hostid = NULL;
963 		int prefixlen;
964 
965 		if ((iflr->flags & IFLR_PREFIX) != 0) {
966 			struct sockaddr_in6 *sin6;
967 
968 			/*
969 			 * hostid is to fill in the hostid part of the
970 			 * address.  hostid points to the first link-local
971 			 * address attached to the interface.
972 			 */
973 			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp);
974 			if (!ifa)
975 				return EADDRNOTAVAIL;
976 			hostid = IFA_IN6(ifa);
977 
978 		 	/* prefixlen must be <= 64. */
979 			if (64 < iflr->prefixlen)
980 				return EINVAL;
981 			prefixlen = iflr->prefixlen;
982 
983 			/* hostid part must be zero. */
984 			sin6 = (struct sockaddr_in6 *)&iflr->addr;
985 			if (sin6->sin6_addr.s6_addr32[2] != 0
986 			 || sin6->sin6_addr.s6_addr32[3] != 0) {
987 				return EINVAL;
988 			}
989 		} else
990 			prefixlen = iflr->prefixlen;
991 
992 		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
993 		bzero(&ifra, sizeof(ifra));
994 		bcopy(iflr->iflr_name, ifra.ifra_name,
995 			sizeof(ifra.ifra_name));
996 
997 		bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
998 		if (hostid) {
999 			/* fill in hostid part */
1000 			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1001 				hostid->s6_addr32[2];
1002 			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1003 				hostid->s6_addr32[3];
1004 		}
1005 
1006 		if (iflr->dstaddr.ss_family) {	/*XXX*/
1007 			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1008 				iflr->dstaddr.ss_len);
1009 			if (hostid) {
1010 				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1011 					hostid->s6_addr32[2];
1012 				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1013 					hostid->s6_addr32[3];
1014 			}
1015 		}
1016 
1017 		ifra.ifra_prefixmask.sin6_family = AF_INET6;
1018 		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1019 		in6_len2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
1020 
1021 		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
1022 		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, p);
1023 	    }
1024 	case SIOCGLIFADDR:
1025 	case SIOCDLIFADDR:
1026 	    {
1027 		struct in6_ifaddr *ia;
1028 		struct in6_addr mask, candidate, match;
1029 		struct sockaddr_in6 *sin6;
1030 		int cmp;
1031 
1032 		bzero(&mask, sizeof(mask));
1033 		if (iflr->flags & IFLR_PREFIX) {
1034 			/* lookup a prefix rather than address. */
1035 			in6_len2mask(&mask, iflr->prefixlen);
1036 
1037 			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1038 			bcopy(&sin6->sin6_addr, &match, sizeof(match));
1039 			match.s6_addr32[0] &= mask.s6_addr32[0];
1040 			match.s6_addr32[1] &= mask.s6_addr32[1];
1041 			match.s6_addr32[2] &= mask.s6_addr32[2];
1042 			match.s6_addr32[3] &= mask.s6_addr32[3];
1043 
1044 			/* if you set extra bits, that's wrong */
1045 			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
1046 				return EINVAL;
1047 
1048 			cmp = 1;
1049 		} else {
1050 			if (cmd == SIOCGLIFADDR) {
1051 				/* on getting an address, take the 1st match */
1052 				cmp = 0;	/*XXX*/
1053 			} else {
1054 				/* on deleting an address, do exact match */
1055 				in6_len2mask(&mask, 128);
1056 				sin6 = (struct sockaddr_in6 *)&iflr->addr;
1057 				bcopy(&sin6->sin6_addr, &match, sizeof(match));
1058 
1059 				cmp = 1;
1060 			}
1061 		}
1062 
1063 		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1064 		{
1065 			if (ifa->ifa_addr->sa_family != AF_INET6)
1066 				continue;
1067 			if (!cmp)
1068 				break;
1069 			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1070 			candidate.s6_addr32[0] &= mask.s6_addr32[0];
1071 			candidate.s6_addr32[1] &= mask.s6_addr32[1];
1072 			candidate.s6_addr32[2] &= mask.s6_addr32[2];
1073 			candidate.s6_addr32[3] &= mask.s6_addr32[3];
1074 			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
1075 				break;
1076 		}
1077 		if (!ifa)
1078 			return EADDRNOTAVAIL;
1079 		ia = ifa2ia6(ifa);
1080 
1081 		if (cmd == SIOCGLIFADDR) {
1082 			/* fill in the if_laddrreq structure */
1083 			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1084 
1085 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1086 				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1087 					ia->ia_dstaddr.sin6_len);
1088 			} else
1089 				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
1090 
1091 			iflr->prefixlen =
1092 				in6_mask2len(&ia->ia_prefixmask.sin6_addr);
1093 
1094 			iflr->flags = ia->ia6_flags;	/*XXX*/
1095 
1096 			return 0;
1097 		} else {
1098 			struct in6_aliasreq ifra;
1099 
1100 			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1101 			bzero(&ifra, sizeof(ifra));
1102 			bcopy(iflr->iflr_name, ifra.ifra_name,
1103 				sizeof(ifra.ifra_name));
1104 
1105 			bcopy(&ia->ia_addr, &ifra.ifra_addr,
1106 				ia->ia_addr.sin6_len);
1107 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1108 				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1109 					ia->ia_dstaddr.sin6_len);
1110 			}
1111 			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1112 				ia->ia_prefixmask.sin6_len);
1113 
1114 			ifra.ifra_flags = ia->ia6_flags;
1115 			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1116 				ifp, p);
1117 		}
1118 	    }
1119 	}
1120 
1121 	return EOPNOTSUPP;	/*just for safety*/
1122 }
1123 
1124 /*
1125  * Delete any existing route for an interface.
1126  */
1127 void
1128 in6_ifscrub(ifp, ia)
1129 	register struct ifnet *ifp;
1130 	register struct in6_ifaddr *ia;
1131 {
1132 	if ((ia->ia_flags & IFA_ROUTE) == 0)
1133 		return;
1134 	if (ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
1135 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
1136 	else
1137 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1138 	ia->ia_flags &= ~IFA_ROUTE;
1139 
1140 	/* Remove ownaddr's loopback rtentry, if it exists. */
1141 	in6_ifremloop(&(ia->ia_ifa));
1142 }
1143 
1144 /*
1145  * Initialize an interface's intetnet6 address
1146  * and routing table entry.
1147  */
1148 int
1149 in6_ifinit(ifp, ia, sin6, scrub)
1150 	struct ifnet *ifp;
1151 	struct in6_ifaddr *ia;
1152 	struct sockaddr_in6 *sin6;
1153 	int scrub;
1154 {
1155 	struct	sockaddr_in6 oldaddr;
1156 	int	error, flags = RTF_UP;
1157 	int	s = splimp();
1158 
1159 	oldaddr = ia->ia_addr;
1160 	ia->ia_addr = *sin6;
1161 	/*
1162 	 * Give the interface a chance to initialize
1163 	 * if this is its first address,
1164 	 * and to validate the address if necessary.
1165 	 */
1166 	if (ifp->if_ioctl &&
1167 	   (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
1168 		splx(s);
1169 		ia->ia_addr = oldaddr;
1170 		return(error);
1171 	}
1172 
1173 	switch (ifp->if_type) {
1174 	case IFT_ARCNET:
1175 	case IFT_ETHER:
1176 	case IFT_FDDI:
1177 		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
1178 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
1179 		break;
1180 	case IFT_PPP:
1181 		ia->ia_ifa.ifa_rtrequest = nd6_p2p_rtrequest;
1182 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
1183 		break;
1184 	}
1185 
1186 	splx(s);
1187 	if (scrub) {
1188 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
1189 		in6_ifscrub(ifp, ia);
1190 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1191 	}
1192 	/* xxx
1193 	 * in_socktrim
1194 	 */
1195 	/*
1196 	 * Add route for the network.
1197 	 */
1198 	ia->ia_ifa.ifa_metric = ifp->if_metric;
1199 	if (ifp->if_flags & IFF_LOOPBACK) {
1200 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1201 		flags |= RTF_HOST;
1202 	} else if (ifp->if_flags & IFF_POINTOPOINT) {
1203 		if (ia->ia_dstaddr.sin6_family != AF_INET6)
1204 			return(0);
1205 		flags |= RTF_HOST;
1206 	}
1207 	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
1208 		ia->ia_flags |= IFA_ROUTE;
1209 
1210 	/* Add ownaddr as loopback rtentry, if necessary(ex. on p2p link). */
1211 	in6_ifaddloop(&(ia->ia_ifa));
1212 
1213 	return(error);
1214 }
1215 
1216 /*
1217  * Add an address to the list of IP6 multicast addresses for a
1218  * given interface.
1219  */
1220 struct	in6_multi *
1221 in6_addmulti(maddr6, ifp, errorp)
1222 	register struct in6_addr *maddr6;
1223 	register struct ifnet *ifp;
1224 	int *errorp;
1225 {
1226 	struct	in6_multi *in6m;
1227 	struct sockaddr_in6 sin6;
1228 	struct ifmultiaddr *ifma;
1229 	int	s = splnet();
1230 
1231 	*errorp = 0;
1232 
1233 	/*
1234 	 * Call generic routine to add membership or increment
1235 	 * refcount.  It wants addresses in the form of a sockaddr,
1236 	 * so we build one here (being careful to zero the unused bytes).
1237 	 */
1238 	bzero(&sin6, sizeof sin6);
1239 	sin6.sin6_family = AF_INET6;
1240 	sin6.sin6_len = sizeof sin6;
1241 	sin6.sin6_addr = *maddr6;
1242 	*errorp = if_addmulti(ifp, (struct sockaddr *)&sin6, &ifma);
1243 	if (*errorp) {
1244 		splx(s);
1245 		return 0;
1246 	}
1247 
1248 	/*
1249 	 * If ifma->ifma_protospec is null, then if_addmulti() created
1250 	 * a new record.  Otherwise, we are done.
1251 	 */
1252 	if (ifma->ifma_protospec != 0)
1253 		return ifma->ifma_protospec;
1254 
1255 	/* XXX - if_addmulti uses M_WAITOK.  Can this really be called
1256 	   at interrupt time?  If so, need to fix if_addmulti. XXX */
1257 	in6m = (struct in6_multi *)malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
1258 	if (in6m == NULL) {
1259 		splx(s);
1260 		return (NULL);
1261 	}
1262 
1263 	bzero(in6m, sizeof *in6m);
1264 	in6m->in6m_addr = *maddr6;
1265 	in6m->in6m_ifp = ifp;
1266 	in6m->in6m_ifma = ifma;
1267 	ifma->ifma_protospec = in6m;
1268 	LIST_INSERT_HEAD(&in6_multihead, in6m, in6m_entry);
1269 
1270 	/*
1271 	 * Let MLD6 know that we have joined a new IP6 multicast
1272 	 * group.
1273 	 */
1274 	mld6_start_listening(in6m);
1275 	splx(s);
1276 	return(in6m);
1277 }
1278 
1279 /*
1280  * Delete a multicast address record.
1281  */
1282 void
1283 in6_delmulti(in6m)
1284 	struct in6_multi *in6m;
1285 {
1286 	struct ifmultiaddr *ifma = in6m->in6m_ifma;
1287 	int	s = splnet();
1288 
1289 	if (ifma->ifma_refcount == 1) {
1290 		/*
1291 		 * No remaining claims to this record; let MLD6 know
1292 		 * that we are leaving the multicast group.
1293 		 */
1294 		mld6_stop_listening(in6m);
1295 		ifma->ifma_protospec = 0;
1296 		LIST_REMOVE(in6m, in6m_entry);
1297 		free(in6m, M_IPMADDR);
1298 	}
1299 	/* XXX - should be separate API for when we have an ifma? */
1300 	if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
1301 	splx(s);
1302 }
1303 
1304 /*
1305  * Find an IPv6 interface link-local address specific to an interface.
1306  */
1307 struct in6_ifaddr *
1308 in6ifa_ifpforlinklocal(ifp)
1309 	struct ifnet *ifp;
1310 {
1311 	register struct ifaddr *ifa;
1312 
1313 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1314 	{
1315 		if (ifa->ifa_addr == NULL)
1316 			continue;	/* just for safety */
1317 		if (ifa->ifa_addr->sa_family != AF_INET6)
1318 			continue;
1319 		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa)))
1320 			break;
1321 	}
1322 
1323 	return((struct in6_ifaddr *)ifa);
1324 }
1325 
1326 
1327 /*
1328  * find the internet address corresponding to a given interface and address.
1329  */
1330 struct in6_ifaddr *
1331 in6ifa_ifpwithaddr(ifp, addr)
1332 	struct ifnet *ifp;
1333 	struct in6_addr *addr;
1334 {
1335 	register struct ifaddr *ifa;
1336 
1337 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1338 	{
1339 		if (ifa->ifa_addr == NULL)
1340 			continue;	/* just for safety */
1341 		if (ifa->ifa_addr->sa_family != AF_INET6)
1342 			continue;
1343 		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
1344 			break;
1345 	}
1346 
1347 	return((struct in6_ifaddr *)ifa);
1348 }
1349 
1350 /*
1351  * Convert IP6 address to printable (loggable) representation.
1352  */
1353 static char digits[] = "0123456789abcdef";
1354 static int ip6round = 0;
1355 char *
1356 ip6_sprintf(addr)
1357 register struct in6_addr *addr;
1358 {
1359 	static char ip6buf[8][48];
1360 	register int i;
1361 	register char *cp;
1362 	register u_short *a = (u_short *)addr;
1363 	register u_char *d;
1364 	int dcolon = 0;
1365 
1366 	ip6round = (ip6round + 1) & 7;
1367 	cp = ip6buf[ip6round];
1368 
1369 	for (i = 0; i < 8; i++) {
1370 		if (dcolon == 1) {
1371 			if (*a == 0) {
1372 				if (i == 7)
1373 					*cp++ = ':';
1374 				a++;
1375 				continue;
1376 			} else
1377 				dcolon = 2;
1378 		}
1379 		if (*a == 0) {
1380 			if (dcolon == 0 && *(a + 1) == 0) {
1381 				if (i == 0)
1382 					*cp++ = ':';
1383 				*cp++ = ':';
1384 				dcolon = 1;
1385 			} else {
1386 				*cp++ = '0';
1387 				*cp++ = ':';
1388 			}
1389 			a++;
1390 			continue;
1391 		}
1392 		d = (u_char *)a;
1393 		*cp++ = digits[*d >> 4];
1394 		*cp++ = digits[*d++ & 0xf];
1395 		*cp++ = digits[*d >> 4];
1396 		*cp++ = digits[*d & 0xf];
1397 		*cp++ = ':';
1398 		a++;
1399 	}
1400 	*--cp = 0;
1401 	return(ip6buf[ip6round]);
1402 }
1403 
1404 int
1405 in6_localaddr(in6)
1406 	struct in6_addr *in6;
1407 {
1408 	struct in6_ifaddr *ia;
1409 
1410 	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
1411 		return 1;
1412 
1413 	for (ia = in6_ifaddr; ia; ia = ia->ia_next)
1414 		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1415 					      &ia->ia_prefixmask.sin6_addr))
1416 			return 1;
1417 
1418 	return (0);
1419 }
1420 
1421 /*
1422  * Get a scope of the address. Node-local, link-local, site-local or global.
1423  */
1424 int
1425 in6_addrscope (addr)
1426 struct in6_addr *addr;
1427 {
1428 	int scope;
1429 
1430 	if (addr->s6_addr8[0] == 0xfe) {
1431 		scope = addr->s6_addr8[1] & 0xc0;
1432 
1433 		switch (scope) {
1434 		case 0x80:
1435 			return IPV6_ADDR_SCOPE_LINKLOCAL;
1436 			break;
1437 		case 0xc0:
1438 			return IPV6_ADDR_SCOPE_SITELOCAL;
1439 			break;
1440 		default:
1441 			return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
1442 			break;
1443 		}
1444 	}
1445 
1446 
1447 	if (addr->s6_addr8[0] == 0xff) {
1448 		scope = addr->s6_addr8[1] & 0x0f;
1449 
1450 		/*
1451 		 * due to other scope such as reserved,
1452 		 * return scope doesn't work.
1453 		 */
1454 		switch (scope) {
1455 		case IPV6_ADDR_SCOPE_NODELOCAL:
1456 			return IPV6_ADDR_SCOPE_NODELOCAL;
1457 			break;
1458 		case IPV6_ADDR_SCOPE_LINKLOCAL:
1459 			return IPV6_ADDR_SCOPE_LINKLOCAL;
1460 			break;
1461 		case IPV6_ADDR_SCOPE_SITELOCAL:
1462 			return IPV6_ADDR_SCOPE_SITELOCAL;
1463 			break;
1464 		default:
1465 			return IPV6_ADDR_SCOPE_GLOBAL;
1466 			break;
1467 		}
1468 	}
1469 
1470 	if (bcmp(&in6addr_loopback, addr, sizeof(addr) - 1) == 0) {
1471 		if (addr->s6_addr8[15] == 1) /* loopback */
1472 			return IPV6_ADDR_SCOPE_NODELOCAL;
1473 		if (addr->s6_addr8[15] == 0) /* unspecified */
1474 			return IPV6_ADDR_SCOPE_LINKLOCAL;
1475 	}
1476 
1477 	return IPV6_ADDR_SCOPE_GLOBAL;
1478 }
1479 
1480 /*
1481  * return length of part which dst and src are equal
1482  * hard coding...
1483  */
1484 
1485 int
1486 in6_matchlen(src, dst)
1487 struct in6_addr *src, *dst;
1488 {
1489 	int match = 0;
1490 	u_char *s = (u_char *)src, *d = (u_char *)dst;
1491 	u_char *lim = s + 16, r;
1492 
1493 	while (s < lim)
1494 		if ((r = (*d++ ^ *s++)) != 0) {
1495 			while (r < 128) {
1496 				match++;
1497 				r <<= 1;
1498 			}
1499 			break;
1500 		} else
1501 			match += 8;
1502 	return match;
1503 }
1504 
1505 int
1506 in6_are_prefix_equal(p1, p2, len)
1507 	struct in6_addr *p1, *p2;
1508 	int len;
1509 {
1510 	int bytelen, bitlen;
1511 
1512 	/* sanity check */
1513 	if (0 > len || len > 128) {
1514 		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
1515 		    len);
1516 		return(0);
1517 	}
1518 
1519 	bytelen = len / 8;
1520 	bitlen = len % 8;
1521 
1522 	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
1523 		return(0);
1524 	if (p1->s6_addr[bytelen] >> (8 - bitlen) !=
1525 	    p2->s6_addr[bytelen] >> (8 - bitlen))
1526 		return(0);
1527 
1528 	return(1);
1529 }
1530 
1531 void
1532 in6_prefixlen2mask(maskp, len)
1533 	struct in6_addr *maskp;
1534 	int len;
1535 {
1536 	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
1537 	int bytelen, bitlen, i;
1538 
1539 	/* sanity check */
1540 	if (0 > len || len > 128) {
1541 		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
1542 		    len);
1543 		return;
1544 	}
1545 
1546 	bzero(maskp, sizeof(*maskp));
1547 	bytelen = len / 8;
1548 	bitlen = len % 8;
1549 	for (i = 0; i < bytelen; i++)
1550 		maskp->s6_addr[i] = 0xff;
1551 	if (bitlen)
1552 		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
1553 }
1554 
1555 /*
1556  * return the best address out of the same scope
1557  */
1558 
1559 struct in6_ifaddr *
1560 in6_ifawithscope(ifp, dst)
1561 	register struct ifnet *ifp;
1562 	register struct in6_addr *dst;
1563 {
1564 	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
1565 	struct ifaddr *ifa;
1566 	struct in6_ifaddr *besta = NULL, *ia;
1567 	struct in6_ifaddr *dep[3];	/*last-resort: deprecated*/
1568 
1569 	dep[0] = dep[1] = dep[2] = NULL;
1570 
1571 	/*
1572 	 * We first look for addresses in the same scope.
1573 	 * If there is one, return it.
1574 	 * If two or more, return one which matches the dst longest.
1575 	 * If none, return one of global addresses assigned other ifs.
1576 	 */
1577 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1578 	{
1579 		if (ifa->ifa_addr->sa_family != AF_INET6)
1580 			continue;
1581 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
1582 			continue; /* XXX: is there any case to allow anycast? */
1583 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
1584 			continue; /* don't use this interface */
1585 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
1586 			continue;
1587 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
1588 			if (ip6_use_deprecated)
1589 				dep[0] = (struct in6_ifaddr *)ifa;
1590 			continue;
1591 		}
1592 
1593 		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
1594 			/*
1595 			 * call in6_matchlen() as few as possible
1596 			 */
1597 			if (besta) {
1598 				if (blen == -1)
1599 					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
1600 				tlen = in6_matchlen(IFA_IN6(ifa), dst);
1601 				if (tlen > blen) {
1602 					blen = tlen;
1603 					besta = (struct in6_ifaddr *)ifa;
1604 				}
1605 			} else
1606 				besta = (struct in6_ifaddr *)ifa;
1607 		}
1608 	}
1609 	if (besta)
1610 		return besta;
1611 
1612 	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
1613 		if (IPV6_ADDR_SCOPE_GLOBAL !=
1614 		    in6_addrscope(&(ia->ia_addr.sin6_addr)))
1615 			continue;
1616 		/* XXX: is there any case to allow anycast? */
1617 		if ((ia->ia6_flags & IN6_IFF_ANYCAST) != 0)
1618 			continue;
1619 		if ((ia->ia6_flags & IN6_IFF_NOTREADY) != 0)
1620 			continue;
1621 		if ((ia->ia6_flags & IN6_IFF_DETACHED) != 0)
1622 			continue;
1623 		if ((ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
1624 			if (ip6_use_deprecated)
1625 				dep[1] = (struct in6_ifaddr *)ifa;
1626 			continue;
1627 		}
1628 		return ia;
1629 	}
1630 
1631 	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
1632                 if (IPV6_ADDR_SCOPE_SITELOCAL !=
1633                     in6_addrscope(&(ia->ia_addr.sin6_addr)))
1634                         continue;
1635 		/* XXX: is there any case to allow anycast? */
1636 		if ((ia->ia6_flags & IN6_IFF_ANYCAST) != 0)
1637 			continue;
1638 		if ((ia->ia6_flags & IN6_IFF_NOTREADY) != 0)
1639 			continue;
1640 		if ((ia->ia6_flags & IN6_IFF_DETACHED) != 0)
1641 			continue;
1642 		if ((ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
1643 			if (ip6_use_deprecated)
1644 				dep[2] = (struct in6_ifaddr *)ifa;
1645 			continue;
1646 		}
1647 		return ia;
1648 	}
1649 
1650 	/* use the last-resort values, that are, deprecated addresses */
1651 	if (dep[0])
1652 		return dep[0];
1653 	if (dep[1])
1654 		return dep[1];
1655 	if (dep[2])
1656 		return dep[2];
1657 
1658 	return NULL;
1659 }
1660 
1661 /*
1662  * return the best address out of the same scope. if no address was
1663  * found, return the first valid address from designated IF.
1664  */
1665 
1666 struct in6_ifaddr *
1667 in6_ifawithifp(ifp, dst)
1668 	register struct ifnet *ifp;
1669 	register struct in6_addr *dst;
1670 {
1671 	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
1672 	struct ifaddr *ifa;
1673 	struct in6_ifaddr *besta = 0;
1674 	struct in6_ifaddr *dep[2];	/*last-resort: deprecated*/
1675 
1676 	dep[0] = dep[1] = NULL;
1677 
1678 	/*
1679 	 * We first look for addresses in the same scope.
1680 	 * If there is one, return it.
1681 	 * If two or more, return one which matches the dst longest.
1682 	 * If none, return one of global addresses assigned other ifs.
1683 	 */
1684 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1685 	{
1686 		if (ifa->ifa_addr->sa_family != AF_INET6)
1687 			continue;
1688 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
1689 			continue; /* XXX: is there any case to allow anycast? */
1690 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
1691 			continue; /* don't use this interface */
1692 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
1693 			continue;
1694 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
1695 			if (ip6_use_deprecated)
1696 				dep[0] = (struct in6_ifaddr *)ifa;
1697 			continue;
1698 		}
1699 
1700 		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
1701 			/*
1702 			 * call in6_matchlen() as few as possible
1703 			 */
1704 			if (besta) {
1705 				if (blen == -1)
1706 					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
1707 				tlen = in6_matchlen(IFA_IN6(ifa), dst);
1708 				if (tlen > blen) {
1709 					blen = tlen;
1710 					besta = (struct in6_ifaddr *)ifa;
1711 				}
1712 			} else
1713 				besta = (struct in6_ifaddr *)ifa;
1714 		}
1715 	}
1716 	if (besta)
1717 		return(besta);
1718 
1719 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1720 	{
1721 		if (ifa->ifa_addr->sa_family != AF_INET6)
1722 			continue;
1723 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
1724 			continue; /* XXX: is there any case to allow anycast? */
1725 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
1726 			continue; /* don't use this interface */
1727 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
1728 			continue;
1729 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
1730 			if (ip6_use_deprecated)
1731 				dep[1] = (struct in6_ifaddr *)ifa;
1732 			continue;
1733 		}
1734 
1735 		return (struct in6_ifaddr *)ifa;
1736 	}
1737 
1738 	/* use the last-resort values, that are, deprecated addresses */
1739 	if (dep[0])
1740 		return dep[0];
1741 	if (dep[1])
1742 		return dep[1];
1743 
1744 	return NULL;
1745 }
1746 
1747 /*
1748  * perform DAD when interface becomes IFF_UP.
1749  */
1750 void
1751 in6_if_up(ifp)
1752 	struct ifnet *ifp;
1753 {
1754 	struct ifaddr *ifa;
1755 	struct in6_ifaddr *ia;
1756 	struct sockaddr_dl *sdl;
1757 	int type;
1758 	struct ether_addr ea;
1759 	int off;
1760 	int dad_delay;		/* delay ticks before DAD output */
1761 
1762 	bzero(&ea, sizeof(ea));
1763 	sdl = NULL;
1764 
1765 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1766 	{
1767 		if (ifa->ifa_addr->sa_family == AF_INET6
1768 		 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
1769 			goto dad;
1770 		}
1771 		if (ifa->ifa_addr->sa_family != AF_LINK)
1772 			continue;
1773 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1774 		break;
1775 	}
1776 
1777 	switch (ifp->if_type) {
1778 	case IFT_SLIP:
1779 	case IFT_PPP:
1780 #ifdef IFT_DUMMY
1781 	case IFT_DUMMY:
1782 #endif
1783 	case IFT_GIF:
1784 	case IFT_FAITH:
1785 		type = IN6_IFT_P2P;
1786 		in6_ifattach(ifp, type, 0, 1);
1787 		break;
1788 	case IFT_ETHER:
1789 	case IFT_FDDI:
1790 	case IFT_ATM:
1791 		type = IN6_IFT_802;
1792 		if (sdl == NULL)
1793 			break;
1794 		off = sdl->sdl_nlen;
1795 		if (bcmp(&sdl->sdl_data[off], &ea, sizeof(ea)) != 0)
1796 			in6_ifattach(ifp, type, LLADDR(sdl), 0);
1797 		break;
1798 	case IFT_ARCNET:
1799 		type = IN6_IFT_ARCNET;
1800 		if (sdl == NULL)
1801 			break;
1802 		off = sdl->sdl_nlen;
1803 		if (sdl->sdl_data[off] != 0)	/* XXX ?: */
1804 			in6_ifattach(ifp, type, LLADDR(sdl), 0);
1805 		break;
1806 	default:
1807 		break;
1808 	}
1809 
1810 dad:
1811 	dad_delay = 0;
1812 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1813 	{
1814 		if (ifa->ifa_addr->sa_family != AF_INET6)
1815 			continue;
1816 		ia = (struct in6_ifaddr *)ifa;
1817 		if (ia->ia6_flags & IN6_IFF_TENTATIVE)
1818 			nd6_dad_start(ifa, &dad_delay);
1819 	}
1820 }
1821 
1822 /*
1823  * Calculate max IPv6 MTU through all the interfaces and store it
1824  * to in6_maxmtu.
1825  */
1826 void
1827 in6_setmaxmtu()
1828 {
1829 	unsigned long maxmtu = 0;
1830 	struct ifnet *ifp;
1831 
1832 	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
1833 	{
1834 		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
1835 		    nd_ifinfo[ifp->if_index].linkmtu > maxmtu)
1836 			maxmtu =  nd_ifinfo[ifp->if_index].linkmtu;
1837 	}
1838 	if (maxmtu)	/* update only when maxmtu is positive */
1839 		in6_maxmtu = maxmtu;
1840 }
1841 
1842 /*
1843  * Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be
1844  * v4 mapped addr or v4 compat addr
1845  */
1846 void
1847 in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
1848 {
1849 	bzero(sin, sizeof(*sin));
1850 	sin->sin_len = sizeof(struct sockaddr_in);
1851 	sin->sin_family = AF_INET;
1852 	sin->sin_port = sin6->sin6_port;
1853 	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
1854 }
1855 
1856 /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
1857 void
1858 in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
1859 {
1860 	bzero(sin6, sizeof(*sin6));
1861 	sin6->sin6_len = sizeof(struct sockaddr_in6);
1862 	sin6->sin6_family = AF_INET6;
1863 	sin6->sin6_port = sin->sin_port;
1864 	sin6->sin6_addr.s6_addr32[0] = 0;
1865 	sin6->sin6_addr.s6_addr32[1] = 0;
1866 	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
1867 	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
1868 }
1869 
1870 /* Convert sockaddr_in6 into sockaddr_in. */
1871 void
1872 in6_sin6_2_sin_in_sock(struct sockaddr *nam)
1873 {
1874 	struct sockaddr_in *sin_p;
1875 	struct sockaddr_in6 sin6;
1876 
1877 	/*
1878 	 * Save original sockaddr_in6 addr and convert it
1879 	 * to sockaddr_in.
1880 	 */
1881 	sin6 = *(struct sockaddr_in6 *)nam;
1882 	sin_p = (struct sockaddr_in *)nam;
1883 	in6_sin6_2_sin(sin_p, &sin6);
1884 }
1885 
1886 /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
1887 void
1888 in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
1889 {
1890 	struct sockaddr_in *sin_p;
1891 	struct sockaddr_in6 *sin6_p;
1892 
1893 	MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
1894 	       M_WAITOK);
1895 	sin_p = (struct sockaddr_in *)*nam;
1896 	in6_sin_2_v4mapsin6(sin_p, sin6_p);
1897 	FREE(*nam, M_SONAME);
1898 	*nam = (struct sockaddr *)sin6_p;
1899 }
1900