xref: /freebsd/sys/netinet6/in6.c (revision a93cda789aef8bb33ab335ebfe328971d33c4e39)
1caf43b02SWarner Losh /*-
282cd038dSYoshinobu Inoue  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
382cd038dSYoshinobu Inoue  * All rights reserved.
482cd038dSYoshinobu Inoue  *
582cd038dSYoshinobu Inoue  * Redistribution and use in source and binary forms, with or without
682cd038dSYoshinobu Inoue  * modification, are permitted provided that the following conditions
782cd038dSYoshinobu Inoue  * are met:
882cd038dSYoshinobu Inoue  * 1. Redistributions of source code must retain the above copyright
982cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer.
1082cd038dSYoshinobu Inoue  * 2. Redistributions in binary form must reproduce the above copyright
1182cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer in the
1282cd038dSYoshinobu Inoue  *    documentation and/or other materials provided with the distribution.
1382cd038dSYoshinobu Inoue  * 3. Neither the name of the project nor the names of its contributors
1482cd038dSYoshinobu Inoue  *    may be used to endorse or promote products derived from this software
1582cd038dSYoshinobu Inoue  *    without specific prior written permission.
1682cd038dSYoshinobu Inoue  *
1782cd038dSYoshinobu Inoue  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1882cd038dSYoshinobu Inoue  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1982cd038dSYoshinobu Inoue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2082cd038dSYoshinobu Inoue  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2182cd038dSYoshinobu Inoue  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2282cd038dSYoshinobu Inoue  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2382cd038dSYoshinobu Inoue  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2482cd038dSYoshinobu Inoue  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2582cd038dSYoshinobu Inoue  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2682cd038dSYoshinobu Inoue  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2782cd038dSYoshinobu Inoue  * SUCH DAMAGE.
28b48287a3SDavid E. O'Brien  *
29b48287a3SDavid E. O'Brien  *	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $
3082cd038dSYoshinobu Inoue  */
3182cd038dSYoshinobu Inoue 
32caf43b02SWarner Losh /*-
3382cd038dSYoshinobu Inoue  * Copyright (c) 1982, 1986, 1991, 1993
3482cd038dSYoshinobu Inoue  *	The Regents of the University of California.  All rights reserved.
3582cd038dSYoshinobu Inoue  *
3682cd038dSYoshinobu Inoue  * Redistribution and use in source and binary forms, with or without
3782cd038dSYoshinobu Inoue  * modification, are permitted provided that the following conditions
3882cd038dSYoshinobu Inoue  * are met:
3982cd038dSYoshinobu Inoue  * 1. Redistributions of source code must retain the above copyright
4082cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer.
4182cd038dSYoshinobu Inoue  * 2. Redistributions in binary form must reproduce the above copyright
4282cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer in the
4382cd038dSYoshinobu Inoue  *    documentation and/or other materials provided with the distribution.
4482cd038dSYoshinobu Inoue  * 4. Neither the name of the University nor the names of its contributors
4582cd038dSYoshinobu Inoue  *    may be used to endorse or promote products derived from this software
4682cd038dSYoshinobu Inoue  *    without specific prior written permission.
4782cd038dSYoshinobu Inoue  *
4882cd038dSYoshinobu Inoue  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4982cd038dSYoshinobu Inoue  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5082cd038dSYoshinobu Inoue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5182cd038dSYoshinobu Inoue  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5282cd038dSYoshinobu Inoue  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5382cd038dSYoshinobu Inoue  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5482cd038dSYoshinobu Inoue  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5582cd038dSYoshinobu Inoue  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5682cd038dSYoshinobu Inoue  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5782cd038dSYoshinobu Inoue  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5882cd038dSYoshinobu Inoue  * SUCH DAMAGE.
5982cd038dSYoshinobu Inoue  *
6082cd038dSYoshinobu Inoue  *	@(#)in.c	8.2 (Berkeley) 11/15/93
6182cd038dSYoshinobu Inoue  */
6282cd038dSYoshinobu Inoue 
63b48287a3SDavid E. O'Brien #include <sys/cdefs.h>
64b48287a3SDavid E. O'Brien __FBSDID("$FreeBSD$");
65b48287a3SDavid E. O'Brien 
6699c750a8SKonstantin Belousov #include "opt_compat.h"
67686cdd19SJun-ichiro itojun Hagino #include "opt_inet.h"
68686cdd19SJun-ichiro itojun Hagino #include "opt_inet6.h"
69686cdd19SJun-ichiro itojun Hagino 
7082cd038dSYoshinobu Inoue #include <sys/param.h>
7182cd038dSYoshinobu Inoue #include <sys/errno.h>
725ce0eb7fSBjoern A. Zeeb #include <sys/jail.h>
7382cd038dSYoshinobu Inoue #include <sys/malloc.h>
7482cd038dSYoshinobu Inoue #include <sys/socket.h>
7582cd038dSYoshinobu Inoue #include <sys/socketvar.h>
7682cd038dSYoshinobu Inoue #include <sys/sockio.h>
7782cd038dSYoshinobu Inoue #include <sys/systm.h>
78acd3428bSRobert Watson #include <sys/priv.h>
7982cd038dSYoshinobu Inoue #include <sys/proc.h>
8082cd038dSYoshinobu Inoue #include <sys/time.h>
8182cd038dSYoshinobu Inoue #include <sys/kernel.h>
8282cd038dSYoshinobu Inoue #include <sys/syslog.h>
8382cd038dSYoshinobu Inoue 
8482cd038dSYoshinobu Inoue #include <net/if.h>
859bb7d0f4SQing Li #include <net/if_var.h>
8682cd038dSYoshinobu Inoue #include <net/if_types.h>
8782cd038dSYoshinobu Inoue #include <net/route.h>
8882cd038dSYoshinobu Inoue #include <net/if_dl.h>
894b79449eSBjoern A. Zeeb #include <net/vnet.h>
9082cd038dSYoshinobu Inoue 
9182cd038dSYoshinobu Inoue #include <netinet/in.h>
9282cd038dSYoshinobu Inoue #include <netinet/in_var.h>
936e6b3f7cSQing Li #include <net/if_llatbl.h>
9482cd038dSYoshinobu Inoue #include <netinet/if_ether.h>
9533841545SHajimu UMEMOTO #include <netinet/in_systm.h>
9633841545SHajimu UMEMOTO #include <netinet/ip.h>
9733841545SHajimu UMEMOTO #include <netinet/in_pcb.h>
9808b68b0eSGleb Smirnoff #include <netinet/ip_carp.h>
9982cd038dSYoshinobu Inoue 
100686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h>
10182cd038dSYoshinobu Inoue #include <netinet6/ip6_var.h>
10288ff5695SSUZUKI Shinsuke #include <netinet6/nd6.h>
10382cd038dSYoshinobu Inoue #include <netinet6/mld6_var.h>
104686cdd19SJun-ichiro itojun Hagino #include <netinet6/ip6_mroute.h>
10582cd038dSYoshinobu Inoue #include <netinet6/in6_ifattach.h>
106686cdd19SJun-ichiro itojun Hagino #include <netinet6/scope6_var.h>
10733841545SHajimu UMEMOTO #include <netinet6/in6_pcb.h>
108686cdd19SJun-ichiro itojun Hagino 
10982cd038dSYoshinobu Inoue /*
11082cd038dSYoshinobu Inoue  * Definitions of some costant IP6 addresses.
11182cd038dSYoshinobu Inoue  */
11282cd038dSYoshinobu Inoue const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
11382cd038dSYoshinobu Inoue const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
11482cd038dSYoshinobu Inoue const struct in6_addr in6addr_nodelocal_allnodes =
11582cd038dSYoshinobu Inoue 	IN6ADDR_NODELOCAL_ALLNODES_INIT;
11682cd038dSYoshinobu Inoue const struct in6_addr in6addr_linklocal_allnodes =
11782cd038dSYoshinobu Inoue 	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
11882cd038dSYoshinobu Inoue const struct in6_addr in6addr_linklocal_allrouters =
11982cd038dSYoshinobu Inoue 	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
12033cde130SBruce M Simpson const struct in6_addr in6addr_linklocal_allv2routers =
12133cde130SBruce M Simpson 	IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT;
12282cd038dSYoshinobu Inoue 
12382cd038dSYoshinobu Inoue const struct in6_addr in6mask0 = IN6MASK0;
12482cd038dSYoshinobu Inoue const struct in6_addr in6mask32 = IN6MASK32;
12582cd038dSYoshinobu Inoue const struct in6_addr in6mask64 = IN6MASK64;
12682cd038dSYoshinobu Inoue const struct in6_addr in6mask96 = IN6MASK96;
12782cd038dSYoshinobu Inoue const struct in6_addr in6mask128 = IN6MASK128;
12882cd038dSYoshinobu Inoue 
12959aecc96SHajimu UMEMOTO const struct sockaddr_in6 sa6_any =
13059aecc96SHajimu UMEMOTO 	{ sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 };
13133841545SHajimu UMEMOTO 
13282cd038dSYoshinobu Inoue static int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
133b40ce416SJulian Elischer 	struct ifnet *, struct thread *));
13433841545SHajimu UMEMOTO static int in6_ifinit __P((struct ifnet *, struct in6_ifaddr *,
13533841545SHajimu UMEMOTO 	struct sockaddr_in6 *, int));
1369233d8f3SDavid E. O'Brien static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
13782cd038dSYoshinobu Inoue 
1389494d596SBrooks Davis int	(*faithprefix_p)(struct in6_addr *);
1399494d596SBrooks Davis 
140b590b6aeSGleb Smirnoff #define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
141b590b6aeSGleb Smirnoff #define ia62ifa(ia6)	(&((ia6)->ia_ifa))
14282cd038dSYoshinobu Inoue 
143b590b6aeSGleb Smirnoff void
144b590b6aeSGleb Smirnoff in6_ifaddloop(struct ifaddr *ifa)
145b590b6aeSGleb Smirnoff {
146b590b6aeSGleb Smirnoff 	struct sockaddr_dl gateway;
147b590b6aeSGleb Smirnoff 	struct sockaddr_in6 mask, addr;
148b590b6aeSGleb Smirnoff 	struct rtentry rt;
149b590b6aeSGleb Smirnoff 	struct in6_ifaddr *ia;
150b590b6aeSGleb Smirnoff 	struct ifnet *ifp;
151b590b6aeSGleb Smirnoff 	struct llentry *ln;
152b590b6aeSGleb Smirnoff 
153b590b6aeSGleb Smirnoff 	ia = ifa2ia6(ifa);
154b590b6aeSGleb Smirnoff 	ifp = ifa->ifa_ifp;
155b590b6aeSGleb Smirnoff 	IF_AFDATA_LOCK(ifp);
1560f1aca65SQing Li 	ifa->ifa_rtrequest = nd6_rtrequest;
157b590b6aeSGleb Smirnoff 	ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR |
158b590b6aeSGleb Smirnoff 	    LLE_EXCLUSIVE), (struct sockaddr *)&ia->ia_addr);
159b590b6aeSGleb Smirnoff 	IF_AFDATA_UNLOCK(ifp);
160b590b6aeSGleb Smirnoff 	if (ln != NULL) {
161b590b6aeSGleb Smirnoff 		ln->la_expire = 0;  /* for IPv6 this means permanent */
162b590b6aeSGleb Smirnoff 		ln->ln_state = ND6_LLINFO_REACHABLE;
163b590b6aeSGleb Smirnoff 		/*
164b590b6aeSGleb Smirnoff 		 * initialize for rtmsg generation
165b590b6aeSGleb Smirnoff 		 */
166b590b6aeSGleb Smirnoff 		bzero(&gateway, sizeof(gateway));
167b590b6aeSGleb Smirnoff 		gateway.sdl_len = sizeof(gateway);
168b590b6aeSGleb Smirnoff 		gateway.sdl_family = AF_LINK;
169b590b6aeSGleb Smirnoff 		gateway.sdl_nlen = 0;
170b590b6aeSGleb Smirnoff 		gateway.sdl_alen = 6;
171b590b6aeSGleb Smirnoff 		memcpy(gateway.sdl_data, &ln->ll_addr.mac_aligned,
172b590b6aeSGleb Smirnoff 		    sizeof(ln->ll_addr));
173b590b6aeSGleb Smirnoff 		LLE_WUNLOCK(ln);
174b590b6aeSGleb Smirnoff 	}
175b590b6aeSGleb Smirnoff 
176b590b6aeSGleb Smirnoff 	bzero(&rt, sizeof(rt));
177b590b6aeSGleb Smirnoff 	rt.rt_gateway = (struct sockaddr *)&gateway;
178b590b6aeSGleb Smirnoff 	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
179b590b6aeSGleb Smirnoff 	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
180b590b6aeSGleb Smirnoff 	rt_mask(&rt) = (struct sockaddr *)&mask;
181b590b6aeSGleb Smirnoff 	rt_key(&rt) = (struct sockaddr *)&addr;
182b590b6aeSGleb Smirnoff 	rt.rt_flags = RTF_UP | RTF_HOST | RTF_STATIC;
18381d5d46bSBjoern A. Zeeb 	/* Announce arrival of local address to all FIBs. */
184b590b6aeSGleb Smirnoff 	rt_newaddrmsg(RTM_ADD, ifa, 0, &rt);
185b590b6aeSGleb Smirnoff }
186b590b6aeSGleb Smirnoff 
187b590b6aeSGleb Smirnoff void
188b590b6aeSGleb Smirnoff in6_ifremloop(struct ifaddr *ifa)
189b590b6aeSGleb Smirnoff {
190b590b6aeSGleb Smirnoff 	struct sockaddr_dl gateway;
191b590b6aeSGleb Smirnoff 	struct sockaddr_in6 mask, addr;
192b590b6aeSGleb Smirnoff 	struct rtentry rt0;
193b590b6aeSGleb Smirnoff 	struct in6_ifaddr *ia;
194b590b6aeSGleb Smirnoff 	struct ifnet *ifp;
195b590b6aeSGleb Smirnoff 
196b590b6aeSGleb Smirnoff 	ia = ifa2ia6(ifa);
197b590b6aeSGleb Smirnoff 	ifp = ifa->ifa_ifp;
198b590b6aeSGleb Smirnoff 	IF_AFDATA_LOCK(ifp);
199b590b6aeSGleb Smirnoff 	lla_lookup(LLTABLE6(ifp), (LLE_DELETE | LLE_IFADDR),
200b590b6aeSGleb Smirnoff 	    (struct sockaddr *)&ia->ia_addr);
201b590b6aeSGleb Smirnoff 	IF_AFDATA_UNLOCK(ifp);
202b590b6aeSGleb Smirnoff 
203b590b6aeSGleb Smirnoff 	/*
204b590b6aeSGleb Smirnoff 	 * initialize for rtmsg generation
205b590b6aeSGleb Smirnoff 	 */
206b590b6aeSGleb Smirnoff 	bzero(&gateway, sizeof(gateway));
207b590b6aeSGleb Smirnoff 	gateway.sdl_len = sizeof(gateway);
208b590b6aeSGleb Smirnoff 	gateway.sdl_family = AF_LINK;
209b590b6aeSGleb Smirnoff 	gateway.sdl_nlen = 0;
210b590b6aeSGleb Smirnoff 	gateway.sdl_alen = ifp->if_addrlen;
211b590b6aeSGleb Smirnoff 	bzero(&rt0, sizeof(rt0));
212b590b6aeSGleb Smirnoff 	rt0.rt_gateway = (struct sockaddr *)&gateway;
213b590b6aeSGleb Smirnoff 	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
214b590b6aeSGleb Smirnoff 	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
215b590b6aeSGleb Smirnoff 	rt_mask(&rt0) = (struct sockaddr *)&mask;
216b590b6aeSGleb Smirnoff 	rt_key(&rt0) = (struct sockaddr *)&addr;
217b590b6aeSGleb Smirnoff 	rt0.rt_flags = RTF_HOST | RTF_STATIC;
21881d5d46bSBjoern A. Zeeb 	/* Announce removal of local address to all FIBs. */
219b590b6aeSGleb Smirnoff 	rt_newaddrmsg(RTM_DELETE, ifa, 0, &rt0);
220b590b6aeSGleb Smirnoff }
22182cd038dSYoshinobu Inoue 
22282cd038dSYoshinobu Inoue int
2231272577eSXin LI in6_mask2len(struct in6_addr *mask, u_char *lim0)
22482cd038dSYoshinobu Inoue {
22533841545SHajimu UMEMOTO 	int x = 0, y;
22633841545SHajimu UMEMOTO 	u_char *lim = lim0, *p;
22782cd038dSYoshinobu Inoue 
22806cd0a3fSHajimu UMEMOTO 	/* ignore the scope_id part */
22906cd0a3fSHajimu UMEMOTO 	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
23033841545SHajimu UMEMOTO 		lim = (u_char *)mask + sizeof(*mask);
23133841545SHajimu UMEMOTO 	for (p = (u_char *)mask; p < lim; x++, p++) {
23233841545SHajimu UMEMOTO 		if (*p != 0xff)
23382cd038dSYoshinobu Inoue 			break;
23482cd038dSYoshinobu Inoue 	}
23582cd038dSYoshinobu Inoue 	y = 0;
23633841545SHajimu UMEMOTO 	if (p < lim) {
23782cd038dSYoshinobu Inoue 		for (y = 0; y < 8; y++) {
23833841545SHajimu UMEMOTO 			if ((*p & (0x80 >> y)) == 0)
23982cd038dSYoshinobu Inoue 				break;
24082cd038dSYoshinobu Inoue 		}
24182cd038dSYoshinobu Inoue 	}
24233841545SHajimu UMEMOTO 
24333841545SHajimu UMEMOTO 	/*
24433841545SHajimu UMEMOTO 	 * when the limit pointer is given, do a stricter check on the
24533841545SHajimu UMEMOTO 	 * remaining bits.
24633841545SHajimu UMEMOTO 	 */
24733841545SHajimu UMEMOTO 	if (p < lim) {
24833841545SHajimu UMEMOTO 		if (y != 0 && (*p & (0x00ff >> y)) != 0)
24933841545SHajimu UMEMOTO 			return (-1);
25033841545SHajimu UMEMOTO 		for (p = p + 1; p < lim; p++)
25133841545SHajimu UMEMOTO 			if (*p != 0)
25233841545SHajimu UMEMOTO 				return (-1);
25333841545SHajimu UMEMOTO 	}
25433841545SHajimu UMEMOTO 
25582cd038dSYoshinobu Inoue 	return x * 8 + y;
25682cd038dSYoshinobu Inoue }
25782cd038dSYoshinobu Inoue 
25899c750a8SKonstantin Belousov #ifdef COMPAT_FREEBSD32
25999c750a8SKonstantin Belousov struct in6_ndifreq32 {
26099c750a8SKonstantin Belousov         char ifname[IFNAMSIZ];
26199c750a8SKonstantin Belousov         uint32_t ifindex;
26299c750a8SKonstantin Belousov };
26399c750a8SKonstantin Belousov #define	SIOCGDEFIFACE32_IN6     _IOWR('i', 86, struct in6_ndifreq32)
26499c750a8SKonstantin Belousov #endif
26599c750a8SKonstantin Belousov 
26682cd038dSYoshinobu Inoue int
2671272577eSXin LI in6_control(struct socket *so, u_long cmd, caddr_t data,
2681272577eSXin LI     struct ifnet *ifp, struct thread *td)
26982cd038dSYoshinobu Inoue {
27082cd038dSYoshinobu Inoue 	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
27133841545SHajimu UMEMOTO 	struct	in6_ifaddr *ia = NULL;
27282cd038dSYoshinobu Inoue 	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
273743eee66SSUZUKI Shinsuke 	struct sockaddr_in6 *sa6;
27408b68b0eSGleb Smirnoff 	int carp_attached = 0;
275acd3428bSRobert Watson 	int error;
27671212473SGleb Smirnoff 	u_long ocmd = cmd;
27771212473SGleb Smirnoff 
27871212473SGleb Smirnoff 	/*
27971212473SGleb Smirnoff 	 * Compat to make pre-10.x ifconfig(8) operable.
28071212473SGleb Smirnoff 	 */
28171212473SGleb Smirnoff 	if (cmd == OSIOCAIFADDR_IN6)
28271212473SGleb Smirnoff 		cmd = SIOCAIFADDR_IN6;
28382cd038dSYoshinobu Inoue 
284686cdd19SJun-ichiro itojun Hagino 	switch (cmd) {
285686cdd19SJun-ichiro itojun Hagino 	case SIOCGETSGCNT_IN6:
286686cdd19SJun-ichiro itojun Hagino 	case SIOCGETMIFCNT_IN6:
28781d5d46bSBjoern A. Zeeb 		/*
28881d5d46bSBjoern A. Zeeb 		 * XXX mrt_ioctl has a 3rd, unused, FIB argument in route.c.
28981d5d46bSBjoern A. Zeeb 		 * We cannot see how that would be needed, so do not adjust the
29081d5d46bSBjoern A. Zeeb 		 * KPI blindly; more likely should clean up the IPv4 variant.
29181d5d46bSBjoern A. Zeeb 		 */
2926be2e366SBruce M Simpson 		return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP);
293686cdd19SJun-ichiro itojun Hagino 	}
29482cd038dSYoshinobu Inoue 
2957fc91b3fSHajimu UMEMOTO 	switch(cmd) {
2967fc91b3fSHajimu UMEMOTO 	case SIOCAADDRCTL_POLICY:
2977fc91b3fSHajimu UMEMOTO 	case SIOCDADDRCTL_POLICY:
298acd3428bSRobert Watson 		if (td != NULL) {
299acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_ADDRCTRL6);
300acd3428bSRobert Watson 			if (error)
301acd3428bSRobert Watson 				return (error);
302acd3428bSRobert Watson 		}
3037fc91b3fSHajimu UMEMOTO 		return (in6_src_ioctl(cmd, data));
3047fc91b3fSHajimu UMEMOTO 	}
3057fc91b3fSHajimu UMEMOTO 
306686cdd19SJun-ichiro itojun Hagino 	if (ifp == NULL)
30782cd038dSYoshinobu Inoue 		return (EOPNOTSUPP);
30882cd038dSYoshinobu Inoue 
30982cd038dSYoshinobu Inoue 	switch (cmd) {
31082cd038dSYoshinobu Inoue 	case SIOCSNDFLUSH_IN6:
31182cd038dSYoshinobu Inoue 	case SIOCSPFXFLUSH_IN6:
31282cd038dSYoshinobu Inoue 	case SIOCSRTRFLUSH_IN6:
313686cdd19SJun-ichiro itojun Hagino 	case SIOCSDEFIFACE_IN6:
314686cdd19SJun-ichiro itojun Hagino 	case SIOCSIFINFO_FLAGS:
3159a1bde18SColin Percival 	case SIOCSIFINFO_IN6:
316acd3428bSRobert Watson 		if (td != NULL) {
317acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_ND6);
318acd3428bSRobert Watson 			if (error)
319acd3428bSRobert Watson 				return (error);
320acd3428bSRobert Watson 		}
32106cd0a3fSHajimu UMEMOTO 		/* FALLTHROUGH */
32233841545SHajimu UMEMOTO 	case OSIOCGIFINFO_IN6:
32382cd038dSYoshinobu Inoue 	case SIOCGIFINFO_IN6:
32482cd038dSYoshinobu Inoue 	case SIOCGDRLST_IN6:
32582cd038dSYoshinobu Inoue 	case SIOCGPRLST_IN6:
32682cd038dSYoshinobu Inoue 	case SIOCGNBRINFO_IN6:
327686cdd19SJun-ichiro itojun Hagino 	case SIOCGDEFIFACE_IN6:
32882cd038dSYoshinobu Inoue 		return (nd6_ioctl(cmd, data, ifp));
32999c750a8SKonstantin Belousov 
33099c750a8SKonstantin Belousov #ifdef COMPAT_FREEBSD32
33199c750a8SKonstantin Belousov 	case SIOCGDEFIFACE32_IN6:
33299c750a8SKonstantin Belousov 		{
33399c750a8SKonstantin Belousov 			struct in6_ndifreq ndif;
33499c750a8SKonstantin Belousov 			struct in6_ndifreq32 *ndif32;
33599c750a8SKonstantin Belousov 
33699c750a8SKonstantin Belousov 			error = nd6_ioctl(SIOCGDEFIFACE_IN6, (caddr_t)&ndif,
33799c750a8SKonstantin Belousov 			    ifp);
33899c750a8SKonstantin Belousov 			if (error)
33999c750a8SKonstantin Belousov 				return (error);
34099c750a8SKonstantin Belousov 			ndif32 = (struct in6_ndifreq32 *)data;
34199c750a8SKonstantin Belousov 			ndif32->ifindex = ndif.ifindex;
34299c750a8SKonstantin Belousov 			return (0);
34399c750a8SKonstantin Belousov 		}
34499c750a8SKonstantin Belousov #endif
34582cd038dSYoshinobu Inoue 	}
34682cd038dSYoshinobu Inoue 
34782cd038dSYoshinobu Inoue 	switch (cmd) {
34882cd038dSYoshinobu Inoue 	case SIOCSIFPREFIX_IN6:
34982cd038dSYoshinobu Inoue 	case SIOCDIFPREFIX_IN6:
35082cd038dSYoshinobu Inoue 	case SIOCAIFPREFIX_IN6:
35182cd038dSYoshinobu Inoue 	case SIOCCIFPREFIX_IN6:
35282cd038dSYoshinobu Inoue 	case SIOCSGIFPREFIX_IN6:
35382cd038dSYoshinobu Inoue 	case SIOCGIFPREFIX_IN6:
35433841545SHajimu UMEMOTO 		log(LOG_NOTICE,
35533841545SHajimu UMEMOTO 		    "prefix ioctls are now invalidated. "
35633841545SHajimu UMEMOTO 		    "please use ifconfig.\n");
35733841545SHajimu UMEMOTO 		return (EOPNOTSUPP);
35882cd038dSYoshinobu Inoue 	}
35982cd038dSYoshinobu Inoue 
36082cd038dSYoshinobu Inoue 	switch (cmd) {
361686cdd19SJun-ichiro itojun Hagino 	case SIOCSSCOPE6:
362acd3428bSRobert Watson 		if (td != NULL) {
363acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_SCOPE6);
364acd3428bSRobert Watson 			if (error)
365acd3428bSRobert Watson 				return (error);
366acd3428bSRobert Watson 		}
36731b1bfe1SHajimu UMEMOTO 		return (scope6_set(ifp,
36831b1bfe1SHajimu UMEMOTO 		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
369686cdd19SJun-ichiro itojun Hagino 	case SIOCGSCOPE6:
37031b1bfe1SHajimu UMEMOTO 		return (scope6_get(ifp,
37131b1bfe1SHajimu UMEMOTO 		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
372686cdd19SJun-ichiro itojun Hagino 	case SIOCGSCOPE6DEF:
37331b1bfe1SHajimu UMEMOTO 		return (scope6_get_default((struct scope6_id *)
37431b1bfe1SHajimu UMEMOTO 		    ifr->ifr_ifru.ifru_scope_id));
375686cdd19SJun-ichiro itojun Hagino 	}
376686cdd19SJun-ichiro itojun Hagino 
377686cdd19SJun-ichiro itojun Hagino 	switch (cmd) {
37882cd038dSYoshinobu Inoue 	case SIOCALIFADDR:
379acd3428bSRobert Watson 		if (td != NULL) {
38079ba3952SBjoern A. Zeeb 			error = priv_check(td, PRIV_NET_ADDIFADDR);
38179ba3952SBjoern A. Zeeb 			if (error)
38279ba3952SBjoern A. Zeeb 				return (error);
38379ba3952SBjoern A. Zeeb 		}
38479ba3952SBjoern A. Zeeb 		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
38579ba3952SBjoern A. Zeeb 
38679ba3952SBjoern A. Zeeb 	case SIOCDLIFADDR:
38779ba3952SBjoern A. Zeeb 		if (td != NULL) {
38879ba3952SBjoern A. Zeeb 			error = priv_check(td, PRIV_NET_DELIFADDR);
389acd3428bSRobert Watson 			if (error)
390acd3428bSRobert Watson 				return (error);
391acd3428bSRobert Watson 		}
39206cd0a3fSHajimu UMEMOTO 		/* FALLTHROUGH */
39382cd038dSYoshinobu Inoue 	case SIOCGLIFADDR:
394b40ce416SJulian Elischer 		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
39582cd038dSYoshinobu Inoue 	}
39682cd038dSYoshinobu Inoue 
39782cd038dSYoshinobu Inoue 	/*
39882cd038dSYoshinobu Inoue 	 * Find address for this interface, if it exists.
399743eee66SSUZUKI Shinsuke 	 *
400743eee66SSUZUKI Shinsuke 	 * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
401743eee66SSUZUKI Shinsuke 	 * only, and used the first interface address as the target of other
402743eee66SSUZUKI Shinsuke 	 * operations (without checking ifra_addr).  This was because netinet
403743eee66SSUZUKI Shinsuke 	 * code/API assumed at most 1 interface address per interface.
404743eee66SSUZUKI Shinsuke 	 * Since IPv6 allows a node to assign multiple addresses
405743eee66SSUZUKI Shinsuke 	 * on a single interface, we almost always look and check the
406743eee66SSUZUKI Shinsuke 	 * presence of ifra_addr, and reject invalid ones here.
407743eee66SSUZUKI Shinsuke 	 * It also decreases duplicated code among SIOC*_IN6 operations.
40882cd038dSYoshinobu Inoue 	 */
409743eee66SSUZUKI Shinsuke 	switch (cmd) {
410743eee66SSUZUKI Shinsuke 	case SIOCAIFADDR_IN6:
411743eee66SSUZUKI Shinsuke 	case SIOCSIFPHYADDR_IN6:
412743eee66SSUZUKI Shinsuke 		sa6 = &ifra->ifra_addr;
413743eee66SSUZUKI Shinsuke 		break;
414743eee66SSUZUKI Shinsuke 	case SIOCSIFADDR_IN6:
415743eee66SSUZUKI Shinsuke 	case SIOCGIFADDR_IN6:
416743eee66SSUZUKI Shinsuke 	case SIOCSIFDSTADDR_IN6:
417743eee66SSUZUKI Shinsuke 	case SIOCSIFNETMASK_IN6:
418743eee66SSUZUKI Shinsuke 	case SIOCGIFDSTADDR_IN6:
419743eee66SSUZUKI Shinsuke 	case SIOCGIFNETMASK_IN6:
420743eee66SSUZUKI Shinsuke 	case SIOCDIFADDR_IN6:
421743eee66SSUZUKI Shinsuke 	case SIOCGIFPSRCADDR_IN6:
422743eee66SSUZUKI Shinsuke 	case SIOCGIFPDSTADDR_IN6:
423743eee66SSUZUKI Shinsuke 	case SIOCGIFAFLAG_IN6:
424743eee66SSUZUKI Shinsuke 	case SIOCSNDFLUSH_IN6:
425743eee66SSUZUKI Shinsuke 	case SIOCSPFXFLUSH_IN6:
426743eee66SSUZUKI Shinsuke 	case SIOCSRTRFLUSH_IN6:
427743eee66SSUZUKI Shinsuke 	case SIOCGIFALIFETIME_IN6:
428743eee66SSUZUKI Shinsuke 	case SIOCSIFALIFETIME_IN6:
429743eee66SSUZUKI Shinsuke 	case SIOCGIFSTAT_IN6:
430743eee66SSUZUKI Shinsuke 	case SIOCGIFSTAT_ICMP6:
431743eee66SSUZUKI Shinsuke 		sa6 = &ifr->ifr_addr;
432743eee66SSUZUKI Shinsuke 		break;
433743eee66SSUZUKI Shinsuke 	default:
434743eee66SSUZUKI Shinsuke 		sa6 = NULL;
435743eee66SSUZUKI Shinsuke 		break;
436743eee66SSUZUKI Shinsuke 	}
437743eee66SSUZUKI Shinsuke 	if (sa6 && sa6->sin6_family == AF_INET6) {
438743eee66SSUZUKI Shinsuke 		if (sa6->sin6_scope_id != 0)
439743eee66SSUZUKI Shinsuke 			error = sa6_embedscope(sa6, 0);
440a1f7e5f8SHajimu UMEMOTO 		else
441743eee66SSUZUKI Shinsuke 			error = in6_setscope(&sa6->sin6_addr, ifp, NULL);
442a1f7e5f8SHajimu UMEMOTO 		if (error != 0)
443a1f7e5f8SHajimu UMEMOTO 			return (error);
444b89e82ddSJamie Gritton 		if (td != NULL && (error = prison_check_ip6(td->td_ucred,
445b89e82ddSJamie Gritton 		    &sa6->sin6_addr)) != 0)
446b89e82ddSJamie Gritton 			return (error);
447743eee66SSUZUKI Shinsuke 		ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
448743eee66SSUZUKI Shinsuke 	} else
449743eee66SSUZUKI Shinsuke 		ia = NULL;
45082cd038dSYoshinobu Inoue 
45182cd038dSYoshinobu Inoue 	switch (cmd) {
45282cd038dSYoshinobu Inoue 	case SIOCSIFADDR_IN6:
45382cd038dSYoshinobu Inoue 	case SIOCSIFDSTADDR_IN6:
454686cdd19SJun-ichiro itojun Hagino 	case SIOCSIFNETMASK_IN6:
455686cdd19SJun-ichiro itojun Hagino 		/*
456686cdd19SJun-ichiro itojun Hagino 		 * Since IPv6 allows a node to assign multiple addresses
4572ce62dceSSUZUKI Shinsuke 		 * on a single interface, SIOCSIFxxx ioctls are deprecated.
458686cdd19SJun-ichiro itojun Hagino 		 */
45933841545SHajimu UMEMOTO 		/* we decided to obsolete this command (20000704) */
4608c0fec80SRobert Watson 		error = EINVAL;
4618c0fec80SRobert Watson 		goto out;
46233841545SHajimu UMEMOTO 
46333841545SHajimu UMEMOTO 	case SIOCDIFADDR_IN6:
46433841545SHajimu UMEMOTO 		/*
46533841545SHajimu UMEMOTO 		 * for IPv4, we look for existing in_ifaddr here to allow
4662ce62dceSSUZUKI Shinsuke 		 * "ifconfig if0 delete" to remove the first IPv4 address on
4672ce62dceSSUZUKI Shinsuke 		 * the interface.  For IPv6, as the spec allows multiple
4682ce62dceSSUZUKI Shinsuke 		 * interface address from the day one, we consider "remove the
4692ce62dceSSUZUKI Shinsuke 		 * first one" semantics to be not preferable.
47033841545SHajimu UMEMOTO 		 */
4718c0fec80SRobert Watson 		if (ia == NULL) {
4728c0fec80SRobert Watson 			error = EADDRNOTAVAIL;
4738c0fec80SRobert Watson 			goto out;
4748c0fec80SRobert Watson 		}
47533841545SHajimu UMEMOTO 		/* FALLTHROUGH */
47633841545SHajimu UMEMOTO 	case SIOCAIFADDR_IN6:
47733841545SHajimu UMEMOTO 		/*
47833841545SHajimu UMEMOTO 		 * We always require users to specify a valid IPv6 address for
47933841545SHajimu UMEMOTO 		 * the corresponding operation.
48033841545SHajimu UMEMOTO 		 */
48133841545SHajimu UMEMOTO 		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
4828c0fec80SRobert Watson 		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) {
4838c0fec80SRobert Watson 			error = EAFNOSUPPORT;
4848c0fec80SRobert Watson 			goto out;
4858c0fec80SRobert Watson 		}
486acd3428bSRobert Watson 
487acd3428bSRobert Watson 		if (td != NULL) {
48879ba3952SBjoern A. Zeeb 			error = priv_check(td, (cmd == SIOCDIFADDR_IN6) ?
48979ba3952SBjoern A. Zeeb 			    PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR);
490acd3428bSRobert Watson 			if (error)
4918c0fec80SRobert Watson 				goto out;
492acd3428bSRobert Watson 		}
49382cd038dSYoshinobu Inoue 		break;
49482cd038dSYoshinobu Inoue 
49582cd038dSYoshinobu Inoue 	case SIOCGIFADDR_IN6:
49682cd038dSYoshinobu Inoue 		/* This interface is basically deprecated. use SIOCGIFCONF. */
49706cd0a3fSHajimu UMEMOTO 		/* FALLTHROUGH */
49882cd038dSYoshinobu Inoue 	case SIOCGIFAFLAG_IN6:
49982cd038dSYoshinobu Inoue 	case SIOCGIFNETMASK_IN6:
50082cd038dSYoshinobu Inoue 	case SIOCGIFDSTADDR_IN6:
50182cd038dSYoshinobu Inoue 	case SIOCGIFALIFETIME_IN6:
50282cd038dSYoshinobu Inoue 		/* must think again about its semantics */
5038c0fec80SRobert Watson 		if (ia == NULL) {
5048c0fec80SRobert Watson 			error = EADDRNOTAVAIL;
5058c0fec80SRobert Watson 			goto out;
5068c0fec80SRobert Watson 		}
50782cd038dSYoshinobu Inoue 		break;
5088c0fec80SRobert Watson 
50982cd038dSYoshinobu Inoue 	case SIOCSIFALIFETIME_IN6:
51082cd038dSYoshinobu Inoue 	    {
51182cd038dSYoshinobu Inoue 		struct in6_addrlifetime *lt;
51282cd038dSYoshinobu Inoue 
513acd3428bSRobert Watson 		if (td != NULL) {
514acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_ALIFETIME6);
515acd3428bSRobert Watson 			if (error)
5168c0fec80SRobert Watson 				goto out;
517acd3428bSRobert Watson 		}
5188c0fec80SRobert Watson 		if (ia == NULL) {
5198c0fec80SRobert Watson 			error = EADDRNOTAVAIL;
5208c0fec80SRobert Watson 			goto out;
5218c0fec80SRobert Watson 		}
52282cd038dSYoshinobu Inoue 		/* sanity for overflow - beware unsigned */
52382cd038dSYoshinobu Inoue 		lt = &ifr->ifr_ifru.ifru_lifetime;
52459aecc96SHajimu UMEMOTO 		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
52559aecc96SHajimu UMEMOTO 		    lt->ia6t_vltime + time_second < time_second) {
5268c0fec80SRobert Watson 			error = EINVAL;
5278c0fec80SRobert Watson 			goto out;
52882cd038dSYoshinobu Inoue 		}
52959aecc96SHajimu UMEMOTO 		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
53059aecc96SHajimu UMEMOTO 		    lt->ia6t_pltime + time_second < time_second) {
5318c0fec80SRobert Watson 			error = EINVAL;
5328c0fec80SRobert Watson 			goto out;
53382cd038dSYoshinobu Inoue 		}
53482cd038dSYoshinobu Inoue 		break;
53582cd038dSYoshinobu Inoue 	    }
53682cd038dSYoshinobu Inoue 	}
53782cd038dSYoshinobu Inoue 
53882cd038dSYoshinobu Inoue 	switch (cmd) {
53982cd038dSYoshinobu Inoue 	case SIOCGIFADDR_IN6:
54082cd038dSYoshinobu Inoue 		ifr->ifr_addr = ia->ia_addr;
541a1f7e5f8SHajimu UMEMOTO 		if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
5428c0fec80SRobert Watson 			goto out;
54382cd038dSYoshinobu Inoue 		break;
54482cd038dSYoshinobu Inoue 
54582cd038dSYoshinobu Inoue 	case SIOCGIFDSTADDR_IN6:
5468c0fec80SRobert Watson 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
5478c0fec80SRobert Watson 			error = EINVAL;
5488c0fec80SRobert Watson 			goto out;
5498c0fec80SRobert Watson 		}
550686cdd19SJun-ichiro itojun Hagino 		/*
551686cdd19SJun-ichiro itojun Hagino 		 * XXX: should we check if ifa_dstaddr is NULL and return
552686cdd19SJun-ichiro itojun Hagino 		 * an error?
553686cdd19SJun-ichiro itojun Hagino 		 */
55482cd038dSYoshinobu Inoue 		ifr->ifr_dstaddr = ia->ia_dstaddr;
555a1f7e5f8SHajimu UMEMOTO 		if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
5568c0fec80SRobert Watson 			goto out;
55782cd038dSYoshinobu Inoue 		break;
55882cd038dSYoshinobu Inoue 
55982cd038dSYoshinobu Inoue 	case SIOCGIFNETMASK_IN6:
56082cd038dSYoshinobu Inoue 		ifr->ifr_addr = ia->ia_prefixmask;
56182cd038dSYoshinobu Inoue 		break;
56282cd038dSYoshinobu Inoue 
56382cd038dSYoshinobu Inoue 	case SIOCGIFAFLAG_IN6:
56482cd038dSYoshinobu Inoue 		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
56582cd038dSYoshinobu Inoue 		break;
56682cd038dSYoshinobu Inoue 
56782cd038dSYoshinobu Inoue 	case SIOCGIFSTAT_IN6:
5688c0fec80SRobert Watson 		if (ifp == NULL) {
5698c0fec80SRobert Watson 			error = EINVAL;
5708c0fec80SRobert Watson 			goto out;
5718c0fec80SRobert Watson 		}
57282cd038dSYoshinobu Inoue 		bzero(&ifr->ifr_ifru.ifru_stat,
57382cd038dSYoshinobu Inoue 		    sizeof(ifr->ifr_ifru.ifru_stat));
57431b1bfe1SHajimu UMEMOTO 		ifr->ifr_ifru.ifru_stat =
57531b1bfe1SHajimu UMEMOTO 		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
57682cd038dSYoshinobu Inoue 		break;
57782cd038dSYoshinobu Inoue 
57882cd038dSYoshinobu Inoue 	case SIOCGIFSTAT_ICMP6:
5798c0fec80SRobert Watson 		if (ifp == NULL) {
5808c0fec80SRobert Watson 			error = EINVAL;
5818c0fec80SRobert Watson 			goto out;
5828c0fec80SRobert Watson 		}
583f2b1bd14SGeorge V. Neville-Neil 		bzero(&ifr->ifr_ifru.ifru_icmp6stat,
58482cd038dSYoshinobu Inoue 		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
58582cd038dSYoshinobu Inoue 		ifr->ifr_ifru.ifru_icmp6stat =
58631b1bfe1SHajimu UMEMOTO 		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
58782cd038dSYoshinobu Inoue 		break;
58882cd038dSYoshinobu Inoue 
58982cd038dSYoshinobu Inoue 	case SIOCGIFALIFETIME_IN6:
59082cd038dSYoshinobu Inoue 		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
591743eee66SSUZUKI Shinsuke 		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
592743eee66SSUZUKI Shinsuke 			time_t maxexpire;
593743eee66SSUZUKI Shinsuke 			struct in6_addrlifetime *retlt =
594743eee66SSUZUKI Shinsuke 			    &ifr->ifr_ifru.ifru_lifetime;
595743eee66SSUZUKI Shinsuke 
596743eee66SSUZUKI Shinsuke 			/*
597743eee66SSUZUKI Shinsuke 			 * XXX: adjust expiration time assuming time_t is
598743eee66SSUZUKI Shinsuke 			 * signed.
599743eee66SSUZUKI Shinsuke 			 */
600743eee66SSUZUKI Shinsuke 			maxexpire = (-1) &
60136dc24e6SSUZUKI Shinsuke 			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
602743eee66SSUZUKI Shinsuke 			if (ia->ia6_lifetime.ia6t_vltime <
603743eee66SSUZUKI Shinsuke 			    maxexpire - ia->ia6_updatetime) {
604743eee66SSUZUKI Shinsuke 				retlt->ia6t_expire = ia->ia6_updatetime +
605743eee66SSUZUKI Shinsuke 				    ia->ia6_lifetime.ia6t_vltime;
606743eee66SSUZUKI Shinsuke 			} else
607743eee66SSUZUKI Shinsuke 				retlt->ia6t_expire = maxexpire;
608743eee66SSUZUKI Shinsuke 		}
609743eee66SSUZUKI Shinsuke 		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
610743eee66SSUZUKI Shinsuke 			time_t maxexpire;
611743eee66SSUZUKI Shinsuke 			struct in6_addrlifetime *retlt =
612743eee66SSUZUKI Shinsuke 			    &ifr->ifr_ifru.ifru_lifetime;
613743eee66SSUZUKI Shinsuke 
614743eee66SSUZUKI Shinsuke 			/*
615743eee66SSUZUKI Shinsuke 			 * XXX: adjust expiration time assuming time_t is
616743eee66SSUZUKI Shinsuke 			 * signed.
617743eee66SSUZUKI Shinsuke 			 */
618743eee66SSUZUKI Shinsuke 			maxexpire = (-1) &
61936dc24e6SSUZUKI Shinsuke 			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
620743eee66SSUZUKI Shinsuke 			if (ia->ia6_lifetime.ia6t_pltime <
621743eee66SSUZUKI Shinsuke 			    maxexpire - ia->ia6_updatetime) {
622743eee66SSUZUKI Shinsuke 				retlt->ia6t_preferred = ia->ia6_updatetime +
623743eee66SSUZUKI Shinsuke 				    ia->ia6_lifetime.ia6t_pltime;
624743eee66SSUZUKI Shinsuke 			} else
625743eee66SSUZUKI Shinsuke 				retlt->ia6t_preferred = maxexpire;
626743eee66SSUZUKI Shinsuke 		}
62782cd038dSYoshinobu Inoue 		break;
62882cd038dSYoshinobu Inoue 
62982cd038dSYoshinobu Inoue 	case SIOCSIFALIFETIME_IN6:
63082cd038dSYoshinobu Inoue 		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
63182cd038dSYoshinobu Inoue 		/* for sanity */
63282cd038dSYoshinobu Inoue 		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
63382cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_expire =
63482cd038dSYoshinobu Inoue 				time_second + ia->ia6_lifetime.ia6t_vltime;
63582cd038dSYoshinobu Inoue 		} else
63682cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_expire = 0;
63782cd038dSYoshinobu Inoue 		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
63882cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_preferred =
63982cd038dSYoshinobu Inoue 				time_second + ia->ia6_lifetime.ia6t_pltime;
64082cd038dSYoshinobu Inoue 		} else
64182cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_preferred = 0;
64282cd038dSYoshinobu Inoue 		break;
64382cd038dSYoshinobu Inoue 
64482cd038dSYoshinobu Inoue 	case SIOCAIFADDR_IN6:
64533841545SHajimu UMEMOTO 	{
6468c0fec80SRobert Watson 		int i;
647743eee66SSUZUKI Shinsuke 		struct nd_prefixctl pr0;
648743eee66SSUZUKI Shinsuke 		struct nd_prefix *pr;
64982cd038dSYoshinobu Inoue 
65033841545SHajimu UMEMOTO 		/*
65133841545SHajimu UMEMOTO 		 * first, make or update the interface address structure,
65233841545SHajimu UMEMOTO 		 * and link it to the list.
65333841545SHajimu UMEMOTO 		 */
654743eee66SSUZUKI Shinsuke 		if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
6558c0fec80SRobert Watson 			goto out;
6568c0fec80SRobert Watson 		if (ia != NULL)
6578c0fec80SRobert Watson 			ifa_free(&ia->ia_ifa);
658797df30dSSUZUKI Shinsuke 		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
659797df30dSSUZUKI Shinsuke 		    == NULL) {
660797df30dSSUZUKI Shinsuke 			/*
661797df30dSSUZUKI Shinsuke 			 * this can happen when the user specify the 0 valid
662797df30dSSUZUKI Shinsuke 			 * lifetime.
663797df30dSSUZUKI Shinsuke 			 */
664797df30dSSUZUKI Shinsuke 			break;
665797df30dSSUZUKI Shinsuke 		}
66682cd038dSYoshinobu Inoue 
66771212473SGleb Smirnoff 		if (cmd == ocmd && ifra->ifra_vhid > 0) {
66808b68b0eSGleb Smirnoff 			if (carp_attach_p != NULL)
66908b68b0eSGleb Smirnoff 				error = (*carp_attach_p)(&ia->ia_ifa,
67008b68b0eSGleb Smirnoff 				    ifra->ifra_vhid);
67108b68b0eSGleb Smirnoff 			else
67208b68b0eSGleb Smirnoff 				error = EPROTONOSUPPORT;
67308b68b0eSGleb Smirnoff 			if (error)
67408b68b0eSGleb Smirnoff 				goto out;
67508b68b0eSGleb Smirnoff 			else
67608b68b0eSGleb Smirnoff 				carp_attached = 1;
67708b68b0eSGleb Smirnoff 		}
67808b68b0eSGleb Smirnoff 
67933841545SHajimu UMEMOTO 		/*
68033841545SHajimu UMEMOTO 		 * then, make the prefix on-link on the interface.
68133841545SHajimu UMEMOTO 		 * XXX: we'd rather create the prefix before the address, but
68233841545SHajimu UMEMOTO 		 * we need at least one address to install the corresponding
68333841545SHajimu UMEMOTO 		 * interface route, so we configure the address first.
68433841545SHajimu UMEMOTO 		 */
68533841545SHajimu UMEMOTO 
68633841545SHajimu UMEMOTO 		/*
68733841545SHajimu UMEMOTO 		 * convert mask to prefix length (prefixmask has already
68833841545SHajimu UMEMOTO 		 * been validated in in6_update_ifa().
68933841545SHajimu UMEMOTO 		 */
69033841545SHajimu UMEMOTO 		bzero(&pr0, sizeof(pr0));
69133841545SHajimu UMEMOTO 		pr0.ndpr_ifp = ifp;
69233841545SHajimu UMEMOTO 		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
69333841545SHajimu UMEMOTO 		    NULL);
69406cd0a3fSHajimu UMEMOTO 		if (pr0.ndpr_plen == 128) {
69533841545SHajimu UMEMOTO 			break;	/* we don't need to install a host route. */
69606cd0a3fSHajimu UMEMOTO 		}
69733841545SHajimu UMEMOTO 		pr0.ndpr_prefix = ifra->ifra_addr;
69833841545SHajimu UMEMOTO 		/* apply the mask for safety. */
69933841545SHajimu UMEMOTO 		for (i = 0; i < 4; i++) {
70033841545SHajimu UMEMOTO 			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
70133841545SHajimu UMEMOTO 			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
70233841545SHajimu UMEMOTO 		}
70333841545SHajimu UMEMOTO 		/*
70488ff5695SSUZUKI Shinsuke 		 * XXX: since we don't have an API to set prefix (not address)
70588ff5695SSUZUKI Shinsuke 		 * lifetimes, we just use the same lifetimes as addresses.
70688ff5695SSUZUKI Shinsuke 		 * The (temporarily) installed lifetimes can be overridden by
70788ff5695SSUZUKI Shinsuke 		 * later advertised RAs (when accept_rtadv is non 0), which is
70888ff5695SSUZUKI Shinsuke 		 * an intended behavior.
70933841545SHajimu UMEMOTO 		 */
71033841545SHajimu UMEMOTO 		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
71133841545SHajimu UMEMOTO 		pr0.ndpr_raf_auto =
71233841545SHajimu UMEMOTO 		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
71333841545SHajimu UMEMOTO 		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
71433841545SHajimu UMEMOTO 		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
71533841545SHajimu UMEMOTO 
71606cd0a3fSHajimu UMEMOTO 		/* add the prefix if not yet. */
71733841545SHajimu UMEMOTO 		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
71833841545SHajimu UMEMOTO 			/*
71933841545SHajimu UMEMOTO 			 * nd6_prelist_add will install the corresponding
72033841545SHajimu UMEMOTO 			 * interface route.
72133841545SHajimu UMEMOTO 			 */
72208b68b0eSGleb Smirnoff 			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) {
72308b68b0eSGleb Smirnoff 				if (carp_attached)
72408b68b0eSGleb Smirnoff 					(*carp_detach_p)(&ia->ia_ifa);
7258c0fec80SRobert Watson 				goto out;
72608b68b0eSGleb Smirnoff 			}
72733841545SHajimu UMEMOTO 			if (pr == NULL) {
72808b68b0eSGleb Smirnoff 				if (carp_attached)
72908b68b0eSGleb Smirnoff 					(*carp_detach_p)(&ia->ia_ifa);
73006cd0a3fSHajimu UMEMOTO 				log(LOG_ERR, "nd6_prelist_add succeeded but "
73133841545SHajimu UMEMOTO 				    "no prefix\n");
7328c0fec80SRobert Watson 				error = EINVAL;
7338c0fec80SRobert Watson 				goto out;
73433841545SHajimu UMEMOTO 			}
73533841545SHajimu UMEMOTO 		}
736797df30dSSUZUKI Shinsuke 
737797df30dSSUZUKI Shinsuke 		/* relate the address to the prefix */
738797df30dSSUZUKI Shinsuke 		if (ia->ia6_ndpr == NULL) {
73933841545SHajimu UMEMOTO 			ia->ia6_ndpr = pr;
74033841545SHajimu UMEMOTO 			pr->ndpr_refcnt++;
74133841545SHajimu UMEMOTO 
74233841545SHajimu UMEMOTO 			/*
743797df30dSSUZUKI Shinsuke 			 * If this is the first autoconf address from the
744797df30dSSUZUKI Shinsuke 			 * prefix, create a temporary address as well
745797df30dSSUZUKI Shinsuke 			 * (when required).
74633841545SHajimu UMEMOTO 			 */
747797df30dSSUZUKI Shinsuke 			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) &&
748603724d3SBjoern A. Zeeb 			    V_ip6_use_tempaddr && pr->ndpr_refcnt == 1) {
74933841545SHajimu UMEMOTO 				int e;
750743eee66SSUZUKI Shinsuke 				if ((e = in6_tmpifadd(ia, 1, 0)) != 0) {
751797df30dSSUZUKI Shinsuke 					log(LOG_NOTICE, "in6_control: failed "
752797df30dSSUZUKI Shinsuke 					    "to create a temporary address, "
7534835e2c7SHajimu UMEMOTO 					    "errno=%d\n", e);
75433841545SHajimu UMEMOTO 				}
75533841545SHajimu UMEMOTO 			}
75633841545SHajimu UMEMOTO 		}
75733841545SHajimu UMEMOTO 
75833841545SHajimu UMEMOTO 		/*
759797df30dSSUZUKI Shinsuke 		 * this might affect the status of autoconfigured addresses,
760797df30dSSUZUKI Shinsuke 		 * that is, this address might make other addresses detached.
76133841545SHajimu UMEMOTO 		 */
76233841545SHajimu UMEMOTO 		pfxlist_onlink_check();
76377bc4985SHiroki Sato 		if (error == 0 && ia) {
76477bc4985SHiroki Sato 			if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
76577bc4985SHiroki Sato 				/*
76677bc4985SHiroki Sato 				 * Try to clear the flag when a new
76777bc4985SHiroki Sato 				 * IPv6 address is added onto an
76877bc4985SHiroki Sato 				 * IFDISABLED interface and it
76977bc4985SHiroki Sato 				 * succeeds.
77077bc4985SHiroki Sato 				 */
77177bc4985SHiroki Sato 				struct in6_ndireq nd;
77277bc4985SHiroki Sato 
77377bc4985SHiroki Sato 				memset(&nd, 0, sizeof(nd));
77477bc4985SHiroki Sato 				nd.ndi.flags = ND_IFINFO(ifp)->flags;
77577bc4985SHiroki Sato 				nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
77677bc4985SHiroki Sato 				if (nd6_ioctl(SIOCSIFINFO_FLAGS,
77777bc4985SHiroki Sato 				    (caddr_t)&nd, ifp) < 0)
77877bc4985SHiroki Sato 					log(LOG_NOTICE, "SIOCAIFADDR_IN6: "
77977bc4985SHiroki Sato 					    "SIOCSIFINFO_FLAGS for -ifdisabled "
78077bc4985SHiroki Sato 					    "failed.");
78177bc4985SHiroki Sato 				/*
78277bc4985SHiroki Sato 				 * Ignore failure of clearing the flag
78377bc4985SHiroki Sato 				 * intentionally.  The failure means
78477bc4985SHiroki Sato 				 * address duplication was detected.
78577bc4985SHiroki Sato 				 */
78677bc4985SHiroki Sato 			}
78725a4adceSMax Laier 			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
78877bc4985SHiroki Sato 		}
78933841545SHajimu UMEMOTO 		break;
79033841545SHajimu UMEMOTO 	}
79133841545SHajimu UMEMOTO 
79233841545SHajimu UMEMOTO 	case SIOCDIFADDR_IN6:
79333841545SHajimu UMEMOTO 	{
794743eee66SSUZUKI Shinsuke 		struct nd_prefix *pr;
79533841545SHajimu UMEMOTO 
79633841545SHajimu UMEMOTO 		/*
79733841545SHajimu UMEMOTO 		 * If the address being deleted is the only one that owns
79833841545SHajimu UMEMOTO 		 * the corresponding prefix, expire the prefix as well.
79906cd0a3fSHajimu UMEMOTO 		 * XXX: theoretically, we don't have to worry about such
80033841545SHajimu UMEMOTO 		 * relationship, since we separate the address management
80133841545SHajimu UMEMOTO 		 * and the prefix management.  We do this, however, to provide
80233841545SHajimu UMEMOTO 		 * as much backward compatibility as possible in terms of
80333841545SHajimu UMEMOTO 		 * the ioctl operation.
804797df30dSSUZUKI Shinsuke 		 * Note that in6_purgeaddr() will decrement ndpr_refcnt.
80533841545SHajimu UMEMOTO 		 */
806797df30dSSUZUKI Shinsuke 		pr = ia->ia6_ndpr;
80733841545SHajimu UMEMOTO 		in6_purgeaddr(&ia->ia_ifa);
808797df30dSSUZUKI Shinsuke 		if (pr && pr->ndpr_refcnt == 0)
809797df30dSSUZUKI Shinsuke 			prelist_remove(pr);
81025a4adceSMax Laier 		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
81133841545SHajimu UMEMOTO 		break;
81233841545SHajimu UMEMOTO 	}
81333841545SHajimu UMEMOTO 
81433841545SHajimu UMEMOTO 	default:
8158c0fec80SRobert Watson 		if (ifp == NULL || ifp->if_ioctl == 0) {
8168c0fec80SRobert Watson 			error = EOPNOTSUPP;
8178c0fec80SRobert Watson 			goto out;
8188c0fec80SRobert Watson 		}
8198c0fec80SRobert Watson 		error = (*ifp->if_ioctl)(ifp, cmd, data);
8208c0fec80SRobert Watson 		goto out;
82133841545SHajimu UMEMOTO 	}
82233841545SHajimu UMEMOTO 
8238c0fec80SRobert Watson 	error = 0;
8248c0fec80SRobert Watson out:
8258c0fec80SRobert Watson 	if (ia != NULL)
8268c0fec80SRobert Watson 		ifa_free(&ia->ia_ifa);
8278c0fec80SRobert Watson 	return (error);
82833841545SHajimu UMEMOTO }
82933841545SHajimu UMEMOTO 
83081d5d46bSBjoern A. Zeeb 
83133841545SHajimu UMEMOTO /*
8325490110cSBjoern A. Zeeb  * Join necessary multicast groups.  Factored out from in6_update_ifa().
8335490110cSBjoern A. Zeeb  * This entire work should only be done once, for the default FIB.
8345490110cSBjoern A. Zeeb  */
8355490110cSBjoern A. Zeeb static int
8365490110cSBjoern A. Zeeb in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra,
8375490110cSBjoern A. Zeeb     struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol)
8385490110cSBjoern A. Zeeb {
8395490110cSBjoern A. Zeeb 	char ip6buf[INET6_ADDRSTRLEN];
8405490110cSBjoern A. Zeeb 	struct sockaddr_in6 mltaddr, mltmask;
8415490110cSBjoern A. Zeeb 	struct in6_addr llsol;
8425490110cSBjoern A. Zeeb 	struct in6_multi_mship *imm;
8435490110cSBjoern A. Zeeb 	struct rtentry *rt;
8445490110cSBjoern A. Zeeb 	int delay, error;
8455490110cSBjoern A. Zeeb 
8465490110cSBjoern A. Zeeb 	KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__));
8475490110cSBjoern A. Zeeb 
8485490110cSBjoern A. Zeeb 	/* Join solicited multicast addr for new host id. */
8495490110cSBjoern A. Zeeb 	bzero(&llsol, sizeof(struct in6_addr));
8505490110cSBjoern A. Zeeb 	llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
8515490110cSBjoern A. Zeeb 	llsol.s6_addr32[1] = 0;
8525490110cSBjoern A. Zeeb 	llsol.s6_addr32[2] = htonl(1);
8535490110cSBjoern A. Zeeb 	llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
8545490110cSBjoern A. Zeeb 	llsol.s6_addr8[12] = 0xff;
8555490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
8565490110cSBjoern A. Zeeb 		/* XXX: should not happen */
8575490110cSBjoern A. Zeeb 		log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
8585490110cSBjoern A. Zeeb 		goto cleanup;
8595490110cSBjoern A. Zeeb 	}
8605490110cSBjoern A. Zeeb 	delay = 0;
8615490110cSBjoern A. Zeeb 	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
8625490110cSBjoern A. Zeeb 		/*
8635490110cSBjoern A. Zeeb 		 * We need a random delay for DAD on the address being
8645490110cSBjoern A. Zeeb 		 * configured.  It also means delaying transmission of the
8655490110cSBjoern A. Zeeb 		 * corresponding MLD report to avoid report collision.
8665490110cSBjoern A. Zeeb 		 * [RFC 4861, Section 6.3.7]
8675490110cSBjoern A. Zeeb 		 */
8685490110cSBjoern A. Zeeb 		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
8695490110cSBjoern A. Zeeb 	}
8705490110cSBjoern A. Zeeb 	imm = in6_joingroup(ifp, &llsol, &error, delay);
8715490110cSBjoern A. Zeeb 	if (imm == NULL) {
8725490110cSBjoern A. Zeeb 		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
8735490110cSBjoern A. Zeeb 		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &llsol),
8745490110cSBjoern A. Zeeb 		    if_name(ifp), error));
8755490110cSBjoern A. Zeeb 		goto cleanup;
8765490110cSBjoern A. Zeeb 	}
8775490110cSBjoern A. Zeeb 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
8785490110cSBjoern A. Zeeb 	*in6m_sol = imm->i6mm_maddr;
8795490110cSBjoern A. Zeeb 
8805490110cSBjoern A. Zeeb 	bzero(&mltmask, sizeof(mltmask));
8815490110cSBjoern A. Zeeb 	mltmask.sin6_len = sizeof(struct sockaddr_in6);
8825490110cSBjoern A. Zeeb 	mltmask.sin6_family = AF_INET6;
8835490110cSBjoern A. Zeeb 	mltmask.sin6_addr = in6mask32;
8845490110cSBjoern A. Zeeb #define	MLTMASK_LEN  4	/* mltmask's masklen (=32bit=4octet) */
8855490110cSBjoern A. Zeeb 
8865490110cSBjoern A. Zeeb 	/*
8875490110cSBjoern A. Zeeb 	 * Join link-local all-nodes address.
8885490110cSBjoern A. Zeeb 	 */
8895490110cSBjoern A. Zeeb 	bzero(&mltaddr, sizeof(mltaddr));
8905490110cSBjoern A. Zeeb 	mltaddr.sin6_len = sizeof(struct sockaddr_in6);
8915490110cSBjoern A. Zeeb 	mltaddr.sin6_family = AF_INET6;
8925490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_linklocal_allnodes;
8935490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
8945490110cSBjoern A. Zeeb 		goto cleanup; /* XXX: should not fail */
8955490110cSBjoern A. Zeeb 
8965490110cSBjoern A. Zeeb 	/*
8975490110cSBjoern A. Zeeb 	 * XXX: do we really need this automatic routes?  We should probably
8985490110cSBjoern A. Zeeb 	 * reconsider this stuff.  Most applications actually do not need the
8995490110cSBjoern A. Zeeb 	 * routes, since they usually specify the outgoing interface.
9005490110cSBjoern A. Zeeb 	 */
90181d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
9025490110cSBjoern A. Zeeb 	if (rt != NULL) {
9035490110cSBjoern A. Zeeb 		/* XXX: only works in !SCOPEDROUTING case. */
9045490110cSBjoern A. Zeeb 		if (memcmp(&mltaddr.sin6_addr,
9055490110cSBjoern A. Zeeb 		    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
9065490110cSBjoern A. Zeeb 		    MLTMASK_LEN)) {
9075490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
9085490110cSBjoern A. Zeeb 			rt = NULL;
9095490110cSBjoern A. Zeeb 		}
9105490110cSBjoern A. Zeeb 	}
9115490110cSBjoern A. Zeeb 	if (rt == NULL) {
91281d5d46bSBjoern A. Zeeb 		error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
9135490110cSBjoern A. Zeeb 		    (struct sockaddr *)&ia->ia_addr,
9145490110cSBjoern A. Zeeb 		    (struct sockaddr *)&mltmask, RTF_UP,
91581d5d46bSBjoern A. Zeeb 		    (struct rtentry **)0, RT_DEFAULT_FIB);
9165490110cSBjoern A. Zeeb 		if (error)
9175490110cSBjoern A. Zeeb 			goto cleanup;
9185490110cSBjoern A. Zeeb 	} else
9195490110cSBjoern A. Zeeb 		RTFREE_LOCKED(rt);
9205490110cSBjoern A. Zeeb 
9215490110cSBjoern A. Zeeb 	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
9225490110cSBjoern A. Zeeb 	if (imm == NULL) {
9235490110cSBjoern A. Zeeb 		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
9245490110cSBjoern A. Zeeb 		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
9255490110cSBjoern A. Zeeb 		    &mltaddr.sin6_addr), if_name(ifp), error));
9265490110cSBjoern A. Zeeb 		goto cleanup;
9275490110cSBjoern A. Zeeb 	}
9285490110cSBjoern A. Zeeb 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
9295490110cSBjoern A. Zeeb 
9305490110cSBjoern A. Zeeb 	/*
9315490110cSBjoern A. Zeeb 	 * Join node information group address.
9325490110cSBjoern A. Zeeb 	 */
9335490110cSBjoern A. Zeeb 	delay = 0;
9345490110cSBjoern A. Zeeb 	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
9355490110cSBjoern A. Zeeb 		/*
9365490110cSBjoern A. Zeeb 		 * The spec does not say anything about delay for this group,
9375490110cSBjoern A. Zeeb 		 * but the same logic should apply.
9385490110cSBjoern A. Zeeb 		 */
9395490110cSBjoern A. Zeeb 		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
9405490110cSBjoern A. Zeeb 	}
9415490110cSBjoern A. Zeeb 	if (in6_nigroup(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) {
9425490110cSBjoern A. Zeeb 		/* XXX jinmei */
9435490110cSBjoern A. Zeeb 		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay);
9445490110cSBjoern A. Zeeb 		if (imm == NULL)
9455490110cSBjoern A. Zeeb 			nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
9465490110cSBjoern A. Zeeb 			    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
9475490110cSBjoern A. Zeeb 			    &mltaddr.sin6_addr), if_name(ifp), error));
9485490110cSBjoern A. Zeeb 			/* XXX not very fatal, go on... */
9495490110cSBjoern A. Zeeb 		else
9505490110cSBjoern A. Zeeb 			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
9515490110cSBjoern A. Zeeb 	}
9525490110cSBjoern A. Zeeb 
9535490110cSBjoern A. Zeeb 	/*
9545490110cSBjoern A. Zeeb 	 * Join interface-local all-nodes address.
9555490110cSBjoern A. Zeeb 	 * (ff01::1%ifN, and ff01::%ifN/32)
9565490110cSBjoern A. Zeeb 	 */
9575490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
9585490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
9595490110cSBjoern A. Zeeb 		goto cleanup; /* XXX: should not fail */
9605490110cSBjoern A. Zeeb 	/* XXX: again, do we really need the route? */
96181d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
9625490110cSBjoern A. Zeeb 	if (rt != NULL) {
9635490110cSBjoern A. Zeeb 		if (memcmp(&mltaddr.sin6_addr,
9645490110cSBjoern A. Zeeb 		    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
9655490110cSBjoern A. Zeeb 		    MLTMASK_LEN)) {
9665490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
9675490110cSBjoern A. Zeeb 			rt = NULL;
9685490110cSBjoern A. Zeeb 		}
9695490110cSBjoern A. Zeeb 	}
9705490110cSBjoern A. Zeeb 	if (rt == NULL) {
97181d5d46bSBjoern A. Zeeb 		error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
9725490110cSBjoern A. Zeeb 		    (struct sockaddr *)&ia->ia_addr,
9735490110cSBjoern A. Zeeb 		    (struct sockaddr *)&mltmask, RTF_UP,
97481d5d46bSBjoern A. Zeeb 		    (struct rtentry **)0, RT_DEFAULT_FIB);
9755490110cSBjoern A. Zeeb 		if (error)
9765490110cSBjoern A. Zeeb 			goto cleanup;
9775490110cSBjoern A. Zeeb 	} else
9785490110cSBjoern A. Zeeb 		RTFREE_LOCKED(rt);
9795490110cSBjoern A. Zeeb 
9805490110cSBjoern A. Zeeb 	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
9815490110cSBjoern A. Zeeb 	if (imm == NULL) {
9825490110cSBjoern A. Zeeb 		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
9835490110cSBjoern A. Zeeb 		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
9845490110cSBjoern A. Zeeb 		    &mltaddr.sin6_addr), if_name(ifp), error));
9855490110cSBjoern A. Zeeb 		goto cleanup;
9865490110cSBjoern A. Zeeb 	}
9875490110cSBjoern A. Zeeb 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
9885490110cSBjoern A. Zeeb #undef	MLTMASK_LEN
9895490110cSBjoern A. Zeeb 
9905490110cSBjoern A. Zeeb cleanup:
9915490110cSBjoern A. Zeeb 	return (error);
9925490110cSBjoern A. Zeeb }
9935490110cSBjoern A. Zeeb 
9945490110cSBjoern A. Zeeb /*
99533841545SHajimu UMEMOTO  * Update parameters of an IPv6 interface address.
99633841545SHajimu UMEMOTO  * If necessary, a new entry is created and linked into address chains.
99733841545SHajimu UMEMOTO  * This function is separated from in6_control().
99833841545SHajimu UMEMOTO  * XXX: should this be performed under splnet()?
99933841545SHajimu UMEMOTO  */
100033841545SHajimu UMEMOTO int
10011272577eSXin LI in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
10021272577eSXin LI     struct in6_ifaddr *ia, int flags)
100333841545SHajimu UMEMOTO {
100433841545SHajimu UMEMOTO 	int error = 0, hostIsNew = 0, plen = -1;
100533841545SHajimu UMEMOTO 	struct sockaddr_in6 dst6;
100633841545SHajimu UMEMOTO 	struct in6_addrlifetime *lt;
1007743eee66SSUZUKI Shinsuke 	struct in6_multi *in6m_sol;
1008743eee66SSUZUKI Shinsuke 	int delay;
10091d54aa3bSBjoern A. Zeeb 	char ip6buf[INET6_ADDRSTRLEN];
101033841545SHajimu UMEMOTO 
101133841545SHajimu UMEMOTO 	/* Validate parameters */
101233841545SHajimu UMEMOTO 	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
101333841545SHajimu UMEMOTO 		return (EINVAL);
101433841545SHajimu UMEMOTO 
1015686cdd19SJun-ichiro itojun Hagino 	/*
1016686cdd19SJun-ichiro itojun Hagino 	 * The destination address for a p2p link must have a family
1017686cdd19SJun-ichiro itojun Hagino 	 * of AF_UNSPEC or AF_INET6.
1018686cdd19SJun-ichiro itojun Hagino 	 */
1019686cdd19SJun-ichiro itojun Hagino 	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
1020686cdd19SJun-ichiro itojun Hagino 	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
1021686cdd19SJun-ichiro itojun Hagino 	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
1022686cdd19SJun-ichiro itojun Hagino 		return (EAFNOSUPPORT);
1023686cdd19SJun-ichiro itojun Hagino 	/*
102433841545SHajimu UMEMOTO 	 * validate ifra_prefixmask.  don't check sin6_family, netmask
102533841545SHajimu UMEMOTO 	 * does not carry fields other than sin6_len.
1026686cdd19SJun-ichiro itojun Hagino 	 */
102733841545SHajimu UMEMOTO 	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
102833841545SHajimu UMEMOTO 		return (EINVAL);
102982cd038dSYoshinobu Inoue 	/*
103033841545SHajimu UMEMOTO 	 * Because the IPv6 address architecture is classless, we require
103133841545SHajimu UMEMOTO 	 * users to specify a (non 0) prefix length (mask) for a new address.
103233841545SHajimu UMEMOTO 	 * We also require the prefix (when specified) mask is valid, and thus
103333841545SHajimu UMEMOTO 	 * reject a non-consecutive mask.
103482cd038dSYoshinobu Inoue 	 */
103533841545SHajimu UMEMOTO 	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
103633841545SHajimu UMEMOTO 		return (EINVAL);
103733841545SHajimu UMEMOTO 	if (ifra->ifra_prefixmask.sin6_len != 0) {
103833841545SHajimu UMEMOTO 		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
103933841545SHajimu UMEMOTO 		    (u_char *)&ifra->ifra_prefixmask +
104033841545SHajimu UMEMOTO 		    ifra->ifra_prefixmask.sin6_len);
104133841545SHajimu UMEMOTO 		if (plen <= 0)
104233841545SHajimu UMEMOTO 			return (EINVAL);
104306cd0a3fSHajimu UMEMOTO 	} else {
104433841545SHajimu UMEMOTO 		/*
104533841545SHajimu UMEMOTO 		 * In this case, ia must not be NULL.  We just use its prefix
104633841545SHajimu UMEMOTO 		 * length.
104733841545SHajimu UMEMOTO 		 */
104833841545SHajimu UMEMOTO 		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
104982cd038dSYoshinobu Inoue 	}
105033841545SHajimu UMEMOTO 	/*
105133841545SHajimu UMEMOTO 	 * If the destination address on a p2p interface is specified,
105233841545SHajimu UMEMOTO 	 * and the address is a scoped one, validate/set the scope
105333841545SHajimu UMEMOTO 	 * zone identifier.
105433841545SHajimu UMEMOTO 	 */
105533841545SHajimu UMEMOTO 	dst6 = ifra->ifra_dstaddr;
105606cd0a3fSHajimu UMEMOTO 	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
105733841545SHajimu UMEMOTO 	    (dst6.sin6_family == AF_INET6)) {
1058a1f7e5f8SHajimu UMEMOTO 		struct in6_addr in6_tmp;
105959aecc96SHajimu UMEMOTO 		u_int32_t zoneid;
106033841545SHajimu UMEMOTO 
1061a1f7e5f8SHajimu UMEMOTO 		in6_tmp = dst6.sin6_addr;
1062a1f7e5f8SHajimu UMEMOTO 		if (in6_setscope(&in6_tmp, ifp, &zoneid))
1063a1f7e5f8SHajimu UMEMOTO 			return (EINVAL); /* XXX: should be impossible */
1064a1f7e5f8SHajimu UMEMOTO 
1065a1f7e5f8SHajimu UMEMOTO 		if (dst6.sin6_scope_id != 0) {
1066a1f7e5f8SHajimu UMEMOTO 			if (dst6.sin6_scope_id != zoneid)
10679a4f9608SHajimu UMEMOTO 				return (EINVAL);
1068a1f7e5f8SHajimu UMEMOTO 		} else		/* user omit to specify the ID. */
106959aecc96SHajimu UMEMOTO 			dst6.sin6_scope_id = zoneid;
1070a1f7e5f8SHajimu UMEMOTO 
1071a1f7e5f8SHajimu UMEMOTO 		/* convert into the internal form */
1072a1f7e5f8SHajimu UMEMOTO 		if (sa6_embedscope(&dst6, 0))
1073a1f7e5f8SHajimu UMEMOTO 			return (EINVAL); /* XXX: should be impossible */
1074686cdd19SJun-ichiro itojun Hagino 	}
107533841545SHajimu UMEMOTO 	/*
107633841545SHajimu UMEMOTO 	 * The destination address can be specified only for a p2p or a
107733841545SHajimu UMEMOTO 	 * loopback interface.  If specified, the corresponding prefix length
107833841545SHajimu UMEMOTO 	 * must be 128.
107933841545SHajimu UMEMOTO 	 */
108033841545SHajimu UMEMOTO 	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
108133841545SHajimu UMEMOTO 		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
108259aecc96SHajimu UMEMOTO 			/* XXX: noisy message */
10834835e2c7SHajimu UMEMOTO 			nd6log((LOG_INFO, "in6_update_ifa: a destination can "
10844835e2c7SHajimu UMEMOTO 			    "be specified for a p2p or a loopback IF only\n"));
108533841545SHajimu UMEMOTO 			return (EINVAL);
108633841545SHajimu UMEMOTO 		}
108733841545SHajimu UMEMOTO 		if (plen != 128) {
10884835e2c7SHajimu UMEMOTO 			nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
10894835e2c7SHajimu UMEMOTO 			    "be 128 when dstaddr is specified\n"));
109033841545SHajimu UMEMOTO 			return (EINVAL);
109133841545SHajimu UMEMOTO 		}
109233841545SHajimu UMEMOTO 	}
109333841545SHajimu UMEMOTO 	/* lifetime consistency check */
109433841545SHajimu UMEMOTO 	lt = &ifra->ifra_lifetime;
1095743eee66SSUZUKI Shinsuke 	if (lt->ia6t_pltime > lt->ia6t_vltime)
1096743eee66SSUZUKI Shinsuke 		return (EINVAL);
109733841545SHajimu UMEMOTO 	if (lt->ia6t_vltime == 0) {
109833841545SHajimu UMEMOTO 		/*
109933841545SHajimu UMEMOTO 		 * the following log might be noisy, but this is a typical
110033841545SHajimu UMEMOTO 		 * configuration mistake or a tool's bug.
110133841545SHajimu UMEMOTO 		 */
11024835e2c7SHajimu UMEMOTO 		nd6log((LOG_INFO,
110333841545SHajimu UMEMOTO 		    "in6_update_ifa: valid lifetime is 0 for %s\n",
11041d54aa3bSBjoern A. Zeeb 		    ip6_sprintf(ip6buf, &ifra->ifra_addr.sin6_addr)));
1105743eee66SSUZUKI Shinsuke 
1106743eee66SSUZUKI Shinsuke 		if (ia == NULL)
1107743eee66SSUZUKI Shinsuke 			return (0); /* there's nothing to do */
110833841545SHajimu UMEMOTO 	}
110982cd038dSYoshinobu Inoue 
111082cd038dSYoshinobu Inoue 	/*
111133841545SHajimu UMEMOTO 	 * If this is a new address, allocate a new ifaddr and link it
111233841545SHajimu UMEMOTO 	 * into chains.
111333841545SHajimu UMEMOTO 	 */
111433841545SHajimu UMEMOTO 	if (ia == NULL) {
111533841545SHajimu UMEMOTO 		hostIsNew = 1;
111609541513SHajimu UMEMOTO 		/*
111709541513SHajimu UMEMOTO 		 * When in6_update_ifa() is called in a process of a received
111806cd0a3fSHajimu UMEMOTO 		 * RA, it is called under an interrupt context.  So, we should
111906cd0a3fSHajimu UMEMOTO 		 * call malloc with M_NOWAIT.
112009541513SHajimu UMEMOTO 		 */
112106cd0a3fSHajimu UMEMOTO 		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
112206cd0a3fSHajimu UMEMOTO 		    M_NOWAIT);
112333841545SHajimu UMEMOTO 		if (ia == NULL)
112433841545SHajimu UMEMOTO 			return (ENOBUFS);
112533841545SHajimu UMEMOTO 		bzero((caddr_t)ia, sizeof(*ia));
11261099f828SRobert Watson 		ifa_init(&ia->ia_ifa);
112709a52a55SJINMEI Tatuya 		LIST_INIT(&ia->ia6_memberships);
1128743eee66SSUZUKI Shinsuke 		/* Initialize the address and masks, and put time stamp */
112933841545SHajimu UMEMOTO 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
113033841545SHajimu UMEMOTO 		ia->ia_addr.sin6_family = AF_INET6;
113133841545SHajimu UMEMOTO 		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
1132743eee66SSUZUKI Shinsuke 		ia->ia6_createtime = time_second;
113333841545SHajimu UMEMOTO 		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
113433841545SHajimu UMEMOTO 			/*
113533841545SHajimu UMEMOTO 			 * XXX: some functions expect that ifa_dstaddr is not
113633841545SHajimu UMEMOTO 			 * NULL for p2p interfaces.
113733841545SHajimu UMEMOTO 			 */
113806cd0a3fSHajimu UMEMOTO 			ia->ia_ifa.ifa_dstaddr =
113906cd0a3fSHajimu UMEMOTO 			    (struct sockaddr *)&ia->ia_dstaddr;
114033841545SHajimu UMEMOTO 		} else {
114133841545SHajimu UMEMOTO 			ia->ia_ifa.ifa_dstaddr = NULL;
114233841545SHajimu UMEMOTO 		}
114319fc74fbSJeffrey Hsu 		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
114433841545SHajimu UMEMOTO 		ia->ia_ifp = ifp;
11458c0fec80SRobert Watson 		ifa_ref(&ia->ia_ifa);			/* if_addrhead */
1146137f91e8SJohn Baldwin 		IF_ADDR_WLOCK(ifp);
1147c4dd3fe1SRobert Watson 		TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
1148137f91e8SJohn Baldwin 		IF_ADDR_WUNLOCK(ifp);
114980af0152SRobert Watson 
1150d1da0a06SRobert Watson 		ifa_ref(&ia->ia_ifa);			/* in6_ifaddrhead */
1151d1da0a06SRobert Watson 		IN6_IFADDR_WLOCK();
115280af0152SRobert Watson 		TAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link);
1153d1da0a06SRobert Watson 		IN6_IFADDR_WUNLOCK();
115433841545SHajimu UMEMOTO 	}
115533841545SHajimu UMEMOTO 
1156743eee66SSUZUKI Shinsuke 	/* update timestamp */
1157743eee66SSUZUKI Shinsuke 	ia->ia6_updatetime = time_second;
1158743eee66SSUZUKI Shinsuke 
115933841545SHajimu UMEMOTO 	/* set prefix mask */
116033841545SHajimu UMEMOTO 	if (ifra->ifra_prefixmask.sin6_len) {
116133841545SHajimu UMEMOTO 		/*
116233841545SHajimu UMEMOTO 		 * We prohibit changing the prefix length of an existing
116333841545SHajimu UMEMOTO 		 * address, because
116433841545SHajimu UMEMOTO 		 * + such an operation should be rare in IPv6, and
116533841545SHajimu UMEMOTO 		 * + the operation would confuse prefix management.
116633841545SHajimu UMEMOTO 		 */
116733841545SHajimu UMEMOTO 		if (ia->ia_prefixmask.sin6_len &&
116833841545SHajimu UMEMOTO 		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
11694835e2c7SHajimu UMEMOTO 			nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
117033841545SHajimu UMEMOTO 			    " existing (%s) address should not be changed\n",
11711d54aa3bSBjoern A. Zeeb 			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
117233841545SHajimu UMEMOTO 			error = EINVAL;
117333841545SHajimu UMEMOTO 			goto unlink;
117433841545SHajimu UMEMOTO 		}
117533841545SHajimu UMEMOTO 		ia->ia_prefixmask = ifra->ifra_prefixmask;
117633841545SHajimu UMEMOTO 	}
117733841545SHajimu UMEMOTO 
117833841545SHajimu UMEMOTO 	/*
117933841545SHajimu UMEMOTO 	 * If a new destination address is specified, scrub the old one and
118033841545SHajimu UMEMOTO 	 * install the new destination.  Note that the interface must be
118133841545SHajimu UMEMOTO 	 * p2p or loopback (see the check above.)
118233841545SHajimu UMEMOTO 	 */
118333841545SHajimu UMEMOTO 	if (dst6.sin6_family == AF_INET6 &&
118406cd0a3fSHajimu UMEMOTO 	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
118533841545SHajimu UMEMOTO 		int e;
118633841545SHajimu UMEMOTO 
118733841545SHajimu UMEMOTO 		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
118806cd0a3fSHajimu UMEMOTO 		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
11894835e2c7SHajimu UMEMOTO 			nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
119033841545SHajimu UMEMOTO 			    "a route to the old destination: %s\n",
11911d54aa3bSBjoern A. Zeeb 			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
119233841545SHajimu UMEMOTO 			/* proceed anyway... */
119306cd0a3fSHajimu UMEMOTO 		} else
119433841545SHajimu UMEMOTO 			ia->ia_flags &= ~IFA_ROUTE;
119533841545SHajimu UMEMOTO 		ia->ia_dstaddr = dst6;
119633841545SHajimu UMEMOTO 	}
119733841545SHajimu UMEMOTO 
1198a1f7e5f8SHajimu UMEMOTO 	/*
1199a1f7e5f8SHajimu UMEMOTO 	 * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
1200a1f7e5f8SHajimu UMEMOTO 	 * to see if the address is deprecated or invalidated, but initialize
1201a1f7e5f8SHajimu UMEMOTO 	 * these members for applications.
1202a1f7e5f8SHajimu UMEMOTO 	 */
1203a1f7e5f8SHajimu UMEMOTO 	ia->ia6_lifetime = ifra->ifra_lifetime;
1204a1f7e5f8SHajimu UMEMOTO 	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
1205a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_expire =
1206a1f7e5f8SHajimu UMEMOTO 		    time_second + ia->ia6_lifetime.ia6t_vltime;
1207a1f7e5f8SHajimu UMEMOTO 	} else
1208a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_expire = 0;
1209a1f7e5f8SHajimu UMEMOTO 	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
1210a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_preferred =
1211a1f7e5f8SHajimu UMEMOTO 		    time_second + ia->ia6_lifetime.ia6t_pltime;
1212a1f7e5f8SHajimu UMEMOTO 	} else
1213a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_preferred = 0;
1214a1f7e5f8SHajimu UMEMOTO 
121533841545SHajimu UMEMOTO 	/* reset the interface and routing table appropriately. */
121633841545SHajimu UMEMOTO 	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
121733841545SHajimu UMEMOTO 		goto unlink;
121833841545SHajimu UMEMOTO 
121933841545SHajimu UMEMOTO 	/*
1220a1f7e5f8SHajimu UMEMOTO 	 * configure address flags.
1221a1f7e5f8SHajimu UMEMOTO 	 */
1222a1f7e5f8SHajimu UMEMOTO 	ia->ia6_flags = ifra->ifra_flags;
1223a1f7e5f8SHajimu UMEMOTO 	/*
1224a1f7e5f8SHajimu UMEMOTO 	 * backward compatibility - if IN6_IFF_DEPRECATED is set from the
1225a1f7e5f8SHajimu UMEMOTO 	 * userland, make it deprecated.
1226a1f7e5f8SHajimu UMEMOTO 	 */
1227a1f7e5f8SHajimu UMEMOTO 	if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
1228a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_pltime = 0;
1229a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_preferred = time_second;
1230a1f7e5f8SHajimu UMEMOTO 	}
1231a1f7e5f8SHajimu UMEMOTO 	/*
1232743eee66SSUZUKI Shinsuke 	 * Make the address tentative before joining multicast addresses,
1233743eee66SSUZUKI Shinsuke 	 * so that corresponding MLD responses would not have a tentative
1234743eee66SSUZUKI Shinsuke 	 * source address.
1235a1f7e5f8SHajimu UMEMOTO 	 */
1236743eee66SSUZUKI Shinsuke 	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/* safety */
1237743eee66SSUZUKI Shinsuke 	if (hostIsNew && in6if_do_dad(ifp))
1238a1f7e5f8SHajimu UMEMOTO 		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1239a1f7e5f8SHajimu UMEMOTO 
1240a283298cSHiroki Sato 	/* DAD should be performed after ND6_IFF_IFDISABLED is cleared. */
1241a283298cSHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
1242a283298cSHiroki Sato 		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1243a283298cSHiroki Sato 
1244a1f7e5f8SHajimu UMEMOTO 	/*
1245a1f7e5f8SHajimu UMEMOTO 	 * We are done if we have simply modified an existing address.
1246a1f7e5f8SHajimu UMEMOTO 	 */
1247a1f7e5f8SHajimu UMEMOTO 	if (!hostIsNew)
1248a1f7e5f8SHajimu UMEMOTO 		return (error);
1249a1f7e5f8SHajimu UMEMOTO 
1250a1f7e5f8SHajimu UMEMOTO 	/*
125133841545SHajimu UMEMOTO 	 * Beyond this point, we should call in6_purgeaddr upon an error,
125233841545SHajimu UMEMOTO 	 * not just go to unlink.
125333841545SHajimu UMEMOTO 	 */
125433841545SHajimu UMEMOTO 
12555490110cSBjoern A. Zeeb 	/* Join necessary multicast groups. */
1256743eee66SSUZUKI Shinsuke 	in6m_sol = NULL;
125733841545SHajimu UMEMOTO 	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
12585490110cSBjoern A. Zeeb 		error = in6_update_ifa_join_mc(ifp, ifra, ia, flags, &in6m_sol);
1259743eee66SSUZUKI Shinsuke 		if (error)
1260743eee66SSUZUKI Shinsuke 			goto cleanup;
126133841545SHajimu UMEMOTO 	}
126282cd038dSYoshinobu Inoue 
1263743eee66SSUZUKI Shinsuke 	/*
1264743eee66SSUZUKI Shinsuke 	 * Perform DAD, if needed.
126581d5d46bSBjoern A. Zeeb 	 * XXX It may be of use, if we can administratively disable DAD.
1266743eee66SSUZUKI Shinsuke 	 */
12678c0fec80SRobert Watson 	if (in6if_do_dad(ifp) && ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
1268743eee66SSUZUKI Shinsuke 	    (ia->ia6_flags & IN6_IFF_TENTATIVE))
1269743eee66SSUZUKI Shinsuke 	{
1270743eee66SSUZUKI Shinsuke 		int mindelay, maxdelay;
1271743eee66SSUZUKI Shinsuke 
1272743eee66SSUZUKI Shinsuke 		delay = 0;
1273743eee66SSUZUKI Shinsuke 		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1274743eee66SSUZUKI Shinsuke 			/*
1275743eee66SSUZUKI Shinsuke 			 * We need to impose a delay before sending an NS
1276743eee66SSUZUKI Shinsuke 			 * for DAD.  Check if we also needed a delay for the
1277743eee66SSUZUKI Shinsuke 			 * corresponding MLD message.  If we did, the delay
1278743eee66SSUZUKI Shinsuke 			 * should be larger than the MLD delay (this could be
1279743eee66SSUZUKI Shinsuke 			 * relaxed a bit, but this simple logic is at least
1280743eee66SSUZUKI Shinsuke 			 * safe).
128133cde130SBruce M Simpson 			 * XXX: Break data hiding guidelines and look at
128233cde130SBruce M Simpson 			 * state for the solicited multicast group.
1283743eee66SSUZUKI Shinsuke 			 */
1284743eee66SSUZUKI Shinsuke 			mindelay = 0;
1285743eee66SSUZUKI Shinsuke 			if (in6m_sol != NULL &&
128633cde130SBruce M Simpson 			    in6m_sol->in6m_state == MLD_REPORTING_MEMBER) {
1287743eee66SSUZUKI Shinsuke 				mindelay = in6m_sol->in6m_timer;
1288743eee66SSUZUKI Shinsuke 			}
1289743eee66SSUZUKI Shinsuke 			maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
1290743eee66SSUZUKI Shinsuke 			if (maxdelay - mindelay == 0)
1291743eee66SSUZUKI Shinsuke 				delay = 0;
1292743eee66SSUZUKI Shinsuke 			else {
1293743eee66SSUZUKI Shinsuke 				delay =
1294743eee66SSUZUKI Shinsuke 				    (arc4random() % (maxdelay - mindelay)) +
1295743eee66SSUZUKI Shinsuke 				    mindelay;
1296743eee66SSUZUKI Shinsuke 			}
1297743eee66SSUZUKI Shinsuke 		}
1298743eee66SSUZUKI Shinsuke 		nd6_dad_start((struct ifaddr *)ia, delay);
1299743eee66SSUZUKI Shinsuke 	}
1300743eee66SSUZUKI Shinsuke 
13018c0fec80SRobert Watson 	KASSERT(hostIsNew, ("in6_update_ifa: !hostIsNew"));
13028c0fec80SRobert Watson 	ifa_free(&ia->ia_ifa);
130382cd038dSYoshinobu Inoue 	return (error);
130482cd038dSYoshinobu Inoue 
130533841545SHajimu UMEMOTO   unlink:
130633841545SHajimu UMEMOTO 	/*
130733841545SHajimu UMEMOTO 	 * XXX: if a change of an existing address failed, keep the entry
130833841545SHajimu UMEMOTO 	 * anyway.
130933841545SHajimu UMEMOTO 	 */
13108c0fec80SRobert Watson 	if (hostIsNew) {
131133841545SHajimu UMEMOTO 		in6_unlink_ifa(ia, ifp);
13123cfed08dSRobert Watson 		ifa_free(&ia->ia_ifa);
13138c0fec80SRobert Watson 	}
131433841545SHajimu UMEMOTO 	return (error);
1315a1f7e5f8SHajimu UMEMOTO 
1316a1f7e5f8SHajimu UMEMOTO   cleanup:
13178c0fec80SRobert Watson 	KASSERT(hostIsNew, ("in6_update_ifa: cleanup: !hostIsNew"));
13188c0fec80SRobert Watson 	ifa_free(&ia->ia_ifa);
1319a1f7e5f8SHajimu UMEMOTO 	in6_purgeaddr(&ia->ia_ifa);
1320a1f7e5f8SHajimu UMEMOTO 	return error;
1321686cdd19SJun-ichiro itojun Hagino }
1322686cdd19SJun-ichiro itojun Hagino 
13235490110cSBjoern A. Zeeb /*
13245490110cSBjoern A. Zeeb  * Leave multicast groups.  Factored out from in6_purgeaddr().
13255490110cSBjoern A. Zeeb  * This entire work should only be done once, for the default FIB.
13265490110cSBjoern A. Zeeb  */
13275490110cSBjoern A. Zeeb static int
13285490110cSBjoern A. Zeeb in6_purgeaddr_mc(struct ifnet *ifp, struct in6_ifaddr *ia, struct ifaddr *ifa0)
13295490110cSBjoern A. Zeeb {
13305490110cSBjoern A. Zeeb 	struct sockaddr_in6 mltaddr, mltmask;
13315490110cSBjoern A. Zeeb 	struct in6_multi_mship *imm;
13325490110cSBjoern A. Zeeb 	struct rtentry *rt;
13335490110cSBjoern A. Zeeb 	int error;
13345490110cSBjoern A. Zeeb 
13355490110cSBjoern A. Zeeb 	/*
13365490110cSBjoern A. Zeeb 	 * Leave from multicast groups we have joined for the interface.
13375490110cSBjoern A. Zeeb 	 */
13385490110cSBjoern A. Zeeb 	while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
13395490110cSBjoern A. Zeeb 		LIST_REMOVE(imm, i6mm_chain);
13405490110cSBjoern A. Zeeb 		in6_leavegroup(imm);
13415490110cSBjoern A. Zeeb 	}
13425490110cSBjoern A. Zeeb 
13435490110cSBjoern A. Zeeb 	/*
13445490110cSBjoern A. Zeeb 	 * Remove the link-local all-nodes address.
13455490110cSBjoern A. Zeeb 	 */
13465490110cSBjoern A. Zeeb 	bzero(&mltmask, sizeof(mltmask));
13475490110cSBjoern A. Zeeb 	mltmask.sin6_len = sizeof(struct sockaddr_in6);
13485490110cSBjoern A. Zeeb 	mltmask.sin6_family = AF_INET6;
13495490110cSBjoern A. Zeeb 	mltmask.sin6_addr = in6mask32;
13505490110cSBjoern A. Zeeb 
13515490110cSBjoern A. Zeeb 	bzero(&mltaddr, sizeof(mltaddr));
13525490110cSBjoern A. Zeeb 	mltaddr.sin6_len = sizeof(struct sockaddr_in6);
13535490110cSBjoern A. Zeeb 	mltaddr.sin6_family = AF_INET6;
13545490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_linklocal_allnodes;
13555490110cSBjoern A. Zeeb 
13565490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
13575490110cSBjoern A. Zeeb 		return (error);
13585490110cSBjoern A. Zeeb 
135981d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
13605490110cSBjoern A. Zeeb 	if (rt != NULL && rt->rt_gateway != NULL &&
13615490110cSBjoern A. Zeeb 	    (memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
13625490110cSBjoern A. Zeeb 		    &ia->ia_addr.sin6_addr,
13635490110cSBjoern A. Zeeb 		    sizeof(ia->ia_addr.sin6_addr)) == 0)) {
13645490110cSBjoern A. Zeeb 		/*
13655490110cSBjoern A. Zeeb 		 * If no more IPv6 address exists on this interface then
13665490110cSBjoern A. Zeeb 		 * remove the multicast address route.
13675490110cSBjoern A. Zeeb 		 */
13685490110cSBjoern A. Zeeb 		if (ifa0 == NULL) {
13695490110cSBjoern A. Zeeb 			memcpy(&mltaddr.sin6_addr, &satosin6(rt_key(rt))->sin6_addr,
13705490110cSBjoern A. Zeeb 			       sizeof(mltaddr.sin6_addr));
13715490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
137281d5d46bSBjoern A. Zeeb 			error = in6_rtrequest(RTM_DELETE,
13735490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltaddr,
13745490110cSBjoern A. Zeeb 			    (struct sockaddr *)&ia->ia_addr,
13755490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltmask, RTF_UP,
137681d5d46bSBjoern A. Zeeb 			    (struct rtentry **)0, RT_DEFAULT_FIB);
13775490110cSBjoern A. Zeeb 			if (error)
13785490110cSBjoern A. Zeeb 				log(LOG_INFO, "%s: link-local all-nodes "
13795490110cSBjoern A. Zeeb 				    "multicast address deletion error\n",
13805490110cSBjoern A. Zeeb 				    __func__);
13815490110cSBjoern A. Zeeb 		} else {
13825490110cSBjoern A. Zeeb 			/*
13835490110cSBjoern A. Zeeb 			 * Replace the gateway of the route.
13845490110cSBjoern A. Zeeb 			 */
13855490110cSBjoern A. Zeeb 			struct sockaddr_in6 sa;
13865490110cSBjoern A. Zeeb 
13875490110cSBjoern A. Zeeb 			bzero(&sa, sizeof(sa));
13885490110cSBjoern A. Zeeb 			sa.sin6_len = sizeof(struct sockaddr_in6);
13895490110cSBjoern A. Zeeb 			sa.sin6_family = AF_INET6;
13905490110cSBjoern A. Zeeb 			memcpy(&sa.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
13915490110cSBjoern A. Zeeb 			       sizeof(sa.sin6_addr));
13925490110cSBjoern A. Zeeb 			in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
13935490110cSBjoern A. Zeeb 			memcpy(rt->rt_gateway, &sa, sizeof(sa));
13945490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
13955490110cSBjoern A. Zeeb 		}
13965490110cSBjoern A. Zeeb 	} else {
13975490110cSBjoern A. Zeeb 		if (rt != NULL)
13985490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
13995490110cSBjoern A. Zeeb 	}
14005490110cSBjoern A. Zeeb 
14015490110cSBjoern A. Zeeb 	/*
14025490110cSBjoern A. Zeeb 	 * Remove the node-local all-nodes address.
14035490110cSBjoern A. Zeeb 	 */
14045490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
14055490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
14065490110cSBjoern A. Zeeb 		return (error);
14075490110cSBjoern A. Zeeb 
140881d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
14095490110cSBjoern A. Zeeb 	if (rt != NULL && rt->rt_gateway != NULL &&
14105490110cSBjoern A. Zeeb 	    (memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
14115490110cSBjoern A. Zeeb 		    &ia->ia_addr.sin6_addr,
14125490110cSBjoern A. Zeeb 		    sizeof(ia->ia_addr.sin6_addr)) == 0)) {
14135490110cSBjoern A. Zeeb 		/*
14145490110cSBjoern A. Zeeb 		 * If no more IPv6 address exists on this interface then
14155490110cSBjoern A. Zeeb 		 * remove the multicast address route.
14165490110cSBjoern A. Zeeb 		 */
14175490110cSBjoern A. Zeeb 		if (ifa0 == NULL) {
14185490110cSBjoern A. Zeeb 			memcpy(&mltaddr.sin6_addr, &satosin6(rt_key(rt))->sin6_addr,
14195490110cSBjoern A. Zeeb 			       sizeof(mltaddr.sin6_addr));
14205490110cSBjoern A. Zeeb 
14215490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
142281d5d46bSBjoern A. Zeeb 			error = in6_rtrequest(RTM_DELETE,
14235490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltaddr,
14245490110cSBjoern A. Zeeb 			    (struct sockaddr *)&ia->ia_addr,
14255490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltmask, RTF_UP,
142681d5d46bSBjoern A. Zeeb 			    (struct rtentry **)0, RT_DEFAULT_FIB);
14275490110cSBjoern A. Zeeb 			if (error)
14285490110cSBjoern A. Zeeb 				log(LOG_INFO, "%s: node-local all-nodes"
14295490110cSBjoern A. Zeeb 				    "multicast address deletion error\n",
14305490110cSBjoern A. Zeeb 				    __func__);
14315490110cSBjoern A. Zeeb 		} else {
14325490110cSBjoern A. Zeeb 			/*
14335490110cSBjoern A. Zeeb 			 * Replace the gateway of the route.
14345490110cSBjoern A. Zeeb 			 */
14355490110cSBjoern A. Zeeb 			struct sockaddr_in6 sa;
14365490110cSBjoern A. Zeeb 
14375490110cSBjoern A. Zeeb 			bzero(&sa, sizeof(sa));
14385490110cSBjoern A. Zeeb 			sa.sin6_len = sizeof(struct sockaddr_in6);
14395490110cSBjoern A. Zeeb 			sa.sin6_family = AF_INET6;
14405490110cSBjoern A. Zeeb 			memcpy(&sa.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
14415490110cSBjoern A. Zeeb 			       sizeof(sa.sin6_addr));
14425490110cSBjoern A. Zeeb 			in6_setscope(&sa.sin6_addr, ifa0->ifa_ifp, NULL);
14435490110cSBjoern A. Zeeb 			memcpy(rt->rt_gateway, &sa, sizeof(sa));
14445490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
14455490110cSBjoern A. Zeeb 		}
14465490110cSBjoern A. Zeeb 	} else {
14475490110cSBjoern A. Zeeb 		if (rt != NULL)
14485490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
14495490110cSBjoern A. Zeeb 	}
14505490110cSBjoern A. Zeeb 
14515490110cSBjoern A. Zeeb 	return (0);
14525490110cSBjoern A. Zeeb }
14535490110cSBjoern A. Zeeb 
1454686cdd19SJun-ichiro itojun Hagino void
14551272577eSXin LI in6_purgeaddr(struct ifaddr *ifa)
1456686cdd19SJun-ichiro itojun Hagino {
145733841545SHajimu UMEMOTO 	struct ifnet *ifp = ifa->ifa_ifp;
145833841545SHajimu UMEMOTO 	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
1459511e8a53SQing Li 	int plen, error;
1460f5b50e25SJohn Baldwin 	struct ifaddr *ifa0;
1461511e8a53SQing Li 
146208b68b0eSGleb Smirnoff 	if (ifa->ifa_carp)
146308b68b0eSGleb Smirnoff 		(*carp_detach_p)(ifa);
146408b68b0eSGleb Smirnoff 
1465511e8a53SQing Li 	/*
1466511e8a53SQing Li 	 * find another IPv6 address as the gateway for the
1467511e8a53SQing Li 	 * link-local and node-local all-nodes multicast
1468511e8a53SQing Li 	 * address routes
1469511e8a53SQing Li 	 */
1470137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1471f5b50e25SJohn Baldwin 	TAILQ_FOREACH(ifa0, &ifp->if_addrhead, ifa_link) {
1472511e8a53SQing Li 		if ((ifa0->ifa_addr->sa_family != AF_INET6) ||
1473511e8a53SQing Li 		    memcmp(&satosin6(ifa0->ifa_addr)->sin6_addr,
1474511e8a53SQing Li 			   &ia->ia_addr.sin6_addr,
1475511e8a53SQing Li 			   sizeof(struct in6_addr)) == 0)
1476511e8a53SQing Li 			continue;
1477511e8a53SQing Li 		else
1478511e8a53SQing Li 			break;
1479511e8a53SQing Li 	}
14808c0fec80SRobert Watson 	if (ifa0 != NULL)
14818c0fec80SRobert Watson 		ifa_ref(ifa0);
1482137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
1483686cdd19SJun-ichiro itojun Hagino 
1484df813b7eSQing Li 	/*
1485df813b7eSQing Li 	 * Remove the loopback route to the interface address.
1486d134008aSQing Li 	 * The check for the current setting of "nd6_useloopback"
1487d134008aSQing Li 	 * is not needed.
1488df813b7eSQing Li 	 */
1489c7ab6602SQing Li 	if (ia->ia_flags & IFA_RTSELF) {
14909bb7d0f4SQing Li 		error = ifa_del_loopback_route((struct ifaddr *)ia,
14919bb7d0f4SQing Li 				       (struct sockaddr *)&ia->ia_addr);
1492c7ab6602SQing Li 		if (error == 0)
1493c7ab6602SQing Li 			ia->ia_flags &= ~IFA_RTSELF;
1494c7ab6602SQing Li 	}
149505b262e2SQing Li 
149633841545SHajimu UMEMOTO 	/* stop DAD processing */
149733841545SHajimu UMEMOTO 	nd6_dad_stop(ifa);
149833841545SHajimu UMEMOTO 
149981d5d46bSBjoern A. Zeeb 	/* Remove local address entry from lltable. */
1500b590b6aeSGleb Smirnoff 	in6_ifremloop(ifa);
1501511e8a53SQing Li 
15025490110cSBjoern A. Zeeb 	/* Leave multicast groups. */
15035490110cSBjoern A. Zeeb 	error = in6_purgeaddr_mc(ifp, ia, ifa0);
150482cd038dSYoshinobu Inoue 
15054aa7588cSBjoern A. Zeeb 	if (ifa0 != NULL)
15064aa7588cSBjoern A. Zeeb 		ifa_free(ifa0);
1507511e8a53SQing Li 
1508511e8a53SQing Li 	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1509511e8a53SQing Li 	if ((ia->ia_flags & IFA_ROUTE) && plen == 128) {
151081d5d46bSBjoern A. Zeeb 		error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags |
151181d5d46bSBjoern A. Zeeb 		    (ia->ia_dstaddr.sin6_family == AF_INET6) ? RTF_HOST : 0);
1512511e8a53SQing Li 		if (error != 0)
151381d5d46bSBjoern A. Zeeb 			log(LOG_INFO, "%s: err=%d, destination address delete "
151481d5d46bSBjoern A. Zeeb 			    "failed\n", __func__, error);
1515511e8a53SQing Li 		ia->ia_flags &= ~IFA_ROUTE;
1516511e8a53SQing Li 	}
1517511e8a53SQing Li 
151833841545SHajimu UMEMOTO 	in6_unlink_ifa(ia, ifp);
151933841545SHajimu UMEMOTO }
152033841545SHajimu UMEMOTO 
152133841545SHajimu UMEMOTO static void
15221272577eSXin LI in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
152333841545SHajimu UMEMOTO {
152433841545SHajimu UMEMOTO 	int	s = splnet();
152533841545SHajimu UMEMOTO 
1526137f91e8SJohn Baldwin 	IF_ADDR_WLOCK(ifp);
1527c4dd3fe1SRobert Watson 	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
1528137f91e8SJohn Baldwin 	IF_ADDR_WUNLOCK(ifp);
15298c0fec80SRobert Watson 	ifa_free(&ia->ia_ifa);			/* if_addrhead */
1530686cdd19SJun-ichiro itojun Hagino 
1531f291b9cdSRobert Watson 	/*
1532f291b9cdSRobert Watson 	 * Defer the release of what might be the last reference to the
1533f291b9cdSRobert Watson 	 * in6_ifaddr so that it can't be freed before the remainder of the
1534f291b9cdSRobert Watson 	 * cleanup.
1535f291b9cdSRobert Watson 	 */
1536d1da0a06SRobert Watson 	IN6_IFADDR_WLOCK();
153780af0152SRobert Watson 	TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link);
1538d1da0a06SRobert Watson 	IN6_IFADDR_WUNLOCK();
153982cd038dSYoshinobu Inoue 
1540686cdd19SJun-ichiro itojun Hagino 	/*
1541797df30dSSUZUKI Shinsuke 	 * Release the reference to the base prefix.  There should be a
1542797df30dSSUZUKI Shinsuke 	 * positive reference.
1543686cdd19SJun-ichiro itojun Hagino 	 */
154480af0152SRobert Watson 	if (ia->ia6_ndpr == NULL) {
1545797df30dSSUZUKI Shinsuke 		nd6log((LOG_NOTICE,
1546797df30dSSUZUKI Shinsuke 		    "in6_unlink_ifa: autoconf'ed address "
154780af0152SRobert Watson 		    "%p has no prefix\n", ia));
154833841545SHajimu UMEMOTO 	} else {
154980af0152SRobert Watson 		ia->ia6_ndpr->ndpr_refcnt--;
155080af0152SRobert Watson 		ia->ia6_ndpr = NULL;
1551686cdd19SJun-ichiro itojun Hagino 	}
1552686cdd19SJun-ichiro itojun Hagino 
1553797df30dSSUZUKI Shinsuke 	/*
1554797df30dSSUZUKI Shinsuke 	 * Also, if the address being removed is autoconf'ed, call
1555797df30dSSUZUKI Shinsuke 	 * pfxlist_onlink_check() since the release might affect the status of
1556797df30dSSUZUKI Shinsuke 	 * other (detached) addresses.
1557797df30dSSUZUKI Shinsuke 	 */
155880af0152SRobert Watson 	if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) {
155933841545SHajimu UMEMOTO 		pfxlist_onlink_check();
156033841545SHajimu UMEMOTO 	}
1561f291b9cdSRobert Watson 	ifa_free(&ia->ia_ifa);			/* in6_ifaddrhead */
156233841545SHajimu UMEMOTO 	splx(s);
156333841545SHajimu UMEMOTO }
156433841545SHajimu UMEMOTO 
156533841545SHajimu UMEMOTO void
15661272577eSXin LI in6_purgeif(struct ifnet *ifp)
156733841545SHajimu UMEMOTO {
156833841545SHajimu UMEMOTO 	struct ifaddr *ifa, *nifa;
156933841545SHajimu UMEMOTO 
1570c4dd3fe1SRobert Watson 	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, nifa) {
157133841545SHajimu UMEMOTO 		if (ifa->ifa_addr->sa_family != AF_INET6)
157233841545SHajimu UMEMOTO 			continue;
157333841545SHajimu UMEMOTO 		in6_purgeaddr(ifa);
157433841545SHajimu UMEMOTO 	}
157533841545SHajimu UMEMOTO 
157633841545SHajimu UMEMOTO 	in6_ifdetach(ifp);
157782cd038dSYoshinobu Inoue }
157882cd038dSYoshinobu Inoue 
157982cd038dSYoshinobu Inoue /*
158082cd038dSYoshinobu Inoue  * SIOC[GAD]LIFADDR.
158145b65a5eSGreg Lehey  *	SIOCGLIFADDR: get first address. (?)
158282cd038dSYoshinobu Inoue  *	SIOCGLIFADDR with IFLR_PREFIX:
158382cd038dSYoshinobu Inoue  *		get first address that matches the specified prefix.
158482cd038dSYoshinobu Inoue  *	SIOCALIFADDR: add the specified address.
158582cd038dSYoshinobu Inoue  *	SIOCALIFADDR with IFLR_PREFIX:
158682cd038dSYoshinobu Inoue  *		add the specified prefix, filling hostid part from
158782cd038dSYoshinobu Inoue  *		the first link-local address.  prefixlen must be <= 64.
158882cd038dSYoshinobu Inoue  *	SIOCDLIFADDR: delete the specified address.
158982cd038dSYoshinobu Inoue  *	SIOCDLIFADDR with IFLR_PREFIX:
159082cd038dSYoshinobu Inoue  *		delete the first address that matches the specified prefix.
159182cd038dSYoshinobu Inoue  * return values:
159282cd038dSYoshinobu Inoue  *	EINVAL on invalid parameters
159382cd038dSYoshinobu Inoue  *	EADDRNOTAVAIL on prefix match failed/specified address not found
159482cd038dSYoshinobu Inoue  *	other values may be returned from in6_ioctl()
159582cd038dSYoshinobu Inoue  *
159682cd038dSYoshinobu Inoue  * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
159782cd038dSYoshinobu Inoue  * this is to accomodate address naming scheme other than RFC2374,
159882cd038dSYoshinobu Inoue  * in the future.
159982cd038dSYoshinobu Inoue  * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
160082cd038dSYoshinobu Inoue  * address encoding scheme. (see figure on page 8)
160182cd038dSYoshinobu Inoue  */
160282cd038dSYoshinobu Inoue static int
16031272577eSXin LI in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
16041272577eSXin LI     struct ifnet *ifp, struct thread *td)
160582cd038dSYoshinobu Inoue {
160682cd038dSYoshinobu Inoue 	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
160782cd038dSYoshinobu Inoue 	struct ifaddr *ifa;
1608686cdd19SJun-ichiro itojun Hagino 	struct sockaddr *sa;
160982cd038dSYoshinobu Inoue 
161082cd038dSYoshinobu Inoue 	/* sanity checks */
161182cd038dSYoshinobu Inoue 	if (!data || !ifp) {
161282cd038dSYoshinobu Inoue 		panic("invalid argument to in6_lifaddr_ioctl");
161306cd0a3fSHajimu UMEMOTO 		/* NOTREACHED */
161482cd038dSYoshinobu Inoue 	}
161582cd038dSYoshinobu Inoue 
161682cd038dSYoshinobu Inoue 	switch (cmd) {
161782cd038dSYoshinobu Inoue 	case SIOCGLIFADDR:
161882cd038dSYoshinobu Inoue 		/* address must be specified on GET with IFLR_PREFIX */
161982cd038dSYoshinobu Inoue 		if ((iflr->flags & IFLR_PREFIX) == 0)
162082cd038dSYoshinobu Inoue 			break;
162182cd038dSYoshinobu Inoue 		/* FALLTHROUGH */
162282cd038dSYoshinobu Inoue 	case SIOCALIFADDR:
162382cd038dSYoshinobu Inoue 	case SIOCDLIFADDR:
162482cd038dSYoshinobu Inoue 		/* address must be specified on ADD and DELETE */
1625686cdd19SJun-ichiro itojun Hagino 		sa = (struct sockaddr *)&iflr->addr;
1626686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_family != AF_INET6)
162782cd038dSYoshinobu Inoue 			return EINVAL;
1628686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_len != sizeof(struct sockaddr_in6))
162982cd038dSYoshinobu Inoue 			return EINVAL;
163082cd038dSYoshinobu Inoue 		/* XXX need improvement */
1631686cdd19SJun-ichiro itojun Hagino 		sa = (struct sockaddr *)&iflr->dstaddr;
1632686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_family && sa->sa_family != AF_INET6)
163382cd038dSYoshinobu Inoue 			return EINVAL;
1634686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
163582cd038dSYoshinobu Inoue 			return EINVAL;
163682cd038dSYoshinobu Inoue 		break;
163782cd038dSYoshinobu Inoue 	default: /* shouldn't happen */
1638686cdd19SJun-ichiro itojun Hagino #if 0
1639686cdd19SJun-ichiro itojun Hagino 		panic("invalid cmd to in6_lifaddr_ioctl");
1640686cdd19SJun-ichiro itojun Hagino 		/* NOTREACHED */
1641686cdd19SJun-ichiro itojun Hagino #else
164282cd038dSYoshinobu Inoue 		return EOPNOTSUPP;
1643686cdd19SJun-ichiro itojun Hagino #endif
164482cd038dSYoshinobu Inoue 	}
164582cd038dSYoshinobu Inoue 	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
164682cd038dSYoshinobu Inoue 		return EINVAL;
164782cd038dSYoshinobu Inoue 
164882cd038dSYoshinobu Inoue 	switch (cmd) {
164982cd038dSYoshinobu Inoue 	case SIOCALIFADDR:
165082cd038dSYoshinobu Inoue 	    {
165182cd038dSYoshinobu Inoue 		struct in6_aliasreq ifra;
165282cd038dSYoshinobu Inoue 		struct in6_addr *hostid = NULL;
165382cd038dSYoshinobu Inoue 		int prefixlen;
165482cd038dSYoshinobu Inoue 
16558c0fec80SRobert Watson 		ifa = NULL;
165682cd038dSYoshinobu Inoue 		if ((iflr->flags & IFLR_PREFIX) != 0) {
165782cd038dSYoshinobu Inoue 			struct sockaddr_in6 *sin6;
165882cd038dSYoshinobu Inoue 
165982cd038dSYoshinobu Inoue 			/*
166082cd038dSYoshinobu Inoue 			 * hostid is to fill in the hostid part of the
166182cd038dSYoshinobu Inoue 			 * address.  hostid points to the first link-local
166282cd038dSYoshinobu Inoue 			 * address attached to the interface.
166382cd038dSYoshinobu Inoue 			 */
1664686cdd19SJun-ichiro itojun Hagino 			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
166582cd038dSYoshinobu Inoue 			if (!ifa)
166682cd038dSYoshinobu Inoue 				return EADDRNOTAVAIL;
166782cd038dSYoshinobu Inoue 			hostid = IFA_IN6(ifa);
166882cd038dSYoshinobu Inoue 
166982cd038dSYoshinobu Inoue 			/* prefixlen must be <= 64. */
167082cd038dSYoshinobu Inoue 			if (64 < iflr->prefixlen)
167182cd038dSYoshinobu Inoue 				return EINVAL;
167282cd038dSYoshinobu Inoue 			prefixlen = iflr->prefixlen;
167382cd038dSYoshinobu Inoue 
167482cd038dSYoshinobu Inoue 			/* hostid part must be zero. */
167582cd038dSYoshinobu Inoue 			sin6 = (struct sockaddr_in6 *)&iflr->addr;
167659aecc96SHajimu UMEMOTO 			if (sin6->sin6_addr.s6_addr32[2] != 0 ||
167759aecc96SHajimu UMEMOTO 			    sin6->sin6_addr.s6_addr32[3] != 0) {
167882cd038dSYoshinobu Inoue 				return EINVAL;
167982cd038dSYoshinobu Inoue 			}
168082cd038dSYoshinobu Inoue 		} else
168182cd038dSYoshinobu Inoue 			prefixlen = iflr->prefixlen;
168282cd038dSYoshinobu Inoue 
168382cd038dSYoshinobu Inoue 		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
168482cd038dSYoshinobu Inoue 		bzero(&ifra, sizeof(ifra));
168506cd0a3fSHajimu UMEMOTO 		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
168682cd038dSYoshinobu Inoue 
1687686cdd19SJun-ichiro itojun Hagino 		bcopy(&iflr->addr, &ifra.ifra_addr,
1688686cdd19SJun-ichiro itojun Hagino 		    ((struct sockaddr *)&iflr->addr)->sa_len);
168982cd038dSYoshinobu Inoue 		if (hostid) {
169082cd038dSYoshinobu Inoue 			/* fill in hostid part */
169182cd038dSYoshinobu Inoue 			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
169282cd038dSYoshinobu Inoue 			    hostid->s6_addr32[2];
169382cd038dSYoshinobu Inoue 			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
169482cd038dSYoshinobu Inoue 			    hostid->s6_addr32[3];
169582cd038dSYoshinobu Inoue 		}
169682cd038dSYoshinobu Inoue 
1697686cdd19SJun-ichiro itojun Hagino 		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
169882cd038dSYoshinobu Inoue 			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1699686cdd19SJun-ichiro itojun Hagino 			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
170082cd038dSYoshinobu Inoue 			if (hostid) {
170182cd038dSYoshinobu Inoue 				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
170282cd038dSYoshinobu Inoue 				    hostid->s6_addr32[2];
170382cd038dSYoshinobu Inoue 				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
170482cd038dSYoshinobu Inoue 				    hostid->s6_addr32[3];
170582cd038dSYoshinobu Inoue 			}
170682cd038dSYoshinobu Inoue 		}
17078c0fec80SRobert Watson 		if (ifa != NULL)
17088c0fec80SRobert Watson 			ifa_free(ifa);
170982cd038dSYoshinobu Inoue 
171082cd038dSYoshinobu Inoue 		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1711ae360dddSHajimu UMEMOTO 		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
171282cd038dSYoshinobu Inoue 
171382cd038dSYoshinobu Inoue 		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
1714b40ce416SJulian Elischer 		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
171582cd038dSYoshinobu Inoue 	    }
171682cd038dSYoshinobu Inoue 	case SIOCGLIFADDR:
171782cd038dSYoshinobu Inoue 	case SIOCDLIFADDR:
171882cd038dSYoshinobu Inoue 	    {
171982cd038dSYoshinobu Inoue 		struct in6_ifaddr *ia;
172082cd038dSYoshinobu Inoue 		struct in6_addr mask, candidate, match;
172182cd038dSYoshinobu Inoue 		struct sockaddr_in6 *sin6;
172282cd038dSYoshinobu Inoue 		int cmp;
172382cd038dSYoshinobu Inoue 
172482cd038dSYoshinobu Inoue 		bzero(&mask, sizeof(mask));
172582cd038dSYoshinobu Inoue 		if (iflr->flags & IFLR_PREFIX) {
172682cd038dSYoshinobu Inoue 			/* lookup a prefix rather than address. */
1727ae360dddSHajimu UMEMOTO 			in6_prefixlen2mask(&mask, iflr->prefixlen);
172882cd038dSYoshinobu Inoue 
172982cd038dSYoshinobu Inoue 			sin6 = (struct sockaddr_in6 *)&iflr->addr;
173082cd038dSYoshinobu Inoue 			bcopy(&sin6->sin6_addr, &match, sizeof(match));
173182cd038dSYoshinobu Inoue 			match.s6_addr32[0] &= mask.s6_addr32[0];
173282cd038dSYoshinobu Inoue 			match.s6_addr32[1] &= mask.s6_addr32[1];
173382cd038dSYoshinobu Inoue 			match.s6_addr32[2] &= mask.s6_addr32[2];
173482cd038dSYoshinobu Inoue 			match.s6_addr32[3] &= mask.s6_addr32[3];
173582cd038dSYoshinobu Inoue 
173682cd038dSYoshinobu Inoue 			/* if you set extra bits, that's wrong */
173782cd038dSYoshinobu Inoue 			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
173882cd038dSYoshinobu Inoue 				return EINVAL;
173982cd038dSYoshinobu Inoue 
174082cd038dSYoshinobu Inoue 			cmp = 1;
174182cd038dSYoshinobu Inoue 		} else {
174282cd038dSYoshinobu Inoue 			if (cmd == SIOCGLIFADDR) {
174382cd038dSYoshinobu Inoue 				/* on getting an address, take the 1st match */
174482cd038dSYoshinobu Inoue 				cmp = 0;	/* XXX */
174582cd038dSYoshinobu Inoue 			} else {
174682cd038dSYoshinobu Inoue 				/* on deleting an address, do exact match */
1747ae360dddSHajimu UMEMOTO 				in6_prefixlen2mask(&mask, 128);
174882cd038dSYoshinobu Inoue 				sin6 = (struct sockaddr_in6 *)&iflr->addr;
174982cd038dSYoshinobu Inoue 				bcopy(&sin6->sin6_addr, &match, sizeof(match));
175082cd038dSYoshinobu Inoue 
175182cd038dSYoshinobu Inoue 				cmp = 1;
175282cd038dSYoshinobu Inoue 			}
175382cd038dSYoshinobu Inoue 		}
175482cd038dSYoshinobu Inoue 
1755137f91e8SJohn Baldwin 		IF_ADDR_RLOCK(ifp);
1756c4dd3fe1SRobert Watson 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
175782cd038dSYoshinobu Inoue 			if (ifa->ifa_addr->sa_family != AF_INET6)
175882cd038dSYoshinobu Inoue 				continue;
175982cd038dSYoshinobu Inoue 			if (!cmp)
176082cd038dSYoshinobu Inoue 				break;
176133841545SHajimu UMEMOTO 
176233841545SHajimu UMEMOTO 			/*
176333841545SHajimu UMEMOTO 			 * XXX: this is adhoc, but is necessary to allow
176433841545SHajimu UMEMOTO 			 * a user to specify fe80::/64 (not /10) for a
176533841545SHajimu UMEMOTO 			 * link-local address.
176633841545SHajimu UMEMOTO 			 */
1767a1f7e5f8SHajimu UMEMOTO 			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1768a1f7e5f8SHajimu UMEMOTO 			in6_clearscope(&candidate);
176982cd038dSYoshinobu Inoue 			candidate.s6_addr32[0] &= mask.s6_addr32[0];
177082cd038dSYoshinobu Inoue 			candidate.s6_addr32[1] &= mask.s6_addr32[1];
177182cd038dSYoshinobu Inoue 			candidate.s6_addr32[2] &= mask.s6_addr32[2];
177282cd038dSYoshinobu Inoue 			candidate.s6_addr32[3] &= mask.s6_addr32[3];
177382cd038dSYoshinobu Inoue 			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
177482cd038dSYoshinobu Inoue 				break;
177582cd038dSYoshinobu Inoue 		}
17769f745f61SJohn Baldwin 		if (ifa != NULL)
17779f745f61SJohn Baldwin 			ifa_ref(ifa);
1778137f91e8SJohn Baldwin 		IF_ADDR_RUNLOCK(ifp);
177982cd038dSYoshinobu Inoue 		if (!ifa)
178082cd038dSYoshinobu Inoue 			return EADDRNOTAVAIL;
178182cd038dSYoshinobu Inoue 		ia = ifa2ia6(ifa);
178282cd038dSYoshinobu Inoue 
178382cd038dSYoshinobu Inoue 		if (cmd == SIOCGLIFADDR) {
1784a1f7e5f8SHajimu UMEMOTO 			int error;
178533841545SHajimu UMEMOTO 
178682cd038dSYoshinobu Inoue 			/* fill in the if_laddrreq structure */
178782cd038dSYoshinobu Inoue 			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1788a1f7e5f8SHajimu UMEMOTO 			error = sa6_recoverscope(
1789a1f7e5f8SHajimu UMEMOTO 			    (struct sockaddr_in6 *)&iflr->addr);
17909f745f61SJohn Baldwin 			if (error != 0) {
17919f745f61SJohn Baldwin 				ifa_free(ifa);
1792a1f7e5f8SHajimu UMEMOTO 				return (error);
17939f745f61SJohn Baldwin 			}
1794a1f7e5f8SHajimu UMEMOTO 
179582cd038dSYoshinobu Inoue 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
179682cd038dSYoshinobu Inoue 				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
179782cd038dSYoshinobu Inoue 				    ia->ia_dstaddr.sin6_len);
1798a1f7e5f8SHajimu UMEMOTO 				error = sa6_recoverscope(
1799a1f7e5f8SHajimu UMEMOTO 				    (struct sockaddr_in6 *)&iflr->dstaddr);
18009f745f61SJohn Baldwin 				if (error != 0) {
18019f745f61SJohn Baldwin 					ifa_free(ifa);
1802a1f7e5f8SHajimu UMEMOTO 					return (error);
18039f745f61SJohn Baldwin 				}
180482cd038dSYoshinobu Inoue 			} else
180582cd038dSYoshinobu Inoue 				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
180682cd038dSYoshinobu Inoue 
180782cd038dSYoshinobu Inoue 			iflr->prefixlen =
180806cd0a3fSHajimu UMEMOTO 			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
180982cd038dSYoshinobu Inoue 
181082cd038dSYoshinobu Inoue 			iflr->flags = ia->ia6_flags;	/* XXX */
18119f745f61SJohn Baldwin 			ifa_free(ifa);
181282cd038dSYoshinobu Inoue 
181382cd038dSYoshinobu Inoue 			return 0;
181482cd038dSYoshinobu Inoue 		} else {
181582cd038dSYoshinobu Inoue 			struct in6_aliasreq ifra;
181682cd038dSYoshinobu Inoue 
181782cd038dSYoshinobu Inoue 			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
181882cd038dSYoshinobu Inoue 			bzero(&ifra, sizeof(ifra));
181982cd038dSYoshinobu Inoue 			bcopy(iflr->iflr_name, ifra.ifra_name,
182082cd038dSYoshinobu Inoue 			    sizeof(ifra.ifra_name));
182182cd038dSYoshinobu Inoue 
182282cd038dSYoshinobu Inoue 			bcopy(&ia->ia_addr, &ifra.ifra_addr,
182382cd038dSYoshinobu Inoue 			    ia->ia_addr.sin6_len);
182482cd038dSYoshinobu Inoue 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
182582cd038dSYoshinobu Inoue 				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
182682cd038dSYoshinobu Inoue 				    ia->ia_dstaddr.sin6_len);
1827686cdd19SJun-ichiro itojun Hagino 			} else {
1828686cdd19SJun-ichiro itojun Hagino 				bzero(&ifra.ifra_dstaddr,
1829686cdd19SJun-ichiro itojun Hagino 				    sizeof(ifra.ifra_dstaddr));
183082cd038dSYoshinobu Inoue 			}
183182cd038dSYoshinobu Inoue 			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
183282cd038dSYoshinobu Inoue 			    ia->ia_prefixmask.sin6_len);
183382cd038dSYoshinobu Inoue 
183482cd038dSYoshinobu Inoue 			ifra.ifra_flags = ia->ia6_flags;
18359f745f61SJohn Baldwin 			ifa_free(ifa);
183682cd038dSYoshinobu Inoue 			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1837b40ce416SJulian Elischer 			    ifp, td);
183882cd038dSYoshinobu Inoue 		}
183982cd038dSYoshinobu Inoue 	    }
184082cd038dSYoshinobu Inoue 	}
184182cd038dSYoshinobu Inoue 
184282cd038dSYoshinobu Inoue 	return EOPNOTSUPP;	/* just for safety */
184382cd038dSYoshinobu Inoue }
184482cd038dSYoshinobu Inoue 
184582cd038dSYoshinobu Inoue /*
184681d5d46bSBjoern A. Zeeb  * Initialize an interface's IPv6 address and routing table entry.
184782cd038dSYoshinobu Inoue  */
184833841545SHajimu UMEMOTO static int
18491272577eSXin LI in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
18501272577eSXin LI     struct sockaddr_in6 *sin6, int newhost)
185182cd038dSYoshinobu Inoue {
185233841545SHajimu UMEMOTO 	int	error = 0, plen, ifacount = 0;
185382cd038dSYoshinobu Inoue 	int	s = splimp();
185433841545SHajimu UMEMOTO 	struct ifaddr *ifa;
185582cd038dSYoshinobu Inoue 
185682cd038dSYoshinobu Inoue 	/*
185782cd038dSYoshinobu Inoue 	 * Give the interface a chance to initialize
185882cd038dSYoshinobu Inoue 	 * if this is its first address,
185982cd038dSYoshinobu Inoue 	 * and to validate the address if necessary.
186082cd038dSYoshinobu Inoue 	 */
1861137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1862c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
186333841545SHajimu UMEMOTO 		if (ifa->ifa_addr->sa_family != AF_INET6)
186433841545SHajimu UMEMOTO 			continue;
186533841545SHajimu UMEMOTO 		ifacount++;
186633841545SHajimu UMEMOTO 	}
1867137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
186833841545SHajimu UMEMOTO 
186933841545SHajimu UMEMOTO 	ia->ia_addr = *sin6;
187033841545SHajimu UMEMOTO 
1871ba5da2a0SIan Dowse 	if (ifacount <= 1 && ifp->if_ioctl) {
1872ba5da2a0SIan Dowse 		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
1873ba5da2a0SIan Dowse 		if (error) {
187482cd038dSYoshinobu Inoue 			splx(s);
187582cd038dSYoshinobu Inoue 			return (error);
187682cd038dSYoshinobu Inoue 		}
1877ba5da2a0SIan Dowse 	}
187882cd038dSYoshinobu Inoue 	splx(s);
187933841545SHajimu UMEMOTO 
188082cd038dSYoshinobu Inoue 	ia->ia_ifa.ifa_metric = ifp->if_metric;
188133841545SHajimu UMEMOTO 
188233841545SHajimu UMEMOTO 	/* we could do in(6)_socktrim here, but just omit it at this moment. */
188333841545SHajimu UMEMOTO 
188433841545SHajimu UMEMOTO 	/*
188533841545SHajimu UMEMOTO 	 * Special case:
188680343432SHajimu UMEMOTO 	 * If a new destination address is specified for a point-to-point
188733841545SHajimu UMEMOTO 	 * interface, install a route to the destination as an interface
18886e6b3f7cSQing Li 	 * direct route.
188980343432SHajimu UMEMOTO 	 * XXX: the logic below rejects assigning multiple addresses on a p2p
1890a59af512SGeorge V. Neville-Neil 	 * interface that share the same destination.
189133841545SHajimu UMEMOTO 	 */
189233841545SHajimu UMEMOTO 	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
189309b03548SQing Li 	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
189409b03548SQing Li 	    ia->ia_dstaddr.sin6_family == AF_INET6) {
1895a59af512SGeorge V. Neville-Neil 		int rtflags = RTF_UP | RTF_HOST;
189681d5d46bSBjoern A. Zeeb 		error = rtinit(&ia->ia_ifa, RTM_ADD, ia->ia_flags | rtflags);
189781d5d46bSBjoern A. Zeeb 		if (error)
189833841545SHajimu UMEMOTO 			return (error);
189982cd038dSYoshinobu Inoue 		ia->ia_flags |= IFA_ROUTE;
190014417253SQing Li 		/*
190114417253SQing Li 		 * Handle the case for ::1 .
190214417253SQing Li 		 */
190314417253SQing Li 		if (ifp->if_flags & IFF_LOOPBACK)
190414417253SQing Li 			ia->ia_flags |= IFA_RTSELF;
190533841545SHajimu UMEMOTO 	}
190682cd038dSYoshinobu Inoue 
190705b262e2SQing Li 	/*
190805b262e2SQing Li 	 * add a loopback route to self
190905b262e2SQing Li 	 */
191014417253SQing Li 	if (!(ia->ia_flags & IFA_RTSELF) && V_nd6_useloopback) {
19119bb7d0f4SQing Li 		error = ifa_add_loopback_route((struct ifaddr *)ia,
19129bb7d0f4SQing Li 				       (struct sockaddr *)&ia->ia_addr);
1913c7ab6602SQing Li 		if (error == 0)
1914c7ab6602SQing Li 			ia->ia_flags |= IFA_RTSELF;
191505b262e2SQing Li 	}
191605b262e2SQing Li 
191781d5d46bSBjoern A. Zeeb 	/* Add local address to lltable, if necessary (ex. on p2p link). */
1918b590b6aeSGleb Smirnoff 	if (newhost)
1919b590b6aeSGleb Smirnoff 		in6_ifaddloop(&(ia->ia_ifa));
192082cd038dSYoshinobu Inoue 
192182cd038dSYoshinobu Inoue 	return (error);
192282cd038dSYoshinobu Inoue }
192382cd038dSYoshinobu Inoue 
192482cd038dSYoshinobu Inoue /*
192582cd038dSYoshinobu Inoue  * Find an IPv6 interface link-local address specific to an interface.
19268c0fec80SRobert Watson  * ifaddr is returned referenced.
192782cd038dSYoshinobu Inoue  */
192882cd038dSYoshinobu Inoue struct in6_ifaddr *
19291272577eSXin LI in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
193082cd038dSYoshinobu Inoue {
193133841545SHajimu UMEMOTO 	struct ifaddr *ifa;
193282cd038dSYoshinobu Inoue 
1933137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1934c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
193582cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
193682cd038dSYoshinobu Inoue 			continue;
1937686cdd19SJun-ichiro itojun Hagino 		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
1938686cdd19SJun-ichiro itojun Hagino 			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
1939686cdd19SJun-ichiro itojun Hagino 			     ignoreflags) != 0)
1940686cdd19SJun-ichiro itojun Hagino 				continue;
19418c0fec80SRobert Watson 			ifa_ref(ifa);
194282cd038dSYoshinobu Inoue 			break;
194382cd038dSYoshinobu Inoue 		}
1944686cdd19SJun-ichiro itojun Hagino 	}
1945137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
194682cd038dSYoshinobu Inoue 
194782cd038dSYoshinobu Inoue 	return ((struct in6_ifaddr *)ifa);
194882cd038dSYoshinobu Inoue }
194982cd038dSYoshinobu Inoue 
195082cd038dSYoshinobu Inoue 
195182cd038dSYoshinobu Inoue /*
195282cd038dSYoshinobu Inoue  * find the internet address corresponding to a given interface and address.
19538c0fec80SRobert Watson  * ifaddr is returned referenced.
195482cd038dSYoshinobu Inoue  */
195582cd038dSYoshinobu Inoue struct in6_ifaddr *
19561272577eSXin LI in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
195782cd038dSYoshinobu Inoue {
195833841545SHajimu UMEMOTO 	struct ifaddr *ifa;
195982cd038dSYoshinobu Inoue 
1960137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1961c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
196282cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
196382cd038dSYoshinobu Inoue 			continue;
19648c0fec80SRobert Watson 		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) {
19658c0fec80SRobert Watson 			ifa_ref(ifa);
196682cd038dSYoshinobu Inoue 			break;
196782cd038dSYoshinobu Inoue 		}
19688c0fec80SRobert Watson 	}
1969137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
197082cd038dSYoshinobu Inoue 
197182cd038dSYoshinobu Inoue 	return ((struct in6_ifaddr *)ifa);
197282cd038dSYoshinobu Inoue }
197382cd038dSYoshinobu Inoue 
197482cd038dSYoshinobu Inoue /*
19751d54aa3bSBjoern A. Zeeb  * Convert IP6 address to printable (loggable) representation. Caller
19761d54aa3bSBjoern A. Zeeb  * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long.
197782cd038dSYoshinobu Inoue  */
197882cd038dSYoshinobu Inoue static char digits[] = "0123456789abcdef";
197982cd038dSYoshinobu Inoue char *
19801d54aa3bSBjoern A. Zeeb ip6_sprintf(char *ip6buf, const struct in6_addr *addr)
198182cd038dSYoshinobu Inoue {
19828e96292dSAlfred Perlstein 	int i, cnt = 0, maxcnt = 0, idx = 0, index = 0;
198333841545SHajimu UMEMOTO 	char *cp;
198459aecc96SHajimu UMEMOTO 	const u_int16_t *a = (const u_int16_t *)addr;
198559aecc96SHajimu UMEMOTO 	const u_int8_t *d;
1986e521ae0cSBjoern A. Zeeb 	int dcolon = 0, zero = 0;
198782cd038dSYoshinobu Inoue 
19881d54aa3bSBjoern A. Zeeb 	cp = ip6buf;
198982cd038dSYoshinobu Inoue 
199082cd038dSYoshinobu Inoue 	for (i = 0; i < 8; i++) {
19918e96292dSAlfred Perlstein 		if (*(a + i) == 0) {
19928e96292dSAlfred Perlstein 			cnt++;
19938e96292dSAlfred Perlstein 			if (cnt == 1)
19948e96292dSAlfred Perlstein 				idx = i;
19958e96292dSAlfred Perlstein 		}
19968e96292dSAlfred Perlstein 		else if (maxcnt < cnt) {
19978e96292dSAlfred Perlstein 			maxcnt = cnt;
19988e96292dSAlfred Perlstein 			index = idx;
19998e96292dSAlfred Perlstein 			cnt = 0;
20008e96292dSAlfred Perlstein 		}
20018e96292dSAlfred Perlstein 	}
20028e96292dSAlfred Perlstein 	if (maxcnt < cnt) {
20038e96292dSAlfred Perlstein 		maxcnt = cnt;
20048e96292dSAlfred Perlstein 		index = idx;
20058e96292dSAlfred Perlstein 	}
20068e96292dSAlfred Perlstein 
20078e96292dSAlfred Perlstein 	for (i = 0; i < 8; i++) {
200882cd038dSYoshinobu Inoue 		if (dcolon == 1) {
200982cd038dSYoshinobu Inoue 			if (*a == 0) {
201082cd038dSYoshinobu Inoue 				if (i == 7)
201182cd038dSYoshinobu Inoue 					*cp++ = ':';
201282cd038dSYoshinobu Inoue 				a++;
201382cd038dSYoshinobu Inoue 				continue;
201482cd038dSYoshinobu Inoue 			} else
201582cd038dSYoshinobu Inoue 				dcolon = 2;
201682cd038dSYoshinobu Inoue 		}
201782cd038dSYoshinobu Inoue 		if (*a == 0) {
20188e96292dSAlfred Perlstein 			if (dcolon == 0 && *(a + 1) == 0 && i == index) {
201982cd038dSYoshinobu Inoue 				if (i == 0)
202082cd038dSYoshinobu Inoue 					*cp++ = ':';
202182cd038dSYoshinobu Inoue 				*cp++ = ':';
202282cd038dSYoshinobu Inoue 				dcolon = 1;
202382cd038dSYoshinobu Inoue 			} else {
202482cd038dSYoshinobu Inoue 				*cp++ = '0';
202582cd038dSYoshinobu Inoue 				*cp++ = ':';
202682cd038dSYoshinobu Inoue 			}
202782cd038dSYoshinobu Inoue 			a++;
202882cd038dSYoshinobu Inoue 			continue;
202982cd038dSYoshinobu Inoue 		}
2030c4c0c592SAlfred Perlstein 		d = (const u_char *)a;
2031e521ae0cSBjoern A. Zeeb 		/* Try to eliminate leading zeros in printout like in :0001. */
2032e521ae0cSBjoern A. Zeeb 		zero = 1;
2033e521ae0cSBjoern A. Zeeb 		*cp = digits[*d >> 4];
2034e521ae0cSBjoern A. Zeeb 		if (*cp != '0') {
2035e521ae0cSBjoern A. Zeeb 			zero = 0;
2036e521ae0cSBjoern A. Zeeb 			cp++;
2037e521ae0cSBjoern A. Zeeb 		}
2038e521ae0cSBjoern A. Zeeb 		*cp = digits[*d++ & 0xf];
2039e521ae0cSBjoern A. Zeeb 		if (zero == 0 || (*cp != '0')) {
2040e521ae0cSBjoern A. Zeeb 			zero = 0;
2041e521ae0cSBjoern A. Zeeb 			cp++;
2042e521ae0cSBjoern A. Zeeb 		}
2043e521ae0cSBjoern A. Zeeb 		*cp = digits[*d >> 4];
2044e521ae0cSBjoern A. Zeeb 		if (zero == 0 || (*cp != '0')) {
2045e521ae0cSBjoern A. Zeeb 			zero = 0;
2046e521ae0cSBjoern A. Zeeb 			cp++;
2047e521ae0cSBjoern A. Zeeb 		}
204882cd038dSYoshinobu Inoue 		*cp++ = digits[*d & 0xf];
204982cd038dSYoshinobu Inoue 		*cp++ = ':';
205082cd038dSYoshinobu Inoue 		a++;
205182cd038dSYoshinobu Inoue 	}
20521d54aa3bSBjoern A. Zeeb 	*--cp = '\0';
20531d54aa3bSBjoern A. Zeeb 	return (ip6buf);
205482cd038dSYoshinobu Inoue }
205582cd038dSYoshinobu Inoue 
205682cd038dSYoshinobu Inoue int
20571272577eSXin LI in6_localaddr(struct in6_addr *in6)
205882cd038dSYoshinobu Inoue {
205982cd038dSYoshinobu Inoue 	struct in6_ifaddr *ia;
206082cd038dSYoshinobu Inoue 
206182cd038dSYoshinobu Inoue 	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
206282cd038dSYoshinobu Inoue 		return 1;
206382cd038dSYoshinobu Inoue 
2064d1da0a06SRobert Watson 	IN6_IFADDR_RLOCK();
206580af0152SRobert Watson 	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
206682cd038dSYoshinobu Inoue 		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
206706cd0a3fSHajimu UMEMOTO 		    &ia->ia_prefixmask.sin6_addr)) {
2068d1da0a06SRobert Watson 			IN6_IFADDR_RUNLOCK();
206982cd038dSYoshinobu Inoue 			return 1;
207006cd0a3fSHajimu UMEMOTO 		}
207106cd0a3fSHajimu UMEMOTO 	}
2072d1da0a06SRobert Watson 	IN6_IFADDR_RUNLOCK();
207382cd038dSYoshinobu Inoue 
207482cd038dSYoshinobu Inoue 	return (0);
207582cd038dSYoshinobu Inoue }
207682cd038dSYoshinobu Inoue 
207790bc35deSBjoern A. Zeeb /*
207890bc35deSBjoern A. Zeeb  * Return 1 if an internet address is for the local host and configured
207990bc35deSBjoern A. Zeeb  * on one of its interfaces.
208090bc35deSBjoern A. Zeeb  */
208190bc35deSBjoern A. Zeeb int
208290bc35deSBjoern A. Zeeb in6_localip(struct in6_addr *in6)
208390bc35deSBjoern A. Zeeb {
208490bc35deSBjoern A. Zeeb 	struct in6_ifaddr *ia;
208590bc35deSBjoern A. Zeeb 
208690bc35deSBjoern A. Zeeb 	IN6_IFADDR_RLOCK();
208790bc35deSBjoern A. Zeeb 	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
208890bc35deSBjoern A. Zeeb 		if (IN6_ARE_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr)) {
208990bc35deSBjoern A. Zeeb 			IN6_IFADDR_RUNLOCK();
209090bc35deSBjoern A. Zeeb 			return (1);
209190bc35deSBjoern A. Zeeb 		}
209290bc35deSBjoern A. Zeeb 	}
209390bc35deSBjoern A. Zeeb 	IN6_IFADDR_RUNLOCK();
209490bc35deSBjoern A. Zeeb 	return (0);
209590bc35deSBjoern A. Zeeb }
209690bc35deSBjoern A. Zeeb 
209790bc35deSBjoern A. Zeeb 
209833841545SHajimu UMEMOTO int
20991272577eSXin LI in6_is_addr_deprecated(struct sockaddr_in6 *sa6)
210033841545SHajimu UMEMOTO {
210133841545SHajimu UMEMOTO 	struct in6_ifaddr *ia;
210233841545SHajimu UMEMOTO 
2103d1da0a06SRobert Watson 	IN6_IFADDR_RLOCK();
210480af0152SRobert Watson 	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
210533841545SHajimu UMEMOTO 		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
210633841545SHajimu UMEMOTO 				       &sa6->sin6_addr) &&
2107d1da0a06SRobert Watson 		    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
2108d1da0a06SRobert Watson 			IN6_IFADDR_RUNLOCK();
210933841545SHajimu UMEMOTO 			return (1); /* true */
2110d1da0a06SRobert Watson 		}
211133841545SHajimu UMEMOTO 
211233841545SHajimu UMEMOTO 		/* XXX: do we still have to go thru the rest of the list? */
211333841545SHajimu UMEMOTO 	}
2114d1da0a06SRobert Watson 	IN6_IFADDR_RUNLOCK();
211533841545SHajimu UMEMOTO 
211633841545SHajimu UMEMOTO 	return (0);		/* false */
211733841545SHajimu UMEMOTO }
211833841545SHajimu UMEMOTO 
211982cd038dSYoshinobu Inoue /*
212082cd038dSYoshinobu Inoue  * return length of part which dst and src are equal
212182cd038dSYoshinobu Inoue  * hard coding...
212282cd038dSYoshinobu Inoue  */
212382cd038dSYoshinobu Inoue int
21241272577eSXin LI in6_matchlen(struct in6_addr *src, struct in6_addr *dst)
212582cd038dSYoshinobu Inoue {
212682cd038dSYoshinobu Inoue 	int match = 0;
212782cd038dSYoshinobu Inoue 	u_char *s = (u_char *)src, *d = (u_char *)dst;
212882cd038dSYoshinobu Inoue 	u_char *lim = s + 16, r;
212982cd038dSYoshinobu Inoue 
213082cd038dSYoshinobu Inoue 	while (s < lim)
213182cd038dSYoshinobu Inoue 		if ((r = (*d++ ^ *s++)) != 0) {
213282cd038dSYoshinobu Inoue 			while (r < 128) {
213382cd038dSYoshinobu Inoue 				match++;
213482cd038dSYoshinobu Inoue 				r <<= 1;
213582cd038dSYoshinobu Inoue 			}
213682cd038dSYoshinobu Inoue 			break;
213782cd038dSYoshinobu Inoue 		} else
213882cd038dSYoshinobu Inoue 			match += 8;
213982cd038dSYoshinobu Inoue 	return match;
214082cd038dSYoshinobu Inoue }
214182cd038dSYoshinobu Inoue 
2142686cdd19SJun-ichiro itojun Hagino /* XXX: to be scope conscious */
214382cd038dSYoshinobu Inoue int
21441272577eSXin LI in6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len)
214582cd038dSYoshinobu Inoue {
214682cd038dSYoshinobu Inoue 	int bytelen, bitlen;
214782cd038dSYoshinobu Inoue 
214882cd038dSYoshinobu Inoue 	/* sanity check */
214982cd038dSYoshinobu Inoue 	if (0 > len || len > 128) {
215082cd038dSYoshinobu Inoue 		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
215182cd038dSYoshinobu Inoue 		    len);
215282cd038dSYoshinobu Inoue 		return (0);
215382cd038dSYoshinobu Inoue 	}
215482cd038dSYoshinobu Inoue 
215582cd038dSYoshinobu Inoue 	bytelen = len / 8;
215682cd038dSYoshinobu Inoue 	bitlen = len % 8;
215782cd038dSYoshinobu Inoue 
215882cd038dSYoshinobu Inoue 	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
215982cd038dSYoshinobu Inoue 		return (0);
216014135e2cSColin Percival 	if (bitlen != 0 &&
216114135e2cSColin Percival 	    p1->s6_addr[bytelen] >> (8 - bitlen) !=
216282cd038dSYoshinobu Inoue 	    p2->s6_addr[bytelen] >> (8 - bitlen))
216382cd038dSYoshinobu Inoue 		return (0);
216482cd038dSYoshinobu Inoue 
216582cd038dSYoshinobu Inoue 	return (1);
216682cd038dSYoshinobu Inoue }
216782cd038dSYoshinobu Inoue 
216882cd038dSYoshinobu Inoue void
21691272577eSXin LI in6_prefixlen2mask(struct in6_addr *maskp, int len)
217082cd038dSYoshinobu Inoue {
217182cd038dSYoshinobu Inoue 	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
217282cd038dSYoshinobu Inoue 	int bytelen, bitlen, i;
217382cd038dSYoshinobu Inoue 
217482cd038dSYoshinobu Inoue 	/* sanity check */
217582cd038dSYoshinobu Inoue 	if (0 > len || len > 128) {
217682cd038dSYoshinobu Inoue 		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
217782cd038dSYoshinobu Inoue 		    len);
217882cd038dSYoshinobu Inoue 		return;
217982cd038dSYoshinobu Inoue 	}
218082cd038dSYoshinobu Inoue 
218182cd038dSYoshinobu Inoue 	bzero(maskp, sizeof(*maskp));
218282cd038dSYoshinobu Inoue 	bytelen = len / 8;
218382cd038dSYoshinobu Inoue 	bitlen = len % 8;
218482cd038dSYoshinobu Inoue 	for (i = 0; i < bytelen; i++)
218582cd038dSYoshinobu Inoue 		maskp->s6_addr[i] = 0xff;
218682cd038dSYoshinobu Inoue 	if (bitlen)
218782cd038dSYoshinobu Inoue 		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
218882cd038dSYoshinobu Inoue }
218982cd038dSYoshinobu Inoue 
219082cd038dSYoshinobu Inoue /*
219182cd038dSYoshinobu Inoue  * return the best address out of the same scope. if no address was
219282cd038dSYoshinobu Inoue  * found, return the first valid address from designated IF.
219382cd038dSYoshinobu Inoue  */
219482cd038dSYoshinobu Inoue struct in6_ifaddr *
21951272577eSXin LI in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
219682cd038dSYoshinobu Inoue {
219782cd038dSYoshinobu Inoue 	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
219882cd038dSYoshinobu Inoue 	struct ifaddr *ifa;
219982cd038dSYoshinobu Inoue 	struct in6_ifaddr *besta = 0;
220082cd038dSYoshinobu Inoue 	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
220182cd038dSYoshinobu Inoue 
220282cd038dSYoshinobu Inoue 	dep[0] = dep[1] = NULL;
220382cd038dSYoshinobu Inoue 
220482cd038dSYoshinobu Inoue 	/*
220582cd038dSYoshinobu Inoue 	 * We first look for addresses in the same scope.
220682cd038dSYoshinobu Inoue 	 * If there is one, return it.
220782cd038dSYoshinobu Inoue 	 * If two or more, return one which matches the dst longest.
220882cd038dSYoshinobu Inoue 	 * If none, return one of global addresses assigned other ifs.
220982cd038dSYoshinobu Inoue 	 */
2210137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
2211c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
221282cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
221382cd038dSYoshinobu Inoue 			continue;
221482cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
221582cd038dSYoshinobu Inoue 			continue; /* XXX: is there any case to allow anycast? */
221682cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
221782cd038dSYoshinobu Inoue 			continue; /* don't use this interface */
221882cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
221982cd038dSYoshinobu Inoue 			continue;
222082cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2221603724d3SBjoern A. Zeeb 			if (V_ip6_use_deprecated)
222282cd038dSYoshinobu Inoue 				dep[0] = (struct in6_ifaddr *)ifa;
222382cd038dSYoshinobu Inoue 			continue;
222482cd038dSYoshinobu Inoue 		}
222582cd038dSYoshinobu Inoue 
222682cd038dSYoshinobu Inoue 		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
222782cd038dSYoshinobu Inoue 			/*
222882cd038dSYoshinobu Inoue 			 * call in6_matchlen() as few as possible
222982cd038dSYoshinobu Inoue 			 */
223082cd038dSYoshinobu Inoue 			if (besta) {
223182cd038dSYoshinobu Inoue 				if (blen == -1)
223282cd038dSYoshinobu Inoue 					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
223382cd038dSYoshinobu Inoue 				tlen = in6_matchlen(IFA_IN6(ifa), dst);
223482cd038dSYoshinobu Inoue 				if (tlen > blen) {
223582cd038dSYoshinobu Inoue 					blen = tlen;
223682cd038dSYoshinobu Inoue 					besta = (struct in6_ifaddr *)ifa;
223782cd038dSYoshinobu Inoue 				}
223882cd038dSYoshinobu Inoue 			} else
223982cd038dSYoshinobu Inoue 				besta = (struct in6_ifaddr *)ifa;
224082cd038dSYoshinobu Inoue 		}
224182cd038dSYoshinobu Inoue 	}
2242ac6ba962SRobert Watson 	if (besta) {
22438c0fec80SRobert Watson 		ifa_ref(&besta->ia_ifa);
2244137f91e8SJohn Baldwin 		IF_ADDR_RUNLOCK(ifp);
224582cd038dSYoshinobu Inoue 		return (besta);
2246ac6ba962SRobert Watson 	}
224782cd038dSYoshinobu Inoue 
2248c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
224982cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
225082cd038dSYoshinobu Inoue 			continue;
225182cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
225282cd038dSYoshinobu Inoue 			continue; /* XXX: is there any case to allow anycast? */
225382cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
225482cd038dSYoshinobu Inoue 			continue; /* don't use this interface */
225582cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
225682cd038dSYoshinobu Inoue 			continue;
225782cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2258603724d3SBjoern A. Zeeb 			if (V_ip6_use_deprecated)
225982cd038dSYoshinobu Inoue 				dep[1] = (struct in6_ifaddr *)ifa;
226082cd038dSYoshinobu Inoue 			continue;
226182cd038dSYoshinobu Inoue 		}
226282cd038dSYoshinobu Inoue 
22638c0fec80SRobert Watson 		if (ifa != NULL)
22648c0fec80SRobert Watson 			ifa_ref(ifa);
2265137f91e8SJohn Baldwin 		IF_ADDR_RUNLOCK(ifp);
226682cd038dSYoshinobu Inoue 		return (struct in6_ifaddr *)ifa;
226782cd038dSYoshinobu Inoue 	}
2268137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
226982cd038dSYoshinobu Inoue 
227082cd038dSYoshinobu Inoue 	/* use the last-resort values, that are, deprecated addresses */
227182cd038dSYoshinobu Inoue 	if (dep[0])
227282cd038dSYoshinobu Inoue 		return dep[0];
227382cd038dSYoshinobu Inoue 	if (dep[1])
227482cd038dSYoshinobu Inoue 		return dep[1];
227582cd038dSYoshinobu Inoue 
227682cd038dSYoshinobu Inoue 	return NULL;
227782cd038dSYoshinobu Inoue }
227882cd038dSYoshinobu Inoue 
227982cd038dSYoshinobu Inoue /*
228082cd038dSYoshinobu Inoue  * perform DAD when interface becomes IFF_UP.
228182cd038dSYoshinobu Inoue  */
228282cd038dSYoshinobu Inoue void
22831272577eSXin LI in6_if_up(struct ifnet *ifp)
228482cd038dSYoshinobu Inoue {
228582cd038dSYoshinobu Inoue 	struct ifaddr *ifa;
228682cd038dSYoshinobu Inoue 	struct in6_ifaddr *ia;
2287743eee66SSUZUKI Shinsuke 
2288137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
2289c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
2290743eee66SSUZUKI Shinsuke 		if (ifa->ifa_addr->sa_family != AF_INET6)
2291743eee66SSUZUKI Shinsuke 			continue;
2292743eee66SSUZUKI Shinsuke 		ia = (struct in6_ifaddr *)ifa;
2293743eee66SSUZUKI Shinsuke 		if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
2294743eee66SSUZUKI Shinsuke 			/*
2295743eee66SSUZUKI Shinsuke 			 * The TENTATIVE flag was likely set by hand
2296743eee66SSUZUKI Shinsuke 			 * beforehand, implicitly indicating the need for DAD.
2297743eee66SSUZUKI Shinsuke 			 * We may be able to skip the random delay in this
2298743eee66SSUZUKI Shinsuke 			 * case, but we impose delays just in case.
2299743eee66SSUZUKI Shinsuke 			 */
2300743eee66SSUZUKI Shinsuke 			nd6_dad_start(ifa,
2301743eee66SSUZUKI Shinsuke 			    arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
2302743eee66SSUZUKI Shinsuke 		}
2303743eee66SSUZUKI Shinsuke 	}
2304137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
230582cd038dSYoshinobu Inoue 
2306686cdd19SJun-ichiro itojun Hagino 	/*
2307686cdd19SJun-ichiro itojun Hagino 	 * special cases, like 6to4, are handled in in6_ifattach
2308686cdd19SJun-ichiro itojun Hagino 	 */
2309686cdd19SJun-ichiro itojun Hagino 	in6_ifattach(ifp, NULL);
231082cd038dSYoshinobu Inoue }
231182cd038dSYoshinobu Inoue 
231233841545SHajimu UMEMOTO int
23131272577eSXin LI in6if_do_dad(struct ifnet *ifp)
231433841545SHajimu UMEMOTO {
231533841545SHajimu UMEMOTO 	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
231633841545SHajimu UMEMOTO 		return (0);
231733841545SHajimu UMEMOTO 
2318a283298cSHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
2319a283298cSHiroki Sato 		return (0);
2320a283298cSHiroki Sato 
232133841545SHajimu UMEMOTO 	switch (ifp->if_type) {
232233841545SHajimu UMEMOTO #ifdef IFT_DUMMY
232333841545SHajimu UMEMOTO 	case IFT_DUMMY:
232433841545SHajimu UMEMOTO #endif
232533841545SHajimu UMEMOTO 	case IFT_FAITH:
232633841545SHajimu UMEMOTO 		/*
232733841545SHajimu UMEMOTO 		 * These interfaces do not have the IFF_LOOPBACK flag,
232833841545SHajimu UMEMOTO 		 * but loop packets back.  We do not have to do DAD on such
232933841545SHajimu UMEMOTO 		 * interfaces.  We should even omit it, because loop-backed
233033841545SHajimu UMEMOTO 		 * NS would confuse the DAD procedure.
233133841545SHajimu UMEMOTO 		 */
233233841545SHajimu UMEMOTO 		return (0);
233333841545SHajimu UMEMOTO 	default:
233433841545SHajimu UMEMOTO 		/*
233533841545SHajimu UMEMOTO 		 * Our DAD routine requires the interface up and running.
233633841545SHajimu UMEMOTO 		 * However, some interfaces can be up before the RUNNING
233733841545SHajimu UMEMOTO 		 * status.  Additionaly, users may try to assign addresses
233833841545SHajimu UMEMOTO 		 * before the interface becomes up (or running).
233933841545SHajimu UMEMOTO 		 * We simply skip DAD in such a case as a work around.
234033841545SHajimu UMEMOTO 		 * XXX: we should rather mark "tentative" on such addresses,
234133841545SHajimu UMEMOTO 		 * and do DAD after the interface becomes ready.
234233841545SHajimu UMEMOTO 		 */
234313f4c340SRobert Watson 		if (!((ifp->if_flags & IFF_UP) &&
234413f4c340SRobert Watson 		    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
234533841545SHajimu UMEMOTO 			return (0);
234633841545SHajimu UMEMOTO 
234733841545SHajimu UMEMOTO 		return (1);
234833841545SHajimu UMEMOTO 	}
234933841545SHajimu UMEMOTO }
235033841545SHajimu UMEMOTO 
235182cd038dSYoshinobu Inoue /*
235282cd038dSYoshinobu Inoue  * Calculate max IPv6 MTU through all the interfaces and store it
235382cd038dSYoshinobu Inoue  * to in6_maxmtu.
235482cd038dSYoshinobu Inoue  */
235582cd038dSYoshinobu Inoue void
23561272577eSXin LI in6_setmaxmtu(void)
235782cd038dSYoshinobu Inoue {
235882cd038dSYoshinobu Inoue 	unsigned long maxmtu = 0;
235982cd038dSYoshinobu Inoue 	struct ifnet *ifp;
236082cd038dSYoshinobu Inoue 
236177dfcdc4SRobert Watson 	IFNET_RLOCK_NOSLEEP();
23623b0b2840SJohn Baldwin 	TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
236331b3783cSHajimu UMEMOTO 		/* this function can be called during ifnet initialization */
236431b3783cSHajimu UMEMOTO 		if (!ifp->if_afdata[AF_INET6])
236531b3783cSHajimu UMEMOTO 			continue;
236682cd038dSYoshinobu Inoue 		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
236731b3783cSHajimu UMEMOTO 		    IN6_LINKMTU(ifp) > maxmtu)
236831b3783cSHajimu UMEMOTO 			maxmtu = IN6_LINKMTU(ifp);
236982cd038dSYoshinobu Inoue 	}
237077dfcdc4SRobert Watson 	IFNET_RUNLOCK_NOSLEEP();
237182cd038dSYoshinobu Inoue 	if (maxmtu)	     /* update only when maxmtu is positive */
2372603724d3SBjoern A. Zeeb 		V_in6_maxmtu = maxmtu;
237382cd038dSYoshinobu Inoue }
237482cd038dSYoshinobu Inoue 
2375743eee66SSUZUKI Shinsuke /*
2376743eee66SSUZUKI Shinsuke  * Provide the length of interface identifiers to be used for the link attached
2377743eee66SSUZUKI Shinsuke  * to the given interface.  The length should be defined in "IPv6 over
2378743eee66SSUZUKI Shinsuke  * xxx-link" document.  Note that address architecture might also define
2379743eee66SSUZUKI Shinsuke  * the length for a particular set of address prefixes, regardless of the
2380743eee66SSUZUKI Shinsuke  * link type.  As clarified in rfc2462bis, those two definitions should be
2381743eee66SSUZUKI Shinsuke  * consistent, and those really are as of August 2004.
2382743eee66SSUZUKI Shinsuke  */
2383743eee66SSUZUKI Shinsuke int
23841272577eSXin LI in6_if2idlen(struct ifnet *ifp)
2385743eee66SSUZUKI Shinsuke {
2386743eee66SSUZUKI Shinsuke 	switch (ifp->if_type) {
2387743eee66SSUZUKI Shinsuke 	case IFT_ETHER:		/* RFC2464 */
2388743eee66SSUZUKI Shinsuke #ifdef IFT_PROPVIRTUAL
2389743eee66SSUZUKI Shinsuke 	case IFT_PROPVIRTUAL:	/* XXX: no RFC. treat it as ether */
2390743eee66SSUZUKI Shinsuke #endif
2391743eee66SSUZUKI Shinsuke #ifdef IFT_L2VLAN
2392743eee66SSUZUKI Shinsuke 	case IFT_L2VLAN:	/* ditto */
2393743eee66SSUZUKI Shinsuke #endif
2394743eee66SSUZUKI Shinsuke #ifdef IFT_IEEE80211
2395743eee66SSUZUKI Shinsuke 	case IFT_IEEE80211:	/* ditto */
2396743eee66SSUZUKI Shinsuke #endif
2397743eee66SSUZUKI Shinsuke #ifdef IFT_MIP
2398743eee66SSUZUKI Shinsuke 	case IFT_MIP:	/* ditto */
2399743eee66SSUZUKI Shinsuke #endif
2400e4cd31ddSJeff Roberson 	case IFT_INFINIBAND:
2401743eee66SSUZUKI Shinsuke 		return (64);
2402743eee66SSUZUKI Shinsuke 	case IFT_FDDI:		/* RFC2467 */
2403743eee66SSUZUKI Shinsuke 		return (64);
2404743eee66SSUZUKI Shinsuke 	case IFT_ISO88025:	/* RFC2470 (IPv6 over Token Ring) */
2405743eee66SSUZUKI Shinsuke 		return (64);
2406743eee66SSUZUKI Shinsuke 	case IFT_PPP:		/* RFC2472 */
2407743eee66SSUZUKI Shinsuke 		return (64);
2408743eee66SSUZUKI Shinsuke 	case IFT_ARCNET:	/* RFC2497 */
2409743eee66SSUZUKI Shinsuke 		return (64);
2410743eee66SSUZUKI Shinsuke 	case IFT_FRELAY:	/* RFC2590 */
2411743eee66SSUZUKI Shinsuke 		return (64);
2412743eee66SSUZUKI Shinsuke 	case IFT_IEEE1394:	/* RFC3146 */
2413743eee66SSUZUKI Shinsuke 		return (64);
2414743eee66SSUZUKI Shinsuke 	case IFT_GIF:
2415743eee66SSUZUKI Shinsuke 		return (64);	/* draft-ietf-v6ops-mech-v2-07 */
2416743eee66SSUZUKI Shinsuke 	case IFT_LOOP:
2417743eee66SSUZUKI Shinsuke 		return (64);	/* XXX: is this really correct? */
2418743eee66SSUZUKI Shinsuke 	default:
2419743eee66SSUZUKI Shinsuke 		/*
2420743eee66SSUZUKI Shinsuke 		 * Unknown link type:
2421743eee66SSUZUKI Shinsuke 		 * It might be controversial to use the today's common constant
2422743eee66SSUZUKI Shinsuke 		 * of 64 for these cases unconditionally.  For full compliance,
2423743eee66SSUZUKI Shinsuke 		 * we should return an error in this case.  On the other hand,
2424743eee66SSUZUKI Shinsuke 		 * if we simply miss the standard for the link type or a new
2425743eee66SSUZUKI Shinsuke 		 * standard is defined for a new link type, the IFID length
2426743eee66SSUZUKI Shinsuke 		 * is very likely to be the common constant.  As a compromise,
2427743eee66SSUZUKI Shinsuke 		 * we always use the constant, but make an explicit notice
2428743eee66SSUZUKI Shinsuke 		 * indicating the "unknown" case.
2429743eee66SSUZUKI Shinsuke 		 */
2430743eee66SSUZUKI Shinsuke 		printf("in6_if2idlen: unknown link type (%d)\n", ifp->if_type);
2431743eee66SSUZUKI Shinsuke 		return (64);
2432743eee66SSUZUKI Shinsuke 	}
2433743eee66SSUZUKI Shinsuke }
2434743eee66SSUZUKI Shinsuke 
24356e6b3f7cSQing Li #include <sys/sysctl.h>
24366e6b3f7cSQing Li 
24376e6b3f7cSQing Li struct in6_llentry {
24386e6b3f7cSQing Li 	struct llentry		base;
24396e6b3f7cSQing Li 	struct sockaddr_in6	l3_addr6;
24406e6b3f7cSQing Li };
24416e6b3f7cSQing Li 
24426e6b3f7cSQing Li /*
24436e6b3f7cSQing Li  * Deletes an address from the address table.
24446e6b3f7cSQing Li  * This function is called by the timer functions
24456e6b3f7cSQing Li  * such as arptimer() and nd6_llinfo_timer(), and
24466e6b3f7cSQing Li  * the caller does the locking.
24476e6b3f7cSQing Li  */
24486e6b3f7cSQing Li static void
24496e6b3f7cSQing Li in6_lltable_free(struct lltable *llt, struct llentry *lle)
24506e6b3f7cSQing Li {
2451fbc2ca1bSKip Macy 	LLE_WUNLOCK(lle);
2452fbc2ca1bSKip Macy 	LLE_LOCK_DESTROY(lle);
24536e6b3f7cSQing Li 	free(lle, M_LLTABLE);
24546e6b3f7cSQing Li }
24556e6b3f7cSQing Li 
2456*a93cda78SKip Macy static struct llentry *
2457*a93cda78SKip Macy in6_lltable_new(const struct sockaddr *l3addr, u_int flags)
2458*a93cda78SKip Macy {
2459*a93cda78SKip Macy 	struct in6_llentry *lle;
2460*a93cda78SKip Macy 
2461*a93cda78SKip Macy 	lle = malloc(sizeof(struct in6_llentry), M_LLTABLE,
2462*a93cda78SKip Macy 	    M_DONTWAIT | M_ZERO);
2463*a93cda78SKip Macy 	if (lle == NULL)		/* NB: caller generates msg */
2464*a93cda78SKip Macy 		return NULL;
2465*a93cda78SKip Macy 
2466*a93cda78SKip Macy 	lle->l3_addr6 = *(const struct sockaddr_in6 *)l3addr;
2467*a93cda78SKip Macy 	lle->base.lle_refcnt = 1;
2468*a93cda78SKip Macy 	lle->base.lle_free = in6_lltable_free;
2469*a93cda78SKip Macy 	LLE_LOCK_INIT(&lle->base);
2470*a93cda78SKip Macy 	callout_init_rw(&lle->base.ln_timer_ch, &lle->base.lle_lock,
2471*a93cda78SKip Macy 	    CALLOUT_RETURNUNLOCKED);
2472*a93cda78SKip Macy 
2473*a93cda78SKip Macy 	return &lle->base;
2474*a93cda78SKip Macy }
2475*a93cda78SKip Macy 
2476c9d763bfSQing Li static void
2477c9d763bfSQing Li in6_lltable_prefix_free(struct lltable *llt,
2478c9d763bfSQing Li 			const struct sockaddr *prefix,
24795b84dc78SQing Li 			const struct sockaddr *mask,
24805b84dc78SQing Li 			u_int flags)
2481c9d763bfSQing Li {
2482c9d763bfSQing Li 	const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix;
2483c9d763bfSQing Li 	const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask;
2484c9d763bfSQing Li 	struct llentry *lle, *next;
2485c9d763bfSQing Li 	register int i;
2486c9d763bfSQing Li 
24875b84dc78SQing Li 	/*
24885b84dc78SQing Li 	 * (flags & LLE_STATIC) means deleting all entries
24895b84dc78SQing Li 	 * including static ND6 entries
24905b84dc78SQing Li 	 */
2491c9d763bfSQing Li 	for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
2492c9d763bfSQing Li 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
2493c9d763bfSQing Li 			if (IN6_ARE_MASKED_ADDR_EQUAL(
2494c9d763bfSQing Li 				    &((struct sockaddr_in6 *)L3_ADDR(lle))->sin6_addr,
2495c9d763bfSQing Li 				    &pfx->sin6_addr,
24965b84dc78SQing Li 				    &msk->sin6_addr) &&
24975b84dc78SQing Li 			    ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC))) {
2498becba438SBjoern A. Zeeb 				int canceled;
2499becba438SBjoern A. Zeeb 
2500becba438SBjoern A. Zeeb 				canceled = callout_drain(&lle->la_timer);
2501c9d763bfSQing Li 				LLE_WLOCK(lle);
2502becba438SBjoern A. Zeeb 				if (canceled)
2503becba438SBjoern A. Zeeb 					LLE_REMREF(lle);
2504c9d763bfSQing Li 				llentry_free(lle);
2505c9d763bfSQing Li 			}
2506c9d763bfSQing Li 		}
2507c9d763bfSQing Li 	}
2508c9d763bfSQing Li }
2509c9d763bfSQing Li 
25106e6b3f7cSQing Li static int
2511c7ab6602SQing Li in6_lltable_rtcheck(struct ifnet *ifp,
2512c7ab6602SQing Li 		    u_int flags,
2513c7ab6602SQing Li 		    const struct sockaddr *l3addr)
25146e6b3f7cSQing Li {
25156e6b3f7cSQing Li 	struct rtentry *rt;
25166e6b3f7cSQing Li 	char ip6buf[INET6_ADDRSTRLEN];
25176e6b3f7cSQing Li 
25186e6b3f7cSQing Li 	KASSERT(l3addr->sa_family == AF_INET6,
25196e6b3f7cSQing Li 	    ("sin_family %d", l3addr->sa_family));
25206e6b3f7cSQing Li 
252181d5d46bSBjoern A. Zeeb 	/* Our local addresses are always only installed on the default FIB. */
25226e6b3f7cSQing Li 	/* XXX rtalloc1 should take a const param */
252381d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0,
252481d5d46bSBjoern A. Zeeb 	    RT_DEFAULT_FIB);
25256e6b3f7cSQing Li 	if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
25266e6b3f7cSQing Li 		struct ifaddr *ifa;
25276e6b3f7cSQing Li 		/*
25286e6b3f7cSQing Li 		 * Create an ND6 cache for an IPv6 neighbor
25296e6b3f7cSQing Li 		 * that is not covered by our own prefix.
25306e6b3f7cSQing Li 		 */
25316e6b3f7cSQing Li 		/* XXX ifaof_ifpforaddr should take a const param */
25326e6b3f7cSQing Li 		ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
25336e6b3f7cSQing Li 		if (ifa != NULL) {
25348c0fec80SRobert Watson 			ifa_free(ifa);
25356e6b3f7cSQing Li 			if (rt != NULL)
25362e730beaSBjoern A. Zeeb 				RTFREE_LOCKED(rt);
25376e6b3f7cSQing Li 			return 0;
25386e6b3f7cSQing Li 		}
25396e6b3f7cSQing Li 		log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
25406e6b3f7cSQing Li 		    ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
25416e6b3f7cSQing Li 		if (rt != NULL)
25422e730beaSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
25436e6b3f7cSQing Li 		return EINVAL;
25446e6b3f7cSQing Li 	}
25452e730beaSBjoern A. Zeeb 	RTFREE_LOCKED(rt);
25466e6b3f7cSQing Li 	return 0;
25476e6b3f7cSQing Li }
25486e6b3f7cSQing Li 
25496e6b3f7cSQing Li static struct llentry *
25506e6b3f7cSQing Li in6_lltable_lookup(struct lltable *llt, u_int flags,
25516e6b3f7cSQing Li 	const struct sockaddr *l3addr)
25526e6b3f7cSQing Li {
25536e6b3f7cSQing Li 	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
25546e6b3f7cSQing Li 	struct ifnet *ifp = llt->llt_ifp;
25556e6b3f7cSQing Li 	struct llentry *lle;
25566e6b3f7cSQing Li 	struct llentries *lleh;
25576e6b3f7cSQing Li 	u_int hashkey;
25586e6b3f7cSQing Li 
25596e6b3f7cSQing Li 	IF_AFDATA_LOCK_ASSERT(ifp);
25606e6b3f7cSQing Li 	KASSERT(l3addr->sa_family == AF_INET6,
25616e6b3f7cSQing Li 	    ("sin_family %d", l3addr->sa_family));
25626e6b3f7cSQing Li 
25636e6b3f7cSQing Li 	hashkey = sin6->sin6_addr.s6_addr32[3];
25646e6b3f7cSQing Li 	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
25656e6b3f7cSQing Li 	LIST_FOREACH(lle, lleh, lle_next) {
2566dc495497SQing Li 		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)L3_ADDR(lle);
25676e6b3f7cSQing Li 		if (lle->la_flags & LLE_DELETED)
25686e6b3f7cSQing Li 			continue;
2569dc495497SQing Li 		if (bcmp(&sa6->sin6_addr, &sin6->sin6_addr,
2570dc495497SQing Li 			 sizeof(struct in6_addr)) == 0)
25716e6b3f7cSQing Li 			break;
25726e6b3f7cSQing Li 	}
25736e6b3f7cSQing Li 
25746e6b3f7cSQing Li 	if (lle == NULL) {
25756e6b3f7cSQing Li 		if (!(flags & LLE_CREATE))
25766e6b3f7cSQing Li 			return (NULL);
25776e6b3f7cSQing Li 		/*
25786e6b3f7cSQing Li 		 * A route that covers the given address must have
25796e6b3f7cSQing Li 		 * been installed 1st because we are doing a resolution,
25806e6b3f7cSQing Li 		 * verify this.
25816e6b3f7cSQing Li 		 */
25826e6b3f7cSQing Li 		if (!(flags & LLE_IFADDR) &&
2583c7ab6602SQing Li 		    in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
25846e6b3f7cSQing Li 			return NULL;
25856e6b3f7cSQing Li 
25866e6b3f7cSQing Li 		lle = in6_lltable_new(l3addr, flags);
25876e6b3f7cSQing Li 		if (lle == NULL) {
25886e6b3f7cSQing Li 			log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
25896e6b3f7cSQing Li 			return NULL;
25906e6b3f7cSQing Li 		}
25916e6b3f7cSQing Li 		lle->la_flags = flags & ~LLE_CREATE;
25926e6b3f7cSQing Li 		if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
25936e6b3f7cSQing Li 			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
25946e6b3f7cSQing Li 			lle->la_flags |= (LLE_VALID | LLE_STATIC);
25956e6b3f7cSQing Li 		}
25966e6b3f7cSQing Li 
25976e6b3f7cSQing Li 		lle->lle_tbl  = llt;
25986e6b3f7cSQing Li 		lle->lle_head = lleh;
25996e6b3f7cSQing Li 		LIST_INSERT_HEAD(lleh, lle, lle_next);
26006e6b3f7cSQing Li 	} else if (flags & LLE_DELETE) {
2601ebf1c744SQing Li 		if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
26026e6b3f7cSQing Li 			LLE_WLOCK(lle);
26036e6b3f7cSQing Li 			lle->la_flags = LLE_DELETED;
26046e6b3f7cSQing Li 			LLE_WUNLOCK(lle);
26056cb2b4e7SQing Li #ifdef DIAGNOSTIC
26066e6b3f7cSQing Li 			log(LOG_INFO, "ifaddr cache = %p  is deleted\n", lle);
26076e6b3f7cSQing Li #endif
2608ebf1c744SQing Li 		}
26096e6b3f7cSQing Li 		lle = (void *)-1;
26106e6b3f7cSQing Li 	}
26116e6b3f7cSQing Li 	if (LLE_IS_VALID(lle)) {
26126e6b3f7cSQing Li 		if (flags & LLE_EXCLUSIVE)
26136e6b3f7cSQing Li 			LLE_WLOCK(lle);
26146e6b3f7cSQing Li 		else
26156e6b3f7cSQing Li 			LLE_RLOCK(lle);
26166e6b3f7cSQing Li 	}
26176e6b3f7cSQing Li 	return (lle);
26186e6b3f7cSQing Li }
26196e6b3f7cSQing Li 
26206e6b3f7cSQing Li static int
26216e6b3f7cSQing Li in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
26226e6b3f7cSQing Li {
26236e6b3f7cSQing Li 	struct ifnet *ifp = llt->llt_ifp;
26246e6b3f7cSQing Li 	struct llentry *lle;
26256e6b3f7cSQing Li 	/* XXX stack use */
26266e6b3f7cSQing Li 	struct {
26276e6b3f7cSQing Li 		struct rt_msghdr	rtm;
26286e6b3f7cSQing Li 		struct sockaddr_in6	sin6;
26296e6b3f7cSQing Li 		/*
26306e6b3f7cSQing Li 		 * ndp.c assumes that sdl is word aligned
26316e6b3f7cSQing Li 		 */
26326e6b3f7cSQing Li #ifdef __LP64__
26336e6b3f7cSQing Li 		uint32_t		pad;
26346e6b3f7cSQing Li #endif
26356e6b3f7cSQing Li 		struct sockaddr_dl	sdl;
26366e6b3f7cSQing Li 	} ndpc;
26376e6b3f7cSQing Li 	int i, error;
26386e6b3f7cSQing Li 
26399452b0d2SQing Li 	if (ifp->if_flags & IFF_LOOPBACK)
26409452b0d2SQing Li 		return 0;
26419452b0d2SQing Li 
2642dc56e98fSRobert Watson 	LLTABLE_LOCK_ASSERT();
26436e6b3f7cSQing Li 
26446e6b3f7cSQing Li 	error = 0;
26456e6b3f7cSQing Li 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
26466e6b3f7cSQing Li 		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
26476e6b3f7cSQing Li 			struct sockaddr_dl *sdl;
26486e6b3f7cSQing Li 
26496e6b3f7cSQing Li 			/* skip deleted or invalid entries */
26506e6b3f7cSQing Li 			if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
26516e6b3f7cSQing Li 				continue;
2652813dd6aeSBjoern A. Zeeb 			/* Skip if jailed and not a valid IP of the prison. */
2653b89e82ddSJamie Gritton 			if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
2654813dd6aeSBjoern A. Zeeb 				continue;
26556e6b3f7cSQing Li 			/*
26566e6b3f7cSQing Li 			 * produce a msg made of:
26576e6b3f7cSQing Li 			 *  struct rt_msghdr;
26586e6b3f7cSQing Li 			 *  struct sockaddr_in6 (IPv6)
26596e6b3f7cSQing Li 			 *  struct sockaddr_dl;
26606e6b3f7cSQing Li 			 */
26616e6b3f7cSQing Li 			bzero(&ndpc, sizeof(ndpc));
26626e6b3f7cSQing Li 			ndpc.rtm.rtm_msglen = sizeof(ndpc);
266314981d80SQing Li 			ndpc.rtm.rtm_version = RTM_VERSION;
266414981d80SQing Li 			ndpc.rtm.rtm_type = RTM_GET;
266514981d80SQing Li 			ndpc.rtm.rtm_flags = RTF_UP;
266614981d80SQing Li 			ndpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
26676e6b3f7cSQing Li 			ndpc.sin6.sin6_family = AF_INET6;
26686e6b3f7cSQing Li 			ndpc.sin6.sin6_len = sizeof(ndpc.sin6);
26696e6b3f7cSQing Li 			bcopy(L3_ADDR(lle), &ndpc.sin6, L3_ADDR_LEN(lle));
26706e6b3f7cSQing Li 
26716e6b3f7cSQing Li 			/* publish */
26726e6b3f7cSQing Li 			if (lle->la_flags & LLE_PUB)
26736e6b3f7cSQing Li 				ndpc.rtm.rtm_flags |= RTF_ANNOUNCE;
26746e6b3f7cSQing Li 
26756e6b3f7cSQing Li 			sdl = &ndpc.sdl;
26766e6b3f7cSQing Li 			sdl->sdl_family = AF_LINK;
26776e6b3f7cSQing Li 			sdl->sdl_len = sizeof(*sdl);
26786e6b3f7cSQing Li 			sdl->sdl_alen = ifp->if_addrlen;
26796e6b3f7cSQing Li 			sdl->sdl_index = ifp->if_index;
26806e6b3f7cSQing Li 			sdl->sdl_type = ifp->if_type;
26816e6b3f7cSQing Li 			bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
26826e6b3f7cSQing Li 			ndpc.rtm.rtm_rmx.rmx_expire =
26836e6b3f7cSQing Li 			    lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
26848eca593cSQing Li 			ndpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
26856e6b3f7cSQing Li 			if (lle->la_flags & LLE_STATIC)
26866e6b3f7cSQing Li 				ndpc.rtm.rtm_flags |= RTF_STATIC;
26876e6b3f7cSQing Li 			ndpc.rtm.rtm_index = ifp->if_index;
26886e6b3f7cSQing Li 			error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc));
26896e6b3f7cSQing Li 			if (error)
26906e6b3f7cSQing Li 				break;
26916e6b3f7cSQing Li 		}
26926e6b3f7cSQing Li 	}
26936e6b3f7cSQing Li 	return error;
26946e6b3f7cSQing Li }
26956e6b3f7cSQing Li 
269631b1bfe1SHajimu UMEMOTO void *
26971272577eSXin LI in6_domifattach(struct ifnet *ifp)
269831b1bfe1SHajimu UMEMOTO {
269931b1bfe1SHajimu UMEMOTO 	struct in6_ifextra *ext;
270031b1bfe1SHajimu UMEMOTO 
270131b1bfe1SHajimu UMEMOTO 	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
270231b1bfe1SHajimu UMEMOTO 	bzero(ext, sizeof(*ext));
270331b1bfe1SHajimu UMEMOTO 
270431b1bfe1SHajimu UMEMOTO 	ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
270531b1bfe1SHajimu UMEMOTO 	    M_IFADDR, M_WAITOK);
270631b1bfe1SHajimu UMEMOTO 	bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
270731b1bfe1SHajimu UMEMOTO 
270831b1bfe1SHajimu UMEMOTO 	ext->icmp6_ifstat =
270931b1bfe1SHajimu UMEMOTO 	    (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
271031b1bfe1SHajimu UMEMOTO 	    M_IFADDR, M_WAITOK);
271131b1bfe1SHajimu UMEMOTO 	bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
271231b1bfe1SHajimu UMEMOTO 
271331b1bfe1SHajimu UMEMOTO 	ext->nd_ifinfo = nd6_ifattach(ifp);
271431b1bfe1SHajimu UMEMOTO 	ext->scope6_id = scope6_ifattach(ifp);
27156e6b3f7cSQing Li 	ext->lltable = lltable_init(ifp, AF_INET6);
27166e6b3f7cSQing Li 	if (ext->lltable != NULL) {
2717c9d763bfSQing Li 		ext->lltable->llt_prefix_free = in6_lltable_prefix_free;
27186e6b3f7cSQing Li 		ext->lltable->llt_lookup = in6_lltable_lookup;
27196e6b3f7cSQing Li 		ext->lltable->llt_dump = in6_lltable_dump;
27206e6b3f7cSQing Li 	}
272133cde130SBruce M Simpson 
272233cde130SBruce M Simpson 	ext->mld_ifinfo = mld_domifattach(ifp);
272333cde130SBruce M Simpson 
272431b1bfe1SHajimu UMEMOTO 	return ext;
272531b1bfe1SHajimu UMEMOTO }
272631b1bfe1SHajimu UMEMOTO 
272731b1bfe1SHajimu UMEMOTO void
27281272577eSXin LI in6_domifdetach(struct ifnet *ifp, void *aux)
272931b1bfe1SHajimu UMEMOTO {
273031b1bfe1SHajimu UMEMOTO 	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
273131b1bfe1SHajimu UMEMOTO 
273233cde130SBruce M Simpson 	mld_domifdetach(ifp);
273331b1bfe1SHajimu UMEMOTO 	scope6_ifdetach(ext->scope6_id);
273431b1bfe1SHajimu UMEMOTO 	nd6_ifdetach(ext->nd_ifinfo);
27356e6b3f7cSQing Li 	lltable_free(ext->lltable);
273631b1bfe1SHajimu UMEMOTO 	free(ext->in6_ifstat, M_IFADDR);
273731b1bfe1SHajimu UMEMOTO 	free(ext->icmp6_ifstat, M_IFADDR);
273831b1bfe1SHajimu UMEMOTO 	free(ext, M_IFADDR);
273931b1bfe1SHajimu UMEMOTO }
274031b1bfe1SHajimu UMEMOTO 
274182cd038dSYoshinobu Inoue /*
274282cd038dSYoshinobu Inoue  * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
274382cd038dSYoshinobu Inoue  * v4 mapped addr or v4 compat addr
274482cd038dSYoshinobu Inoue  */
274582cd038dSYoshinobu Inoue void
274682cd038dSYoshinobu Inoue in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
274782cd038dSYoshinobu Inoue {
27481272577eSXin LI 
274982cd038dSYoshinobu Inoue 	bzero(sin, sizeof(*sin));
275082cd038dSYoshinobu Inoue 	sin->sin_len = sizeof(struct sockaddr_in);
275182cd038dSYoshinobu Inoue 	sin->sin_family = AF_INET;
275282cd038dSYoshinobu Inoue 	sin->sin_port = sin6->sin6_port;
275382cd038dSYoshinobu Inoue 	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
275482cd038dSYoshinobu Inoue }
275582cd038dSYoshinobu Inoue 
275682cd038dSYoshinobu Inoue /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
275782cd038dSYoshinobu Inoue void
275882cd038dSYoshinobu Inoue in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
275982cd038dSYoshinobu Inoue {
276082cd038dSYoshinobu Inoue 	bzero(sin6, sizeof(*sin6));
276182cd038dSYoshinobu Inoue 	sin6->sin6_len = sizeof(struct sockaddr_in6);
276282cd038dSYoshinobu Inoue 	sin6->sin6_family = AF_INET6;
276382cd038dSYoshinobu Inoue 	sin6->sin6_port = sin->sin_port;
276482cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[0] = 0;
276582cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[1] = 0;
276682cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
276782cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
276882cd038dSYoshinobu Inoue }
276982cd038dSYoshinobu Inoue 
277082cd038dSYoshinobu Inoue /* Convert sockaddr_in6 into sockaddr_in. */
277182cd038dSYoshinobu Inoue void
277282cd038dSYoshinobu Inoue in6_sin6_2_sin_in_sock(struct sockaddr *nam)
277382cd038dSYoshinobu Inoue {
277482cd038dSYoshinobu Inoue 	struct sockaddr_in *sin_p;
277582cd038dSYoshinobu Inoue 	struct sockaddr_in6 sin6;
277682cd038dSYoshinobu Inoue 
277782cd038dSYoshinobu Inoue 	/*
277882cd038dSYoshinobu Inoue 	 * Save original sockaddr_in6 addr and convert it
277982cd038dSYoshinobu Inoue 	 * to sockaddr_in.
278082cd038dSYoshinobu Inoue 	 */
278182cd038dSYoshinobu Inoue 	sin6 = *(struct sockaddr_in6 *)nam;
278282cd038dSYoshinobu Inoue 	sin_p = (struct sockaddr_in *)nam;
278382cd038dSYoshinobu Inoue 	in6_sin6_2_sin(sin_p, &sin6);
278482cd038dSYoshinobu Inoue }
278582cd038dSYoshinobu Inoue 
278682cd038dSYoshinobu Inoue /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
278782cd038dSYoshinobu Inoue void
278882cd038dSYoshinobu Inoue in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
278982cd038dSYoshinobu Inoue {
279082cd038dSYoshinobu Inoue 	struct sockaddr_in *sin_p;
279182cd038dSYoshinobu Inoue 	struct sockaddr_in6 *sin6_p;
279282cd038dSYoshinobu Inoue 
27931ede983cSDag-Erling Smørgrav 	sin6_p = malloc(sizeof *sin6_p, M_SONAME,
2794a163d034SWarner Losh 	       M_WAITOK);
279582cd038dSYoshinobu Inoue 	sin_p = (struct sockaddr_in *)*nam;
279682cd038dSYoshinobu Inoue 	in6_sin_2_v4mapsin6(sin_p, sin6_p);
27971ede983cSDag-Erling Smørgrav 	free(*nam, M_SONAME);
279882cd038dSYoshinobu Inoue 	*nam = (struct sockaddr *)sin6_p;
279982cd038dSYoshinobu Inoue }
2800