xref: /openbsd-src/sys/netinet6/in6.c (revision 1fddfc4566c916e4b69b4a23f11a516bcaddb26a)
1*1fddfc45Sflorian /*	$OpenBSD: in6.c,v 1.267 2024/06/07 09:48:19 florian Exp $	*/
22c239e58Sitojun /*	$KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $	*/
3f4f4d166Sitojun 
4d3b325d0Sderaadt /*
5287546eaSitojun  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6287546eaSitojun  * All rights reserved.
7287546eaSitojun  *
8287546eaSitojun  * Redistribution and use in source and binary forms, with or without
9287546eaSitojun  * modification, are permitted provided that the following conditions
10287546eaSitojun  * are met:
11287546eaSitojun  * 1. Redistributions of source code must retain the above copyright
12287546eaSitojun  *    notice, this list of conditions and the following disclaimer.
13287546eaSitojun  * 2. Redistributions in binary form must reproduce the above copyright
14287546eaSitojun  *    notice, this list of conditions and the following disclaimer in the
15287546eaSitojun  *    documentation and/or other materials provided with the distribution.
16287546eaSitojun  * 3. Neither the name of the project nor the names of its contributors
17287546eaSitojun  *    may be used to endorse or promote products derived from this software
18287546eaSitojun  *    without specific prior written permission.
19287546eaSitojun  *
20287546eaSitojun  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21287546eaSitojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22287546eaSitojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23287546eaSitojun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24287546eaSitojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25287546eaSitojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26287546eaSitojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27287546eaSitojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28287546eaSitojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29287546eaSitojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30287546eaSitojun  * SUCH DAMAGE.
31d3b325d0Sderaadt  */
32d3b325d0Sderaadt 
33287546eaSitojun /*
34287546eaSitojun  * Copyright (c) 1982, 1986, 1991, 1993
35287546eaSitojun  *	The Regents of the University of California.  All rights reserved.
36287546eaSitojun  *
37287546eaSitojun  * Redistribution and use in source and binary forms, with or without
38287546eaSitojun  * modification, are permitted provided that the following conditions
39287546eaSitojun  * are met:
40287546eaSitojun  * 1. Redistributions of source code must retain the above copyright
41287546eaSitojun  *    notice, this list of conditions and the following disclaimer.
42287546eaSitojun  * 2. Redistributions in binary form must reproduce the above copyright
43287546eaSitojun  *    notice, this list of conditions and the following disclaimer in the
44287546eaSitojun  *    documentation and/or other materials provided with the distribution.
4529295d1cSmillert  * 3. Neither the name of the University nor the names of its contributors
46287546eaSitojun  *    may be used to endorse or promote products derived from this software
47287546eaSitojun  *    without specific prior written permission.
48287546eaSitojun  *
49287546eaSitojun  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50287546eaSitojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51287546eaSitojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52287546eaSitojun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53287546eaSitojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54287546eaSitojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55287546eaSitojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56287546eaSitojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57287546eaSitojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58287546eaSitojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59287546eaSitojun  * SUCH DAMAGE.
60287546eaSitojun  *
61287546eaSitojun  *	@(#)in.c	8.2 (Berkeley) 11/15/93
62287546eaSitojun  */
63287546eaSitojun 
64276c252dSbluhm #include "carp.h"
65276c252dSbluhm 
66d3b325d0Sderaadt #include <sys/param.h>
67d3b325d0Sderaadt #include <sys/ioctl.h>
68d3b325d0Sderaadt #include <sys/errno.h>
69d3b325d0Sderaadt #include <sys/malloc.h>
70d3b325d0Sderaadt #include <sys/socket.h>
71d3b325d0Sderaadt #include <sys/socketvar.h>
72287546eaSitojun #include <sys/sockio.h>
73377da2e0Sderaadt #include <sys/mbuf.h>
74d3b325d0Sderaadt #include <sys/systm.h>
75287546eaSitojun #include <sys/time.h>
76287546eaSitojun #include <sys/kernel.h>
77287546eaSitojun #include <sys/syslog.h>
78d3b325d0Sderaadt 
79d3b325d0Sderaadt #include <net/if.h>
80cfc71c8bSclaudio #include <net/if_dl.h>
81d3b325d0Sderaadt #include <net/if_types.h>
82d3b325d0Sderaadt #include <net/route.h>
83d3b325d0Sderaadt 
84d3b325d0Sderaadt #include <netinet/in.h>
85287546eaSitojun #include <netinet/if_ether.h>
86d3b325d0Sderaadt 
87dc572864Sbluhm #include <netinet6/in6_var.h>
887832ad60Sitojun #include <netinet/ip6.h>
89287546eaSitojun #include <netinet6/ip6_var.h>
90cab0f1b1Sitojun #include <netinet6/nd6.h>
91287546eaSitojun #include <netinet6/mld6_var.h>
92d9c6379eSclaudio #ifdef MROUTING
93287546eaSitojun #include <netinet6/ip6_mroute.h>
94d9c6379eSclaudio #endif
95287546eaSitojun #include <netinet6/in6_ifattach.h>
96a7e28db1Sbluhm #if NCARP > 0
97a7e28db1Sbluhm #include <netinet/ip_carp.h>
98a7e28db1Sbluhm #endif
99d3b325d0Sderaadt 
100d3b325d0Sderaadt /*
101ecd7743bSitojun  * Definitions of some constant IP6 addresses.
102d3b325d0Sderaadt  */
103d3b325d0Sderaadt const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
104d3b325d0Sderaadt const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
105d4070096Sitojun const struct in6_addr in6addr_intfacelocal_allnodes =
106d4070096Sitojun 	IN6ADDR_INTFACELOCAL_ALLNODES_INIT;
107287546eaSitojun const struct in6_addr in6addr_linklocal_allnodes =
108287546eaSitojun 	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
10970af887bSflorian const struct in6_addr in6addr_linklocal_allrouters =
11070af887bSflorian 	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
111287546eaSitojun 
112287546eaSitojun const struct in6_addr in6mask0 = IN6MASK0;
113287546eaSitojun const struct in6_addr in6mask32 = IN6MASK32;
114287546eaSitojun const struct in6_addr in6mask64 = IN6MASK64;
115287546eaSitojun const struct in6_addr in6mask96 = IN6MASK96;
116287546eaSitojun const struct in6_addr in6mask128 = IN6MASK128;
117287546eaSitojun 
11853224561Sguenther int in6_ioctl(u_long, caddr_t, struct ifnet *, int);
119fdc18db1Stb int in6_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *);
12089076952Stb int in6_ioctl_get(u_long, caddr_t, struct ifnet *);
121aeb66976Stb int in6_check_embed_scope(struct sockaddr_in6 *, unsigned int);
122aeb66976Stb int in6_clear_scope_id(struct sockaddr_in6 *, unsigned int);
123525dbc5aSjsing int in6_ifinit(struct ifnet *, struct in6_ifaddr *, int);
124525dbc5aSjsing void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
125287546eaSitojun 
126525dbc5aSjsing const struct sockaddr_in6 sa6_any = {
127525dbc5aSjsing 	sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0
128525dbc5aSjsing };
12930a4dc1cSitojun 
130287546eaSitojun int
in6_mask2len(struct in6_addr * mask,u_char * lim0)131ee37ea65Smcbride in6_mask2len(struct in6_addr *mask, u_char *lim0)
132287546eaSitojun {
133d8a7e3a7Sitojun 	int x = 0, y;
134d8a7e3a7Sitojun 	u_char *lim = lim0, *p;
135287546eaSitojun 
136d8a7e3a7Sitojun 	/* ignore the scope_id part */
137d8a7e3a7Sitojun 	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
138d8a7e3a7Sitojun 		lim = (u_char *)mask + sizeof(*mask);
139d8a7e3a7Sitojun 	for (p = (u_char *)mask; p < lim; x++, p++) {
140d8a7e3a7Sitojun 		if (*p != 0xff)
141287546eaSitojun 			break;
142287546eaSitojun 	}
143287546eaSitojun 	y = 0;
144d8a7e3a7Sitojun 	if (p < lim) {
145287546eaSitojun 		for (y = 0; y < 8; y++) {
146d8a7e3a7Sitojun 			if ((*p & (0x80 >> y)) == 0)
147287546eaSitojun 				break;
148287546eaSitojun 		}
149287546eaSitojun 	}
150d8a7e3a7Sitojun 
151d8a7e3a7Sitojun 	/*
152d8a7e3a7Sitojun 	 * when the limit pointer is given, do a stricter check on the
153d8a7e3a7Sitojun 	 * remaining bits.
154d8a7e3a7Sitojun 	 */
155d8a7e3a7Sitojun 	if (p < lim) {
156d8a7e3a7Sitojun 		if (y != 0 && (*p & (0x00ff >> y)) != 0)
157d8a7e3a7Sitojun 			return (-1);
158d8a7e3a7Sitojun 		for (p = p + 1; p < lim; p++)
159d8a7e3a7Sitojun 			if (*p != 0)
160d8a7e3a7Sitojun 				return (-1);
161d8a7e3a7Sitojun 	}
162d8a7e3a7Sitojun 
163287546eaSitojun 	return x * 8 + y;
164287546eaSitojun }
165d3b325d0Sderaadt 
166d3b325d0Sderaadt int
in6_nam2sin6(const struct mbuf * nam,struct sockaddr_in6 ** sin6)167b2a698eaSbluhm in6_nam2sin6(const struct mbuf *nam, struct sockaddr_in6 **sin6)
168b2a698eaSbluhm {
169b2a698eaSbluhm 	struct sockaddr *sa = mtod(nam, struct sockaddr *);
170b2a698eaSbluhm 
171b2a698eaSbluhm 	if (nam->m_len < offsetof(struct sockaddr, sa_data))
172b2a698eaSbluhm 		return EINVAL;
173b2a698eaSbluhm 	if (sa->sa_family != AF_INET6)
174b2a698eaSbluhm 		return EAFNOSUPPORT;
175b2a698eaSbluhm 	if (sa->sa_len != nam->m_len)
176b2a698eaSbluhm 		return EINVAL;
177b2a698eaSbluhm 	if (sa->sa_len != sizeof(struct sockaddr_in6))
178b2a698eaSbluhm 		return EINVAL;
179b2a698eaSbluhm 	*sin6 = satosin6(sa);
180b2a698eaSbluhm 
181b2a698eaSbluhm 	return 0;
182b2a698eaSbluhm }
183b2a698eaSbluhm 
184b2a698eaSbluhm int
in6_sa2sin6(struct sockaddr * sa,struct sockaddr_in6 ** sin6)1855c135f85Sbluhm in6_sa2sin6(struct sockaddr *sa, struct sockaddr_in6 **sin6)
1865c135f85Sbluhm {
1875c135f85Sbluhm 	if (sa->sa_family != AF_INET6)
1885c135f85Sbluhm 		return EAFNOSUPPORT;
1895c135f85Sbluhm 	if (sa->sa_len != sizeof(struct sockaddr_in6))
1905c135f85Sbluhm 		return EINVAL;
1915c135f85Sbluhm 	*sin6 = satosin6(sa);
1925c135f85Sbluhm 
1935c135f85Sbluhm 	return 0;
1945c135f85Sbluhm }
1955c135f85Sbluhm 
1965c135f85Sbluhm int
in6_control(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp)19781bfb674Smpi in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
198d3b325d0Sderaadt {
199d732431aSmpi 	int privileged;
200287546eaSitojun 
201287546eaSitojun 	privileged = 0;
202287546eaSitojun 	if ((so->so_state & SS_PRIV) != 0)
203287546eaSitojun 		privileged++;
204d3b325d0Sderaadt 
205287546eaSitojun 	switch (cmd) {
20629477734Sflorian #ifdef MROUTING
207287546eaSitojun 	case SIOCGETSGCNT_IN6:
208287546eaSitojun 	case SIOCGETMIFCNT_IN6:
209a9069a72Skn 		return mrt6_ioctl(so, cmd, data);
2106c1326fdSmpi #endif /* MROUTING */
21129477734Sflorian 	default:
212a9069a72Skn 		return in6_ioctl(cmd, data, ifp, privileged);
21329477734Sflorian 	}
214d732431aSmpi }
215d732431aSmpi 
216d732431aSmpi int
in6_ioctl(u_long cmd,caddr_t data,struct ifnet * ifp,int privileged)217d732431aSmpi in6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged)
218d732431aSmpi {
219d8a7e3a7Sitojun 	if (ifp == NULL)
220145df85aSmpi 		return (ENXIO);
221145df85aSmpi 
222287546eaSitojun 	switch (cmd) {
223287546eaSitojun 	case SIOCGIFINFO_IN6:
224287546eaSitojun 	case SIOCGNBRINFO_IN6:
225287546eaSitojun 		return (nd6_ioctl(cmd, data, ifp));
22689076952Stb 	case SIOCGIFDSTADDR_IN6:
22789076952Stb 	case SIOCGIFNETMASK_IN6:
22889076952Stb 	case SIOCGIFAFLAG_IN6:
22989076952Stb 	case SIOCGIFALIFETIME_IN6:
23089076952Stb 		return (in6_ioctl_get(cmd, data, ifp));
23189076952Stb 	case SIOCAIFADDR_IN6:
23289076952Stb 	case SIOCDIFADDR_IN6:
233fdc18db1Stb 		if (!privileged)
234fdc18db1Stb 			return (EPERM);
235fdc18db1Stb 		return (in6_ioctl_change_ifaddr(cmd, data, ifp));
23689076952Stb 	case SIOCSIFADDR:
23789076952Stb 	case SIOCSIFDSTADDR:
23889076952Stb 	case SIOCSIFBRDADDR:
23989076952Stb 	case SIOCSIFNETMASK:
24089076952Stb 		/*
24189076952Stb 		 * Do not pass those ioctl to driver handler since they are not
24289076952Stb 		 * properly set up. Instead just error out.
24389076952Stb 		 */
24489076952Stb 		return (EINVAL);
24589076952Stb 	default:
24689076952Stb 		return (EOPNOTSUPP);
247d3b325d0Sderaadt 	}
248fdc18db1Stb }
249fdc18db1Stb 
250fdc18db1Stb int
in6_ioctl_change_ifaddr(u_long cmd,caddr_t data,struct ifnet * ifp)251fdc18db1Stb in6_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
252fdc18db1Stb {
253fdc18db1Stb 	struct	in6_ifaddr *ia6 = NULL;
254fdc18db1Stb 	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
2555c135f85Sbluhm 	struct	sockaddr *sa;
2565c135f85Sbluhm 	struct	sockaddr_in6 *sa6 = NULL;
257fdc18db1Stb 	int	error = 0, newifaddr = 0, plen;
258d3b325d0Sderaadt 
259287546eaSitojun 	/*
260287546eaSitojun 	 * Find address for this interface, if it exists.
261f04bc9a1Sitojun 	 *
262f04bc9a1Sitojun 	 * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
263f04bc9a1Sitojun 	 * only, and used the first interface address as the target of other
264f04bc9a1Sitojun 	 * operations (without checking ifra_addr).  This was because netinet
265f04bc9a1Sitojun 	 * code/API assumed at most 1 interface address per interface.
266f04bc9a1Sitojun 	 * Since IPv6 allows a node to assign multiple addresses
267f04bc9a1Sitojun 	 * on a single interface, we almost always look and check the
268f04bc9a1Sitojun 	 * presence of ifra_addr, and reject invalid ones here.
269f04bc9a1Sitojun 	 * It also decreases duplicated code among SIOC*_IN6 operations.
2705c135f85Sbluhm 	 *
2715c135f85Sbluhm 	 * We always require users to specify a valid IPv6 address for
2725c135f85Sbluhm 	 * the corresponding operation.
273287546eaSitojun 	 */
274fdc18db1Stb 	switch (cmd) {
275fdc18db1Stb 	case SIOCAIFADDR_IN6:
2765c135f85Sbluhm 		sa = sin6tosa(&ifra->ifra_addr);
277fdc18db1Stb 		break;
278fdc18db1Stb 	case SIOCDIFADDR_IN6:
2795c135f85Sbluhm 		sa = sin6tosa(&((struct in6_ifreq *)data)->ifr_addr);
280fdc18db1Stb 		break;
281fdc18db1Stb 	default:
2825c135f85Sbluhm 		panic("%s: invalid ioctl %lu", __func__, cmd);
2835c135f85Sbluhm 	}
2845c135f85Sbluhm 	if (sa->sa_family == AF_INET6) {
2855c135f85Sbluhm 		error = in6_sa2sin6(sa, &sa6);
2865c135f85Sbluhm 		if (error)
2875c135f85Sbluhm 			return (error);
288fdc18db1Stb 	}
289dd66399bStb 
2903cf38294Skn 	KERNEL_LOCK();
291dd66399bStb 	NET_LOCK();
292dd66399bStb 
2935c135f85Sbluhm 	if (sa6 != NULL) {
294aeb66976Stb 		error = in6_check_embed_scope(sa6, ifp->if_index);
295aeb66976Stb 		if (error)
296dd66399bStb 			goto err;
297aeb66976Stb 		error = in6_clear_scope_id(sa6, ifp->if_index);
298aeb66976Stb 		if (error)
299dd66399bStb 			goto err;
300b9e83c60Sbluhm 		ia6 = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
301fdc18db1Stb 	}
302287546eaSitojun 
303287546eaSitojun 	switch (cmd) {
304287546eaSitojun 	case SIOCDIFADDR_IN6:
305f4f4d166Sitojun 		/*
30630a4dc1cSitojun 		 * for IPv4, we look for existing in_ifaddr here to allow
307f04bc9a1Sitojun 		 * "ifconfig if0 delete" to remove the first IPv4 address on
308f04bc9a1Sitojun 		 * the interface.  For IPv6, as the spec allows multiple
309f04bc9a1Sitojun 		 * interface address from the day one, we consider "remove the
310f04bc9a1Sitojun 		 * first one" semantics to be not preferable.
311f4f4d166Sitojun 		 */
312dd66399bStb 		if (ia6 == NULL) {
313dd66399bStb 			error = EADDRNOTAVAIL;
314fdc18db1Stb 			break;
315dd66399bStb 		}
316fdc18db1Stb 		in6_purgeaddr(&ia6->ia_ifa);
317f22742abSdlg 		if_addrhooks_run(ifp);
318fdc18db1Stb 		break;
319fdc18db1Stb 
320287546eaSitojun 	case SIOCAIFADDR_IN6:
321efa3c3ddSanton 		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
322efa3c3ddSanton 		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) {
323efa3c3ddSanton 			error = EAFNOSUPPORT;
324efa3c3ddSanton 			break;
325efa3c3ddSanton 		}
326efa3c3ddSanton 
32789076952Stb 		/* reject read-only flags */
32889076952Stb 		if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
32989076952Stb 		    (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 ||
33089076952Stb 		    (ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
33189076952Stb 			error = EINVAL;
33289076952Stb 			break;
33389076952Stb 		}
33489076952Stb 
33589076952Stb 		if (ia6 == NULL)
33689076952Stb 			newifaddr = 1;
33789076952Stb 
33889076952Stb 		/*
33989076952Stb 		 * Make the address tentative before joining multicast
34089076952Stb 		 * addresses, so that corresponding MLD responses would
34189076952Stb 		 * not have a tentative source address.
34289076952Stb 		 */
34389076952Stb 		if (newifaddr && in6if_do_dad(ifp))
34489076952Stb 			ifra->ifra_flags |= IN6_IFF_TENTATIVE;
34589076952Stb 
34689076952Stb 		/*
34789076952Stb 		 * first, make or update the interface address structure,
34889076952Stb 		 * and link it to the list. try to enable inet6 if there
34989076952Stb 		 * is no link-local yet.
35089076952Stb 		 */
35189076952Stb 		error = in6_ifattach(ifp);
3525c135f85Sbluhm 		if (error)
35389076952Stb 			break;
35489076952Stb 		error = in6_update_ifa(ifp, ifra, ia6);
3555c135f85Sbluhm 		if (error)
35689076952Stb 			break;
35789076952Stb 
3585c135f85Sbluhm 		ia6 = NULL;
3595c135f85Sbluhm 		if (sa6 != NULL)
3605c135f85Sbluhm 			ia6 = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
36189076952Stb 		if (ia6 == NULL) {
36289076952Stb 			/*
36389076952Stb 			 * this can happen when the user specify the 0 valid
36489076952Stb 			 * lifetime.
36589076952Stb 			 */
36689076952Stb 			break;
36789076952Stb 		}
36889076952Stb 
36989076952Stb 		/* Perform DAD, if needed. */
37089076952Stb 		if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
37189076952Stb 			nd6_dad_start(&ia6->ia_ifa);
37289076952Stb 
37389076952Stb 		if (!newifaddr) {
374f22742abSdlg 			if_addrhooks_run(ifp);
37589076952Stb 			break;
37689076952Stb 		}
37789076952Stb 
37889076952Stb 		plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
37989076952Stb 		if ((ifp->if_flags & IFF_LOOPBACK) || plen == 128) {
380f22742abSdlg 			if_addrhooks_run(ifp);
38189076952Stb 			break;	/* No need to install a connected route. */
38289076952Stb 		}
38389076952Stb 
38462cb75b3Sdlg 		error = rt_ifa_add(&ia6->ia_ifa,
38562cb75b3Sdlg 		    RTF_CLONING | RTF_CONNECTED | RTF_MPATH,
3868f960e22Sdlg 		    ia6->ia_ifa.ifa_addr, ifp->if_rdomain);
38789076952Stb 		if (error) {
38889076952Stb 			in6_purgeaddr(&ia6->ia_ifa);
38989076952Stb 			break;
39089076952Stb 		}
391f22742abSdlg 		if_addrhooks_run(ifp);
39289076952Stb 		break;
39389076952Stb 	}
39489076952Stb 
39589076952Stb err:
39689076952Stb 	NET_UNLOCK();
3973cf38294Skn 	KERNEL_UNLOCK();
39889076952Stb 	return (error);
39989076952Stb }
40089076952Stb 
40189076952Stb int
in6_ioctl_get(u_long cmd,caddr_t data,struct ifnet * ifp)40289076952Stb in6_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp)
40389076952Stb {
40489076952Stb 	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
40589076952Stb 	struct	in6_ifaddr *ia6 = NULL;
4065c135f85Sbluhm 	struct	sockaddr *sa;
4075c135f85Sbluhm 	struct	sockaddr_in6 *sa6 = NULL;
40889076952Stb 	int	error = 0;
40989076952Stb 
4105c135f85Sbluhm 	sa = sin6tosa(&ifr->ifr_addr);
4115c135f85Sbluhm 	if (sa->sa_family == AF_INET6) {
412bf722da6Sbluhm 		sa->sa_len = sizeof(struct sockaddr_in6);
4135c135f85Sbluhm 		error = in6_sa2sin6(sa, &sa6);
4145c135f85Sbluhm 		if (error)
4155c135f85Sbluhm 			return (error);
4165c135f85Sbluhm 	}
41789076952Stb 
4186a1c2aefSbluhm 	NET_LOCK_SHARED();
41989076952Stb 
4205c135f85Sbluhm 	if (sa6 != NULL) {
421aeb66976Stb 		error = in6_check_embed_scope(sa6, ifp->if_index);
422aeb66976Stb 		if (error)
42389076952Stb 			goto err;
424aeb66976Stb 		error = in6_clear_scope_id(sa6, ifp->if_index);
425aeb66976Stb 		if (error)
42689076952Stb 			goto err;
42789076952Stb 		ia6 = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
42889076952Stb 	}
42989076952Stb 
430287546eaSitojun 	/* must think again about its semantics */
431dd66399bStb 	if (ia6 == NULL) {
432dd66399bStb 		error = EADDRNOTAVAIL;
433dd66399bStb 		goto err;
434dd66399bStb 	}
435287546eaSitojun 
436287546eaSitojun 	switch (cmd) {
437287546eaSitojun 	case SIOCGIFDSTADDR_IN6:
438dd66399bStb 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
439dd66399bStb 			error = EINVAL;
440dd66399bStb 			break;
441dd66399bStb 		}
442d8a7e3a7Sitojun 		/*
443d8a7e3a7Sitojun 		 * XXX: should we check if ifa_dstaddr is NULL and return
444d8a7e3a7Sitojun 		 * an error?
445d8a7e3a7Sitojun 		 */
446b9e83c60Sbluhm 		ifr->ifr_dstaddr = ia6->ia_dstaddr;
447287546eaSitojun 		break;
448287546eaSitojun 
449287546eaSitojun 	case SIOCGIFNETMASK_IN6:
450b9e83c60Sbluhm 		ifr->ifr_addr = ia6->ia_prefixmask;
451287546eaSitojun 		break;
452287546eaSitojun 
453287546eaSitojun 	case SIOCGIFAFLAG_IN6:
454b9e83c60Sbluhm 		ifr->ifr_ifru.ifru_flags6 = ia6->ia6_flags;
455287546eaSitojun 		break;
456287546eaSitojun 
457287546eaSitojun 	case SIOCGIFALIFETIME_IN6:
458b9e83c60Sbluhm 		ifr->ifr_ifru.ifru_lifetime = ia6->ia6_lifetime;
459b9e83c60Sbluhm 		if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
46056b4879eSmpi 			time_t expire, maxexpire;
461d8a7e3a7Sitojun 			struct in6_addrlifetime *retlt =
462d8a7e3a7Sitojun 			    &ifr->ifr_ifru.ifru_lifetime;
463d8a7e3a7Sitojun 
464d8a7e3a7Sitojun 			/*
465d8a7e3a7Sitojun 			 * XXX: adjust expiration time assuming time_t is
466d8a7e3a7Sitojun 			 * signed.
467d8a7e3a7Sitojun 			 */
46891a535ffSguenther 			maxexpire =
46991a535ffSguenther 			    (time_t)~(1ULL << ((sizeof(maxexpire) * 8) - 1));
470b9e83c60Sbluhm 			if (ia6->ia6_lifetime.ia6t_vltime <
471b9e83c60Sbluhm 			    maxexpire - ia6->ia6_updatetime) {
47256b4879eSmpi 				expire = ia6->ia6_updatetime +
473b9e83c60Sbluhm 				    ia6->ia6_lifetime.ia6t_vltime;
47456b4879eSmpi 				if (expire != 0) {
4753209772dScheloha 					expire -= getuptime();
4763209772dScheloha 					expire += gettime();
47756b4879eSmpi 				}
47856b4879eSmpi 				retlt->ia6t_expire = expire;
479d8a7e3a7Sitojun 			} else
480d8a7e3a7Sitojun 				retlt->ia6t_expire = maxexpire;
481d8a7e3a7Sitojun 		}
482b9e83c60Sbluhm 		if (ia6->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
483c5364f84Sflorian 			time_t expire, maxexpire;
484d8a7e3a7Sitojun 			struct in6_addrlifetime *retlt =
485d8a7e3a7Sitojun 			    &ifr->ifr_ifru.ifru_lifetime;
486d8a7e3a7Sitojun 
487d8a7e3a7Sitojun 			/*
488d8a7e3a7Sitojun 			 * XXX: adjust expiration time assuming time_t is
489d8a7e3a7Sitojun 			 * signed.
490d8a7e3a7Sitojun 			 */
49191a535ffSguenther 			maxexpire =
49291a535ffSguenther 			    (time_t)~(1ULL << ((sizeof(maxexpire) * 8) - 1));
493b9e83c60Sbluhm 			if (ia6->ia6_lifetime.ia6t_pltime <
494b9e83c60Sbluhm 			    maxexpire - ia6->ia6_updatetime) {
495c5364f84Sflorian 				expire = ia6->ia6_updatetime +
496b9e83c60Sbluhm 				    ia6->ia6_lifetime.ia6t_pltime;
497c5364f84Sflorian 				if (expire != 0) {
4983209772dScheloha 					expire -= getuptime();
4993209772dScheloha 					expire += gettime();
500c5364f84Sflorian 				}
501c5364f84Sflorian 				retlt->ia6t_preferred = expire;
502d8a7e3a7Sitojun 			} else
503d8a7e3a7Sitojun 				retlt->ia6t_preferred = maxexpire;
504d8a7e3a7Sitojun 		}
505287546eaSitojun 		break;
506287546eaSitojun 
507d8a7e3a7Sitojun 	default:
5085c135f85Sbluhm 		panic("%s: invalid ioctl %lu", __func__, cmd);
509d8a7e3a7Sitojun 	}
510d8a7e3a7Sitojun 
511dd66399bStb err:
5126a1c2aefSbluhm 	NET_UNLOCK_SHARED();
513dd66399bStb 	return (error);
514d8a7e3a7Sitojun }
515d8a7e3a7Sitojun 
516aeb66976Stb int
in6_check_embed_scope(struct sockaddr_in6 * sa6,unsigned int ifidx)517aeb66976Stb in6_check_embed_scope(struct sockaddr_in6 *sa6, unsigned int ifidx)
518aeb66976Stb {
519aeb66976Stb 	if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
520aeb66976Stb 		if (sa6->sin6_addr.s6_addr16[1] == 0) {
521aeb66976Stb 			/* link ID is not embedded by the user */
522aeb66976Stb 			sa6->sin6_addr.s6_addr16[1] = htons(ifidx);
523aeb66976Stb 		} else if (sa6->sin6_addr.s6_addr16[1] != htons(ifidx))
524aeb66976Stb 			return EINVAL;	/* link ID contradicts */
525aeb66976Stb 	}
526aeb66976Stb 	return 0;
527aeb66976Stb }
528aeb66976Stb 
529aeb66976Stb int
in6_clear_scope_id(struct sockaddr_in6 * sa6,unsigned int ifidx)530aeb66976Stb in6_clear_scope_id(struct sockaddr_in6 *sa6, unsigned int ifidx)
531aeb66976Stb {
532aeb66976Stb 	if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
533aeb66976Stb 		if (sa6->sin6_scope_id) {
534aeb66976Stb 			if (sa6->sin6_scope_id != (u_int32_t)ifidx)
535aeb66976Stb 				return EINVAL;
536aeb66976Stb 			sa6->sin6_scope_id = 0; /* XXX: good way? */
537aeb66976Stb 		}
538aeb66976Stb 	}
539aeb66976Stb 	return 0;
540aeb66976Stb }
541aeb66976Stb 
542d8a7e3a7Sitojun /*
543d8a7e3a7Sitojun  * Update parameters of an IPv6 interface address.
544d8a7e3a7Sitojun  * If necessary, a new entry is created and linked into address chains.
545d8a7e3a7Sitojun  * This function is separated from in6_control().
546d8a7e3a7Sitojun  */
547d8a7e3a7Sitojun int
in6_update_ifa(struct ifnet * ifp,struct in6_aliasreq * ifra,struct in6_ifaddr * ia6)548ee37ea65Smcbride in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
549b9e83c60Sbluhm     struct in6_ifaddr *ia6)
550d8a7e3a7Sitojun {
551d8a7e3a7Sitojun 	int error = 0, hostIsNew = 0, plen = -1;
552*1fddfc45Sflorian 	struct sockaddr_in6 dst6, gw6;
553d8a7e3a7Sitojun 	struct in6_addrlifetime *lt;
554d8a7e3a7Sitojun 	struct in6_multi_mship *imm;
555d8a7e3a7Sitojun 	struct rtentry *rt;
556bbcf0337Smpi 	char addr[INET6_ADDRSTRLEN];
557d8a7e3a7Sitojun 
55866736630Smpi 	NET_ASSERT_LOCKED();
559c81f9a03Smcbride 
560d8a7e3a7Sitojun 	/* Validate parameters */
561d8a7e3a7Sitojun 	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
562d8a7e3a7Sitojun 		return (EINVAL);
563d8a7e3a7Sitojun 
564f4f4d166Sitojun 	/*
5657186e918Sflorian 	 * The destination address for a p2p link or the address of the
5667186e918Sflorian 	 * announcing router for an autoconf address must have a family of
5677186e918Sflorian 	 * AF_UNSPEC or AF_INET6.
568f4f4d166Sitojun 	 */
5697186e918Sflorian 	if ((ifp->if_flags & IFF_POINTOPOINT) ||
5707186e918Sflorian 	    (ifp->if_flags & IFF_LOOPBACK) ||
5717186e918Sflorian 	    (ifra->ifra_flags & IN6_IFF_AUTOCONF)) {
5727186e918Sflorian 		if (ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
573f4f4d166Sitojun 		    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
574f4f4d166Sitojun 			return (EAFNOSUPPORT);
575727c267dShenning 
5767186e918Sflorian 	} else if (ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
5777186e918Sflorian 			return (EINVAL);
5787186e918Sflorian 
579f4f4d166Sitojun 	/*
580d8a7e3a7Sitojun 	 * validate ifra_prefixmask.  don't check sin6_family, netmask
581d8a7e3a7Sitojun 	 * does not carry fields other than sin6_len.
582f4f4d166Sitojun 	 */
583d8a7e3a7Sitojun 	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
584d8a7e3a7Sitojun 		return (EINVAL);
585d8a7e3a7Sitojun 	/*
586d8a7e3a7Sitojun 	 * Because the IPv6 address architecture is classless, we require
587d8a7e3a7Sitojun 	 * users to specify a (non 0) prefix length (mask) for a new address.
588d8a7e3a7Sitojun 	 * We also require the prefix (when specified) mask is valid, and thus
589d8a7e3a7Sitojun 	 * reject a non-consecutive mask.
590d8a7e3a7Sitojun 	 */
591b9e83c60Sbluhm 	if (ia6 == NULL && ifra->ifra_prefixmask.sin6_len == 0)
592d8a7e3a7Sitojun 		return (EINVAL);
593d8a7e3a7Sitojun 	if (ifra->ifra_prefixmask.sin6_len != 0) {
594d8a7e3a7Sitojun 		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
595d8a7e3a7Sitojun 		    (u_char *)&ifra->ifra_prefixmask +
596d8a7e3a7Sitojun 		    ifra->ifra_prefixmask.sin6_len);
597d8a7e3a7Sitojun 		if (plen <= 0)
598d8a7e3a7Sitojun 			return (EINVAL);
599d8a7e3a7Sitojun 	} else {
600d8a7e3a7Sitojun 		/*
601b9e83c60Sbluhm 		 * In this case, ia6 must not be NULL.  We just use its prefix
602d8a7e3a7Sitojun 		 * length.
603d8a7e3a7Sitojun 		 */
604b9e83c60Sbluhm 		plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
605d3b325d0Sderaadt 	}
6067186e918Sflorian 
607*1fddfc45Sflorian 	if (ifra->ifra_flags & IN6_IFF_AUTOCONF) {
608*1fddfc45Sflorian 		gw6 = ifra->ifra_dstaddr;
609*1fddfc45Sflorian 		memset(&dst6, 0, sizeof(dst6));
610*1fddfc45Sflorian 	} else {
611d8a7e3a7Sitojun 		dst6 = ifra->ifra_dstaddr;
612*1fddfc45Sflorian 		memset(&gw6, 0, sizeof(gw6));
613*1fddfc45Sflorian 	}
6147186e918Sflorian 	if (dst6.sin6_family == AF_INET6) {
615aeb66976Stb 		error = in6_check_embed_scope(&dst6, ifp->if_index);
616aeb66976Stb 		if (error)
617aeb66976Stb 			return error;
6187186e918Sflorian 
6197186e918Sflorian 		if (((ifp->if_flags & IFF_POINTOPOINT) ||
6207186e918Sflorian 		    (ifp->if_flags & IFF_LOOPBACK)) && plen != 128)
621d8a7e3a7Sitojun 			return (EINVAL);
622248db9a2Sitojun 	}
623*1fddfc45Sflorian 	if (gw6.sin6_family == AF_INET6) {
624*1fddfc45Sflorian 		error = in6_check_embed_scope(&gw6, ifp->if_index);
625*1fddfc45Sflorian 		if (error)
626*1fddfc45Sflorian 			return error;
627*1fddfc45Sflorian 	}
628d8a7e3a7Sitojun 	/* lifetime consistency check */
629d8a7e3a7Sitojun 	lt = &ifra->ifra_lifetime;
630d8a7e3a7Sitojun 	if (lt->ia6t_pltime > lt->ia6t_vltime)
631d8a7e3a7Sitojun 		return (EINVAL);
632d8a7e3a7Sitojun 	if (lt->ia6t_vltime == 0) {
633287546eaSitojun 		/*
634d8a7e3a7Sitojun 		 * the following log might be noisy, but this is a typical
635d8a7e3a7Sitojun 		 * configuration mistake or a tool's bug.
636287546eaSitojun 		 */
637d61e4f47Sbluhm 		nd6log((LOG_INFO, "%s: valid lifetime is 0 for %s\n", __func__,
638bbcf0337Smpi 		    inet_ntop(AF_INET6, &ifra->ifra_addr.sin6_addr,
639bbcf0337Smpi 		    addr, sizeof(addr))));
640d8a7e3a7Sitojun 
641b9e83c60Sbluhm 		if (ia6 == NULL)
642d8a7e3a7Sitojun 			return (0); /* there's nothing to do */
643287546eaSitojun 	}
644287546eaSitojun 
645d8a7e3a7Sitojun 	/*
646d8a7e3a7Sitojun 	 * If this is a new address, allocate a new ifaddr and link it
647d8a7e3a7Sitojun 	 * into chains.
648d8a7e3a7Sitojun 	 */
649b9e83c60Sbluhm 	if (ia6 == NULL) {
650d8a7e3a7Sitojun 		hostIsNew = 1;
651b9e83c60Sbluhm 		ia6 = malloc(sizeof(*ia6), M_IFADDR, M_WAITOK | M_ZERO);
65218a44669Sbluhm 		refcnt_init_trace(&ia6->ia_ifa.ifa_refcnt,
65318a44669Sbluhm 		    DT_REFCNT_IDX_IFADDR);
654b9e83c60Sbluhm 		LIST_INIT(&ia6->ia6_memberships);
655d8a7e3a7Sitojun 		/* Initialize the address and masks, and put time stamp */
656b9e83c60Sbluhm 		ia6->ia_ifa.ifa_addr = sin6tosa(&ia6->ia_addr);
657b9e83c60Sbluhm 		ia6->ia_addr.sin6_family = AF_INET6;
658b9e83c60Sbluhm 		ia6->ia_addr.sin6_len = sizeof(ia6->ia_addr);
6593209772dScheloha 		ia6->ia6_updatetime = getuptime();
6607186e918Sflorian 		if ((ifp->if_flags & IFF_POINTOPOINT) ||
6617186e918Sflorian 		    (ifp->if_flags & IFF_LOOPBACK)) {
662d8a7e3a7Sitojun 			/*
663d8a7e3a7Sitojun 			 * XXX: some functions expect that ifa_dstaddr is not
664d8a7e3a7Sitojun 			 * NULL for p2p interfaces.
665d8a7e3a7Sitojun 			 */
666b9e83c60Sbluhm 			ia6->ia_ifa.ifa_dstaddr = sin6tosa(&ia6->ia_dstaddr);
667d8a7e3a7Sitojun 		} else {
668b9e83c60Sbluhm 			ia6->ia_ifa.ifa_dstaddr = NULL;
669d8a7e3a7Sitojun 		}
670b9e83c60Sbluhm 		ia6->ia_ifa.ifa_netmask = sin6tosa(&ia6->ia_prefixmask);
671287546eaSitojun 
672b9e83c60Sbluhm 		ia6->ia_ifp = ifp;
673b9e83c60Sbluhm 		ia6->ia_addr = ifra->ifra_addr;
674b9e83c60Sbluhm 		ifa_add(ifp, &ia6->ia_ifa);
675d8a7e3a7Sitojun 	}
676d8a7e3a7Sitojun 
677d8a7e3a7Sitojun 	/* set prefix mask */
678d8a7e3a7Sitojun 	if (ifra->ifra_prefixmask.sin6_len) {
679d8a7e3a7Sitojun 		/*
680d8a7e3a7Sitojun 		 * We prohibit changing the prefix length of an existing
681d8a7e3a7Sitojun 		 * address, because
682d8a7e3a7Sitojun 		 * + such an operation should be rare in IPv6, and
683d8a7e3a7Sitojun 		 * + the operation would confuse prefix management.
684d8a7e3a7Sitojun 		 */
685b9e83c60Sbluhm 		if (ia6->ia_prefixmask.sin6_len &&
686b9e83c60Sbluhm 		    in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL) != plen) {
687d8a7e3a7Sitojun 			error = EINVAL;
688d8a7e3a7Sitojun 			goto unlink;
689d8a7e3a7Sitojun 		}
690b9e83c60Sbluhm 		ia6->ia_prefixmask = ifra->ifra_prefixmask;
691d8a7e3a7Sitojun 	}
692d8a7e3a7Sitojun 
693d8a7e3a7Sitojun 	/*
694d8a7e3a7Sitojun 	 * If a new destination address is specified, scrub the old one and
6957186e918Sflorian 	 * install the new destination.
696d8a7e3a7Sitojun 	 */
6977186e918Sflorian 	if (((ifp->if_flags & IFF_POINTOPOINT)  ||
6987186e918Sflorian 	    (ifp->if_flags & IFF_LOOPBACK)) && dst6.sin6_family == AF_INET6 &&
699b9e83c60Sbluhm 	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia6->ia_dstaddr.sin6_addr)) {
700daed62aeSmpi 		struct ifaddr *ifa = &ia6->ia_ifa;
701d8a7e3a7Sitojun 
702b9e83c60Sbluhm 		if ((ia6->ia_flags & IFA_ROUTE) != 0 &&
7038f960e22Sdlg 		    rt_ifa_del(ifa, RTF_HOST, ifa->ifa_dstaddr,
7048f960e22Sdlg 		     ifp->if_rdomain) != 0) {
705d61e4f47Sbluhm 			nd6log((LOG_ERR, "%s: failed to remove a route "
706d61e4f47Sbluhm 			    "to the old destination: %s\n", __func__,
707b9e83c60Sbluhm 			    inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr,
708bbcf0337Smpi 			    addr, sizeof(addr))));
709d8a7e3a7Sitojun 			/* proceed anyway... */
710d8a7e3a7Sitojun 		} else
711b9e83c60Sbluhm 			ia6->ia_flags &= ~IFA_ROUTE;
712b9e83c60Sbluhm 		ia6->ia_dstaddr = dst6;
713d8a7e3a7Sitojun 	}
714d8a7e3a7Sitojun 
7157186e918Sflorian 	if ((ifra->ifra_flags & IN6_IFF_AUTOCONF) &&
716*1fddfc45Sflorian 	    gw6.sin6_family == AF_INET6 &&
7177186e918Sflorian 	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia6->ia_gwaddr.sin6_addr)) {
7187186e918Sflorian 		/* Set or update announcing router */
719*1fddfc45Sflorian 		ia6->ia_gwaddr = gw6;
7207186e918Sflorian 	}
7217186e918Sflorian 
722d8a7e3a7Sitojun 	/*
723d8a7e3a7Sitojun 	 * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
724d8a7e3a7Sitojun 	 * to see if the address is deprecated or invalidated, but initialize
725d8a7e3a7Sitojun 	 * these members for applications.
726d8a7e3a7Sitojun 	 */
7273209772dScheloha 	ia6->ia6_updatetime = getuptime();
728b9e83c60Sbluhm 	ia6->ia6_lifetime = ifra->ifra_lifetime;
729b9e83c60Sbluhm 	if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
730b9e83c60Sbluhm 		ia6->ia6_lifetime.ia6t_expire =
7313209772dScheloha 		    getuptime() + ia6->ia6_lifetime.ia6t_vltime;
732287546eaSitojun 	} else
733b9e83c60Sbluhm 		ia6->ia6_lifetime.ia6t_expire = 0;
734b9e83c60Sbluhm 	if (ia6->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
735b9e83c60Sbluhm 		ia6->ia6_lifetime.ia6t_preferred =
7363209772dScheloha 		    getuptime() + ia6->ia6_lifetime.ia6t_pltime;
737287546eaSitojun 	} else
738b9e83c60Sbluhm 		ia6->ia6_lifetime.ia6t_preferred = 0;
739287546eaSitojun 
740d8a7e3a7Sitojun 	/* reset the interface and routing table appropriately. */
741b9e83c60Sbluhm 	if ((error = in6_ifinit(ifp, ia6, hostIsNew)) != 0)
742d8a7e3a7Sitojun 		goto unlink;
743d8a7e3a7Sitojun 
744d505a6a7Sflorian 	/* re-run DAD */
745d505a6a7Sflorian 	if (ia6->ia6_flags & (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED))
746d505a6a7Sflorian 		ifra->ifra_flags |= IN6_IFF_TENTATIVE;
747287546eaSitojun 	/*
7487d37e67aSitojun 	 * configure address flags.
7497d37e67aSitojun 	 */
750b9e83c60Sbluhm 	ia6->ia6_flags = ifra->ifra_flags;
751d8a7e3a7Sitojun 
752c6bbd2a8Sflorian 	nd6_expire_timer_update(ia6);
753c6bbd2a8Sflorian 
754d8a7e3a7Sitojun 	/*
755c61d7628Sitojun 	 * We are done if we have simply modified an existing address.
756c61d7628Sitojun 	 */
7576859a790Sflorian 	if (!hostIsNew) {
7586859a790Sflorian 		/* DAD sends RTM_CHGADDRATTR when done. */
7596859a790Sflorian 		if (!(ia6->ia6_flags & IN6_IFF_TENTATIVE))
7606859a790Sflorian 			rtm_addr(RTM_CHGADDRATTR, &ia6->ia_ifa);
761c61d7628Sitojun 		return (error);
7626859a790Sflorian 	}
763c61d7628Sitojun 
764c61d7628Sitojun 	/*
765d8a7e3a7Sitojun 	 * Beyond this point, we should call in6_purgeaddr upon an error,
766d8a7e3a7Sitojun 	 * not just go to unlink.
767d8a7e3a7Sitojun 	 */
768d8a7e3a7Sitojun 
769c61d7628Sitojun 	/* join necessary multiast groups */
770d8a7e3a7Sitojun 	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
771d8a7e3a7Sitojun 		struct sockaddr_in6 mltaddr, mltmask;
772287546eaSitojun 
773d8a7e3a7Sitojun 		/* join solicited multicast addr for new host id */
774d8a7e3a7Sitojun 		struct sockaddr_in6 llsol;
775287546eaSitojun 
776d8a7e3a7Sitojun 		bzero(&llsol, sizeof(llsol));
777d8a7e3a7Sitojun 		llsol.sin6_family = AF_INET6;
778d8a7e3a7Sitojun 		llsol.sin6_len = sizeof(llsol);
779d8a7e3a7Sitojun 		llsol.sin6_addr.s6_addr16[0] = htons(0xff02);
780d8a7e3a7Sitojun 		llsol.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
781d8a7e3a7Sitojun 		llsol.sin6_addr.s6_addr32[1] = 0;
782d8a7e3a7Sitojun 		llsol.sin6_addr.s6_addr32[2] = htonl(1);
783d8a7e3a7Sitojun 		llsol.sin6_addr.s6_addr32[3] =
784d8a7e3a7Sitojun 		    ifra->ifra_addr.sin6_addr.s6_addr32[3];
785d8a7e3a7Sitojun 		llsol.sin6_addr.s6_addr8[12] = 0xff;
786c61d7628Sitojun 		imm = in6_joingroup(ifp, &llsol.sin6_addr, &error);
7873236de58Smpi 		if (!imm)
788d8a7e3a7Sitojun 			goto cleanup;
789b9e83c60Sbluhm 		LIST_INSERT_HEAD(&ia6->ia6_memberships, imm, i6mm_chain);
790d8a7e3a7Sitojun 
791d8a7e3a7Sitojun 		bzero(&mltmask, sizeof(mltmask));
792d8a7e3a7Sitojun 		mltmask.sin6_len = sizeof(struct sockaddr_in6);
793d8a7e3a7Sitojun 		mltmask.sin6_family = AF_INET6;
794d8a7e3a7Sitojun 		mltmask.sin6_addr = in6mask32;
795d8a7e3a7Sitojun 
796d8a7e3a7Sitojun 		/*
797d8a7e3a7Sitojun 		 * join link-local all-nodes address
798d8a7e3a7Sitojun 		 */
799d8a7e3a7Sitojun 		bzero(&mltaddr, sizeof(mltaddr));
800d8a7e3a7Sitojun 		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
801d8a7e3a7Sitojun 		mltaddr.sin6_family = AF_INET6;
802d8a7e3a7Sitojun 		mltaddr.sin6_addr = in6addr_linklocal_allnodes;
803d8a7e3a7Sitojun 		mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
804d4070096Sitojun 		mltaddr.sin6_scope_id = 0;
805d8a7e3a7Sitojun 
806d8a7e3a7Sitojun 		/*
807d8a7e3a7Sitojun 		 * XXX: do we really need this automatic routes?
808d8a7e3a7Sitojun 		 * We should probably reconsider this stuff.  Most applications
809d8a7e3a7Sitojun 		 * actually do not need the routes, since they usually specify
810d8a7e3a7Sitojun 		 * the outgoing interface.
811d8a7e3a7Sitojun 		 */
8125148b194Smpi 		rt = rtalloc(sin6tosa(&mltaddr), 0, ifp->if_rdomain);
813d8a7e3a7Sitojun 		if (rt) {
81466f69fe1Smpi 			/* 32bit came from "mltmask" */
815d8a7e3a7Sitojun 			if (memcmp(&mltaddr.sin6_addr,
816c3c56496Sbluhm 			    &satosin6(rt_key(rt))->sin6_addr,
817d8a7e3a7Sitojun 			    32 / 8)) {
81827ae666cSmpi 				rtfree(rt);
819d8a7e3a7Sitojun 				rt = NULL;
820d8a7e3a7Sitojun 			}
821d8a7e3a7Sitojun 		}
822d8a7e3a7Sitojun 		if (!rt) {
823d8a7e3a7Sitojun 			struct rt_addrinfo info;
824d8a7e3a7Sitojun 
825d8a7e3a7Sitojun 			bzero(&info, sizeof(info));
82666f69fe1Smpi 			info.rti_ifa = &ia6->ia_ifa;
827c3c56496Sbluhm 			info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
8283ccf3a0fSmpi 			info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr);
829c3c56496Sbluhm 			info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask);
830b9e83c60Sbluhm 			info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr);
831b71b7f0aSmpi 			info.rti_flags = RTF_MULTICAST;
8327ffb277fSbluhm 			error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, NULL,
833ba79ddd5Ssperreault 			    ifp->if_rdomain);
834d8a7e3a7Sitojun 			if (error)
835d8a7e3a7Sitojun 				goto cleanup;
836d8a7e3a7Sitojun 		} else {
83727ae666cSmpi 			rtfree(rt);
838d8a7e3a7Sitojun 		}
839d8a7e3a7Sitojun 		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
8403236de58Smpi 		if (!imm)
841d8a7e3a7Sitojun 			goto cleanup;
842b9e83c60Sbluhm 		LIST_INSERT_HEAD(&ia6->ia6_memberships, imm, i6mm_chain);
843d8a7e3a7Sitojun 
844d8a7e3a7Sitojun 		/*
845d4070096Sitojun 		 * join interface-local all-nodes address.
846d8a7e3a7Sitojun 		 * (ff01::1%ifN, and ff01::%ifN/32)
847d8a7e3a7Sitojun 		 */
8489c794535Sbluhm 		bzero(&mltaddr, sizeof(mltaddr));
849d4070096Sitojun 		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
850d4070096Sitojun 		mltaddr.sin6_family = AF_INET6;
851d4070096Sitojun 		mltaddr.sin6_addr = in6addr_intfacelocal_allnodes;
852d4070096Sitojun 		mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
853d4070096Sitojun 		mltaddr.sin6_scope_id = 0;
854d8a7e3a7Sitojun 
855d8a7e3a7Sitojun 		/* XXX: again, do we really need the route? */
8565148b194Smpi 		rt = rtalloc(sin6tosa(&mltaddr), 0, ifp->if_rdomain);
857d8a7e3a7Sitojun 		if (rt) {
858d8a7e3a7Sitojun 			/* 32bit came from "mltmask" */
859d8a7e3a7Sitojun 			if (memcmp(&mltaddr.sin6_addr,
860c3c56496Sbluhm 			    &satosin6(rt_key(rt))->sin6_addr,
861d8a7e3a7Sitojun 			    32 / 8)) {
86227ae666cSmpi 				rtfree(rt);
863d8a7e3a7Sitojun 				rt = NULL;
864d8a7e3a7Sitojun 			}
865d8a7e3a7Sitojun 		}
866d8a7e3a7Sitojun 		if (!rt) {
867d8a7e3a7Sitojun 			struct rt_addrinfo info;
868d8a7e3a7Sitojun 
869d8a7e3a7Sitojun 			bzero(&info, sizeof(info));
87066f69fe1Smpi 			info.rti_ifa = &ia6->ia_ifa;
871c3c56496Sbluhm 			info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
8723ccf3a0fSmpi 			info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr);
873c3c56496Sbluhm 			info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask);
874b9e83c60Sbluhm 			info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr);
875b71b7f0aSmpi 			info.rti_flags = RTF_MULTICAST;
8767ffb277fSbluhm 			error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, NULL,
8770ffd01d4Sbluhm 			    ifp->if_rdomain);
878d8a7e3a7Sitojun 			if (error)
879d8a7e3a7Sitojun 				goto cleanup;
880d8a7e3a7Sitojun 		} else {
88127ae666cSmpi 			rtfree(rt);
882d8a7e3a7Sitojun 		}
883c61d7628Sitojun 		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
8843236de58Smpi 		if (!imm)
885d8a7e3a7Sitojun 			goto cleanup;
886b9e83c60Sbluhm 		LIST_INSERT_HEAD(&ia6->ia6_memberships, imm, i6mm_chain);
887d8a7e3a7Sitojun 	}
888d8a7e3a7Sitojun 
889287546eaSitojun 	return (error);
890287546eaSitojun 
891d8a7e3a7Sitojun   unlink:
892d8a7e3a7Sitojun 	/*
893d8a7e3a7Sitojun 	 * XXX: if a change of an existing address failed, keep the entry
894d8a7e3a7Sitojun 	 * anyway.
895d8a7e3a7Sitojun 	 */
896d8a7e3a7Sitojun 	if (hostIsNew)
897b9e83c60Sbluhm 		in6_unlink_ifa(ia6, ifp);
898d8a7e3a7Sitojun 	return (error);
89922770369Sitojun 
900d8a7e3a7Sitojun   cleanup:
901b9e83c60Sbluhm 	in6_purgeaddr(&ia6->ia_ifa);
902d8a7e3a7Sitojun 	return error;
90322770369Sitojun }
90422770369Sitojun 
90522770369Sitojun void
in6_purgeaddr(struct ifaddr * ifa)906ee37ea65Smcbride in6_purgeaddr(struct ifaddr *ifa)
90722770369Sitojun {
908d8a7e3a7Sitojun 	struct ifnet *ifp = ifa->ifa_ifp;
9099ea9b1e7Smpi 	struct in6_ifaddr *ia6 = ifatoia6(ifa);
910d8a7e3a7Sitojun 	struct in6_multi_mship *imm;
91122770369Sitojun 
912b0d0a571Sitojun 	/* stop DAD processing */
913b0d0a571Sitojun 	nd6_dad_stop(ifa);
914b0d0a571Sitojun 
915287546eaSitojun 	/*
916d8a7e3a7Sitojun 	 * delete route to the destination of the address being purged.
917d8a7e3a7Sitojun 	 * The interface must be p2p or loopback in this case.
918287546eaSitojun 	 */
9196c41171aSmpi 	if ((ifp->if_flags & IFF_POINTOPOINT) && (ia6->ia_flags & IFA_ROUTE) &&
9206c41171aSmpi 	    ia6->ia_dstaddr.sin6_len != 0) {
921d8a7e3a7Sitojun 		int e;
922287546eaSitojun 
9238f960e22Sdlg 		e = rt_ifa_del(ifa, RTF_HOST, ifa->ifa_dstaddr,
9248f960e22Sdlg 		    ifp->if_rdomain);
9258f960e22Sdlg 		if (e != 0) {
926bbcf0337Smpi 			char addr[INET6_ADDRSTRLEN];
927d8a7e3a7Sitojun 			log(LOG_ERR, "in6_purgeaddr: failed to remove "
928d8a7e3a7Sitojun 			    "a route to the p2p destination: %s on %s, "
929d8a7e3a7Sitojun 			    "errno=%d\n",
930b9e83c60Sbluhm 			    inet_ntop(AF_INET6, &ia6->ia_addr.sin6_addr,
931bbcf0337Smpi 				addr, sizeof(addr)),
932bbcf0337Smpi 			    ifp->if_xname, e);
933d8a7e3a7Sitojun 			/* proceed anyway... */
934d8a7e3a7Sitojun 		} else
935b9e83c60Sbluhm 			ia6->ia_flags &= ~IFA_ROUTE;
936287546eaSitojun 	}
937287546eaSitojun 
9389ea9b1e7Smpi 	/* Remove ownaddr's loopback rtentry, if it exists. */
939dfa661caSmpi 	rt_ifa_dellocal(&(ia6->ia_ifa));
940d8a7e3a7Sitojun 
941d8a7e3a7Sitojun 	/*
942d8a7e3a7Sitojun 	 * leave from multicast groups we have joined for the interface
943d8a7e3a7Sitojun 	 */
944b9e83c60Sbluhm 	while (!LIST_EMPTY(&ia6->ia6_memberships)) {
945b9e83c60Sbluhm 		imm = LIST_FIRST(&ia6->ia6_memberships);
946d8a7e3a7Sitojun 		LIST_REMOVE(imm, i6mm_chain);
947d8a7e3a7Sitojun 		in6_leavegroup(imm);
948d8a7e3a7Sitojun 	}
949d8a7e3a7Sitojun 
950b9e83c60Sbluhm 	in6_unlink_ifa(ia6, ifp);
951d8a7e3a7Sitojun }
952d8a7e3a7Sitojun 
953525dbc5aSjsing void
in6_unlink_ifa(struct in6_ifaddr * ia6,struct ifnet * ifp)954b9e83c60Sbluhm in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp)
955d8a7e3a7Sitojun {
956ef6620bcSmpi 	struct ifaddr *ifa = &ia6->ia_ifa;
95790e1bc04Smpi 	int plen;
958ef6620bcSmpi 
95966736630Smpi 	NET_ASSERT_LOCKED();
960d8a7e3a7Sitojun 
961203dbc93Sbluhm 	/* Release the reference to the base prefix. */
96290e1bc04Smpi 	plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
96390e1bc04Smpi 	if ((ifp->if_flags & IFF_LOOPBACK) == 0 && plen != 128) {
96467f077d8Smpi 		rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED,
9658f960e22Sdlg 		    ifa->ifa_addr, ifp->if_rdomain);
96667f077d8Smpi 	}
967d8a7e3a7Sitojun 
96803edf7baSmpi 	rt_ifa_purge(ifa);
96903edf7baSmpi 	ifa_del(ifp, ifa);
97003edf7baSmpi 
97103edf7baSmpi 	ia6->ia_ifp = NULL;
972f42926caSkn 	ifafree(ifa);
973d8a7e3a7Sitojun }
974d8a7e3a7Sitojun 
975287546eaSitojun /*
976df8d9afdSjsg  * Initialize an interface's inet6 address
977287546eaSitojun  * and routing table entry.
978287546eaSitojun  */
979525dbc5aSjsing int
in6_ifinit(struct ifnet * ifp,struct in6_ifaddr * ia6,int newhost)980b9e83c60Sbluhm in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost)
981d3b325d0Sderaadt {
982d8a7e3a7Sitojun 	int	error = 0, plen, ifacount = 0;
983d8a7e3a7Sitojun 	struct ifaddr *ifa;
984d3b325d0Sderaadt 
98566736630Smpi 	NET_ASSERT_LOCKED();
986fafd72b5Smpi 
987d3b325d0Sderaadt 	/*
988d3b325d0Sderaadt 	 * Give the interface a chance to initialize
989f33d0285Smcbride 	 * if this is its first address (or it is a CARP interface)
990d3b325d0Sderaadt 	 * and to validate the address if necessary.
991d3b325d0Sderaadt 	 */
9921573508eSmiod 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
993d8a7e3a7Sitojun 		if (ifa->ifa_addr->sa_family != AF_INET6)
994d8a7e3a7Sitojun 			continue;
995d8a7e3a7Sitojun 		ifacount++;
996d8a7e3a7Sitojun 	}
997d8a7e3a7Sitojun 
9987da1c795Smpi 	if ((ifacount <= 1 || ifp->if_type == IFT_CARP ||
999ddeaef8bSmpi 	    (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))) &&
1000b9e83c60Sbluhm 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia6))) {
1001287546eaSitojun 		return (error);
1002d3b325d0Sderaadt 	}
1003d8a7e3a7Sitojun 
1004b9e83c60Sbluhm 	ia6->ia_ifa.ifa_metric = ifp->if_metric;
1005d8a7e3a7Sitojun 
1006d8a7e3a7Sitojun 	/* we could do in(6)_socktrim here, but just omit it at this moment. */
1007d8a7e3a7Sitojun 
1008d8a7e3a7Sitojun 	/*
1009d8a7e3a7Sitojun 	 * Special case:
1010d8a7e3a7Sitojun 	 * If the destination address is specified for a point-to-point
1011d8a7e3a7Sitojun 	 * interface, install a route to the destination as an interface
1012d8a7e3a7Sitojun 	 * direct route.
1013d8a7e3a7Sitojun 	 */
1014b9e83c60Sbluhm 	plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL); /* XXX */
10156c41171aSmpi 	if ((ifp->if_flags & IFF_POINTOPOINT) && plen == 128 &&
10166c41171aSmpi 	    ia6->ia_dstaddr.sin6_family == AF_INET6) {
1017daed62aeSmpi 		ifa = &ia6->ia_ifa;
101862cb75b3Sdlg 		error = rt_ifa_add(ifa, RTF_HOST | RTF_MPATH,
10198f960e22Sdlg 		    ifa->ifa_dstaddr, ifp->if_rdomain);
1020daed62aeSmpi 		if (error != 0)
1021d8a7e3a7Sitojun 			return (error);
1022b9e83c60Sbluhm 		ia6->ia_flags |= IFA_ROUTE;
1023d8a7e3a7Sitojun 	}
1024d3b325d0Sderaadt 
1025dcb17c31Smpi 	if (newhost)
1026f68cfd0eSmpi 		error = rt_ifa_addlocal(&(ia6->ia_ifa));
1027287546eaSitojun 
1028287546eaSitojun 	return (error);
1029287546eaSitojun }
1030287546eaSitojun 
1031287546eaSitojun /*
1032287546eaSitojun  * Add an address to the list of IP6 multicast addresses for a
1033287546eaSitojun  * given interface.
1034287546eaSitojun  */
1035287546eaSitojun struct in6_multi *
in6_addmulti(struct in6_addr * maddr6,struct ifnet * ifp,int * errorp)1036ee37ea65Smcbride in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp, int *errorp)
1037287546eaSitojun {
1038287546eaSitojun 	struct	in6_ifreq ifr;
1039287546eaSitojun 	struct	in6_multi *in6m;
1040f9fc830cSmpi 
104166736630Smpi 	NET_ASSERT_LOCKED();
1042287546eaSitojun 
1043287546eaSitojun 	*errorp = 0;
1044287546eaSitojun 	/*
1045287546eaSitojun 	 * See if address already in list.
1046287546eaSitojun 	 */
1047287546eaSitojun 	IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
1048287546eaSitojun 	if (in6m != NULL) {
1049287546eaSitojun 		/*
1050678831beSjsg 		 * Found it; just increment the reference count.
1051287546eaSitojun 		 */
1052a409c69cSkn 		refcnt_take(&in6m->in6m_refcnt);
1053287546eaSitojun 	} else {
1054287546eaSitojun 		/*
1055287546eaSitojun 		 * New address; allocate a new multicast record
1056287546eaSitojun 		 * and link it into the interface's multicast list.
1057287546eaSitojun 		 */
10589c794535Sbluhm 		in6m = malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT | M_ZERO);
1059287546eaSitojun 		if (in6m == NULL) {
1060287546eaSitojun 			*errorp = ENOBUFS;
1061287546eaSitojun 			return (NULL);
1062287546eaSitojun 		}
10632bea58a8Smpi 
10642bea58a8Smpi 		in6m->in6m_sin.sin6_len = sizeof(struct sockaddr_in6);
10652bea58a8Smpi 		in6m->in6m_sin.sin6_family = AF_INET6;
10662bea58a8Smpi 		in6m->in6m_sin.sin6_addr = *maddr6;
1067a409c69cSkn 		refcnt_init_trace(&in6m->in6m_refcnt, DT_REFCNT_IDX_IFMADDR);
106833082e9fSmpi 		in6m->in6m_ifidx = ifp->if_index;
10692bea58a8Smpi 		in6m->in6m_ifma.ifma_addr = sin6tosa(&in6m->in6m_sin);
1070d3b325d0Sderaadt 
1071d3b325d0Sderaadt 		/*
1072d3b325d0Sderaadt 		 * Ask the network driver to update its multicast reception
1073d3b325d0Sderaadt 		 * filter appropriately for the new address.
1074d3b325d0Sderaadt 		 */
10752bea58a8Smpi 		memcpy(&ifr.ifr_addr, &in6m->in6m_sin, sizeof(in6m->in6m_sin));
1076bfb4dd3fSmvs 		KERNEL_LOCK();
10772bea58a8Smpi 		*errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
1078bfb4dd3fSmvs 		KERNEL_UNLOCK();
1079287546eaSitojun 		if (*errorp) {
1080c90e561bStedu 			free(in6m, M_IPMADDR, sizeof(*in6m));
1081287546eaSitojun 			return (NULL);
1082d3b325d0Sderaadt 		}
10832bea58a8Smpi 
10842bea58a8Smpi 		TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &in6m->in6m_ifma,
10852bea58a8Smpi 		    ifma_list);
10862bea58a8Smpi 
1087287546eaSitojun 		/*
1088287546eaSitojun 		 * Let MLD6 know that we have joined a new IP6 multicast
1089287546eaSitojun 		 * group.
1090287546eaSitojun 		 */
1091287546eaSitojun 		mld6_start_listening(in6m);
1092d3b325d0Sderaadt 	}
10932bea58a8Smpi 
1094287546eaSitojun 	return (in6m);
1095d3b325d0Sderaadt }
1096d3b325d0Sderaadt 
1097d3b325d0Sderaadt /*
1098287546eaSitojun  * Delete a multicast address record.
1099d3b325d0Sderaadt  */
1100287546eaSitojun void
in6_delmulti(struct in6_multi * in6m)1101ee37ea65Smcbride in6_delmulti(struct in6_multi *in6m)
1102287546eaSitojun {
1103287546eaSitojun 	struct	in6_ifreq ifr;
11042bea58a8Smpi 	struct	ifnet *ifp;
1105f9fc830cSmpi 
110666736630Smpi 	NET_ASSERT_LOCKED();
1107d3b325d0Sderaadt 
1108a409c69cSkn 	if (refcnt_rele(&in6m->in6m_refcnt) != 0) {
1109287546eaSitojun 		/*
1110287546eaSitojun 		 * No remaining claims to this record; let MLD6 know
1111287546eaSitojun 		 * that we are leaving the multicast group.
1112287546eaSitojun 		 */
1113287546eaSitojun 		mld6_stop_listening(in6m);
111433082e9fSmpi 		ifp = if_get(in6m->in6m_ifidx);
1115287546eaSitojun 
1116287546eaSitojun 		/*
1117287546eaSitojun 		 * Notify the network driver to update its multicast
1118287546eaSitojun 		 * reception filter.
1119287546eaSitojun 		 */
112033082e9fSmpi 		if (ifp != NULL) {
1121287546eaSitojun 			bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
1122287546eaSitojun 			ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
1123287546eaSitojun 			ifr.ifr_addr.sin6_family = AF_INET6;
1124287546eaSitojun 			ifr.ifr_addr.sin6_addr = in6m->in6m_addr;
11254b9a5ba9Svisa 			KERNEL_LOCK();
112633082e9fSmpi 			(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
11274b9a5ba9Svisa 			KERNEL_UNLOCK();
11282bea58a8Smpi 
112933082e9fSmpi 			TAILQ_REMOVE(&ifp->if_maddrlist, &in6m->in6m_ifma,
113033082e9fSmpi 			    ifma_list);
113133082e9fSmpi 		}
113202ca5288Sclaudio 		if_put(ifp);
11332bea58a8Smpi 
1134c90e561bStedu 		free(in6m, M_IPMADDR, sizeof(*in6m));
1135d3b325d0Sderaadt 	}
1136d3b325d0Sderaadt }
1137287546eaSitojun 
113834dbf6d6Smpi /*
113934dbf6d6Smpi  * Return 1 if the multicast group represented by ``maddr6'' has been
114034dbf6d6Smpi  * joined by interface ``ifp'', 0 otherwise.
114134dbf6d6Smpi  */
114234dbf6d6Smpi int
in6_hasmulti(struct in6_addr * maddr6,struct ifnet * ifp)114334dbf6d6Smpi in6_hasmulti(struct in6_addr *maddr6, struct ifnet *ifp)
114434dbf6d6Smpi {
114534dbf6d6Smpi 	struct in6_multi *in6m;
114634dbf6d6Smpi 	int joined;
114734dbf6d6Smpi 
114834dbf6d6Smpi 	IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
114934dbf6d6Smpi 	joined = (in6m != NULL);
115034dbf6d6Smpi 
115134dbf6d6Smpi 	return (joined);
115234dbf6d6Smpi }
115334dbf6d6Smpi 
11547b2ccaf7Sitojun struct in6_multi_mship *
in6_joingroup(struct ifnet * ifp,struct in6_addr * addr,int * errorp)1155ee37ea65Smcbride in6_joingroup(struct ifnet *ifp, struct in6_addr *addr, int *errorp)
11567b2ccaf7Sitojun {
11577b2ccaf7Sitojun 	struct in6_multi_mship *imm;
11587b2ccaf7Sitojun 
11597b2ccaf7Sitojun 	imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT);
11607b2ccaf7Sitojun 	if (!imm) {
11617b2ccaf7Sitojun 		*errorp = ENOBUFS;
11627b2ccaf7Sitojun 		return NULL;
11637b2ccaf7Sitojun 	}
11647b2ccaf7Sitojun 	imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp);
11657b2ccaf7Sitojun 	if (!imm->i6mm_maddr) {
1166678831beSjsg 		/* *errorp is already set */
1167c90e561bStedu 		free(imm, M_IPMADDR, sizeof(*imm));
11687b2ccaf7Sitojun 		return NULL;
11697b2ccaf7Sitojun 	}
11707b2ccaf7Sitojun 	return imm;
11717b2ccaf7Sitojun }
11727b2ccaf7Sitojun 
1173743125a4Sflorian void
in6_leavegroup(struct in6_multi_mship * imm)1174525dbc5aSjsing in6_leavegroup(struct in6_multi_mship *imm)
11757b2ccaf7Sitojun {
11767b2ccaf7Sitojun 
11777b2ccaf7Sitojun 	if (imm->i6mm_maddr)
11787b2ccaf7Sitojun 		in6_delmulti(imm->i6mm_maddr);
1179c90e561bStedu 	free(imm,  M_IPMADDR, sizeof(*imm));
11807b2ccaf7Sitojun }
11817b2ccaf7Sitojun 
1182287546eaSitojun /*
1183287546eaSitojun  * Find an IPv6 interface link-local address specific to an interface.
1184287546eaSitojun  */
1185287546eaSitojun struct in6_ifaddr *
in6ifa_ifpforlinklocal(struct ifnet * ifp,int ignoreflags)1186ee37ea65Smcbride in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
1187287546eaSitojun {
11889063e41fSitojun 	struct ifaddr *ifa;
1189287546eaSitojun 
11901573508eSmiod 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1191287546eaSitojun 		if (ifa->ifa_addr->sa_family != AF_INET6)
1192287546eaSitojun 			continue;
1193f4f4d166Sitojun 		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
1194de654afdSbluhm 			if ((ifatoia6(ifa)->ia6_flags & ignoreflags) != 0)
1195f4f4d166Sitojun 				continue;
1196287546eaSitojun 			break;
1197287546eaSitojun 		}
1198f4f4d166Sitojun 	}
1199287546eaSitojun 
12006143cd01Sbluhm 	return (ifatoia6(ifa));
1201287546eaSitojun }
1202287546eaSitojun 
1203287546eaSitojun 
1204287546eaSitojun /*
1205287546eaSitojun  * find the internet address corresponding to a given interface and address.
1206287546eaSitojun  */
1207287546eaSitojun struct in6_ifaddr *
in6ifa_ifpwithaddr(struct ifnet * ifp,struct in6_addr * addr)1208ee37ea65Smcbride in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
1209287546eaSitojun {
12109063e41fSitojun 	struct ifaddr *ifa;
1211287546eaSitojun 
12121573508eSmiod 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1213287546eaSitojun 		if (ifa->ifa_addr->sa_family != AF_INET6)
1214287546eaSitojun 			continue;
1215287546eaSitojun 		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
1216287546eaSitojun 			break;
1217287546eaSitojun 	}
1218287546eaSitojun 
12196143cd01Sbluhm 	return (ifatoia6(ifa));
1220287546eaSitojun }
1221287546eaSitojun 
1222287546eaSitojun /*
1223287546eaSitojun  * Get a scope of the address. Node-local, link-local, site-local or global.
1224287546eaSitojun  */
1225287546eaSitojun int
in6_addrscope(struct in6_addr * addr)1226ee37ea65Smcbride in6_addrscope(struct in6_addr *addr)
1227287546eaSitojun {
1228287546eaSitojun 	int scope;
1229287546eaSitojun 
1230287546eaSitojun 	if (addr->s6_addr8[0] == 0xfe) {
1231287546eaSitojun 		scope = addr->s6_addr8[1] & 0xc0;
1232287546eaSitojun 
1233287546eaSitojun 		switch (scope) {
1234287546eaSitojun 		case 0x80:
12355453c090Sderaadt 			return __IPV6_ADDR_SCOPE_LINKLOCAL;
1236287546eaSitojun 			break;
1237287546eaSitojun 		case 0xc0:
12385453c090Sderaadt 			return __IPV6_ADDR_SCOPE_SITELOCAL;
1239287546eaSitojun 			break;
1240287546eaSitojun 		default:
12415453c090Sderaadt 			return __IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
1242287546eaSitojun 			break;
1243287546eaSitojun 		}
1244287546eaSitojun 	}
1245287546eaSitojun 
1246287546eaSitojun 
1247287546eaSitojun 	if (addr->s6_addr8[0] == 0xff) {
1248287546eaSitojun 		scope = addr->s6_addr8[1] & 0x0f;
1249287546eaSitojun 
1250287546eaSitojun 		/*
1251287546eaSitojun 		 * due to other scope such as reserved,
1252287546eaSitojun 		 * return scope doesn't work.
1253287546eaSitojun 		 */
1254287546eaSitojun 		switch (scope) {
12555453c090Sderaadt 		case __IPV6_ADDR_SCOPE_INTFACELOCAL:
12565453c090Sderaadt 			return __IPV6_ADDR_SCOPE_INTFACELOCAL;
1257287546eaSitojun 			break;
12585453c090Sderaadt 		case __IPV6_ADDR_SCOPE_LINKLOCAL:
12595453c090Sderaadt 			return __IPV6_ADDR_SCOPE_LINKLOCAL;
1260287546eaSitojun 			break;
12615453c090Sderaadt 		case __IPV6_ADDR_SCOPE_SITELOCAL:
12625453c090Sderaadt 			return __IPV6_ADDR_SCOPE_SITELOCAL;
1263287546eaSitojun 			break;
1264287546eaSitojun 		default:
12655453c090Sderaadt 			return __IPV6_ADDR_SCOPE_GLOBAL;
1266287546eaSitojun 			break;
1267287546eaSitojun 		}
1268287546eaSitojun 	}
1269287546eaSitojun 
12709b6307b6Sitojun 	if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
1271287546eaSitojun 		if (addr->s6_addr8[15] == 1) /* loopback */
12725453c090Sderaadt 			return __IPV6_ADDR_SCOPE_INTFACELOCAL;
1273287546eaSitojun 		if (addr->s6_addr8[15] == 0) /* unspecified */
12745453c090Sderaadt 			return __IPV6_ADDR_SCOPE_LINKLOCAL;
1275287546eaSitojun 	}
1276287546eaSitojun 
12775453c090Sderaadt 	return __IPV6_ADDR_SCOPE_GLOBAL;
1278287546eaSitojun }
1279287546eaSitojun 
1280f4f4d166Sitojun int
in6_addr2scopeid(unsigned int ifidx,struct in6_addr * addr)12811a3ab866Smpi in6_addr2scopeid(unsigned int ifidx, struct in6_addr *addr)
1282f4f4d166Sitojun {
1283f4f4d166Sitojun 	int scope = in6_addrscope(addr);
1284f4f4d166Sitojun 
1285f4f4d166Sitojun 	switch(scope) {
12865453c090Sderaadt 	case __IPV6_ADDR_SCOPE_INTFACELOCAL:
12875453c090Sderaadt 	case __IPV6_ADDR_SCOPE_LINKLOCAL:
1288f4f4d166Sitojun 		/* XXX: we do not distinguish between a link and an I/F. */
12891a3ab866Smpi 		return (ifidx);
1290f4f4d166Sitojun 
12915453c090Sderaadt 	case __IPV6_ADDR_SCOPE_SITELOCAL:
1292f4f4d166Sitojun 		return (0);	/* XXX: invalid. */
1293f4f4d166Sitojun 
1294f4f4d166Sitojun 	default:
1295f4f4d166Sitojun 		return (0);	/* XXX: treat as global. */
1296f4f4d166Sitojun 	}
1297f4f4d166Sitojun }
1298f4f4d166Sitojun 
1299287546eaSitojun /*
1300287546eaSitojun  * return length of part which dst and src are equal
1301287546eaSitojun  * hard coding...
1302287546eaSitojun  */
1303287546eaSitojun int
in6_matchlen(struct in6_addr * src,struct in6_addr * dst)1304ee37ea65Smcbride in6_matchlen(struct in6_addr *src, struct in6_addr *dst)
1305287546eaSitojun {
1306287546eaSitojun 	int match = 0;
1307287546eaSitojun 	u_char *s = (u_char *)src, *d = (u_char *)dst;
1308287546eaSitojun 	u_char *lim = s + 16, r;
1309287546eaSitojun 
1310287546eaSitojun 	while (s < lim)
1311287546eaSitojun 		if ((r = (*d++ ^ *s++)) != 0) {
1312287546eaSitojun 			while (r < 128) {
1313287546eaSitojun 				match++;
1314287546eaSitojun 				r <<= 1;
1315287546eaSitojun 			}
1316287546eaSitojun 			break;
1317287546eaSitojun 		} else
1318287546eaSitojun 			match += 8;
1319287546eaSitojun 	return match;
1320287546eaSitojun }
1321287546eaSitojun 
1322287546eaSitojun void
in6_prefixlen2mask(struct in6_addr * maskp,int len)1323ee37ea65Smcbride in6_prefixlen2mask(struct in6_addr *maskp, int len)
1324287546eaSitojun {
1325287546eaSitojun 	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
1326287546eaSitojun 	int bytelen, bitlen, i;
1327287546eaSitojun 
1328287546eaSitojun 	/* sanity check */
1329fc94afa0Stedu 	if (0 > len || len > 128) {
1330287546eaSitojun 		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
1331287546eaSitojun 		    len);
1332287546eaSitojun 		return;
1333287546eaSitojun 	}
1334287546eaSitojun 
1335287546eaSitojun 	bzero(maskp, sizeof(*maskp));
1336287546eaSitojun 	bytelen = len / 8;
1337287546eaSitojun 	bitlen = len % 8;
1338287546eaSitojun 	for (i = 0; i < bytelen; i++)
1339287546eaSitojun 		maskp->s6_addr[i] = 0xff;
1340fc94afa0Stedu 	/* len == 128 is ok because bitlen == 0 then */
1341287546eaSitojun 	if (bitlen)
1342287546eaSitojun 		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
1343287546eaSitojun }
1344287546eaSitojun 
1345287546eaSitojun /*
1346287546eaSitojun  * return the best address out of the same scope
1347287546eaSitojun  */
1348287546eaSitojun struct in6_ifaddr *
in6_ifawithscope(struct ifnet * oifp,struct in6_addr * dst,u_int rdomain,struct rtentry * rt)13497186e918Sflorian in6_ifawithscope(struct ifnet *oifp, struct in6_addr *dst, u_int rdomain,
13507186e918Sflorian     struct rtentry *rt)
1351287546eaSitojun {
1352d374aaacSitojun 	int dst_scope =	in6_addrscope(dst), src_scope, best_scope = 0;
1353f4f4d166Sitojun 	int blen = -1;
1354287546eaSitojun 	struct ifaddr *ifa;
1355f4f4d166Sitojun 	struct ifnet *ifp;
1356b9e83c60Sbluhm 	struct in6_ifaddr *ia6_best = NULL;
13577186e918Sflorian 	struct in6_addr *gw6 = NULL;
13587186e918Sflorian 
13597186e918Sflorian 	if (rt) {
13607186e918Sflorian 		if (rt->rt_gateway != NULL &&
13617186e918Sflorian 		    rt->rt_gateway->sa_family == AF_INET6)
13627186e918Sflorian 			gw6 = &(satosin6(rt->rt_gateway)->sin6_addr);
13637186e918Sflorian 	}
1364287546eaSitojun 
1365f4f4d166Sitojun 	if (oifp == NULL) {
1366d61e4f47Sbluhm 		printf("%s: output interface is not specified\n", __func__);
1367f4f4d166Sitojun 		return (NULL);
1368f4f4d166Sitojun 	}
1369287546eaSitojun 
137010319ffdSflorian 	/* We search for all addresses on all interfaces from the beginning. */
1371ccb45f8eSkn 	TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
1372ba79ddd5Ssperreault 		if (ifp->if_rdomain != rdomain)
1373ba79ddd5Ssperreault 			continue;
1374a7e28db1Sbluhm #if NCARP > 0
1375a7e28db1Sbluhm 		/*
1376a7e28db1Sbluhm 		 * Never use a carp address of an interface which is not
1377a7e28db1Sbluhm 		 * the master.
1378a7e28db1Sbluhm 		 */
1379442f4bb4Smpi 		if (ifp->if_type == IFT_CARP && !carp_iamatch(ifp))
1380a7e28db1Sbluhm 			continue;
1381a7e28db1Sbluhm #endif
1382ba79ddd5Ssperreault 
1383f4f4d166Sitojun 		/*
1384f4f4d166Sitojun 		 * We can never take an address that breaks the scope zone
1385f4f4d166Sitojun 		 * of the destination.
1386f4f4d166Sitojun 		 */
13871a3ab866Smpi 		if (in6_addr2scopeid(ifp->if_index, dst) !=
13881a3ab866Smpi 		    in6_addr2scopeid(oifp->if_index, dst))
1389f4f4d166Sitojun 			continue;
1390f4f4d166Sitojun 
13911573508eSmiod 		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
139210319ffdSflorian 			int tlen = -1;
1393f4f4d166Sitojun 
1394287546eaSitojun 			if (ifa->ifa_addr->sa_family != AF_INET6)
1395287546eaSitojun 				continue;
1396f4f4d166Sitojun 
1397f4f4d166Sitojun 			src_scope = in6_addrscope(IFA_IN6(ifa));
1398f4f4d166Sitojun 
1399f4f4d166Sitojun 			/*
1400f4f4d166Sitojun 			 * Don't use an address before completing DAD
1401f4f4d166Sitojun 			 * nor a duplicated address.
1402f4f4d166Sitojun 			 */
1403b2ea68e0Smpi 			if (ifatoia6(ifa)->ia6_flags &
1404b2ea68e0Smpi 			    (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED))
1405287546eaSitojun 				continue;
1406f4f4d166Sitojun 
140710319ffdSflorian 			/*
140810319ffdSflorian 			 * RFC 6724 allows anycast addresses as source address
140910319ffdSflorian 			 * because the restriction was removed in RFC 4291.
141010319ffdSflorian 			 * However RFC 4443 states that ICMPv6 responses
141110319ffdSflorian 			 * MUST use a unicast source address.
141210319ffdSflorian 			 *
141310319ffdSflorian 			 * XXX Skip anycast addresses for now since
141410319ffdSflorian 			 * icmp6_reflect() uses this function for source
141510319ffdSflorian 			 * address selection.
141610319ffdSflorian 			 */
1417de654afdSbluhm 			if (ifatoia6(ifa)->ia6_flags & IN6_IFF_ANYCAST)
1418f4f4d166Sitojun 				continue;
1419f4f4d166Sitojun 
1420de654afdSbluhm 			if (ifatoia6(ifa)->ia6_flags & IN6_IFF_DETACHED)
1421f4f4d166Sitojun 				continue;
1422f4f4d166Sitojun 
1423f4f4d166Sitojun 			/*
1424f4f4d166Sitojun 			 * If this is the first address we find,
1425f4f4d166Sitojun 			 * keep it anyway.
1426f4f4d166Sitojun 			 */
1427b9e83c60Sbluhm 			if (ia6_best == NULL)
1428f4f4d166Sitojun 				goto replace;
1429f4f4d166Sitojun 
1430f4f4d166Sitojun 			/*
1431b9e83c60Sbluhm 			 * ia6_best is never NULL beyond this line except
1432f4f4d166Sitojun 			 * within the block labeled "replace".
1433f4f4d166Sitojun 			 */
1434f4f4d166Sitojun 
1435f4f4d166Sitojun 			/*
143610319ffdSflorian 			 * Rule 2: Prefer appropriate scope.
143710319ffdSflorian 			 * Find the address with the smallest scope that is
143810319ffdSflorian 			 * bigger (or equal) to the scope of the destination
143910319ffdSflorian 			 * address.
144010319ffdSflorian 			 * Accept an address with smaller scope than the
144110319ffdSflorian 			 * destination if non exists with bigger scope.
1442f4f4d166Sitojun 			 */
144310319ffdSflorian 			if (best_scope < src_scope) {
144410319ffdSflorian 				if (best_scope < dst_scope)
1445f4f4d166Sitojun 					goto replace;
144610319ffdSflorian 				else
1447f4f4d166Sitojun 					continue;
144810319ffdSflorian 			} else if (src_scope < best_scope) {
144910319ffdSflorian 				if (src_scope < dst_scope)
145010319ffdSflorian 					continue;
145110319ffdSflorian 				else
145210319ffdSflorian 					goto replace;
145310319ffdSflorian 			}
1454f4f4d166Sitojun 
145510319ffdSflorian 			/* Rule 3: Avoid deprecated addresses. */
1456de654afdSbluhm 			if (ifatoia6(ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
1457287546eaSitojun 				/*
1458f4f4d166Sitojun 				 * Ignore any deprecated addresses if
1459f4f4d166Sitojun 				 * specified by configuration.
1460287546eaSitojun 				 */
1461f4f4d166Sitojun 				if (!ip6_use_deprecated)
1462f4f4d166Sitojun 					continue;
1463f4f4d166Sitojun 
1464f4f4d166Sitojun 				/*
1465f4f4d166Sitojun 				 * If we have already found a non-deprecated
1466f4f4d166Sitojun 				 * candidate, just ignore deprecated addresses.
1467f4f4d166Sitojun 				 */
1468b9e83c60Sbluhm 				if ((ia6_best->ia6_flags & IN6_IFF_DEPRECATED)
1469f4f4d166Sitojun 				    == 0)
1470f4f4d166Sitojun 					continue;
147110319ffdSflorian 			} else if ((ia6_best->ia6_flags & IN6_IFF_DEPRECATED))
1472f4f4d166Sitojun 				goto replace;
1473f4f4d166Sitojun 
147410319ffdSflorian 			/*
147510319ffdSflorian 			 * Rule 4: Prefer home addresses.
147610319ffdSflorian 			 * We do not support home addresses.
147710319ffdSflorian 			 */
147810319ffdSflorian 
147910319ffdSflorian 			/* Rule 5: Prefer outgoing interface */
1480cfef168aSbluhm 			if (ia6_best->ia_ifp == oifp && ifp != oifp)
1481cfef168aSbluhm 				continue;
1482cfef168aSbluhm 			if (ia6_best->ia_ifp != oifp && ifp == oifp)
1483cfef168aSbluhm 				goto replace;
1484cfef168aSbluhm 
1485f4f4d166Sitojun 			/*
148610319ffdSflorian 			 * Rule 5.5: Prefer addresses in a prefix advertised
148710319ffdSflorian 			 * by the next-hop.
1488f4f4d166Sitojun 			 */
14897186e918Sflorian 			if (gw6) {
14907186e918Sflorian 				struct in6_addr *in6_bestgw, *in6_newgw;
14917186e918Sflorian 
14927186e918Sflorian 				in6_bestgw = &ia6_best->ia_gwaddr.sin6_addr;
14937186e918Sflorian 				in6_newgw = &ifatoia6(ifa)->ia_gwaddr.sin6_addr;
14947186e918Sflorian 				if (!IN6_ARE_ADDR_EQUAL(in6_bestgw, gw6) &&
14957186e918Sflorian 				    IN6_ARE_ADDR_EQUAL(in6_newgw, gw6))
14967186e918Sflorian 					goto replace;
14977186e918Sflorian 			}
1498f4f4d166Sitojun 
1499f4f4d166Sitojun 			/*
150010319ffdSflorian 			 * Rule 6: Prefer matching label.
150110319ffdSflorian 			 * We do not implement policy tables.
1502f4f4d166Sitojun 			 */
1503988e29a9Sstsp 
150410319ffdSflorian 			/* Rule 7: Prefer temporary addresses. */
150510319ffdSflorian 			if ((ia6_best->ia6_flags & IN6_IFF_TEMPORARY) &&
150610319ffdSflorian 			    !(ifatoia6(ifa)->ia6_flags & IN6_IFF_TEMPORARY))
150710319ffdSflorian 				continue;
150810319ffdSflorian 			if (!(ia6_best->ia6_flags & IN6_IFF_TEMPORARY) &&
150910319ffdSflorian 			    (ifatoia6(ifa)->ia6_flags & IN6_IFF_TEMPORARY))
1510988e29a9Sstsp 				goto replace;
151110319ffdSflorian 
151210319ffdSflorian 			/* Rule 8: Use longest matching prefix. */
1513287546eaSitojun 			tlen = in6_matchlen(IFA_IN6(ifa), dst);
151410319ffdSflorian 			if (tlen > blen) {
1515d35187fbSstsp #if NCARP > 0
1516d35187fbSstsp 				/*
1517d35187fbSstsp 				 * Don't let carp interfaces win a tie against
1518d35187fbSstsp 				 * the output interface based on matchlen.
1519d35187fbSstsp 				 * We should only use a carp address if no
1520d35187fbSstsp 				 * other interface has a usable address.
1521d35187fbSstsp 				 * Otherwise, when communicating from a carp
1522fae51641Sbenno 				 * master to a carp backup, the backup system
1523fae51641Sbenno 				 * won't respond since the carp address is also
1524fae51641Sbenno 				 * configured as a local address on the backup.
1525d35187fbSstsp 				 * Note that carp interfaces in backup state
1526d35187fbSstsp 				 * were already skipped above.
1527d35187fbSstsp 				 */
1528d35187fbSstsp 				if (ifp->if_type == IFT_CARP &&
1529d35187fbSstsp 				    oifp->if_type != IFT_CARP)
1530d35187fbSstsp 					continue;
1531d35187fbSstsp #endif
1532f4f4d166Sitojun 				goto replace;
15337bd1e8e8Sflorian 			} else if (tlen < blen)
15347bd1e8e8Sflorian 				continue;
15357bd1e8e8Sflorian 
15367bd1e8e8Sflorian 			/*
15377bd1e8e8Sflorian 			 * If the eight rules fail to choose a single address,
15387bd1e8e8Sflorian 			 * the tiebreaker is implementation-specific.
15397bd1e8e8Sflorian 			 */
15407bd1e8e8Sflorian 
15417bd1e8e8Sflorian 			 /* Prefer address with highest pltime. */
15427bd1e8e8Sflorian 			if (ia6_best->ia6_updatetime +
15437bd1e8e8Sflorian 			    ia6_best->ia6_lifetime.ia6t_pltime <
15447bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_updatetime +
15457bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_lifetime.ia6t_pltime)
15467bd1e8e8Sflorian 				goto replace;
15477bd1e8e8Sflorian 			else if (ia6_best->ia6_updatetime +
15487bd1e8e8Sflorian 			    ia6_best->ia6_lifetime.ia6t_pltime >
15497bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_updatetime +
15507bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_lifetime.ia6t_pltime)
15517bd1e8e8Sflorian 				continue;
15527bd1e8e8Sflorian 
15537bd1e8e8Sflorian 			/* Prefer address with highest vltime. */
15547bd1e8e8Sflorian 			if (ia6_best->ia6_updatetime +
15557bd1e8e8Sflorian 			    ia6_best->ia6_lifetime.ia6t_vltime <
15567bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_updatetime +
15577bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_lifetime.ia6t_vltime)
15587bd1e8e8Sflorian 				goto replace;
15597bd1e8e8Sflorian 			else if (ia6_best->ia6_updatetime +
15607bd1e8e8Sflorian 			    ia6_best->ia6_lifetime.ia6t_vltime >
15617bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_updatetime +
15627bd1e8e8Sflorian 			    ifatoia6(ifa)->ia6_lifetime.ia6t_vltime)
15637bd1e8e8Sflorian 				continue;
15647bd1e8e8Sflorian 
1565f4f4d166Sitojun 			continue;
1566f4f4d166Sitojun 		  replace:
1567b9e83c60Sbluhm 			ia6_best = ifatoia6(ifa);
1568f4f4d166Sitojun 			blen = tlen >= 0 ? tlen :
1569f4f4d166Sitojun 			    in6_matchlen(IFA_IN6(ifa), dst);
1570d61e4f47Sbluhm 			best_scope =
1571d61e4f47Sbluhm 			    in6_addrscope(&ia6_best->ia_addr.sin6_addr);
1572287546eaSitojun 		}
1573287546eaSitojun 	}
1574287546eaSitojun 
1575f4f4d166Sitojun 	/* count statistics for future improvements */
1576b9e83c60Sbluhm 	if (ia6_best == NULL)
157731e14cacSjca 		ip6stat_inc(ip6s_sources_none);
1578f4f4d166Sitojun 	else {
1579b9e83c60Sbluhm 		if (oifp == ia6_best->ia_ifp)
158031e14cacSjca 			ip6stat_inc(ip6s_sources_sameif + best_scope);
1581f4f4d166Sitojun 		else
158231e14cacSjca 			ip6stat_inc(ip6s_sources_otherif + best_scope);
1583287546eaSitojun 
1584f4f4d166Sitojun 		if (best_scope == dst_scope)
158531e14cacSjca 			ip6stat_inc(ip6s_sources_samescope + best_scope);
1586f4f4d166Sitojun 		else
158731e14cacSjca 			ip6stat_inc(ip6s_sources_otherscope + best_scope);
1588f4f4d166Sitojun 
1589b9e83c60Sbluhm 		if ((ia6_best->ia6_flags & IN6_IFF_DEPRECATED) != 0)
159031e14cacSjca 			ip6stat_inc(ip6s_sources_deprecated + best_scope);
1591f4f4d166Sitojun 	}
1592f4f4d166Sitojun 
1593b9e83c60Sbluhm 	return (ia6_best);
1594287546eaSitojun }
1595287546eaSitojun 
1596ce832999Sitojun int
in6if_do_dad(struct ifnet * ifp)1597ee37ea65Smcbride in6if_do_dad(struct ifnet *ifp)
1598ce832999Sitojun {
1599ce832999Sitojun 	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
1600ce832999Sitojun 		return (0);
1601ce832999Sitojun 
1602ce832999Sitojun 	switch (ifp->if_type) {
1603a7e28db1Sbluhm #if NCARP > 0
1604a7e28db1Sbluhm 	case IFT_CARP:
1605a7e28db1Sbluhm 		/*
1606a7e28db1Sbluhm 		 * XXX: DAD does not work currently on carp(4)
1607a7e28db1Sbluhm 		 * so disable it for now.
1608a7e28db1Sbluhm 		 */
1609a7e28db1Sbluhm 		return (0);
1610a7e28db1Sbluhm #endif
1611ce832999Sitojun 	default:
1612ce832999Sitojun 		/*
1613ce832999Sitojun 		 * Our DAD routine requires the interface up and running.
1614ce832999Sitojun 		 * However, some interfaces can be up before the RUNNING
1615678831beSjsg 		 * status.  Additionally, users may try to assign addresses
1616ce832999Sitojun 		 * before the interface becomes up (or running).
1617ce832999Sitojun 		 * We simply skip DAD in such a case as a work around.
1618ce832999Sitojun 		 * XXX: we should rather mark "tentative" on such addresses,
1619ce832999Sitojun 		 * and do DAD after the interface becomes ready.
1620ce832999Sitojun 		 */
1621ce832999Sitojun 		if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) !=
1622ce832999Sitojun 		    (IFF_UP|IFF_RUNNING))
1623ce832999Sitojun 			return (0);
1624ce832999Sitojun 
1625ce832999Sitojun 		return (1);
1626ce832999Sitojun 	}
1627ce832999Sitojun }
1628