xref: /freebsd/sys/netinet6/in6.c (revision 7d26db17927ed2063fb108f1dffcb17b3eaee6db)
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 
1095df1b6b5SHiroki Sato VNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix);
1105df1b6b5SHiroki Sato #define V_icmp6_nodeinfo_oldmcprefix	VNET(icmp6_nodeinfo_oldmcprefix)
1115df1b6b5SHiroki Sato 
11282cd038dSYoshinobu Inoue /*
11382cd038dSYoshinobu Inoue  * Definitions of some costant IP6 addresses.
11482cd038dSYoshinobu Inoue  */
11582cd038dSYoshinobu Inoue const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
11682cd038dSYoshinobu Inoue const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
11782cd038dSYoshinobu Inoue const struct in6_addr in6addr_nodelocal_allnodes =
11882cd038dSYoshinobu Inoue 	IN6ADDR_NODELOCAL_ALLNODES_INIT;
11982cd038dSYoshinobu Inoue const struct in6_addr in6addr_linklocal_allnodes =
12082cd038dSYoshinobu Inoue 	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
12182cd038dSYoshinobu Inoue const struct in6_addr in6addr_linklocal_allrouters =
12282cd038dSYoshinobu Inoue 	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
12333cde130SBruce M Simpson const struct in6_addr in6addr_linklocal_allv2routers =
12433cde130SBruce M Simpson 	IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT;
12582cd038dSYoshinobu Inoue 
12682cd038dSYoshinobu Inoue const struct in6_addr in6mask0 = IN6MASK0;
12782cd038dSYoshinobu Inoue const struct in6_addr in6mask32 = IN6MASK32;
12882cd038dSYoshinobu Inoue const struct in6_addr in6mask64 = IN6MASK64;
12982cd038dSYoshinobu Inoue const struct in6_addr in6mask96 = IN6MASK96;
13082cd038dSYoshinobu Inoue const struct in6_addr in6mask128 = IN6MASK128;
13182cd038dSYoshinobu Inoue 
13259aecc96SHajimu UMEMOTO const struct sockaddr_in6 sa6_any =
13359aecc96SHajimu UMEMOTO 	{ sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 };
13433841545SHajimu UMEMOTO 
1356f56329aSXin LI static int in6_lifaddr_ioctl(struct socket *, u_long, caddr_t,
1366f56329aSXin LI 	struct ifnet *, struct thread *);
1376f56329aSXin LI static int in6_ifinit(struct ifnet *, struct in6_ifaddr *,
1386f56329aSXin LI 	struct sockaddr_in6 *, int);
1399233d8f3SDavid E. O'Brien static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
14082cd038dSYoshinobu Inoue 
1419494d596SBrooks Davis int	(*faithprefix_p)(struct in6_addr *);
1429494d596SBrooks Davis 
143b590b6aeSGleb Smirnoff #define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
144b590b6aeSGleb Smirnoff #define ia62ifa(ia6)	(&((ia6)->ia_ifa))
14582cd038dSYoshinobu Inoue 
146b590b6aeSGleb Smirnoff void
147b590b6aeSGleb Smirnoff in6_ifaddloop(struct ifaddr *ifa)
148b590b6aeSGleb Smirnoff {
149b590b6aeSGleb Smirnoff 	struct sockaddr_dl gateway;
150b590b6aeSGleb Smirnoff 	struct sockaddr_in6 mask, addr;
151b590b6aeSGleb Smirnoff 	struct rtentry rt;
152b590b6aeSGleb Smirnoff 	struct in6_ifaddr *ia;
153b590b6aeSGleb Smirnoff 	struct ifnet *ifp;
154b590b6aeSGleb Smirnoff 	struct llentry *ln;
155b590b6aeSGleb Smirnoff 
156b590b6aeSGleb Smirnoff 	ia = ifa2ia6(ifa);
157b590b6aeSGleb Smirnoff 	ifp = ifa->ifa_ifp;
158b590b6aeSGleb Smirnoff 	IF_AFDATA_LOCK(ifp);
1590f1aca65SQing Li 	ifa->ifa_rtrequest = nd6_rtrequest;
160b590b6aeSGleb Smirnoff 	ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR |
161b590b6aeSGleb Smirnoff 	    LLE_EXCLUSIVE), (struct sockaddr *)&ia->ia_addr);
162b590b6aeSGleb Smirnoff 	IF_AFDATA_UNLOCK(ifp);
163b590b6aeSGleb Smirnoff 	if (ln != NULL) {
164b590b6aeSGleb Smirnoff 		ln->la_expire = 0;  /* for IPv6 this means permanent */
165b590b6aeSGleb Smirnoff 		ln->ln_state = ND6_LLINFO_REACHABLE;
166b590b6aeSGleb Smirnoff 		/*
167b590b6aeSGleb Smirnoff 		 * initialize for rtmsg generation
168b590b6aeSGleb Smirnoff 		 */
169b590b6aeSGleb Smirnoff 		bzero(&gateway, sizeof(gateway));
170b590b6aeSGleb Smirnoff 		gateway.sdl_len = sizeof(gateway);
171b590b6aeSGleb Smirnoff 		gateway.sdl_family = AF_LINK;
172b590b6aeSGleb Smirnoff 		gateway.sdl_nlen = 0;
173b590b6aeSGleb Smirnoff 		gateway.sdl_alen = 6;
174b590b6aeSGleb Smirnoff 		memcpy(gateway.sdl_data, &ln->ll_addr.mac_aligned,
175b590b6aeSGleb Smirnoff 		    sizeof(ln->ll_addr));
176b590b6aeSGleb Smirnoff 		LLE_WUNLOCK(ln);
177b590b6aeSGleb Smirnoff 	}
178b590b6aeSGleb Smirnoff 
179b590b6aeSGleb Smirnoff 	bzero(&rt, sizeof(rt));
180b590b6aeSGleb Smirnoff 	rt.rt_gateway = (struct sockaddr *)&gateway;
181b590b6aeSGleb Smirnoff 	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
182b590b6aeSGleb Smirnoff 	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
183b590b6aeSGleb Smirnoff 	rt_mask(&rt) = (struct sockaddr *)&mask;
184b590b6aeSGleb Smirnoff 	rt_key(&rt) = (struct sockaddr *)&addr;
185b590b6aeSGleb Smirnoff 	rt.rt_flags = RTF_UP | RTF_HOST | RTF_STATIC;
18681d5d46bSBjoern A. Zeeb 	/* Announce arrival of local address to all FIBs. */
187b590b6aeSGleb Smirnoff 	rt_newaddrmsg(RTM_ADD, ifa, 0, &rt);
188b590b6aeSGleb Smirnoff }
189b590b6aeSGleb Smirnoff 
190b590b6aeSGleb Smirnoff void
191b590b6aeSGleb Smirnoff in6_ifremloop(struct ifaddr *ifa)
192b590b6aeSGleb Smirnoff {
193b590b6aeSGleb Smirnoff 	struct sockaddr_dl gateway;
194b590b6aeSGleb Smirnoff 	struct sockaddr_in6 mask, addr;
195b590b6aeSGleb Smirnoff 	struct rtentry rt0;
196b590b6aeSGleb Smirnoff 	struct in6_ifaddr *ia;
197b590b6aeSGleb Smirnoff 	struct ifnet *ifp;
198b590b6aeSGleb Smirnoff 
199b590b6aeSGleb Smirnoff 	ia = ifa2ia6(ifa);
200b590b6aeSGleb Smirnoff 	ifp = ifa->ifa_ifp;
2011571132fSOleg Bulyzhin 	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
2021571132fSOleg Bulyzhin 	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
2031571132fSOleg Bulyzhin 	lltable_prefix_free(AF_INET6, (struct sockaddr *)&addr,
2041571132fSOleg Bulyzhin 	            (struct sockaddr *)&mask, LLE_STATIC);
205b590b6aeSGleb Smirnoff 
206b590b6aeSGleb Smirnoff 	/*
207b590b6aeSGleb Smirnoff 	 * initialize for rtmsg generation
208b590b6aeSGleb Smirnoff 	 */
209b590b6aeSGleb Smirnoff 	bzero(&gateway, sizeof(gateway));
210b590b6aeSGleb Smirnoff 	gateway.sdl_len = sizeof(gateway);
211b590b6aeSGleb Smirnoff 	gateway.sdl_family = AF_LINK;
212b590b6aeSGleb Smirnoff 	gateway.sdl_nlen = 0;
213b590b6aeSGleb Smirnoff 	gateway.sdl_alen = ifp->if_addrlen;
214b590b6aeSGleb Smirnoff 	bzero(&rt0, sizeof(rt0));
215b590b6aeSGleb Smirnoff 	rt0.rt_gateway = (struct sockaddr *)&gateway;
216b590b6aeSGleb Smirnoff 	rt_mask(&rt0) = (struct sockaddr *)&mask;
217b590b6aeSGleb Smirnoff 	rt_key(&rt0) = (struct sockaddr *)&addr;
218b590b6aeSGleb Smirnoff 	rt0.rt_flags = RTF_HOST | RTF_STATIC;
21981d5d46bSBjoern A. Zeeb 	/* Announce removal of local address to all FIBs. */
220b590b6aeSGleb Smirnoff 	rt_newaddrmsg(RTM_DELETE, ifa, 0, &rt0);
221b590b6aeSGleb Smirnoff }
22282cd038dSYoshinobu Inoue 
22382cd038dSYoshinobu Inoue int
2241272577eSXin LI in6_mask2len(struct in6_addr *mask, u_char *lim0)
22582cd038dSYoshinobu Inoue {
22633841545SHajimu UMEMOTO 	int x = 0, y;
22733841545SHajimu UMEMOTO 	u_char *lim = lim0, *p;
22882cd038dSYoshinobu Inoue 
22906cd0a3fSHajimu UMEMOTO 	/* ignore the scope_id part */
23006cd0a3fSHajimu UMEMOTO 	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
23133841545SHajimu UMEMOTO 		lim = (u_char *)mask + sizeof(*mask);
23233841545SHajimu UMEMOTO 	for (p = (u_char *)mask; p < lim; x++, p++) {
23333841545SHajimu UMEMOTO 		if (*p != 0xff)
23482cd038dSYoshinobu Inoue 			break;
23582cd038dSYoshinobu Inoue 	}
23682cd038dSYoshinobu Inoue 	y = 0;
23733841545SHajimu UMEMOTO 	if (p < lim) {
23882cd038dSYoshinobu Inoue 		for (y = 0; y < 8; y++) {
23933841545SHajimu UMEMOTO 			if ((*p & (0x80 >> y)) == 0)
24082cd038dSYoshinobu Inoue 				break;
24182cd038dSYoshinobu Inoue 		}
24282cd038dSYoshinobu Inoue 	}
24333841545SHajimu UMEMOTO 
24433841545SHajimu UMEMOTO 	/*
24533841545SHajimu UMEMOTO 	 * when the limit pointer is given, do a stricter check on the
24633841545SHajimu UMEMOTO 	 * remaining bits.
24733841545SHajimu UMEMOTO 	 */
24833841545SHajimu UMEMOTO 	if (p < lim) {
24933841545SHajimu UMEMOTO 		if (y != 0 && (*p & (0x00ff >> y)) != 0)
25033841545SHajimu UMEMOTO 			return (-1);
25133841545SHajimu UMEMOTO 		for (p = p + 1; p < lim; p++)
25233841545SHajimu UMEMOTO 			if (*p != 0)
25333841545SHajimu UMEMOTO 				return (-1);
25433841545SHajimu UMEMOTO 	}
25533841545SHajimu UMEMOTO 
25682cd038dSYoshinobu Inoue 	return x * 8 + y;
25782cd038dSYoshinobu Inoue }
25882cd038dSYoshinobu Inoue 
25999c750a8SKonstantin Belousov #ifdef COMPAT_FREEBSD32
26099c750a8SKonstantin Belousov struct in6_ndifreq32 {
26199c750a8SKonstantin Belousov 	char ifname[IFNAMSIZ];
26299c750a8SKonstantin Belousov 	uint32_t ifindex;
26399c750a8SKonstantin Belousov };
26499c750a8SKonstantin Belousov #define	SIOCGDEFIFACE32_IN6	_IOWR('i', 86, struct in6_ndifreq32)
26599c750a8SKonstantin Belousov #endif
26699c750a8SKonstantin Belousov 
26782cd038dSYoshinobu Inoue int
2681272577eSXin LI in6_control(struct socket *so, u_long cmd, caddr_t data,
2691272577eSXin LI     struct ifnet *ifp, struct thread *td)
27082cd038dSYoshinobu Inoue {
27182cd038dSYoshinobu Inoue 	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
27233841545SHajimu UMEMOTO 	struct	in6_ifaddr *ia = NULL;
27382cd038dSYoshinobu Inoue 	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
274743eee66SSUZUKI Shinsuke 	struct sockaddr_in6 *sa6;
27508b68b0eSGleb Smirnoff 	int carp_attached = 0;
276acd3428bSRobert Watson 	int error;
27771212473SGleb Smirnoff 	u_long ocmd = cmd;
27871212473SGleb Smirnoff 
27971212473SGleb Smirnoff 	/*
28071212473SGleb Smirnoff 	 * Compat to make pre-10.x ifconfig(8) operable.
28171212473SGleb Smirnoff 	 */
28271212473SGleb Smirnoff 	if (cmd == OSIOCAIFADDR_IN6)
28371212473SGleb Smirnoff 		cmd = SIOCAIFADDR_IN6;
28482cd038dSYoshinobu Inoue 
285686cdd19SJun-ichiro itojun Hagino 	switch (cmd) {
286686cdd19SJun-ichiro itojun Hagino 	case SIOCGETSGCNT_IN6:
287686cdd19SJun-ichiro itojun Hagino 	case SIOCGETMIFCNT_IN6:
28881d5d46bSBjoern A. Zeeb 		/*
28981d5d46bSBjoern A. Zeeb 		 * XXX mrt_ioctl has a 3rd, unused, FIB argument in route.c.
29081d5d46bSBjoern A. Zeeb 		 * We cannot see how that would be needed, so do not adjust the
29181d5d46bSBjoern A. Zeeb 		 * KPI blindly; more likely should clean up the IPv4 variant.
29281d5d46bSBjoern A. Zeeb 		 */
2936be2e366SBruce M Simpson 		return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP);
294686cdd19SJun-ichiro itojun Hagino 	}
29582cd038dSYoshinobu Inoue 
2967fc91b3fSHajimu UMEMOTO 	switch(cmd) {
2977fc91b3fSHajimu UMEMOTO 	case SIOCAADDRCTL_POLICY:
2987fc91b3fSHajimu UMEMOTO 	case SIOCDADDRCTL_POLICY:
299acd3428bSRobert Watson 		if (td != NULL) {
300acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_ADDRCTRL6);
301acd3428bSRobert Watson 			if (error)
302acd3428bSRobert Watson 				return (error);
303acd3428bSRobert Watson 		}
3047fc91b3fSHajimu UMEMOTO 		return (in6_src_ioctl(cmd, data));
3057fc91b3fSHajimu UMEMOTO 	}
3067fc91b3fSHajimu UMEMOTO 
307686cdd19SJun-ichiro itojun Hagino 	if (ifp == NULL)
30882cd038dSYoshinobu Inoue 		return (EOPNOTSUPP);
30982cd038dSYoshinobu Inoue 
31082cd038dSYoshinobu Inoue 	switch (cmd) {
31182cd038dSYoshinobu Inoue 	case SIOCSNDFLUSH_IN6:
31282cd038dSYoshinobu Inoue 	case SIOCSPFXFLUSH_IN6:
31382cd038dSYoshinobu Inoue 	case SIOCSRTRFLUSH_IN6:
314686cdd19SJun-ichiro itojun Hagino 	case SIOCSDEFIFACE_IN6:
315686cdd19SJun-ichiro itojun Hagino 	case SIOCSIFINFO_FLAGS:
3169a1bde18SColin Percival 	case SIOCSIFINFO_IN6:
317acd3428bSRobert Watson 		if (td != NULL) {
318acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_ND6);
319acd3428bSRobert Watson 			if (error)
320acd3428bSRobert Watson 				return (error);
321acd3428bSRobert Watson 		}
32206cd0a3fSHajimu UMEMOTO 		/* FALLTHROUGH */
32333841545SHajimu UMEMOTO 	case OSIOCGIFINFO_IN6:
32482cd038dSYoshinobu Inoue 	case SIOCGIFINFO_IN6:
32582cd038dSYoshinobu Inoue 	case SIOCGDRLST_IN6:
32682cd038dSYoshinobu Inoue 	case SIOCGPRLST_IN6:
32782cd038dSYoshinobu Inoue 	case SIOCGNBRINFO_IN6:
328686cdd19SJun-ichiro itojun Hagino 	case SIOCGDEFIFACE_IN6:
32982cd038dSYoshinobu Inoue 		return (nd6_ioctl(cmd, data, ifp));
33099c750a8SKonstantin Belousov 
33199c750a8SKonstantin Belousov #ifdef COMPAT_FREEBSD32
33299c750a8SKonstantin Belousov 	case SIOCGDEFIFACE32_IN6:
33399c750a8SKonstantin Belousov 		{
33499c750a8SKonstantin Belousov 			struct in6_ndifreq ndif;
33599c750a8SKonstantin Belousov 			struct in6_ndifreq32 *ndif32;
33699c750a8SKonstantin Belousov 
33799c750a8SKonstantin Belousov 			error = nd6_ioctl(SIOCGDEFIFACE_IN6, (caddr_t)&ndif,
33899c750a8SKonstantin Belousov 			    ifp);
33999c750a8SKonstantin Belousov 			if (error)
34099c750a8SKonstantin Belousov 				return (error);
34199c750a8SKonstantin Belousov 			ndif32 = (struct in6_ndifreq32 *)data;
34299c750a8SKonstantin Belousov 			ndif32->ifindex = ndif.ifindex;
34399c750a8SKonstantin Belousov 			return (0);
34499c750a8SKonstantin Belousov 		}
34599c750a8SKonstantin Belousov #endif
34682cd038dSYoshinobu Inoue 	}
34782cd038dSYoshinobu Inoue 
34882cd038dSYoshinobu Inoue 	switch (cmd) {
34982cd038dSYoshinobu Inoue 	case SIOCSIFPREFIX_IN6:
35082cd038dSYoshinobu Inoue 	case SIOCDIFPREFIX_IN6:
35182cd038dSYoshinobu Inoue 	case SIOCAIFPREFIX_IN6:
35282cd038dSYoshinobu Inoue 	case SIOCCIFPREFIX_IN6:
35382cd038dSYoshinobu Inoue 	case SIOCSGIFPREFIX_IN6:
35482cd038dSYoshinobu Inoue 	case SIOCGIFPREFIX_IN6:
35533841545SHajimu UMEMOTO 		log(LOG_NOTICE,
35633841545SHajimu UMEMOTO 		    "prefix ioctls are now invalidated. "
35733841545SHajimu UMEMOTO 		    "please use ifconfig.\n");
35833841545SHajimu UMEMOTO 		return (EOPNOTSUPP);
35982cd038dSYoshinobu Inoue 	}
36082cd038dSYoshinobu Inoue 
36182cd038dSYoshinobu Inoue 	switch (cmd) {
362686cdd19SJun-ichiro itojun Hagino 	case SIOCSSCOPE6:
363acd3428bSRobert Watson 		if (td != NULL) {
364acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_SCOPE6);
365acd3428bSRobert Watson 			if (error)
366acd3428bSRobert Watson 				return (error);
367acd3428bSRobert Watson 		}
36831b1bfe1SHajimu UMEMOTO 		return (scope6_set(ifp,
36931b1bfe1SHajimu UMEMOTO 		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
370686cdd19SJun-ichiro itojun Hagino 	case SIOCGSCOPE6:
37131b1bfe1SHajimu UMEMOTO 		return (scope6_get(ifp,
37231b1bfe1SHajimu UMEMOTO 		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
373686cdd19SJun-ichiro itojun Hagino 	case SIOCGSCOPE6DEF:
37431b1bfe1SHajimu UMEMOTO 		return (scope6_get_default((struct scope6_id *)
37531b1bfe1SHajimu UMEMOTO 		    ifr->ifr_ifru.ifru_scope_id));
376686cdd19SJun-ichiro itojun Hagino 	}
377686cdd19SJun-ichiro itojun Hagino 
378686cdd19SJun-ichiro itojun Hagino 	switch (cmd) {
37982cd038dSYoshinobu Inoue 	case SIOCALIFADDR:
380acd3428bSRobert Watson 		if (td != NULL) {
38179ba3952SBjoern A. Zeeb 			error = priv_check(td, PRIV_NET_ADDIFADDR);
38279ba3952SBjoern A. Zeeb 			if (error)
38379ba3952SBjoern A. Zeeb 				return (error);
38479ba3952SBjoern A. Zeeb 		}
38579ba3952SBjoern A. Zeeb 		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
38679ba3952SBjoern A. Zeeb 
38779ba3952SBjoern A. Zeeb 	case SIOCDLIFADDR:
38879ba3952SBjoern A. Zeeb 		if (td != NULL) {
38979ba3952SBjoern A. Zeeb 			error = priv_check(td, PRIV_NET_DELIFADDR);
390acd3428bSRobert Watson 			if (error)
391acd3428bSRobert Watson 				return (error);
392acd3428bSRobert Watson 		}
39306cd0a3fSHajimu UMEMOTO 		/* FALLTHROUGH */
39482cd038dSYoshinobu Inoue 	case SIOCGLIFADDR:
395b40ce416SJulian Elischer 		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
39682cd038dSYoshinobu Inoue 	}
39782cd038dSYoshinobu Inoue 
39882cd038dSYoshinobu Inoue 	/*
39982cd038dSYoshinobu Inoue 	 * Find address for this interface, if it exists.
400743eee66SSUZUKI Shinsuke 	 *
401743eee66SSUZUKI Shinsuke 	 * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
402743eee66SSUZUKI Shinsuke 	 * only, and used the first interface address as the target of other
403743eee66SSUZUKI Shinsuke 	 * operations (without checking ifra_addr).  This was because netinet
404743eee66SSUZUKI Shinsuke 	 * code/API assumed at most 1 interface address per interface.
405743eee66SSUZUKI Shinsuke 	 * Since IPv6 allows a node to assign multiple addresses
406743eee66SSUZUKI Shinsuke 	 * on a single interface, we almost always look and check the
407743eee66SSUZUKI Shinsuke 	 * presence of ifra_addr, and reject invalid ones here.
408743eee66SSUZUKI Shinsuke 	 * It also decreases duplicated code among SIOC*_IN6 operations.
40982cd038dSYoshinobu Inoue 	 */
410743eee66SSUZUKI Shinsuke 	switch (cmd) {
411743eee66SSUZUKI Shinsuke 	case SIOCAIFADDR_IN6:
412743eee66SSUZUKI Shinsuke 	case SIOCSIFPHYADDR_IN6:
413743eee66SSUZUKI Shinsuke 		sa6 = &ifra->ifra_addr;
414743eee66SSUZUKI Shinsuke 		break;
415743eee66SSUZUKI Shinsuke 	case SIOCSIFADDR_IN6:
416743eee66SSUZUKI Shinsuke 	case SIOCGIFADDR_IN6:
417743eee66SSUZUKI Shinsuke 	case SIOCSIFDSTADDR_IN6:
418743eee66SSUZUKI Shinsuke 	case SIOCSIFNETMASK_IN6:
419743eee66SSUZUKI Shinsuke 	case SIOCGIFDSTADDR_IN6:
420743eee66SSUZUKI Shinsuke 	case SIOCGIFNETMASK_IN6:
421743eee66SSUZUKI Shinsuke 	case SIOCDIFADDR_IN6:
422743eee66SSUZUKI Shinsuke 	case SIOCGIFPSRCADDR_IN6:
423743eee66SSUZUKI Shinsuke 	case SIOCGIFPDSTADDR_IN6:
424743eee66SSUZUKI Shinsuke 	case SIOCGIFAFLAG_IN6:
425743eee66SSUZUKI Shinsuke 	case SIOCSNDFLUSH_IN6:
426743eee66SSUZUKI Shinsuke 	case SIOCSPFXFLUSH_IN6:
427743eee66SSUZUKI Shinsuke 	case SIOCSRTRFLUSH_IN6:
428743eee66SSUZUKI Shinsuke 	case SIOCGIFALIFETIME_IN6:
429743eee66SSUZUKI Shinsuke 	case SIOCSIFALIFETIME_IN6:
430743eee66SSUZUKI Shinsuke 	case SIOCGIFSTAT_IN6:
431743eee66SSUZUKI Shinsuke 	case SIOCGIFSTAT_ICMP6:
432743eee66SSUZUKI Shinsuke 		sa6 = &ifr->ifr_addr;
433743eee66SSUZUKI Shinsuke 		break;
434743eee66SSUZUKI Shinsuke 	default:
435743eee66SSUZUKI Shinsuke 		sa6 = NULL;
436743eee66SSUZUKI Shinsuke 		break;
437743eee66SSUZUKI Shinsuke 	}
438743eee66SSUZUKI Shinsuke 	if (sa6 && sa6->sin6_family == AF_INET6) {
439743eee66SSUZUKI Shinsuke 		if (sa6->sin6_scope_id != 0)
440743eee66SSUZUKI Shinsuke 			error = sa6_embedscope(sa6, 0);
441a1f7e5f8SHajimu UMEMOTO 		else
442743eee66SSUZUKI Shinsuke 			error = in6_setscope(&sa6->sin6_addr, ifp, NULL);
443a1f7e5f8SHajimu UMEMOTO 		if (error != 0)
444a1f7e5f8SHajimu UMEMOTO 			return (error);
445b89e82ddSJamie Gritton 		if (td != NULL && (error = prison_check_ip6(td->td_ucred,
446b89e82ddSJamie Gritton 		    &sa6->sin6_addr)) != 0)
447b89e82ddSJamie Gritton 			return (error);
448743eee66SSUZUKI Shinsuke 		ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
449743eee66SSUZUKI Shinsuke 	} else
450743eee66SSUZUKI Shinsuke 		ia = NULL;
45182cd038dSYoshinobu Inoue 
45282cd038dSYoshinobu Inoue 	switch (cmd) {
45382cd038dSYoshinobu Inoue 	case SIOCSIFADDR_IN6:
45482cd038dSYoshinobu Inoue 	case SIOCSIFDSTADDR_IN6:
455686cdd19SJun-ichiro itojun Hagino 	case SIOCSIFNETMASK_IN6:
456686cdd19SJun-ichiro itojun Hagino 		/*
457686cdd19SJun-ichiro itojun Hagino 		 * Since IPv6 allows a node to assign multiple addresses
4582ce62dceSSUZUKI Shinsuke 		 * on a single interface, SIOCSIFxxx ioctls are deprecated.
459686cdd19SJun-ichiro itojun Hagino 		 */
46033841545SHajimu UMEMOTO 		/* we decided to obsolete this command (20000704) */
4618c0fec80SRobert Watson 		error = EINVAL;
4628c0fec80SRobert Watson 		goto out;
46333841545SHajimu UMEMOTO 
46433841545SHajimu UMEMOTO 	case SIOCDIFADDR_IN6:
46533841545SHajimu UMEMOTO 		/*
46633841545SHajimu UMEMOTO 		 * for IPv4, we look for existing in_ifaddr here to allow
4672ce62dceSSUZUKI Shinsuke 		 * "ifconfig if0 delete" to remove the first IPv4 address on
4682ce62dceSSUZUKI Shinsuke 		 * the interface.  For IPv6, as the spec allows multiple
4692ce62dceSSUZUKI Shinsuke 		 * interface address from the day one, we consider "remove the
4702ce62dceSSUZUKI Shinsuke 		 * first one" semantics to be not preferable.
47133841545SHajimu UMEMOTO 		 */
4728c0fec80SRobert Watson 		if (ia == NULL) {
4738c0fec80SRobert Watson 			error = EADDRNOTAVAIL;
4748c0fec80SRobert Watson 			goto out;
4758c0fec80SRobert Watson 		}
47633841545SHajimu UMEMOTO 		/* FALLTHROUGH */
47733841545SHajimu UMEMOTO 	case SIOCAIFADDR_IN6:
47833841545SHajimu UMEMOTO 		/*
47933841545SHajimu UMEMOTO 		 * We always require users to specify a valid IPv6 address for
48033841545SHajimu UMEMOTO 		 * the corresponding operation.
48133841545SHajimu UMEMOTO 		 */
48233841545SHajimu UMEMOTO 		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
4838c0fec80SRobert Watson 		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) {
4848c0fec80SRobert Watson 			error = EAFNOSUPPORT;
4858c0fec80SRobert Watson 			goto out;
4868c0fec80SRobert Watson 		}
487acd3428bSRobert Watson 
488acd3428bSRobert Watson 		if (td != NULL) {
48979ba3952SBjoern A. Zeeb 			error = priv_check(td, (cmd == SIOCDIFADDR_IN6) ?
49079ba3952SBjoern A. Zeeb 			    PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR);
491acd3428bSRobert Watson 			if (error)
4928c0fec80SRobert Watson 				goto out;
493acd3428bSRobert Watson 		}
49482cd038dSYoshinobu Inoue 		break;
49582cd038dSYoshinobu Inoue 
49682cd038dSYoshinobu Inoue 	case SIOCGIFADDR_IN6:
49782cd038dSYoshinobu Inoue 		/* This interface is basically deprecated. use SIOCGIFCONF. */
49806cd0a3fSHajimu UMEMOTO 		/* FALLTHROUGH */
49982cd038dSYoshinobu Inoue 	case SIOCGIFAFLAG_IN6:
50082cd038dSYoshinobu Inoue 	case SIOCGIFNETMASK_IN6:
50182cd038dSYoshinobu Inoue 	case SIOCGIFDSTADDR_IN6:
50282cd038dSYoshinobu Inoue 	case SIOCGIFALIFETIME_IN6:
50382cd038dSYoshinobu Inoue 		/* must think again about its semantics */
5048c0fec80SRobert Watson 		if (ia == NULL) {
5058c0fec80SRobert Watson 			error = EADDRNOTAVAIL;
5068c0fec80SRobert Watson 			goto out;
5078c0fec80SRobert Watson 		}
50882cd038dSYoshinobu Inoue 		break;
5098c0fec80SRobert Watson 
51082cd038dSYoshinobu Inoue 	case SIOCSIFALIFETIME_IN6:
51182cd038dSYoshinobu Inoue 	    {
51282cd038dSYoshinobu Inoue 		struct in6_addrlifetime *lt;
51382cd038dSYoshinobu Inoue 
514acd3428bSRobert Watson 		if (td != NULL) {
515acd3428bSRobert Watson 			error = priv_check(td, PRIV_NETINET_ALIFETIME6);
516acd3428bSRobert Watson 			if (error)
5178c0fec80SRobert Watson 				goto out;
518acd3428bSRobert Watson 		}
5198c0fec80SRobert Watson 		if (ia == NULL) {
5208c0fec80SRobert Watson 			error = EADDRNOTAVAIL;
5218c0fec80SRobert Watson 			goto out;
5228c0fec80SRobert Watson 		}
52382cd038dSYoshinobu Inoue 		/* sanity for overflow - beware unsigned */
52482cd038dSYoshinobu Inoue 		lt = &ifr->ifr_ifru.ifru_lifetime;
52559aecc96SHajimu UMEMOTO 		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
526*7d26db17SHiroki Sato 		    lt->ia6t_vltime + time_uptime < time_uptime) {
5278c0fec80SRobert Watson 			error = EINVAL;
5288c0fec80SRobert Watson 			goto out;
52982cd038dSYoshinobu Inoue 		}
53059aecc96SHajimu UMEMOTO 		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
531*7d26db17SHiroki Sato 		    lt->ia6t_pltime + time_uptime < time_uptime) {
5328c0fec80SRobert Watson 			error = EINVAL;
5338c0fec80SRobert Watson 			goto out;
53482cd038dSYoshinobu Inoue 		}
53582cd038dSYoshinobu Inoue 		break;
53682cd038dSYoshinobu Inoue 	    }
53782cd038dSYoshinobu Inoue 	}
53882cd038dSYoshinobu Inoue 
53982cd038dSYoshinobu Inoue 	switch (cmd) {
54082cd038dSYoshinobu Inoue 	case SIOCGIFADDR_IN6:
54182cd038dSYoshinobu Inoue 		ifr->ifr_addr = ia->ia_addr;
542a1f7e5f8SHajimu UMEMOTO 		if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
5438c0fec80SRobert Watson 			goto out;
54482cd038dSYoshinobu Inoue 		break;
54582cd038dSYoshinobu Inoue 
54682cd038dSYoshinobu Inoue 	case SIOCGIFDSTADDR_IN6:
5478c0fec80SRobert Watson 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
5488c0fec80SRobert Watson 			error = EINVAL;
5498c0fec80SRobert Watson 			goto out;
5508c0fec80SRobert Watson 		}
551686cdd19SJun-ichiro itojun Hagino 		/*
552686cdd19SJun-ichiro itojun Hagino 		 * XXX: should we check if ifa_dstaddr is NULL and return
553686cdd19SJun-ichiro itojun Hagino 		 * an error?
554686cdd19SJun-ichiro itojun Hagino 		 */
55582cd038dSYoshinobu Inoue 		ifr->ifr_dstaddr = ia->ia_dstaddr;
556a1f7e5f8SHajimu UMEMOTO 		if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
5578c0fec80SRobert Watson 			goto out;
55882cd038dSYoshinobu Inoue 		break;
55982cd038dSYoshinobu Inoue 
56082cd038dSYoshinobu Inoue 	case SIOCGIFNETMASK_IN6:
56182cd038dSYoshinobu Inoue 		ifr->ifr_addr = ia->ia_prefixmask;
56282cd038dSYoshinobu Inoue 		break;
56382cd038dSYoshinobu Inoue 
56482cd038dSYoshinobu Inoue 	case SIOCGIFAFLAG_IN6:
56582cd038dSYoshinobu Inoue 		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
56682cd038dSYoshinobu Inoue 		break;
56782cd038dSYoshinobu Inoue 
56882cd038dSYoshinobu Inoue 	case SIOCGIFSTAT_IN6:
5698c0fec80SRobert Watson 		if (ifp == NULL) {
5708c0fec80SRobert Watson 			error = EINVAL;
5718c0fec80SRobert Watson 			goto out;
5728c0fec80SRobert Watson 		}
5732841260cSAndrey V. Elsukov 		COUNTER_ARRAY_COPY(((struct in6_ifextra *)
5742841260cSAndrey V. Elsukov 		    ifp->if_afdata[AF_INET6])->in6_ifstat,
5752841260cSAndrey V. Elsukov 		    &ifr->ifr_ifru.ifru_stat,
5762841260cSAndrey V. Elsukov 		    sizeof(struct in6_ifstat) / sizeof(uint64_t));
57782cd038dSYoshinobu Inoue 		break;
57882cd038dSYoshinobu Inoue 
57982cd038dSYoshinobu Inoue 	case SIOCGIFSTAT_ICMP6:
5808c0fec80SRobert Watson 		if (ifp == NULL) {
5818c0fec80SRobert Watson 			error = EINVAL;
5828c0fec80SRobert Watson 			goto out;
5838c0fec80SRobert Watson 		}
5842841260cSAndrey V. Elsukov 		COUNTER_ARRAY_COPY(((struct in6_ifextra *)
5852841260cSAndrey V. Elsukov 		    ifp->if_afdata[AF_INET6])->icmp6_ifstat,
5862841260cSAndrey V. Elsukov 		    &ifr->ifr_ifru.ifru_icmp6stat,
5872841260cSAndrey V. Elsukov 		    sizeof(struct icmp6_ifstat) / sizeof(uint64_t));
58882cd038dSYoshinobu Inoue 		break;
58982cd038dSYoshinobu Inoue 
59082cd038dSYoshinobu Inoue 	case SIOCGIFALIFETIME_IN6:
59182cd038dSYoshinobu Inoue 		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
592743eee66SSUZUKI Shinsuke 		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
593743eee66SSUZUKI Shinsuke 			time_t maxexpire;
594743eee66SSUZUKI Shinsuke 			struct in6_addrlifetime *retlt =
595743eee66SSUZUKI Shinsuke 			    &ifr->ifr_ifru.ifru_lifetime;
596743eee66SSUZUKI Shinsuke 
597743eee66SSUZUKI Shinsuke 			/*
598743eee66SSUZUKI Shinsuke 			 * XXX: adjust expiration time assuming time_t is
599743eee66SSUZUKI Shinsuke 			 * signed.
600743eee66SSUZUKI Shinsuke 			 */
601743eee66SSUZUKI Shinsuke 			maxexpire = (-1) &
60236dc24e6SSUZUKI Shinsuke 			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
603743eee66SSUZUKI Shinsuke 			if (ia->ia6_lifetime.ia6t_vltime <
604743eee66SSUZUKI Shinsuke 			    maxexpire - ia->ia6_updatetime) {
605743eee66SSUZUKI Shinsuke 				retlt->ia6t_expire = ia->ia6_updatetime +
606743eee66SSUZUKI Shinsuke 				    ia->ia6_lifetime.ia6t_vltime;
607743eee66SSUZUKI Shinsuke 			} else
608743eee66SSUZUKI Shinsuke 				retlt->ia6t_expire = maxexpire;
609743eee66SSUZUKI Shinsuke 		}
610743eee66SSUZUKI Shinsuke 		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
611743eee66SSUZUKI Shinsuke 			time_t maxexpire;
612743eee66SSUZUKI Shinsuke 			struct in6_addrlifetime *retlt =
613743eee66SSUZUKI Shinsuke 			    &ifr->ifr_ifru.ifru_lifetime;
614743eee66SSUZUKI Shinsuke 
615743eee66SSUZUKI Shinsuke 			/*
616743eee66SSUZUKI Shinsuke 			 * XXX: adjust expiration time assuming time_t is
617743eee66SSUZUKI Shinsuke 			 * signed.
618743eee66SSUZUKI Shinsuke 			 */
619743eee66SSUZUKI Shinsuke 			maxexpire = (-1) &
62036dc24e6SSUZUKI Shinsuke 			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
621743eee66SSUZUKI Shinsuke 			if (ia->ia6_lifetime.ia6t_pltime <
622743eee66SSUZUKI Shinsuke 			    maxexpire - ia->ia6_updatetime) {
623743eee66SSUZUKI Shinsuke 				retlt->ia6t_preferred = ia->ia6_updatetime +
624743eee66SSUZUKI Shinsuke 				    ia->ia6_lifetime.ia6t_pltime;
625743eee66SSUZUKI Shinsuke 			} else
626743eee66SSUZUKI Shinsuke 				retlt->ia6t_preferred = maxexpire;
627743eee66SSUZUKI Shinsuke 		}
62882cd038dSYoshinobu Inoue 		break;
62982cd038dSYoshinobu Inoue 
63082cd038dSYoshinobu Inoue 	case SIOCSIFALIFETIME_IN6:
63182cd038dSYoshinobu Inoue 		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
63282cd038dSYoshinobu Inoue 		/* for sanity */
63382cd038dSYoshinobu Inoue 		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
63482cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_expire =
635*7d26db17SHiroki Sato 				time_uptime + ia->ia6_lifetime.ia6t_vltime;
63682cd038dSYoshinobu Inoue 		} else
63782cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_expire = 0;
63882cd038dSYoshinobu Inoue 		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
63982cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_preferred =
640*7d26db17SHiroki Sato 				time_uptime + ia->ia6_lifetime.ia6t_pltime;
64182cd038dSYoshinobu Inoue 		} else
64282cd038dSYoshinobu Inoue 			ia->ia6_lifetime.ia6t_preferred = 0;
64382cd038dSYoshinobu Inoue 		break;
64482cd038dSYoshinobu Inoue 
64582cd038dSYoshinobu Inoue 	case SIOCAIFADDR_IN6:
64633841545SHajimu UMEMOTO 	{
6478c0fec80SRobert Watson 		int i;
648743eee66SSUZUKI Shinsuke 		struct nd_prefixctl pr0;
649743eee66SSUZUKI Shinsuke 		struct nd_prefix *pr;
65082cd038dSYoshinobu Inoue 
65133841545SHajimu UMEMOTO 		/*
65233841545SHajimu UMEMOTO 		 * first, make or update the interface address structure,
65333841545SHajimu UMEMOTO 		 * and link it to the list.
65433841545SHajimu UMEMOTO 		 */
655743eee66SSUZUKI Shinsuke 		if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
6568c0fec80SRobert Watson 			goto out;
6578c0fec80SRobert Watson 		if (ia != NULL)
6588c0fec80SRobert Watson 			ifa_free(&ia->ia_ifa);
659797df30dSSUZUKI Shinsuke 		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
660797df30dSSUZUKI Shinsuke 		    == NULL) {
661797df30dSSUZUKI Shinsuke 			/*
662797df30dSSUZUKI Shinsuke 			 * this can happen when the user specify the 0 valid
663797df30dSSUZUKI Shinsuke 			 * lifetime.
664797df30dSSUZUKI Shinsuke 			 */
665797df30dSSUZUKI Shinsuke 			break;
666797df30dSSUZUKI Shinsuke 		}
66782cd038dSYoshinobu Inoue 
66871212473SGleb Smirnoff 		if (cmd == ocmd && ifra->ifra_vhid > 0) {
66908b68b0eSGleb Smirnoff 			if (carp_attach_p != NULL)
67008b68b0eSGleb Smirnoff 				error = (*carp_attach_p)(&ia->ia_ifa,
67108b68b0eSGleb Smirnoff 				    ifra->ifra_vhid);
67208b68b0eSGleb Smirnoff 			else
67308b68b0eSGleb Smirnoff 				error = EPROTONOSUPPORT;
67408b68b0eSGleb Smirnoff 			if (error)
67508b68b0eSGleb Smirnoff 				goto out;
67608b68b0eSGleb Smirnoff 			else
67708b68b0eSGleb Smirnoff 				carp_attached = 1;
67808b68b0eSGleb Smirnoff 		}
67908b68b0eSGleb Smirnoff 
68033841545SHajimu UMEMOTO 		/*
68133841545SHajimu UMEMOTO 		 * then, make the prefix on-link on the interface.
68233841545SHajimu UMEMOTO 		 * XXX: we'd rather create the prefix before the address, but
68333841545SHajimu UMEMOTO 		 * we need at least one address to install the corresponding
68433841545SHajimu UMEMOTO 		 * interface route, so we configure the address first.
68533841545SHajimu UMEMOTO 		 */
68633841545SHajimu UMEMOTO 
68733841545SHajimu UMEMOTO 		/*
68833841545SHajimu UMEMOTO 		 * convert mask to prefix length (prefixmask has already
68933841545SHajimu UMEMOTO 		 * been validated in in6_update_ifa().
69033841545SHajimu UMEMOTO 		 */
69133841545SHajimu UMEMOTO 		bzero(&pr0, sizeof(pr0));
69233841545SHajimu UMEMOTO 		pr0.ndpr_ifp = ifp;
69333841545SHajimu UMEMOTO 		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
69433841545SHajimu UMEMOTO 		    NULL);
69506cd0a3fSHajimu UMEMOTO 		if (pr0.ndpr_plen == 128) {
69633841545SHajimu UMEMOTO 			break;	/* we don't need to install a host route. */
69706cd0a3fSHajimu UMEMOTO 		}
69833841545SHajimu UMEMOTO 		pr0.ndpr_prefix = ifra->ifra_addr;
69933841545SHajimu UMEMOTO 		/* apply the mask for safety. */
70033841545SHajimu UMEMOTO 		for (i = 0; i < 4; i++) {
70133841545SHajimu UMEMOTO 			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
70233841545SHajimu UMEMOTO 			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
70333841545SHajimu UMEMOTO 		}
70433841545SHajimu UMEMOTO 		/*
70588ff5695SSUZUKI Shinsuke 		 * XXX: since we don't have an API to set prefix (not address)
70688ff5695SSUZUKI Shinsuke 		 * lifetimes, we just use the same lifetimes as addresses.
70788ff5695SSUZUKI Shinsuke 		 * The (temporarily) installed lifetimes can be overridden by
70888ff5695SSUZUKI Shinsuke 		 * later advertised RAs (when accept_rtadv is non 0), which is
70988ff5695SSUZUKI Shinsuke 		 * an intended behavior.
71033841545SHajimu UMEMOTO 		 */
71133841545SHajimu UMEMOTO 		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
71233841545SHajimu UMEMOTO 		pr0.ndpr_raf_auto =
71333841545SHajimu UMEMOTO 		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
71433841545SHajimu UMEMOTO 		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
71533841545SHajimu UMEMOTO 		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
71633841545SHajimu UMEMOTO 
71706cd0a3fSHajimu UMEMOTO 		/* add the prefix if not yet. */
71833841545SHajimu UMEMOTO 		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
71933841545SHajimu UMEMOTO 			/*
72033841545SHajimu UMEMOTO 			 * nd6_prelist_add will install the corresponding
72133841545SHajimu UMEMOTO 			 * interface route.
72233841545SHajimu UMEMOTO 			 */
72308b68b0eSGleb Smirnoff 			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) {
72408b68b0eSGleb Smirnoff 				if (carp_attached)
72508b68b0eSGleb Smirnoff 					(*carp_detach_p)(&ia->ia_ifa);
7268c0fec80SRobert Watson 				goto out;
72708b68b0eSGleb Smirnoff 			}
72833841545SHajimu UMEMOTO 			if (pr == NULL) {
72908b68b0eSGleb Smirnoff 				if (carp_attached)
73008b68b0eSGleb Smirnoff 					(*carp_detach_p)(&ia->ia_ifa);
73106cd0a3fSHajimu UMEMOTO 				log(LOG_ERR, "nd6_prelist_add succeeded but "
73233841545SHajimu UMEMOTO 				    "no prefix\n");
7338c0fec80SRobert Watson 				error = EINVAL;
7348c0fec80SRobert Watson 				goto out;
73533841545SHajimu UMEMOTO 			}
73633841545SHajimu UMEMOTO 		}
737797df30dSSUZUKI Shinsuke 
738797df30dSSUZUKI Shinsuke 		/* relate the address to the prefix */
739797df30dSSUZUKI Shinsuke 		if (ia->ia6_ndpr == NULL) {
74033841545SHajimu UMEMOTO 			ia->ia6_ndpr = pr;
74133841545SHajimu UMEMOTO 			pr->ndpr_refcnt++;
74233841545SHajimu UMEMOTO 
74333841545SHajimu UMEMOTO 			/*
744797df30dSSUZUKI Shinsuke 			 * If this is the first autoconf address from the
745797df30dSSUZUKI Shinsuke 			 * prefix, create a temporary address as well
746797df30dSSUZUKI Shinsuke 			 * (when required).
74733841545SHajimu UMEMOTO 			 */
748797df30dSSUZUKI Shinsuke 			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) &&
749603724d3SBjoern A. Zeeb 			    V_ip6_use_tempaddr && pr->ndpr_refcnt == 1) {
75033841545SHajimu UMEMOTO 				int e;
751743eee66SSUZUKI Shinsuke 				if ((e = in6_tmpifadd(ia, 1, 0)) != 0) {
752797df30dSSUZUKI Shinsuke 					log(LOG_NOTICE, "in6_control: failed "
753797df30dSSUZUKI Shinsuke 					    "to create a temporary address, "
7544835e2c7SHajimu UMEMOTO 					    "errno=%d\n", e);
75533841545SHajimu UMEMOTO 				}
75633841545SHajimu UMEMOTO 			}
75733841545SHajimu UMEMOTO 		}
75833841545SHajimu UMEMOTO 
75933841545SHajimu UMEMOTO 		/*
760797df30dSSUZUKI Shinsuke 		 * this might affect the status of autoconfigured addresses,
761797df30dSSUZUKI Shinsuke 		 * that is, this address might make other addresses detached.
76233841545SHajimu UMEMOTO 		 */
76333841545SHajimu UMEMOTO 		pfxlist_onlink_check();
76477bc4985SHiroki Sato 		if (error == 0 && ia) {
76577bc4985SHiroki Sato 			if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
76677bc4985SHiroki Sato 				/*
76777bc4985SHiroki Sato 				 * Try to clear the flag when a new
76877bc4985SHiroki Sato 				 * IPv6 address is added onto an
76977bc4985SHiroki Sato 				 * IFDISABLED interface and it
77077bc4985SHiroki Sato 				 * succeeds.
77177bc4985SHiroki Sato 				 */
77277bc4985SHiroki Sato 				struct in6_ndireq nd;
77377bc4985SHiroki Sato 
77477bc4985SHiroki Sato 				memset(&nd, 0, sizeof(nd));
77577bc4985SHiroki Sato 				nd.ndi.flags = ND_IFINFO(ifp)->flags;
77677bc4985SHiroki Sato 				nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
77777bc4985SHiroki Sato 				if (nd6_ioctl(SIOCSIFINFO_FLAGS,
77877bc4985SHiroki Sato 				    (caddr_t)&nd, ifp) < 0)
77977bc4985SHiroki Sato 					log(LOG_NOTICE, "SIOCAIFADDR_IN6: "
78077bc4985SHiroki Sato 					    "SIOCSIFINFO_FLAGS for -ifdisabled "
78177bc4985SHiroki Sato 					    "failed.");
78277bc4985SHiroki Sato 				/*
78377bc4985SHiroki Sato 				 * Ignore failure of clearing the flag
78477bc4985SHiroki Sato 				 * intentionally.  The failure means
78577bc4985SHiroki Sato 				 * address duplication was detected.
78677bc4985SHiroki Sato 				 */
78777bc4985SHiroki Sato 			}
78825a4adceSMax Laier 			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
78977bc4985SHiroki Sato 		}
79033841545SHajimu UMEMOTO 		break;
79133841545SHajimu UMEMOTO 	}
79233841545SHajimu UMEMOTO 
79333841545SHajimu UMEMOTO 	case SIOCDIFADDR_IN6:
79433841545SHajimu UMEMOTO 	{
795743eee66SSUZUKI Shinsuke 		struct nd_prefix *pr;
79633841545SHajimu UMEMOTO 
79733841545SHajimu UMEMOTO 		/*
79833841545SHajimu UMEMOTO 		 * If the address being deleted is the only one that owns
79933841545SHajimu UMEMOTO 		 * the corresponding prefix, expire the prefix as well.
80006cd0a3fSHajimu UMEMOTO 		 * XXX: theoretically, we don't have to worry about such
80133841545SHajimu UMEMOTO 		 * relationship, since we separate the address management
80233841545SHajimu UMEMOTO 		 * and the prefix management.  We do this, however, to provide
80333841545SHajimu UMEMOTO 		 * as much backward compatibility as possible in terms of
80433841545SHajimu UMEMOTO 		 * the ioctl operation.
805797df30dSSUZUKI Shinsuke 		 * Note that in6_purgeaddr() will decrement ndpr_refcnt.
80633841545SHajimu UMEMOTO 		 */
807797df30dSSUZUKI Shinsuke 		pr = ia->ia6_ndpr;
80833841545SHajimu UMEMOTO 		in6_purgeaddr(&ia->ia_ifa);
809797df30dSSUZUKI Shinsuke 		if (pr && pr->ndpr_refcnt == 0)
810797df30dSSUZUKI Shinsuke 			prelist_remove(pr);
81125a4adceSMax Laier 		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
81233841545SHajimu UMEMOTO 		break;
81333841545SHajimu UMEMOTO 	}
81433841545SHajimu UMEMOTO 
81533841545SHajimu UMEMOTO 	default:
8168c0fec80SRobert Watson 		if (ifp == NULL || ifp->if_ioctl == 0) {
8178c0fec80SRobert Watson 			error = EOPNOTSUPP;
8188c0fec80SRobert Watson 			goto out;
8198c0fec80SRobert Watson 		}
8208c0fec80SRobert Watson 		error = (*ifp->if_ioctl)(ifp, cmd, data);
8218c0fec80SRobert Watson 		goto out;
82233841545SHajimu UMEMOTO 	}
82333841545SHajimu UMEMOTO 
8248c0fec80SRobert Watson 	error = 0;
8258c0fec80SRobert Watson out:
8268c0fec80SRobert Watson 	if (ia != NULL)
8278c0fec80SRobert Watson 		ifa_free(&ia->ia_ifa);
8288c0fec80SRobert Watson 	return (error);
82933841545SHajimu UMEMOTO }
83033841545SHajimu UMEMOTO 
83181d5d46bSBjoern A. Zeeb 
83233841545SHajimu UMEMOTO /*
8335490110cSBjoern A. Zeeb  * Join necessary multicast groups.  Factored out from in6_update_ifa().
8345490110cSBjoern A. Zeeb  * This entire work should only be done once, for the default FIB.
8355490110cSBjoern A. Zeeb  */
8365490110cSBjoern A. Zeeb static int
8375490110cSBjoern A. Zeeb in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra,
8385490110cSBjoern A. Zeeb     struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol)
8395490110cSBjoern A. Zeeb {
8405490110cSBjoern A. Zeeb 	char ip6buf[INET6_ADDRSTRLEN];
8415490110cSBjoern A. Zeeb 	struct sockaddr_in6 mltaddr, mltmask;
8425490110cSBjoern A. Zeeb 	struct in6_addr llsol;
8435490110cSBjoern A. Zeeb 	struct in6_multi_mship *imm;
8445490110cSBjoern A. Zeeb 	struct rtentry *rt;
8455490110cSBjoern A. Zeeb 	int delay, error;
8465490110cSBjoern A. Zeeb 
8475490110cSBjoern A. Zeeb 	KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__));
8485490110cSBjoern A. Zeeb 
8495490110cSBjoern A. Zeeb 	/* Join solicited multicast addr for new host id. */
8505490110cSBjoern A. Zeeb 	bzero(&llsol, sizeof(struct in6_addr));
8515490110cSBjoern A. Zeeb 	llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
8525490110cSBjoern A. Zeeb 	llsol.s6_addr32[1] = 0;
8535490110cSBjoern A. Zeeb 	llsol.s6_addr32[2] = htonl(1);
8545490110cSBjoern A. Zeeb 	llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
8555490110cSBjoern A. Zeeb 	llsol.s6_addr8[12] = 0xff;
8565490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
8575490110cSBjoern A. Zeeb 		/* XXX: should not happen */
8585490110cSBjoern A. Zeeb 		log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
8595490110cSBjoern A. Zeeb 		goto cleanup;
8605490110cSBjoern A. Zeeb 	}
8615490110cSBjoern A. Zeeb 	delay = 0;
8625490110cSBjoern A. Zeeb 	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
8635490110cSBjoern A. Zeeb 		/*
8645490110cSBjoern A. Zeeb 		 * We need a random delay for DAD on the address being
8655490110cSBjoern A. Zeeb 		 * configured.  It also means delaying transmission of the
8665490110cSBjoern A. Zeeb 		 * corresponding MLD report to avoid report collision.
8675490110cSBjoern A. Zeeb 		 * [RFC 4861, Section 6.3.7]
8685490110cSBjoern A. Zeeb 		 */
8695490110cSBjoern A. Zeeb 		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
8705490110cSBjoern A. Zeeb 	}
8715490110cSBjoern A. Zeeb 	imm = in6_joingroup(ifp, &llsol, &error, delay);
8725490110cSBjoern A. Zeeb 	if (imm == NULL) {
8735490110cSBjoern A. Zeeb 		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
8745490110cSBjoern A. Zeeb 		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &llsol),
8755490110cSBjoern A. Zeeb 		    if_name(ifp), error));
8765490110cSBjoern A. Zeeb 		goto cleanup;
8775490110cSBjoern A. Zeeb 	}
8785490110cSBjoern A. Zeeb 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
8795490110cSBjoern A. Zeeb 	*in6m_sol = imm->i6mm_maddr;
8805490110cSBjoern A. Zeeb 
8815490110cSBjoern A. Zeeb 	bzero(&mltmask, sizeof(mltmask));
8825490110cSBjoern A. Zeeb 	mltmask.sin6_len = sizeof(struct sockaddr_in6);
8835490110cSBjoern A. Zeeb 	mltmask.sin6_family = AF_INET6;
8845490110cSBjoern A. Zeeb 	mltmask.sin6_addr = in6mask32;
8855490110cSBjoern A. Zeeb #define	MLTMASK_LEN  4	/* mltmask's masklen (=32bit=4octet) */
8865490110cSBjoern A. Zeeb 
8875490110cSBjoern A. Zeeb 	/*
8885490110cSBjoern A. Zeeb 	 * Join link-local all-nodes address.
8895490110cSBjoern A. Zeeb 	 */
8905490110cSBjoern A. Zeeb 	bzero(&mltaddr, sizeof(mltaddr));
8915490110cSBjoern A. Zeeb 	mltaddr.sin6_len = sizeof(struct sockaddr_in6);
8925490110cSBjoern A. Zeeb 	mltaddr.sin6_family = AF_INET6;
8935490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_linklocal_allnodes;
8945490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
8955490110cSBjoern A. Zeeb 		goto cleanup; /* XXX: should not fail */
8965490110cSBjoern A. Zeeb 
8975490110cSBjoern A. Zeeb 	/*
8985490110cSBjoern A. Zeeb 	 * XXX: do we really need this automatic routes?  We should probably
8995490110cSBjoern A. Zeeb 	 * reconsider this stuff.  Most applications actually do not need the
9005490110cSBjoern A. Zeeb 	 * routes, since they usually specify the outgoing interface.
9015490110cSBjoern A. Zeeb 	 */
90281d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
9035490110cSBjoern A. Zeeb 	if (rt != NULL) {
9045490110cSBjoern A. Zeeb 		/* XXX: only works in !SCOPEDROUTING case. */
9055490110cSBjoern A. Zeeb 		if (memcmp(&mltaddr.sin6_addr,
9065490110cSBjoern A. Zeeb 		    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
9075490110cSBjoern A. Zeeb 		    MLTMASK_LEN)) {
9085490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
9095490110cSBjoern A. Zeeb 			rt = NULL;
9105490110cSBjoern A. Zeeb 		}
9115490110cSBjoern A. Zeeb 	}
9125490110cSBjoern A. Zeeb 	if (rt == NULL) {
91381d5d46bSBjoern A. Zeeb 		error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
9145490110cSBjoern A. Zeeb 		    (struct sockaddr *)&ia->ia_addr,
9155490110cSBjoern A. Zeeb 		    (struct sockaddr *)&mltmask, RTF_UP,
91681d5d46bSBjoern A. Zeeb 		    (struct rtentry **)0, RT_DEFAULT_FIB);
9175490110cSBjoern A. Zeeb 		if (error)
9185490110cSBjoern A. Zeeb 			goto cleanup;
9195490110cSBjoern A. Zeeb 	} else
9205490110cSBjoern A. Zeeb 		RTFREE_LOCKED(rt);
9215490110cSBjoern A. Zeeb 
9225490110cSBjoern A. Zeeb 	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
9235490110cSBjoern A. Zeeb 	if (imm == NULL) {
9245490110cSBjoern A. Zeeb 		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
9255490110cSBjoern A. Zeeb 		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
9265490110cSBjoern A. Zeeb 		    &mltaddr.sin6_addr), if_name(ifp), error));
9275490110cSBjoern A. Zeeb 		goto cleanup;
9285490110cSBjoern A. Zeeb 	}
9295490110cSBjoern A. Zeeb 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
9305490110cSBjoern A. Zeeb 
9315490110cSBjoern A. Zeeb 	/*
9325490110cSBjoern A. Zeeb 	 * Join node information group address.
9335490110cSBjoern A. Zeeb 	 */
9345490110cSBjoern A. Zeeb 	delay = 0;
9355490110cSBjoern A. Zeeb 	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
9365490110cSBjoern A. Zeeb 		/*
9375490110cSBjoern A. Zeeb 		 * The spec does not say anything about delay for this group,
9385490110cSBjoern A. Zeeb 		 * but the same logic should apply.
9395490110cSBjoern A. Zeeb 		 */
9405490110cSBjoern A. Zeeb 		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
9415490110cSBjoern A. Zeeb 	}
9425490110cSBjoern A. Zeeb 	if (in6_nigroup(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) {
9435490110cSBjoern A. Zeeb 		/* XXX jinmei */
9445490110cSBjoern A. Zeeb 		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay);
9455490110cSBjoern A. Zeeb 		if (imm == NULL)
9465490110cSBjoern A. Zeeb 			nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
9475490110cSBjoern A. Zeeb 			    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
9485490110cSBjoern A. Zeeb 			    &mltaddr.sin6_addr), if_name(ifp), error));
9495490110cSBjoern A. Zeeb 			/* XXX not very fatal, go on... */
9505490110cSBjoern A. Zeeb 		else
9515490110cSBjoern A. Zeeb 			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
9525490110cSBjoern A. Zeeb 	}
9535df1b6b5SHiroki Sato 	if (V_icmp6_nodeinfo_oldmcprefix &&
9545df1b6b5SHiroki Sato 	     in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) {
9555df1b6b5SHiroki Sato 		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay);
9565df1b6b5SHiroki Sato 		if (imm == NULL)
9575df1b6b5SHiroki Sato 			nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
9585df1b6b5SHiroki Sato 			    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
9595df1b6b5SHiroki Sato 			    &mltaddr.sin6_addr), if_name(ifp), error));
9605df1b6b5SHiroki Sato 			/* XXX not very fatal, go on... */
9615df1b6b5SHiroki Sato 		else
9625df1b6b5SHiroki Sato 			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
9635df1b6b5SHiroki Sato 	}
9645490110cSBjoern A. Zeeb 
9655490110cSBjoern A. Zeeb 	/*
9665490110cSBjoern A. Zeeb 	 * Join interface-local all-nodes address.
9675490110cSBjoern A. Zeeb 	 * (ff01::1%ifN, and ff01::%ifN/32)
9685490110cSBjoern A. Zeeb 	 */
9695490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
9705490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
9715490110cSBjoern A. Zeeb 		goto cleanup; /* XXX: should not fail */
9725490110cSBjoern A. Zeeb 	/* XXX: again, do we really need the route? */
97381d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
9745490110cSBjoern A. Zeeb 	if (rt != NULL) {
9755490110cSBjoern A. Zeeb 		if (memcmp(&mltaddr.sin6_addr,
9765490110cSBjoern A. Zeeb 		    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
9775490110cSBjoern A. Zeeb 		    MLTMASK_LEN)) {
9785490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
9795490110cSBjoern A. Zeeb 			rt = NULL;
9805490110cSBjoern A. Zeeb 		}
9815490110cSBjoern A. Zeeb 	}
9825490110cSBjoern A. Zeeb 	if (rt == NULL) {
98381d5d46bSBjoern A. Zeeb 		error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
9845490110cSBjoern A. Zeeb 		    (struct sockaddr *)&ia->ia_addr,
9855490110cSBjoern A. Zeeb 		    (struct sockaddr *)&mltmask, RTF_UP,
98681d5d46bSBjoern A. Zeeb 		    (struct rtentry **)0, RT_DEFAULT_FIB);
9875490110cSBjoern A. Zeeb 		if (error)
9885490110cSBjoern A. Zeeb 			goto cleanup;
9895490110cSBjoern A. Zeeb 	} else
9905490110cSBjoern A. Zeeb 		RTFREE_LOCKED(rt);
9915490110cSBjoern A. Zeeb 
9925490110cSBjoern A. Zeeb 	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
9935490110cSBjoern A. Zeeb 	if (imm == NULL) {
9945490110cSBjoern A. Zeeb 		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
9955490110cSBjoern A. Zeeb 		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
9965490110cSBjoern A. Zeeb 		    &mltaddr.sin6_addr), if_name(ifp), error));
9975490110cSBjoern A. Zeeb 		goto cleanup;
9985490110cSBjoern A. Zeeb 	}
9995490110cSBjoern A. Zeeb 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
10005490110cSBjoern A. Zeeb #undef	MLTMASK_LEN
10015490110cSBjoern A. Zeeb 
10025490110cSBjoern A. Zeeb cleanup:
10035490110cSBjoern A. Zeeb 	return (error);
10045490110cSBjoern A. Zeeb }
10055490110cSBjoern A. Zeeb 
10065490110cSBjoern A. Zeeb /*
100733841545SHajimu UMEMOTO  * Update parameters of an IPv6 interface address.
100833841545SHajimu UMEMOTO  * If necessary, a new entry is created and linked into address chains.
100933841545SHajimu UMEMOTO  * This function is separated from in6_control().
101033841545SHajimu UMEMOTO  */
101133841545SHajimu UMEMOTO int
10121272577eSXin LI in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
10131272577eSXin LI     struct in6_ifaddr *ia, int flags)
101433841545SHajimu UMEMOTO {
101533841545SHajimu UMEMOTO 	int error = 0, hostIsNew = 0, plen = -1;
101633841545SHajimu UMEMOTO 	struct sockaddr_in6 dst6;
101733841545SHajimu UMEMOTO 	struct in6_addrlifetime *lt;
1018743eee66SSUZUKI Shinsuke 	struct in6_multi *in6m_sol;
1019743eee66SSUZUKI Shinsuke 	int delay;
10201d54aa3bSBjoern A. Zeeb 	char ip6buf[INET6_ADDRSTRLEN];
102133841545SHajimu UMEMOTO 
102233841545SHajimu UMEMOTO 	/* Validate parameters */
102333841545SHajimu UMEMOTO 	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
102433841545SHajimu UMEMOTO 		return (EINVAL);
102533841545SHajimu UMEMOTO 
1026686cdd19SJun-ichiro itojun Hagino 	/*
1027686cdd19SJun-ichiro itojun Hagino 	 * The destination address for a p2p link must have a family
1028686cdd19SJun-ichiro itojun Hagino 	 * of AF_UNSPEC or AF_INET6.
1029686cdd19SJun-ichiro itojun Hagino 	 */
1030686cdd19SJun-ichiro itojun Hagino 	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
1031686cdd19SJun-ichiro itojun Hagino 	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
1032686cdd19SJun-ichiro itojun Hagino 	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
1033686cdd19SJun-ichiro itojun Hagino 		return (EAFNOSUPPORT);
1034686cdd19SJun-ichiro itojun Hagino 	/*
103533841545SHajimu UMEMOTO 	 * validate ifra_prefixmask.  don't check sin6_family, netmask
103633841545SHajimu UMEMOTO 	 * does not carry fields other than sin6_len.
1037686cdd19SJun-ichiro itojun Hagino 	 */
103833841545SHajimu UMEMOTO 	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
103933841545SHajimu UMEMOTO 		return (EINVAL);
104082cd038dSYoshinobu Inoue 	/*
104133841545SHajimu UMEMOTO 	 * Because the IPv6 address architecture is classless, we require
104233841545SHajimu UMEMOTO 	 * users to specify a (non 0) prefix length (mask) for a new address.
104333841545SHajimu UMEMOTO 	 * We also require the prefix (when specified) mask is valid, and thus
104433841545SHajimu UMEMOTO 	 * reject a non-consecutive mask.
104582cd038dSYoshinobu Inoue 	 */
104633841545SHajimu UMEMOTO 	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
104733841545SHajimu UMEMOTO 		return (EINVAL);
104833841545SHajimu UMEMOTO 	if (ifra->ifra_prefixmask.sin6_len != 0) {
104933841545SHajimu UMEMOTO 		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
105033841545SHajimu UMEMOTO 		    (u_char *)&ifra->ifra_prefixmask +
105133841545SHajimu UMEMOTO 		    ifra->ifra_prefixmask.sin6_len);
105233841545SHajimu UMEMOTO 		if (plen <= 0)
105333841545SHajimu UMEMOTO 			return (EINVAL);
105406cd0a3fSHajimu UMEMOTO 	} else {
105533841545SHajimu UMEMOTO 		/*
105633841545SHajimu UMEMOTO 		 * In this case, ia must not be NULL.  We just use its prefix
105733841545SHajimu UMEMOTO 		 * length.
105833841545SHajimu UMEMOTO 		 */
105933841545SHajimu UMEMOTO 		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
106082cd038dSYoshinobu Inoue 	}
106133841545SHajimu UMEMOTO 	/*
106233841545SHajimu UMEMOTO 	 * If the destination address on a p2p interface is specified,
106333841545SHajimu UMEMOTO 	 * and the address is a scoped one, validate/set the scope
106433841545SHajimu UMEMOTO 	 * zone identifier.
106533841545SHajimu UMEMOTO 	 */
106633841545SHajimu UMEMOTO 	dst6 = ifra->ifra_dstaddr;
106706cd0a3fSHajimu UMEMOTO 	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
106833841545SHajimu UMEMOTO 	    (dst6.sin6_family == AF_INET6)) {
1069a1f7e5f8SHajimu UMEMOTO 		struct in6_addr in6_tmp;
107059aecc96SHajimu UMEMOTO 		u_int32_t zoneid;
107133841545SHajimu UMEMOTO 
1072a1f7e5f8SHajimu UMEMOTO 		in6_tmp = dst6.sin6_addr;
1073a1f7e5f8SHajimu UMEMOTO 		if (in6_setscope(&in6_tmp, ifp, &zoneid))
1074a1f7e5f8SHajimu UMEMOTO 			return (EINVAL); /* XXX: should be impossible */
1075a1f7e5f8SHajimu UMEMOTO 
1076a1f7e5f8SHajimu UMEMOTO 		if (dst6.sin6_scope_id != 0) {
1077a1f7e5f8SHajimu UMEMOTO 			if (dst6.sin6_scope_id != zoneid)
10789a4f9608SHajimu UMEMOTO 				return (EINVAL);
1079a1f7e5f8SHajimu UMEMOTO 		} else		/* user omit to specify the ID. */
108059aecc96SHajimu UMEMOTO 			dst6.sin6_scope_id = zoneid;
1081a1f7e5f8SHajimu UMEMOTO 
1082a1f7e5f8SHajimu UMEMOTO 		/* convert into the internal form */
1083a1f7e5f8SHajimu UMEMOTO 		if (sa6_embedscope(&dst6, 0))
1084a1f7e5f8SHajimu UMEMOTO 			return (EINVAL); /* XXX: should be impossible */
1085686cdd19SJun-ichiro itojun Hagino 	}
108633841545SHajimu UMEMOTO 	/*
108733841545SHajimu UMEMOTO 	 * The destination address can be specified only for a p2p or a
108833841545SHajimu UMEMOTO 	 * loopback interface.  If specified, the corresponding prefix length
108933841545SHajimu UMEMOTO 	 * must be 128.
109033841545SHajimu UMEMOTO 	 */
109133841545SHajimu UMEMOTO 	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
109233841545SHajimu UMEMOTO 		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
109359aecc96SHajimu UMEMOTO 			/* XXX: noisy message */
10944835e2c7SHajimu UMEMOTO 			nd6log((LOG_INFO, "in6_update_ifa: a destination can "
10954835e2c7SHajimu UMEMOTO 			    "be specified for a p2p or a loopback IF only\n"));
109633841545SHajimu UMEMOTO 			return (EINVAL);
109733841545SHajimu UMEMOTO 		}
109833841545SHajimu UMEMOTO 		if (plen != 128) {
10994835e2c7SHajimu UMEMOTO 			nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
11004835e2c7SHajimu UMEMOTO 			    "be 128 when dstaddr is specified\n"));
110133841545SHajimu UMEMOTO 			return (EINVAL);
110233841545SHajimu UMEMOTO 		}
110333841545SHajimu UMEMOTO 	}
110433841545SHajimu UMEMOTO 	/* lifetime consistency check */
110533841545SHajimu UMEMOTO 	lt = &ifra->ifra_lifetime;
1106743eee66SSUZUKI Shinsuke 	if (lt->ia6t_pltime > lt->ia6t_vltime)
1107743eee66SSUZUKI Shinsuke 		return (EINVAL);
110833841545SHajimu UMEMOTO 	if (lt->ia6t_vltime == 0) {
110933841545SHajimu UMEMOTO 		/*
111033841545SHajimu UMEMOTO 		 * the following log might be noisy, but this is a typical
111133841545SHajimu UMEMOTO 		 * configuration mistake or a tool's bug.
111233841545SHajimu UMEMOTO 		 */
11134835e2c7SHajimu UMEMOTO 		nd6log((LOG_INFO,
111433841545SHajimu UMEMOTO 		    "in6_update_ifa: valid lifetime is 0 for %s\n",
11151d54aa3bSBjoern A. Zeeb 		    ip6_sprintf(ip6buf, &ifra->ifra_addr.sin6_addr)));
1116743eee66SSUZUKI Shinsuke 
1117743eee66SSUZUKI Shinsuke 		if (ia == NULL)
1118743eee66SSUZUKI Shinsuke 			return (0); /* there's nothing to do */
111933841545SHajimu UMEMOTO 	}
112082cd038dSYoshinobu Inoue 
112182cd038dSYoshinobu Inoue 	/*
112233841545SHajimu UMEMOTO 	 * If this is a new address, allocate a new ifaddr and link it
112333841545SHajimu UMEMOTO 	 * into chains.
112433841545SHajimu UMEMOTO 	 */
112533841545SHajimu UMEMOTO 	if (ia == NULL) {
112633841545SHajimu UMEMOTO 		hostIsNew = 1;
112709541513SHajimu UMEMOTO 		/*
112809541513SHajimu UMEMOTO 		 * When in6_update_ifa() is called in a process of a received
112906cd0a3fSHajimu UMEMOTO 		 * RA, it is called under an interrupt context.  So, we should
113006cd0a3fSHajimu UMEMOTO 		 * call malloc with M_NOWAIT.
113109541513SHajimu UMEMOTO 		 */
113206cd0a3fSHajimu UMEMOTO 		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
113306cd0a3fSHajimu UMEMOTO 		    M_NOWAIT);
113433841545SHajimu UMEMOTO 		if (ia == NULL)
113533841545SHajimu UMEMOTO 			return (ENOBUFS);
113633841545SHajimu UMEMOTO 		bzero((caddr_t)ia, sizeof(*ia));
11371099f828SRobert Watson 		ifa_init(&ia->ia_ifa);
113809a52a55SJINMEI Tatuya 		LIST_INIT(&ia->ia6_memberships);
1139743eee66SSUZUKI Shinsuke 		/* Initialize the address and masks, and put time stamp */
114033841545SHajimu UMEMOTO 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
114133841545SHajimu UMEMOTO 		ia->ia_addr.sin6_family = AF_INET6;
114233841545SHajimu UMEMOTO 		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
1143*7d26db17SHiroki Sato 		ia->ia6_createtime = time_uptime;
114433841545SHajimu UMEMOTO 		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
114533841545SHajimu UMEMOTO 			/*
114633841545SHajimu UMEMOTO 			 * XXX: some functions expect that ifa_dstaddr is not
114733841545SHajimu UMEMOTO 			 * NULL for p2p interfaces.
114833841545SHajimu UMEMOTO 			 */
114906cd0a3fSHajimu UMEMOTO 			ia->ia_ifa.ifa_dstaddr =
115006cd0a3fSHajimu UMEMOTO 			    (struct sockaddr *)&ia->ia_dstaddr;
115133841545SHajimu UMEMOTO 		} else {
115233841545SHajimu UMEMOTO 			ia->ia_ifa.ifa_dstaddr = NULL;
115333841545SHajimu UMEMOTO 		}
115419fc74fbSJeffrey Hsu 		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
115533841545SHajimu UMEMOTO 		ia->ia_ifp = ifp;
11568c0fec80SRobert Watson 		ifa_ref(&ia->ia_ifa);			/* if_addrhead */
1157137f91e8SJohn Baldwin 		IF_ADDR_WLOCK(ifp);
1158c4dd3fe1SRobert Watson 		TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
1159137f91e8SJohn Baldwin 		IF_ADDR_WUNLOCK(ifp);
116080af0152SRobert Watson 
1161d1da0a06SRobert Watson 		ifa_ref(&ia->ia_ifa);			/* in6_ifaddrhead */
1162d1da0a06SRobert Watson 		IN6_IFADDR_WLOCK();
116380af0152SRobert Watson 		TAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link);
116468eba526SAndrey V. Elsukov 		LIST_INSERT_HEAD(IN6ADDR_HASH(&ifra->ifra_addr.sin6_addr),
116568eba526SAndrey V. Elsukov 		    ia, ia6_hash);
1166d1da0a06SRobert Watson 		IN6_IFADDR_WUNLOCK();
116733841545SHajimu UMEMOTO 	}
116833841545SHajimu UMEMOTO 
1169743eee66SSUZUKI Shinsuke 	/* update timestamp */
1170*7d26db17SHiroki Sato 	ia->ia6_updatetime = time_uptime;
1171743eee66SSUZUKI Shinsuke 
117233841545SHajimu UMEMOTO 	/* set prefix mask */
117333841545SHajimu UMEMOTO 	if (ifra->ifra_prefixmask.sin6_len) {
117433841545SHajimu UMEMOTO 		/*
117533841545SHajimu UMEMOTO 		 * We prohibit changing the prefix length of an existing
117633841545SHajimu UMEMOTO 		 * address, because
117733841545SHajimu UMEMOTO 		 * + such an operation should be rare in IPv6, and
117833841545SHajimu UMEMOTO 		 * + the operation would confuse prefix management.
117933841545SHajimu UMEMOTO 		 */
118033841545SHajimu UMEMOTO 		if (ia->ia_prefixmask.sin6_len &&
118133841545SHajimu UMEMOTO 		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
11824835e2c7SHajimu UMEMOTO 			nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
118333841545SHajimu UMEMOTO 			    " existing (%s) address should not be changed\n",
11841d54aa3bSBjoern A. Zeeb 			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
118533841545SHajimu UMEMOTO 			error = EINVAL;
118633841545SHajimu UMEMOTO 			goto unlink;
118733841545SHajimu UMEMOTO 		}
118833841545SHajimu UMEMOTO 		ia->ia_prefixmask = ifra->ifra_prefixmask;
11896bdfdb2cSAlexander V. Chernikov 		ia->ia_prefixmask.sin6_family = AF_INET6;
119033841545SHajimu UMEMOTO 	}
119133841545SHajimu UMEMOTO 
119233841545SHajimu UMEMOTO 	/*
119333841545SHajimu UMEMOTO 	 * If a new destination address is specified, scrub the old one and
119433841545SHajimu UMEMOTO 	 * install the new destination.  Note that the interface must be
119533841545SHajimu UMEMOTO 	 * p2p or loopback (see the check above.)
119633841545SHajimu UMEMOTO 	 */
119733841545SHajimu UMEMOTO 	if (dst6.sin6_family == AF_INET6 &&
119806cd0a3fSHajimu UMEMOTO 	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
119933841545SHajimu UMEMOTO 		int e;
120033841545SHajimu UMEMOTO 
120133841545SHajimu UMEMOTO 		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
120206cd0a3fSHajimu UMEMOTO 		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
12034835e2c7SHajimu UMEMOTO 			nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
120433841545SHajimu UMEMOTO 			    "a route to the old destination: %s\n",
12051d54aa3bSBjoern A. Zeeb 			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
120633841545SHajimu UMEMOTO 			/* proceed anyway... */
120706cd0a3fSHajimu UMEMOTO 		} else
120833841545SHajimu UMEMOTO 			ia->ia_flags &= ~IFA_ROUTE;
120933841545SHajimu UMEMOTO 		ia->ia_dstaddr = dst6;
121033841545SHajimu UMEMOTO 	}
121133841545SHajimu UMEMOTO 
1212a1f7e5f8SHajimu UMEMOTO 	/*
1213a1f7e5f8SHajimu UMEMOTO 	 * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
1214a1f7e5f8SHajimu UMEMOTO 	 * to see if the address is deprecated or invalidated, but initialize
1215a1f7e5f8SHajimu UMEMOTO 	 * these members for applications.
1216a1f7e5f8SHajimu UMEMOTO 	 */
1217a1f7e5f8SHajimu UMEMOTO 	ia->ia6_lifetime = ifra->ifra_lifetime;
1218a1f7e5f8SHajimu UMEMOTO 	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
1219a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_expire =
1220*7d26db17SHiroki Sato 		    time_uptime + ia->ia6_lifetime.ia6t_vltime;
1221a1f7e5f8SHajimu UMEMOTO 	} else
1222a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_expire = 0;
1223a1f7e5f8SHajimu UMEMOTO 	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
1224a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_preferred =
1225*7d26db17SHiroki Sato 		    time_uptime + ia->ia6_lifetime.ia6t_pltime;
1226a1f7e5f8SHajimu UMEMOTO 	} else
1227a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_preferred = 0;
1228a1f7e5f8SHajimu UMEMOTO 
122933841545SHajimu UMEMOTO 	/* reset the interface and routing table appropriately. */
123033841545SHajimu UMEMOTO 	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
123133841545SHajimu UMEMOTO 		goto unlink;
123233841545SHajimu UMEMOTO 
123333841545SHajimu UMEMOTO 	/*
1234a1f7e5f8SHajimu UMEMOTO 	 * configure address flags.
1235a1f7e5f8SHajimu UMEMOTO 	 */
1236a1f7e5f8SHajimu UMEMOTO 	ia->ia6_flags = ifra->ifra_flags;
1237a1f7e5f8SHajimu UMEMOTO 	/*
1238a1f7e5f8SHajimu UMEMOTO 	 * backward compatibility - if IN6_IFF_DEPRECATED is set from the
1239a1f7e5f8SHajimu UMEMOTO 	 * userland, make it deprecated.
1240a1f7e5f8SHajimu UMEMOTO 	 */
1241a1f7e5f8SHajimu UMEMOTO 	if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
1242a1f7e5f8SHajimu UMEMOTO 		ia->ia6_lifetime.ia6t_pltime = 0;
1243*7d26db17SHiroki Sato 		ia->ia6_lifetime.ia6t_preferred = time_uptime;
1244a1f7e5f8SHajimu UMEMOTO 	}
1245a1f7e5f8SHajimu UMEMOTO 	/*
1246743eee66SSUZUKI Shinsuke 	 * Make the address tentative before joining multicast addresses,
1247743eee66SSUZUKI Shinsuke 	 * so that corresponding MLD responses would not have a tentative
1248743eee66SSUZUKI Shinsuke 	 * source address.
1249a1f7e5f8SHajimu UMEMOTO 	 */
1250743eee66SSUZUKI Shinsuke 	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/* safety */
1251743eee66SSUZUKI Shinsuke 	if (hostIsNew && in6if_do_dad(ifp))
1252a1f7e5f8SHajimu UMEMOTO 		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1253a1f7e5f8SHajimu UMEMOTO 
1254a283298cSHiroki Sato 	/* DAD should be performed after ND6_IFF_IFDISABLED is cleared. */
1255a283298cSHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
1256a283298cSHiroki Sato 		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1257a283298cSHiroki Sato 
1258a1f7e5f8SHajimu UMEMOTO 	/*
1259a1f7e5f8SHajimu UMEMOTO 	 * We are done if we have simply modified an existing address.
1260a1f7e5f8SHajimu UMEMOTO 	 */
1261a1f7e5f8SHajimu UMEMOTO 	if (!hostIsNew)
1262a1f7e5f8SHajimu UMEMOTO 		return (error);
1263a1f7e5f8SHajimu UMEMOTO 
1264a1f7e5f8SHajimu UMEMOTO 	/*
126533841545SHajimu UMEMOTO 	 * Beyond this point, we should call in6_purgeaddr upon an error,
126633841545SHajimu UMEMOTO 	 * not just go to unlink.
126733841545SHajimu UMEMOTO 	 */
126833841545SHajimu UMEMOTO 
12695490110cSBjoern A. Zeeb 	/* Join necessary multicast groups. */
1270743eee66SSUZUKI Shinsuke 	in6m_sol = NULL;
127133841545SHajimu UMEMOTO 	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
12725490110cSBjoern A. Zeeb 		error = in6_update_ifa_join_mc(ifp, ifra, ia, flags, &in6m_sol);
1273743eee66SSUZUKI Shinsuke 		if (error)
1274743eee66SSUZUKI Shinsuke 			goto cleanup;
127533841545SHajimu UMEMOTO 	}
127682cd038dSYoshinobu Inoue 
1277743eee66SSUZUKI Shinsuke 	/*
1278743eee66SSUZUKI Shinsuke 	 * Perform DAD, if needed.
127981d5d46bSBjoern A. Zeeb 	 * XXX It may be of use, if we can administratively disable DAD.
1280743eee66SSUZUKI Shinsuke 	 */
12818c0fec80SRobert Watson 	if (in6if_do_dad(ifp) && ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
1282743eee66SSUZUKI Shinsuke 	    (ia->ia6_flags & IN6_IFF_TENTATIVE))
1283743eee66SSUZUKI Shinsuke 	{
1284743eee66SSUZUKI Shinsuke 		int mindelay, maxdelay;
1285743eee66SSUZUKI Shinsuke 
1286743eee66SSUZUKI Shinsuke 		delay = 0;
1287743eee66SSUZUKI Shinsuke 		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1288743eee66SSUZUKI Shinsuke 			/*
1289743eee66SSUZUKI Shinsuke 			 * We need to impose a delay before sending an NS
1290743eee66SSUZUKI Shinsuke 			 * for DAD.  Check if we also needed a delay for the
1291743eee66SSUZUKI Shinsuke 			 * corresponding MLD message.  If we did, the delay
1292743eee66SSUZUKI Shinsuke 			 * should be larger than the MLD delay (this could be
1293743eee66SSUZUKI Shinsuke 			 * relaxed a bit, but this simple logic is at least
1294743eee66SSUZUKI Shinsuke 			 * safe).
129533cde130SBruce M Simpson 			 * XXX: Break data hiding guidelines and look at
129633cde130SBruce M Simpson 			 * state for the solicited multicast group.
1297743eee66SSUZUKI Shinsuke 			 */
1298743eee66SSUZUKI Shinsuke 			mindelay = 0;
1299743eee66SSUZUKI Shinsuke 			if (in6m_sol != NULL &&
130033cde130SBruce M Simpson 			    in6m_sol->in6m_state == MLD_REPORTING_MEMBER) {
1301743eee66SSUZUKI Shinsuke 				mindelay = in6m_sol->in6m_timer;
1302743eee66SSUZUKI Shinsuke 			}
1303743eee66SSUZUKI Shinsuke 			maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
1304743eee66SSUZUKI Shinsuke 			if (maxdelay - mindelay == 0)
1305743eee66SSUZUKI Shinsuke 				delay = 0;
1306743eee66SSUZUKI Shinsuke 			else {
1307743eee66SSUZUKI Shinsuke 				delay =
1308743eee66SSUZUKI Shinsuke 				    (arc4random() % (maxdelay - mindelay)) +
1309743eee66SSUZUKI Shinsuke 				    mindelay;
1310743eee66SSUZUKI Shinsuke 			}
1311743eee66SSUZUKI Shinsuke 		}
1312743eee66SSUZUKI Shinsuke 		nd6_dad_start((struct ifaddr *)ia, delay);
1313743eee66SSUZUKI Shinsuke 	}
1314743eee66SSUZUKI Shinsuke 
13158c0fec80SRobert Watson 	KASSERT(hostIsNew, ("in6_update_ifa: !hostIsNew"));
13168c0fec80SRobert Watson 	ifa_free(&ia->ia_ifa);
131782cd038dSYoshinobu Inoue 	return (error);
131882cd038dSYoshinobu Inoue 
131933841545SHajimu UMEMOTO   unlink:
132033841545SHajimu UMEMOTO 	/*
132133841545SHajimu UMEMOTO 	 * XXX: if a change of an existing address failed, keep the entry
132233841545SHajimu UMEMOTO 	 * anyway.
132333841545SHajimu UMEMOTO 	 */
13248c0fec80SRobert Watson 	if (hostIsNew) {
132533841545SHajimu UMEMOTO 		in6_unlink_ifa(ia, ifp);
13263cfed08dSRobert Watson 		ifa_free(&ia->ia_ifa);
13278c0fec80SRobert Watson 	}
132833841545SHajimu UMEMOTO 	return (error);
1329a1f7e5f8SHajimu UMEMOTO 
1330a1f7e5f8SHajimu UMEMOTO   cleanup:
13318c0fec80SRobert Watson 	KASSERT(hostIsNew, ("in6_update_ifa: cleanup: !hostIsNew"));
13328c0fec80SRobert Watson 	ifa_free(&ia->ia_ifa);
1333a1f7e5f8SHajimu UMEMOTO 	in6_purgeaddr(&ia->ia_ifa);
1334a1f7e5f8SHajimu UMEMOTO 	return error;
1335686cdd19SJun-ichiro itojun Hagino }
1336686cdd19SJun-ichiro itojun Hagino 
13375490110cSBjoern A. Zeeb /*
13385490110cSBjoern A. Zeeb  * Leave multicast groups.  Factored out from in6_purgeaddr().
13395490110cSBjoern A. Zeeb  * This entire work should only be done once, for the default FIB.
13405490110cSBjoern A. Zeeb  */
13415490110cSBjoern A. Zeeb static int
13425490110cSBjoern A. Zeeb in6_purgeaddr_mc(struct ifnet *ifp, struct in6_ifaddr *ia, struct ifaddr *ifa0)
13435490110cSBjoern A. Zeeb {
13445490110cSBjoern A. Zeeb 	struct sockaddr_in6 mltaddr, mltmask;
13455490110cSBjoern A. Zeeb 	struct in6_multi_mship *imm;
13465490110cSBjoern A. Zeeb 	struct rtentry *rt;
13475b8f1a86SXin LI 	struct sockaddr_in6 sin6;
13485490110cSBjoern A. Zeeb 	int error;
13495490110cSBjoern A. Zeeb 
13505490110cSBjoern A. Zeeb 	/*
13515490110cSBjoern A. Zeeb 	 * Leave from multicast groups we have joined for the interface.
13525490110cSBjoern A. Zeeb 	 */
13535490110cSBjoern A. Zeeb 	while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
13545490110cSBjoern A. Zeeb 		LIST_REMOVE(imm, i6mm_chain);
13555490110cSBjoern A. Zeeb 		in6_leavegroup(imm);
13565490110cSBjoern A. Zeeb 	}
13575490110cSBjoern A. Zeeb 
13585490110cSBjoern A. Zeeb 	/*
13595490110cSBjoern A. Zeeb 	 * Remove the link-local all-nodes address.
13605490110cSBjoern A. Zeeb 	 */
13615490110cSBjoern A. Zeeb 	bzero(&mltmask, sizeof(mltmask));
13625490110cSBjoern A. Zeeb 	mltmask.sin6_len = sizeof(struct sockaddr_in6);
13635490110cSBjoern A. Zeeb 	mltmask.sin6_family = AF_INET6;
13645490110cSBjoern A. Zeeb 	mltmask.sin6_addr = in6mask32;
13655490110cSBjoern A. Zeeb 
13665490110cSBjoern A. Zeeb 	bzero(&mltaddr, sizeof(mltaddr));
13675490110cSBjoern A. Zeeb 	mltaddr.sin6_len = sizeof(struct sockaddr_in6);
13685490110cSBjoern A. Zeeb 	mltaddr.sin6_family = AF_INET6;
13695490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_linklocal_allnodes;
13705490110cSBjoern A. Zeeb 
13715490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
13725490110cSBjoern A. Zeeb 		return (error);
13735490110cSBjoern A. Zeeb 
13745b8f1a86SXin LI 	/*
13755b8f1a86SXin LI 	 * As for the mltaddr above, proactively prepare the sin6 to avoid
13765b8f1a86SXin LI 	 * rtentry un- and re-locking.
13775b8f1a86SXin LI 	 */
13785b8f1a86SXin LI 	if (ifa0 != NULL) {
13795b8f1a86SXin LI 		bzero(&sin6, sizeof(sin6));
13805b8f1a86SXin LI 		sin6.sin6_len = sizeof(sin6);
13815b8f1a86SXin LI 		sin6.sin6_family = AF_INET6;
13825b8f1a86SXin LI 		memcpy(&sin6.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
13835b8f1a86SXin LI 		    sizeof(sin6.sin6_addr));
13848dcc26feSBjoern A. Zeeb 		error = in6_setscope(&sin6.sin6_addr, ifa0->ifa_ifp, NULL);
13858dcc26feSBjoern A. Zeeb 		if (error != 0)
13868dcc26feSBjoern A. Zeeb 			return (error);
13875b8f1a86SXin LI 	}
13885b8f1a86SXin LI 
138981d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
13905490110cSBjoern A. Zeeb 	if (rt != NULL && rt->rt_gateway != NULL &&
13915490110cSBjoern A. Zeeb 	    (memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
13925490110cSBjoern A. Zeeb 		    &ia->ia_addr.sin6_addr,
13935490110cSBjoern A. Zeeb 		    sizeof(ia->ia_addr.sin6_addr)) == 0)) {
13945490110cSBjoern A. Zeeb 		/*
13955490110cSBjoern A. Zeeb 		 * If no more IPv6 address exists on this interface then
13965490110cSBjoern A. Zeeb 		 * remove the multicast address route.
13975490110cSBjoern A. Zeeb 		 */
13985490110cSBjoern A. Zeeb 		if (ifa0 == NULL) {
1399ea50c13eSGleb Smirnoff 			memcpy(&mltaddr.sin6_addr,
1400ea50c13eSGleb Smirnoff 			    &satosin6(rt_key(rt))->sin6_addr,
14015490110cSBjoern A. Zeeb 			    sizeof(mltaddr.sin6_addr));
14025490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
140381d5d46bSBjoern A. Zeeb 			error = in6_rtrequest(RTM_DELETE,
14045490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltaddr,
14055490110cSBjoern A. Zeeb 			    (struct sockaddr *)&ia->ia_addr,
14065490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltmask, RTF_UP,
140781d5d46bSBjoern A. Zeeb 			    (struct rtentry **)0, RT_DEFAULT_FIB);
14085490110cSBjoern A. Zeeb 			if (error)
14095490110cSBjoern A. Zeeb 				log(LOG_INFO, "%s: link-local all-nodes "
14105490110cSBjoern A. Zeeb 				    "multicast address deletion error\n",
14115490110cSBjoern A. Zeeb 				    __func__);
14125490110cSBjoern A. Zeeb 		} else {
14135490110cSBjoern A. Zeeb 			/*
14145490110cSBjoern A. Zeeb 			 * Replace the gateway of the route.
14155490110cSBjoern A. Zeeb 			 */
14165b8f1a86SXin LI 			memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
14175490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
14185490110cSBjoern A. Zeeb 		}
14195490110cSBjoern A. Zeeb 	} else {
14205490110cSBjoern A. Zeeb 		if (rt != NULL)
14215490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
14225490110cSBjoern A. Zeeb 	}
14235490110cSBjoern A. Zeeb 
14245490110cSBjoern A. Zeeb 	/*
14255490110cSBjoern A. Zeeb 	 * Remove the node-local all-nodes address.
14265490110cSBjoern A. Zeeb 	 */
14275490110cSBjoern A. Zeeb 	mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
14285490110cSBjoern A. Zeeb 	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
14295490110cSBjoern A. Zeeb 		return (error);
14305490110cSBjoern A. Zeeb 
143181d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
14325490110cSBjoern A. Zeeb 	if (rt != NULL && rt->rt_gateway != NULL &&
14335490110cSBjoern A. Zeeb 	    (memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
14345490110cSBjoern A. Zeeb 		    &ia->ia_addr.sin6_addr,
14355490110cSBjoern A. Zeeb 		    sizeof(ia->ia_addr.sin6_addr)) == 0)) {
14365490110cSBjoern A. Zeeb 		/*
14375490110cSBjoern A. Zeeb 		 * If no more IPv6 address exists on this interface then
14385490110cSBjoern A. Zeeb 		 * remove the multicast address route.
14395490110cSBjoern A. Zeeb 		 */
14405490110cSBjoern A. Zeeb 		if (ifa0 == NULL) {
1441ea50c13eSGleb Smirnoff 			memcpy(&mltaddr.sin6_addr,
1442ea50c13eSGleb Smirnoff 			    &satosin6(rt_key(rt))->sin6_addr,
14435490110cSBjoern A. Zeeb 			    sizeof(mltaddr.sin6_addr));
14445490110cSBjoern A. Zeeb 
14455490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
144681d5d46bSBjoern A. Zeeb 			error = in6_rtrequest(RTM_DELETE,
14475490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltaddr,
14485490110cSBjoern A. Zeeb 			    (struct sockaddr *)&ia->ia_addr,
14495490110cSBjoern A. Zeeb 			    (struct sockaddr *)&mltmask, RTF_UP,
145081d5d46bSBjoern A. Zeeb 			    (struct rtentry **)0, RT_DEFAULT_FIB);
14515490110cSBjoern A. Zeeb 			if (error)
14525490110cSBjoern A. Zeeb 				log(LOG_INFO, "%s: node-local all-nodes"
14535490110cSBjoern A. Zeeb 				    "multicast address deletion error\n",
14545490110cSBjoern A. Zeeb 				    __func__);
14555490110cSBjoern A. Zeeb 		} else {
14565490110cSBjoern A. Zeeb 			/*
14575490110cSBjoern A. Zeeb 			 * Replace the gateway of the route.
14585490110cSBjoern A. Zeeb 			 */
14595b8f1a86SXin LI 			memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
14605490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
14615490110cSBjoern A. Zeeb 		}
14625490110cSBjoern A. Zeeb 	} else {
14635490110cSBjoern A. Zeeb 		if (rt != NULL)
14645490110cSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
14655490110cSBjoern A. Zeeb 	}
14665490110cSBjoern A. Zeeb 
14675490110cSBjoern A. Zeeb 	return (0);
14685490110cSBjoern A. Zeeb }
14695490110cSBjoern A. Zeeb 
1470686cdd19SJun-ichiro itojun Hagino void
14711272577eSXin LI in6_purgeaddr(struct ifaddr *ifa)
1472686cdd19SJun-ichiro itojun Hagino {
147333841545SHajimu UMEMOTO 	struct ifnet *ifp = ifa->ifa_ifp;
147433841545SHajimu UMEMOTO 	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
1475511e8a53SQing Li 	int plen, error;
1476f5b50e25SJohn Baldwin 	struct ifaddr *ifa0;
1477511e8a53SQing Li 
147808b68b0eSGleb Smirnoff 	if (ifa->ifa_carp)
147908b68b0eSGleb Smirnoff 		(*carp_detach_p)(ifa);
148008b68b0eSGleb Smirnoff 
1481511e8a53SQing Li 	/*
1482511e8a53SQing Li 	 * find another IPv6 address as the gateway for the
1483511e8a53SQing Li 	 * link-local and node-local all-nodes multicast
1484511e8a53SQing Li 	 * address routes
1485511e8a53SQing Li 	 */
1486137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1487f5b50e25SJohn Baldwin 	TAILQ_FOREACH(ifa0, &ifp->if_addrhead, ifa_link) {
1488511e8a53SQing Li 		if ((ifa0->ifa_addr->sa_family != AF_INET6) ||
1489511e8a53SQing Li 		    memcmp(&satosin6(ifa0->ifa_addr)->sin6_addr,
1490ea50c13eSGleb Smirnoff 		    &ia->ia_addr.sin6_addr, sizeof(struct in6_addr)) == 0)
1491511e8a53SQing Li 			continue;
1492511e8a53SQing Li 		else
1493511e8a53SQing Li 			break;
1494511e8a53SQing Li 	}
14958c0fec80SRobert Watson 	if (ifa0 != NULL)
14968c0fec80SRobert Watson 		ifa_ref(ifa0);
1497137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
1498686cdd19SJun-ichiro itojun Hagino 
1499df813b7eSQing Li 	/*
1500df813b7eSQing Li 	 * Remove the loopback route to the interface address.
1501d134008aSQing Li 	 * The check for the current setting of "nd6_useloopback"
1502d134008aSQing Li 	 * is not needed.
1503df813b7eSQing Li 	 */
1504c7ab6602SQing Li 	if (ia->ia_flags & IFA_RTSELF) {
15059bb7d0f4SQing Li 		error = ifa_del_loopback_route((struct ifaddr *)ia,
15069bb7d0f4SQing Li 		    (struct sockaddr *)&ia->ia_addr);
1507c7ab6602SQing Li 		if (error == 0)
1508c7ab6602SQing Li 			ia->ia_flags &= ~IFA_RTSELF;
1509c7ab6602SQing Li 	}
151005b262e2SQing Li 
151133841545SHajimu UMEMOTO 	/* stop DAD processing */
151233841545SHajimu UMEMOTO 	nd6_dad_stop(ifa);
151333841545SHajimu UMEMOTO 
151481d5d46bSBjoern A. Zeeb 	/* Remove local address entry from lltable. */
1515b590b6aeSGleb Smirnoff 	in6_ifremloop(ifa);
1516511e8a53SQing Li 
15175490110cSBjoern A. Zeeb 	/* Leave multicast groups. */
15185490110cSBjoern A. Zeeb 	error = in6_purgeaddr_mc(ifp, ia, ifa0);
151982cd038dSYoshinobu Inoue 
15204aa7588cSBjoern A. Zeeb 	if (ifa0 != NULL)
15214aa7588cSBjoern A. Zeeb 		ifa_free(ifa0);
1522511e8a53SQing Li 
1523511e8a53SQing Li 	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1524511e8a53SQing Li 	if ((ia->ia_flags & IFA_ROUTE) && plen == 128) {
152581d5d46bSBjoern A. Zeeb 		error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags |
152681d5d46bSBjoern A. Zeeb 		    (ia->ia_dstaddr.sin6_family == AF_INET6) ? RTF_HOST : 0);
1527511e8a53SQing Li 		if (error != 0)
152881d5d46bSBjoern A. Zeeb 			log(LOG_INFO, "%s: err=%d, destination address delete "
152981d5d46bSBjoern A. Zeeb 			    "failed\n", __func__, error);
1530511e8a53SQing Li 		ia->ia_flags &= ~IFA_ROUTE;
1531511e8a53SQing Li 	}
1532511e8a53SQing Li 
153333841545SHajimu UMEMOTO 	in6_unlink_ifa(ia, ifp);
153433841545SHajimu UMEMOTO }
153533841545SHajimu UMEMOTO 
153633841545SHajimu UMEMOTO static void
15371272577eSXin LI in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
153833841545SHajimu UMEMOTO {
153933841545SHajimu UMEMOTO 
1540137f91e8SJohn Baldwin 	IF_ADDR_WLOCK(ifp);
1541c4dd3fe1SRobert Watson 	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
1542137f91e8SJohn Baldwin 	IF_ADDR_WUNLOCK(ifp);
15438c0fec80SRobert Watson 	ifa_free(&ia->ia_ifa);			/* if_addrhead */
1544686cdd19SJun-ichiro itojun Hagino 
1545f291b9cdSRobert Watson 	/*
1546f291b9cdSRobert Watson 	 * Defer the release of what might be the last reference to the
1547f291b9cdSRobert Watson 	 * in6_ifaddr so that it can't be freed before the remainder of the
1548f291b9cdSRobert Watson 	 * cleanup.
1549f291b9cdSRobert Watson 	 */
1550d1da0a06SRobert Watson 	IN6_IFADDR_WLOCK();
155180af0152SRobert Watson 	TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link);
155268eba526SAndrey V. Elsukov 	LIST_REMOVE(ia, ia6_hash);
1553d1da0a06SRobert Watson 	IN6_IFADDR_WUNLOCK();
155482cd038dSYoshinobu Inoue 
1555686cdd19SJun-ichiro itojun Hagino 	/*
1556797df30dSSUZUKI Shinsuke 	 * Release the reference to the base prefix.  There should be a
1557797df30dSSUZUKI Shinsuke 	 * positive reference.
1558686cdd19SJun-ichiro itojun Hagino 	 */
155980af0152SRobert Watson 	if (ia->ia6_ndpr == NULL) {
1560797df30dSSUZUKI Shinsuke 		nd6log((LOG_NOTICE,
1561797df30dSSUZUKI Shinsuke 		    "in6_unlink_ifa: autoconf'ed address "
156280af0152SRobert Watson 		    "%p has no prefix\n", ia));
156333841545SHajimu UMEMOTO 	} else {
156480af0152SRobert Watson 		ia->ia6_ndpr->ndpr_refcnt--;
156580af0152SRobert Watson 		ia->ia6_ndpr = NULL;
1566686cdd19SJun-ichiro itojun Hagino 	}
1567686cdd19SJun-ichiro itojun Hagino 
1568797df30dSSUZUKI Shinsuke 	/*
1569797df30dSSUZUKI Shinsuke 	 * Also, if the address being removed is autoconf'ed, call
1570797df30dSSUZUKI Shinsuke 	 * pfxlist_onlink_check() since the release might affect the status of
1571797df30dSSUZUKI Shinsuke 	 * other (detached) addresses.
1572797df30dSSUZUKI Shinsuke 	 */
157380af0152SRobert Watson 	if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) {
157433841545SHajimu UMEMOTO 		pfxlist_onlink_check();
157533841545SHajimu UMEMOTO 	}
1576f291b9cdSRobert Watson 	ifa_free(&ia->ia_ifa);			/* in6_ifaddrhead */
157733841545SHajimu UMEMOTO }
157833841545SHajimu UMEMOTO 
157933841545SHajimu UMEMOTO void
15801272577eSXin LI in6_purgeif(struct ifnet *ifp)
158133841545SHajimu UMEMOTO {
158233841545SHajimu UMEMOTO 	struct ifaddr *ifa, *nifa;
158333841545SHajimu UMEMOTO 
1584c4dd3fe1SRobert Watson 	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, nifa) {
158533841545SHajimu UMEMOTO 		if (ifa->ifa_addr->sa_family != AF_INET6)
158633841545SHajimu UMEMOTO 			continue;
158733841545SHajimu UMEMOTO 		in6_purgeaddr(ifa);
158833841545SHajimu UMEMOTO 	}
158933841545SHajimu UMEMOTO 
159033841545SHajimu UMEMOTO 	in6_ifdetach(ifp);
159182cd038dSYoshinobu Inoue }
159282cd038dSYoshinobu Inoue 
159382cd038dSYoshinobu Inoue /*
159482cd038dSYoshinobu Inoue  * SIOC[GAD]LIFADDR.
159545b65a5eSGreg Lehey  *	SIOCGLIFADDR: get first address. (?)
159682cd038dSYoshinobu Inoue  *	SIOCGLIFADDR with IFLR_PREFIX:
159782cd038dSYoshinobu Inoue  *		get first address that matches the specified prefix.
159882cd038dSYoshinobu Inoue  *	SIOCALIFADDR: add the specified address.
159982cd038dSYoshinobu Inoue  *	SIOCALIFADDR with IFLR_PREFIX:
160082cd038dSYoshinobu Inoue  *		add the specified prefix, filling hostid part from
160182cd038dSYoshinobu Inoue  *		the first link-local address.  prefixlen must be <= 64.
160282cd038dSYoshinobu Inoue  *	SIOCDLIFADDR: delete the specified address.
160382cd038dSYoshinobu Inoue  *	SIOCDLIFADDR with IFLR_PREFIX:
160482cd038dSYoshinobu Inoue  *		delete the first address that matches the specified prefix.
160582cd038dSYoshinobu Inoue  * return values:
160682cd038dSYoshinobu Inoue  *	EINVAL on invalid parameters
160782cd038dSYoshinobu Inoue  *	EADDRNOTAVAIL on prefix match failed/specified address not found
160882cd038dSYoshinobu Inoue  *	other values may be returned from in6_ioctl()
160982cd038dSYoshinobu Inoue  *
161082cd038dSYoshinobu Inoue  * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
161182cd038dSYoshinobu Inoue  * this is to accomodate address naming scheme other than RFC2374,
161282cd038dSYoshinobu Inoue  * in the future.
161382cd038dSYoshinobu Inoue  * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
161482cd038dSYoshinobu Inoue  * address encoding scheme. (see figure on page 8)
161582cd038dSYoshinobu Inoue  */
161682cd038dSYoshinobu Inoue static int
16171272577eSXin LI in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
16181272577eSXin LI     struct ifnet *ifp, struct thread *td)
161982cd038dSYoshinobu Inoue {
162082cd038dSYoshinobu Inoue 	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
162182cd038dSYoshinobu Inoue 	struct ifaddr *ifa;
1622686cdd19SJun-ichiro itojun Hagino 	struct sockaddr *sa;
162382cd038dSYoshinobu Inoue 
162482cd038dSYoshinobu Inoue 	/* sanity checks */
162582cd038dSYoshinobu Inoue 	if (!data || !ifp) {
162682cd038dSYoshinobu Inoue 		panic("invalid argument to in6_lifaddr_ioctl");
162706cd0a3fSHajimu UMEMOTO 		/* NOTREACHED */
162882cd038dSYoshinobu Inoue 	}
162982cd038dSYoshinobu Inoue 
163082cd038dSYoshinobu Inoue 	switch (cmd) {
163182cd038dSYoshinobu Inoue 	case SIOCGLIFADDR:
163282cd038dSYoshinobu Inoue 		/* address must be specified on GET with IFLR_PREFIX */
163382cd038dSYoshinobu Inoue 		if ((iflr->flags & IFLR_PREFIX) == 0)
163482cd038dSYoshinobu Inoue 			break;
163582cd038dSYoshinobu Inoue 		/* FALLTHROUGH */
163682cd038dSYoshinobu Inoue 	case SIOCALIFADDR:
163782cd038dSYoshinobu Inoue 	case SIOCDLIFADDR:
163882cd038dSYoshinobu Inoue 		/* address must be specified on ADD and DELETE */
1639686cdd19SJun-ichiro itojun Hagino 		sa = (struct sockaddr *)&iflr->addr;
1640686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_family != AF_INET6)
164182cd038dSYoshinobu Inoue 			return EINVAL;
1642686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_len != sizeof(struct sockaddr_in6))
164382cd038dSYoshinobu Inoue 			return EINVAL;
164482cd038dSYoshinobu Inoue 		/* XXX need improvement */
1645686cdd19SJun-ichiro itojun Hagino 		sa = (struct sockaddr *)&iflr->dstaddr;
1646686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_family && sa->sa_family != AF_INET6)
164782cd038dSYoshinobu Inoue 			return EINVAL;
1648686cdd19SJun-ichiro itojun Hagino 		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
164982cd038dSYoshinobu Inoue 			return EINVAL;
165082cd038dSYoshinobu Inoue 		break;
165182cd038dSYoshinobu Inoue 	default: /* shouldn't happen */
1652686cdd19SJun-ichiro itojun Hagino #if 0
1653686cdd19SJun-ichiro itojun Hagino 		panic("invalid cmd to in6_lifaddr_ioctl");
1654686cdd19SJun-ichiro itojun Hagino 		/* NOTREACHED */
1655686cdd19SJun-ichiro itojun Hagino #else
165682cd038dSYoshinobu Inoue 		return EOPNOTSUPP;
1657686cdd19SJun-ichiro itojun Hagino #endif
165882cd038dSYoshinobu Inoue 	}
165982cd038dSYoshinobu Inoue 	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
166082cd038dSYoshinobu Inoue 		return EINVAL;
166182cd038dSYoshinobu Inoue 
166282cd038dSYoshinobu Inoue 	switch (cmd) {
166382cd038dSYoshinobu Inoue 	case SIOCALIFADDR:
166482cd038dSYoshinobu Inoue 	    {
166582cd038dSYoshinobu Inoue 		struct in6_aliasreq ifra;
166682cd038dSYoshinobu Inoue 		struct in6_addr *hostid = NULL;
166782cd038dSYoshinobu Inoue 		int prefixlen;
166882cd038dSYoshinobu Inoue 
16698c0fec80SRobert Watson 		ifa = NULL;
167082cd038dSYoshinobu Inoue 		if ((iflr->flags & IFLR_PREFIX) != 0) {
167182cd038dSYoshinobu Inoue 			struct sockaddr_in6 *sin6;
167282cd038dSYoshinobu Inoue 
167382cd038dSYoshinobu Inoue 			/*
167482cd038dSYoshinobu Inoue 			 * hostid is to fill in the hostid part of the
167582cd038dSYoshinobu Inoue 			 * address.  hostid points to the first link-local
167682cd038dSYoshinobu Inoue 			 * address attached to the interface.
167782cd038dSYoshinobu Inoue 			 */
1678686cdd19SJun-ichiro itojun Hagino 			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
167982cd038dSYoshinobu Inoue 			if (!ifa)
168082cd038dSYoshinobu Inoue 				return EADDRNOTAVAIL;
168182cd038dSYoshinobu Inoue 			hostid = IFA_IN6(ifa);
168282cd038dSYoshinobu Inoue 
168382cd038dSYoshinobu Inoue 			/* prefixlen must be <= 64. */
168415cc25e9SBjoern A. Zeeb 			if (64 < iflr->prefixlen) {
168515cc25e9SBjoern A. Zeeb 				if (ifa != NULL)
168615cc25e9SBjoern A. Zeeb 					ifa_free(ifa);
168782cd038dSYoshinobu Inoue 				return EINVAL;
168815cc25e9SBjoern A. Zeeb 			}
168982cd038dSYoshinobu Inoue 			prefixlen = iflr->prefixlen;
169082cd038dSYoshinobu Inoue 
169182cd038dSYoshinobu Inoue 			/* hostid part must be zero. */
169282cd038dSYoshinobu Inoue 			sin6 = (struct sockaddr_in6 *)&iflr->addr;
169359aecc96SHajimu UMEMOTO 			if (sin6->sin6_addr.s6_addr32[2] != 0 ||
169459aecc96SHajimu UMEMOTO 			    sin6->sin6_addr.s6_addr32[3] != 0) {
169515cc25e9SBjoern A. Zeeb 				if (ifa != NULL)
169615cc25e9SBjoern A. Zeeb 					ifa_free(ifa);
169782cd038dSYoshinobu Inoue 				return EINVAL;
169882cd038dSYoshinobu Inoue 			}
169982cd038dSYoshinobu Inoue 		} else
170082cd038dSYoshinobu Inoue 			prefixlen = iflr->prefixlen;
170182cd038dSYoshinobu Inoue 
170282cd038dSYoshinobu Inoue 		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
170382cd038dSYoshinobu Inoue 		bzero(&ifra, sizeof(ifra));
170406cd0a3fSHajimu UMEMOTO 		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
170582cd038dSYoshinobu Inoue 
1706686cdd19SJun-ichiro itojun Hagino 		bcopy(&iflr->addr, &ifra.ifra_addr,
1707686cdd19SJun-ichiro itojun Hagino 		    ((struct sockaddr *)&iflr->addr)->sa_len);
170882cd038dSYoshinobu Inoue 		if (hostid) {
170982cd038dSYoshinobu Inoue 			/* fill in hostid part */
171082cd038dSYoshinobu Inoue 			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
171182cd038dSYoshinobu Inoue 			    hostid->s6_addr32[2];
171282cd038dSYoshinobu Inoue 			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
171382cd038dSYoshinobu Inoue 			    hostid->s6_addr32[3];
171482cd038dSYoshinobu Inoue 		}
171582cd038dSYoshinobu Inoue 
1716686cdd19SJun-ichiro itojun Hagino 		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
171782cd038dSYoshinobu Inoue 			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1718686cdd19SJun-ichiro itojun Hagino 			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
171982cd038dSYoshinobu Inoue 			if (hostid) {
172082cd038dSYoshinobu Inoue 				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
172182cd038dSYoshinobu Inoue 				    hostid->s6_addr32[2];
172282cd038dSYoshinobu Inoue 				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
172382cd038dSYoshinobu Inoue 				    hostid->s6_addr32[3];
172482cd038dSYoshinobu Inoue 			}
172582cd038dSYoshinobu Inoue 		}
17268c0fec80SRobert Watson 		if (ifa != NULL)
17278c0fec80SRobert Watson 			ifa_free(ifa);
172882cd038dSYoshinobu Inoue 
172982cd038dSYoshinobu Inoue 		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1730ae360dddSHajimu UMEMOTO 		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
173182cd038dSYoshinobu Inoue 
173282cd038dSYoshinobu Inoue 		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
1733b40ce416SJulian Elischer 		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
173482cd038dSYoshinobu Inoue 	    }
173582cd038dSYoshinobu Inoue 	case SIOCGLIFADDR:
173682cd038dSYoshinobu Inoue 	case SIOCDLIFADDR:
173782cd038dSYoshinobu Inoue 	    {
173882cd038dSYoshinobu Inoue 		struct in6_ifaddr *ia;
173982cd038dSYoshinobu Inoue 		struct in6_addr mask, candidate, match;
174082cd038dSYoshinobu Inoue 		struct sockaddr_in6 *sin6;
174182cd038dSYoshinobu Inoue 		int cmp;
174282cd038dSYoshinobu Inoue 
174382cd038dSYoshinobu Inoue 		bzero(&mask, sizeof(mask));
174482cd038dSYoshinobu Inoue 		if (iflr->flags & IFLR_PREFIX) {
174582cd038dSYoshinobu Inoue 			/* lookup a prefix rather than address. */
1746ae360dddSHajimu UMEMOTO 			in6_prefixlen2mask(&mask, iflr->prefixlen);
174782cd038dSYoshinobu Inoue 
174882cd038dSYoshinobu Inoue 			sin6 = (struct sockaddr_in6 *)&iflr->addr;
174982cd038dSYoshinobu Inoue 			bcopy(&sin6->sin6_addr, &match, sizeof(match));
175082cd038dSYoshinobu Inoue 			match.s6_addr32[0] &= mask.s6_addr32[0];
175182cd038dSYoshinobu Inoue 			match.s6_addr32[1] &= mask.s6_addr32[1];
175282cd038dSYoshinobu Inoue 			match.s6_addr32[2] &= mask.s6_addr32[2];
175382cd038dSYoshinobu Inoue 			match.s6_addr32[3] &= mask.s6_addr32[3];
175482cd038dSYoshinobu Inoue 
175582cd038dSYoshinobu Inoue 			/* if you set extra bits, that's wrong */
175682cd038dSYoshinobu Inoue 			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
175782cd038dSYoshinobu Inoue 				return EINVAL;
175882cd038dSYoshinobu Inoue 
175982cd038dSYoshinobu Inoue 			cmp = 1;
176082cd038dSYoshinobu Inoue 		} else {
176182cd038dSYoshinobu Inoue 			if (cmd == SIOCGLIFADDR) {
176282cd038dSYoshinobu Inoue 				/* on getting an address, take the 1st match */
176382cd038dSYoshinobu Inoue 				cmp = 0;	/* XXX */
176482cd038dSYoshinobu Inoue 			} else {
176582cd038dSYoshinobu Inoue 				/* on deleting an address, do exact match */
1766ae360dddSHajimu UMEMOTO 				in6_prefixlen2mask(&mask, 128);
176782cd038dSYoshinobu Inoue 				sin6 = (struct sockaddr_in6 *)&iflr->addr;
176882cd038dSYoshinobu Inoue 				bcopy(&sin6->sin6_addr, &match, sizeof(match));
176982cd038dSYoshinobu Inoue 
177082cd038dSYoshinobu Inoue 				cmp = 1;
177182cd038dSYoshinobu Inoue 			}
177282cd038dSYoshinobu Inoue 		}
177382cd038dSYoshinobu Inoue 
1774137f91e8SJohn Baldwin 		IF_ADDR_RLOCK(ifp);
1775c4dd3fe1SRobert Watson 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
177682cd038dSYoshinobu Inoue 			if (ifa->ifa_addr->sa_family != AF_INET6)
177782cd038dSYoshinobu Inoue 				continue;
177882cd038dSYoshinobu Inoue 			if (!cmp)
177982cd038dSYoshinobu Inoue 				break;
178033841545SHajimu UMEMOTO 
178133841545SHajimu UMEMOTO 			/*
178233841545SHajimu UMEMOTO 			 * XXX: this is adhoc, but is necessary to allow
178333841545SHajimu UMEMOTO 			 * a user to specify fe80::/64 (not /10) for a
178433841545SHajimu UMEMOTO 			 * link-local address.
178533841545SHajimu UMEMOTO 			 */
1786a1f7e5f8SHajimu UMEMOTO 			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1787a1f7e5f8SHajimu UMEMOTO 			in6_clearscope(&candidate);
178882cd038dSYoshinobu Inoue 			candidate.s6_addr32[0] &= mask.s6_addr32[0];
178982cd038dSYoshinobu Inoue 			candidate.s6_addr32[1] &= mask.s6_addr32[1];
179082cd038dSYoshinobu Inoue 			candidate.s6_addr32[2] &= mask.s6_addr32[2];
179182cd038dSYoshinobu Inoue 			candidate.s6_addr32[3] &= mask.s6_addr32[3];
179282cd038dSYoshinobu Inoue 			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
179382cd038dSYoshinobu Inoue 				break;
179482cd038dSYoshinobu Inoue 		}
17959f745f61SJohn Baldwin 		if (ifa != NULL)
17969f745f61SJohn Baldwin 			ifa_ref(ifa);
1797137f91e8SJohn Baldwin 		IF_ADDR_RUNLOCK(ifp);
179882cd038dSYoshinobu Inoue 		if (!ifa)
179982cd038dSYoshinobu Inoue 			return EADDRNOTAVAIL;
180082cd038dSYoshinobu Inoue 		ia = ifa2ia6(ifa);
180182cd038dSYoshinobu Inoue 
180282cd038dSYoshinobu Inoue 		if (cmd == SIOCGLIFADDR) {
1803a1f7e5f8SHajimu UMEMOTO 			int error;
180433841545SHajimu UMEMOTO 
180582cd038dSYoshinobu Inoue 			/* fill in the if_laddrreq structure */
180682cd038dSYoshinobu Inoue 			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1807a1f7e5f8SHajimu UMEMOTO 			error = sa6_recoverscope(
1808a1f7e5f8SHajimu UMEMOTO 			    (struct sockaddr_in6 *)&iflr->addr);
18099f745f61SJohn Baldwin 			if (error != 0) {
18109f745f61SJohn Baldwin 				ifa_free(ifa);
1811a1f7e5f8SHajimu UMEMOTO 				return (error);
18129f745f61SJohn Baldwin 			}
1813a1f7e5f8SHajimu UMEMOTO 
181482cd038dSYoshinobu Inoue 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
181582cd038dSYoshinobu Inoue 				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
181682cd038dSYoshinobu Inoue 				    ia->ia_dstaddr.sin6_len);
1817a1f7e5f8SHajimu UMEMOTO 				error = sa6_recoverscope(
1818a1f7e5f8SHajimu UMEMOTO 				    (struct sockaddr_in6 *)&iflr->dstaddr);
18199f745f61SJohn Baldwin 				if (error != 0) {
18209f745f61SJohn Baldwin 					ifa_free(ifa);
1821a1f7e5f8SHajimu UMEMOTO 					return (error);
18229f745f61SJohn Baldwin 				}
182382cd038dSYoshinobu Inoue 			} else
182482cd038dSYoshinobu Inoue 				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
182582cd038dSYoshinobu Inoue 
182682cd038dSYoshinobu Inoue 			iflr->prefixlen =
182706cd0a3fSHajimu UMEMOTO 			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
182882cd038dSYoshinobu Inoue 
182982cd038dSYoshinobu Inoue 			iflr->flags = ia->ia6_flags;	/* XXX */
18309f745f61SJohn Baldwin 			ifa_free(ifa);
183182cd038dSYoshinobu Inoue 
183282cd038dSYoshinobu Inoue 			return 0;
183382cd038dSYoshinobu Inoue 		} else {
183482cd038dSYoshinobu Inoue 			struct in6_aliasreq ifra;
183582cd038dSYoshinobu Inoue 
183682cd038dSYoshinobu Inoue 			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
183782cd038dSYoshinobu Inoue 			bzero(&ifra, sizeof(ifra));
183882cd038dSYoshinobu Inoue 			bcopy(iflr->iflr_name, ifra.ifra_name,
183982cd038dSYoshinobu Inoue 			    sizeof(ifra.ifra_name));
184082cd038dSYoshinobu Inoue 
184182cd038dSYoshinobu Inoue 			bcopy(&ia->ia_addr, &ifra.ifra_addr,
184282cd038dSYoshinobu Inoue 			    ia->ia_addr.sin6_len);
184382cd038dSYoshinobu Inoue 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
184482cd038dSYoshinobu Inoue 				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
184582cd038dSYoshinobu Inoue 				    ia->ia_dstaddr.sin6_len);
1846686cdd19SJun-ichiro itojun Hagino 			} else {
1847686cdd19SJun-ichiro itojun Hagino 				bzero(&ifra.ifra_dstaddr,
1848686cdd19SJun-ichiro itojun Hagino 				    sizeof(ifra.ifra_dstaddr));
184982cd038dSYoshinobu Inoue 			}
185082cd038dSYoshinobu Inoue 			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
185182cd038dSYoshinobu Inoue 			    ia->ia_prefixmask.sin6_len);
185282cd038dSYoshinobu Inoue 
185382cd038dSYoshinobu Inoue 			ifra.ifra_flags = ia->ia6_flags;
18549f745f61SJohn Baldwin 			ifa_free(ifa);
185582cd038dSYoshinobu Inoue 			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1856b40ce416SJulian Elischer 			    ifp, td);
185782cd038dSYoshinobu Inoue 		}
185882cd038dSYoshinobu Inoue 	    }
185982cd038dSYoshinobu Inoue 	}
186082cd038dSYoshinobu Inoue 
186182cd038dSYoshinobu Inoue 	return EOPNOTSUPP;	/* just for safety */
186282cd038dSYoshinobu Inoue }
186382cd038dSYoshinobu Inoue 
186482cd038dSYoshinobu Inoue /*
186581d5d46bSBjoern A. Zeeb  * Initialize an interface's IPv6 address and routing table entry.
186682cd038dSYoshinobu Inoue  */
186733841545SHajimu UMEMOTO static int
18681272577eSXin LI in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
18691272577eSXin LI     struct sockaddr_in6 *sin6, int newhost)
187082cd038dSYoshinobu Inoue {
187133841545SHajimu UMEMOTO 	int	error = 0, plen, ifacount = 0;
187233841545SHajimu UMEMOTO 	struct ifaddr *ifa;
187382cd038dSYoshinobu Inoue 
187482cd038dSYoshinobu Inoue 	/*
187582cd038dSYoshinobu Inoue 	 * Give the interface a chance to initialize
187682cd038dSYoshinobu Inoue 	 * if this is its first address,
187782cd038dSYoshinobu Inoue 	 * and to validate the address if necessary.
187882cd038dSYoshinobu Inoue 	 */
1879137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1880c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
188133841545SHajimu UMEMOTO 		if (ifa->ifa_addr->sa_family != AF_INET6)
188233841545SHajimu UMEMOTO 			continue;
188333841545SHajimu UMEMOTO 		ifacount++;
188433841545SHajimu UMEMOTO 	}
1885137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
188633841545SHajimu UMEMOTO 
188733841545SHajimu UMEMOTO 	ia->ia_addr = *sin6;
188833841545SHajimu UMEMOTO 
1889ba5da2a0SIan Dowse 	if (ifacount <= 1 && ifp->if_ioctl) {
1890ba5da2a0SIan Dowse 		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
1891c9b652e3SAndre Oppermann 		if (error)
189282cd038dSYoshinobu Inoue 			return (error);
189382cd038dSYoshinobu Inoue 	}
189433841545SHajimu UMEMOTO 
189582cd038dSYoshinobu Inoue 	ia->ia_ifa.ifa_metric = ifp->if_metric;
189633841545SHajimu UMEMOTO 
189733841545SHajimu UMEMOTO 	/* we could do in(6)_socktrim here, but just omit it at this moment. */
189833841545SHajimu UMEMOTO 
189933841545SHajimu UMEMOTO 	/*
190033841545SHajimu UMEMOTO 	 * Special case:
190180343432SHajimu UMEMOTO 	 * If a new destination address is specified for a point-to-point
190233841545SHajimu UMEMOTO 	 * interface, install a route to the destination as an interface
19036e6b3f7cSQing Li 	 * direct route.
190480343432SHajimu UMEMOTO 	 * XXX: the logic below rejects assigning multiple addresses on a p2p
1905a59af512SGeorge V. Neville-Neil 	 * interface that share the same destination.
190633841545SHajimu UMEMOTO 	 */
190733841545SHajimu UMEMOTO 	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
190809b03548SQing Li 	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
190909b03548SQing Li 	    ia->ia_dstaddr.sin6_family == AF_INET6) {
1910a59af512SGeorge V. Neville-Neil 		int rtflags = RTF_UP | RTF_HOST;
191181d5d46bSBjoern A. Zeeb 		error = rtinit(&ia->ia_ifa, RTM_ADD, ia->ia_flags | rtflags);
191281d5d46bSBjoern A. Zeeb 		if (error)
191333841545SHajimu UMEMOTO 			return (error);
191482cd038dSYoshinobu Inoue 		ia->ia_flags |= IFA_ROUTE;
191514417253SQing Li 		/*
191614417253SQing Li 		 * Handle the case for ::1 .
191714417253SQing Li 		 */
191814417253SQing Li 		if (ifp->if_flags & IFF_LOOPBACK)
191914417253SQing Li 			ia->ia_flags |= IFA_RTSELF;
192033841545SHajimu UMEMOTO 	}
192182cd038dSYoshinobu Inoue 
192205b262e2SQing Li 	/*
192305b262e2SQing Li 	 * add a loopback route to self
192405b262e2SQing Li 	 */
192514417253SQing Li 	if (!(ia->ia_flags & IFA_RTSELF) && V_nd6_useloopback) {
19269bb7d0f4SQing Li 		error = ifa_add_loopback_route((struct ifaddr *)ia,
19279bb7d0f4SQing Li 		    (struct sockaddr *)&ia->ia_addr);
1928c7ab6602SQing Li 		if (error == 0)
1929c7ab6602SQing Li 			ia->ia_flags |= IFA_RTSELF;
193005b262e2SQing Li 	}
193105b262e2SQing Li 
193281d5d46bSBjoern A. Zeeb 	/* Add local address to lltable, if necessary (ex. on p2p link). */
1933b590b6aeSGleb Smirnoff 	if (newhost)
1934b590b6aeSGleb Smirnoff 		in6_ifaddloop(&(ia->ia_ifa));
193582cd038dSYoshinobu Inoue 
193682cd038dSYoshinobu Inoue 	return (error);
193782cd038dSYoshinobu Inoue }
193882cd038dSYoshinobu Inoue 
193982cd038dSYoshinobu Inoue /*
194082cd038dSYoshinobu Inoue  * Find an IPv6 interface link-local address specific to an interface.
19418c0fec80SRobert Watson  * ifaddr is returned referenced.
194282cd038dSYoshinobu Inoue  */
194382cd038dSYoshinobu Inoue struct in6_ifaddr *
19441272577eSXin LI in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
194582cd038dSYoshinobu Inoue {
194633841545SHajimu UMEMOTO 	struct ifaddr *ifa;
194782cd038dSYoshinobu Inoue 
1948137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1949c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
195082cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
195182cd038dSYoshinobu Inoue 			continue;
1952686cdd19SJun-ichiro itojun Hagino 		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
1953686cdd19SJun-ichiro itojun Hagino 			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
1954686cdd19SJun-ichiro itojun Hagino 			    ignoreflags) != 0)
1955686cdd19SJun-ichiro itojun Hagino 				continue;
19568c0fec80SRobert Watson 			ifa_ref(ifa);
195782cd038dSYoshinobu Inoue 			break;
195882cd038dSYoshinobu Inoue 		}
1959686cdd19SJun-ichiro itojun Hagino 	}
1960137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
196182cd038dSYoshinobu Inoue 
196282cd038dSYoshinobu Inoue 	return ((struct in6_ifaddr *)ifa);
196382cd038dSYoshinobu Inoue }
196482cd038dSYoshinobu Inoue 
196582cd038dSYoshinobu Inoue 
196682cd038dSYoshinobu Inoue /*
196782cd038dSYoshinobu Inoue  * find the internet address corresponding to a given interface and address.
19688c0fec80SRobert Watson  * ifaddr is returned referenced.
196982cd038dSYoshinobu Inoue  */
197082cd038dSYoshinobu Inoue struct in6_ifaddr *
19711272577eSXin LI in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
197282cd038dSYoshinobu Inoue {
197333841545SHajimu UMEMOTO 	struct ifaddr *ifa;
197482cd038dSYoshinobu Inoue 
1975137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
1976c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
197782cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
197882cd038dSYoshinobu Inoue 			continue;
19798c0fec80SRobert Watson 		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) {
19808c0fec80SRobert Watson 			ifa_ref(ifa);
198182cd038dSYoshinobu Inoue 			break;
198282cd038dSYoshinobu Inoue 		}
19838c0fec80SRobert Watson 	}
1984137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
198582cd038dSYoshinobu Inoue 
198682cd038dSYoshinobu Inoue 	return ((struct in6_ifaddr *)ifa);
198782cd038dSYoshinobu Inoue }
198882cd038dSYoshinobu Inoue 
198982cd038dSYoshinobu Inoue /*
1990af805644SHiroki Sato  * Find a link-local scoped address on ifp and return it if any.
1991af805644SHiroki Sato  */
1992af805644SHiroki Sato struct in6_ifaddr *
1993af805644SHiroki Sato in6ifa_llaonifp(struct ifnet *ifp)
1994af805644SHiroki Sato {
1995af805644SHiroki Sato 	struct sockaddr_in6 *sin6;
1996af805644SHiroki Sato 	struct ifaddr *ifa;
1997af805644SHiroki Sato 
1998af805644SHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
1999af805644SHiroki Sato 		return (NULL);
2000af805644SHiroki Sato 	if_addr_rlock(ifp);
2001af805644SHiroki Sato 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
2002af805644SHiroki Sato 		if (ifa->ifa_addr->sa_family != AF_INET6)
2003af805644SHiroki Sato 			continue;
2004af805644SHiroki Sato 		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
2005af805644SHiroki Sato 		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
2006af805644SHiroki Sato 		    IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr) ||
2007af805644SHiroki Sato 		    IN6_IS_ADDR_MC_NODELOCAL(&sin6->sin6_addr))
2008af805644SHiroki Sato 			break;
2009af805644SHiroki Sato 	}
2010af805644SHiroki Sato 	if_addr_runlock(ifp);
2011af805644SHiroki Sato 
2012af805644SHiroki Sato 	return ((struct in6_ifaddr *)ifa);
2013af805644SHiroki Sato }
2014af805644SHiroki Sato 
2015af805644SHiroki Sato /*
20161d54aa3bSBjoern A. Zeeb  * Convert IP6 address to printable (loggable) representation. Caller
20171d54aa3bSBjoern A. Zeeb  * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long.
201882cd038dSYoshinobu Inoue  */
201982cd038dSYoshinobu Inoue static char digits[] = "0123456789abcdef";
202082cd038dSYoshinobu Inoue char *
20211d54aa3bSBjoern A. Zeeb ip6_sprintf(char *ip6buf, const struct in6_addr *addr)
202282cd038dSYoshinobu Inoue {
20238e96292dSAlfred Perlstein 	int i, cnt = 0, maxcnt = 0, idx = 0, index = 0;
202433841545SHajimu UMEMOTO 	char *cp;
202559aecc96SHajimu UMEMOTO 	const u_int16_t *a = (const u_int16_t *)addr;
202659aecc96SHajimu UMEMOTO 	const u_int8_t *d;
2027e521ae0cSBjoern A. Zeeb 	int dcolon = 0, zero = 0;
202882cd038dSYoshinobu Inoue 
20291d54aa3bSBjoern A. Zeeb 	cp = ip6buf;
203082cd038dSYoshinobu Inoue 
203182cd038dSYoshinobu Inoue 	for (i = 0; i < 8; i++) {
20328e96292dSAlfred Perlstein 		if (*(a + i) == 0) {
20338e96292dSAlfred Perlstein 			cnt++;
20348e96292dSAlfred Perlstein 			if (cnt == 1)
20358e96292dSAlfred Perlstein 				idx = i;
20368e96292dSAlfred Perlstein 		}
20378e96292dSAlfred Perlstein 		else if (maxcnt < cnt) {
20388e96292dSAlfred Perlstein 			maxcnt = cnt;
20398e96292dSAlfred Perlstein 			index = idx;
20408e96292dSAlfred Perlstein 			cnt = 0;
20418e96292dSAlfred Perlstein 		}
20428e96292dSAlfred Perlstein 	}
20438e96292dSAlfred Perlstein 	if (maxcnt < cnt) {
20448e96292dSAlfred Perlstein 		maxcnt = cnt;
20458e96292dSAlfred Perlstein 		index = idx;
20468e96292dSAlfred Perlstein 	}
20478e96292dSAlfred Perlstein 
20488e96292dSAlfred Perlstein 	for (i = 0; i < 8; i++) {
204982cd038dSYoshinobu Inoue 		if (dcolon == 1) {
205082cd038dSYoshinobu Inoue 			if (*a == 0) {
205182cd038dSYoshinobu Inoue 				if (i == 7)
205282cd038dSYoshinobu Inoue 					*cp++ = ':';
205382cd038dSYoshinobu Inoue 				a++;
205482cd038dSYoshinobu Inoue 				continue;
205582cd038dSYoshinobu Inoue 			} else
205682cd038dSYoshinobu Inoue 				dcolon = 2;
205782cd038dSYoshinobu Inoue 		}
205882cd038dSYoshinobu Inoue 		if (*a == 0) {
20598e96292dSAlfred Perlstein 			if (dcolon == 0 && *(a + 1) == 0 && i == index) {
206082cd038dSYoshinobu Inoue 				if (i == 0)
206182cd038dSYoshinobu Inoue 					*cp++ = ':';
206282cd038dSYoshinobu Inoue 				*cp++ = ':';
206382cd038dSYoshinobu Inoue 				dcolon = 1;
206482cd038dSYoshinobu Inoue 			} else {
206582cd038dSYoshinobu Inoue 				*cp++ = '0';
206682cd038dSYoshinobu Inoue 				*cp++ = ':';
206782cd038dSYoshinobu Inoue 			}
206882cd038dSYoshinobu Inoue 			a++;
206982cd038dSYoshinobu Inoue 			continue;
207082cd038dSYoshinobu Inoue 		}
2071c4c0c592SAlfred Perlstein 		d = (const u_char *)a;
2072e521ae0cSBjoern A. Zeeb 		/* Try to eliminate leading zeros in printout like in :0001. */
2073e521ae0cSBjoern A. Zeeb 		zero = 1;
2074e521ae0cSBjoern A. Zeeb 		*cp = digits[*d >> 4];
2075e521ae0cSBjoern A. Zeeb 		if (*cp != '0') {
2076e521ae0cSBjoern A. Zeeb 			zero = 0;
2077e521ae0cSBjoern A. Zeeb 			cp++;
2078e521ae0cSBjoern A. Zeeb 		}
2079e521ae0cSBjoern A. Zeeb 		*cp = digits[*d++ & 0xf];
2080e521ae0cSBjoern A. Zeeb 		if (zero == 0 || (*cp != '0')) {
2081e521ae0cSBjoern A. Zeeb 			zero = 0;
2082e521ae0cSBjoern A. Zeeb 			cp++;
2083e521ae0cSBjoern A. Zeeb 		}
2084e521ae0cSBjoern A. Zeeb 		*cp = digits[*d >> 4];
2085e521ae0cSBjoern A. Zeeb 		if (zero == 0 || (*cp != '0')) {
2086e521ae0cSBjoern A. Zeeb 			zero = 0;
2087e521ae0cSBjoern A. Zeeb 			cp++;
2088e521ae0cSBjoern A. Zeeb 		}
208982cd038dSYoshinobu Inoue 		*cp++ = digits[*d & 0xf];
209082cd038dSYoshinobu Inoue 		*cp++ = ':';
209182cd038dSYoshinobu Inoue 		a++;
209282cd038dSYoshinobu Inoue 	}
20931d54aa3bSBjoern A. Zeeb 	*--cp = '\0';
20941d54aa3bSBjoern A. Zeeb 	return (ip6buf);
209582cd038dSYoshinobu Inoue }
209682cd038dSYoshinobu Inoue 
209782cd038dSYoshinobu Inoue int
20981272577eSXin LI in6_localaddr(struct in6_addr *in6)
209982cd038dSYoshinobu Inoue {
210082cd038dSYoshinobu Inoue 	struct in6_ifaddr *ia;
210182cd038dSYoshinobu Inoue 
210282cd038dSYoshinobu Inoue 	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
210382cd038dSYoshinobu Inoue 		return 1;
210482cd038dSYoshinobu Inoue 
2105d1da0a06SRobert Watson 	IN6_IFADDR_RLOCK();
210680af0152SRobert Watson 	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
210782cd038dSYoshinobu Inoue 		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
210806cd0a3fSHajimu UMEMOTO 		    &ia->ia_prefixmask.sin6_addr)) {
2109d1da0a06SRobert Watson 			IN6_IFADDR_RUNLOCK();
211082cd038dSYoshinobu Inoue 			return 1;
211106cd0a3fSHajimu UMEMOTO 		}
211206cd0a3fSHajimu UMEMOTO 	}
2113d1da0a06SRobert Watson 	IN6_IFADDR_RUNLOCK();
211482cd038dSYoshinobu Inoue 
211582cd038dSYoshinobu Inoue 	return (0);
211682cd038dSYoshinobu Inoue }
211782cd038dSYoshinobu Inoue 
211890bc35deSBjoern A. Zeeb /*
211990bc35deSBjoern A. Zeeb  * Return 1 if an internet address is for the local host and configured
212090bc35deSBjoern A. Zeeb  * on one of its interfaces.
212190bc35deSBjoern A. Zeeb  */
212290bc35deSBjoern A. Zeeb int
212390bc35deSBjoern A. Zeeb in6_localip(struct in6_addr *in6)
212490bc35deSBjoern A. Zeeb {
212590bc35deSBjoern A. Zeeb 	struct in6_ifaddr *ia;
212690bc35deSBjoern A. Zeeb 
212790bc35deSBjoern A. Zeeb 	IN6_IFADDR_RLOCK();
212868eba526SAndrey V. Elsukov 	LIST_FOREACH(ia, IN6ADDR_HASH(in6), ia6_hash) {
212990bc35deSBjoern A. Zeeb 		if (IN6_ARE_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr)) {
213090bc35deSBjoern A. Zeeb 			IN6_IFADDR_RUNLOCK();
213190bc35deSBjoern A. Zeeb 			return (1);
213290bc35deSBjoern A. Zeeb 		}
213390bc35deSBjoern A. Zeeb 	}
213490bc35deSBjoern A. Zeeb 	IN6_IFADDR_RUNLOCK();
213590bc35deSBjoern A. Zeeb 	return (0);
213690bc35deSBjoern A. Zeeb }
213790bc35deSBjoern A. Zeeb 
213833841545SHajimu UMEMOTO int
21391272577eSXin LI in6_is_addr_deprecated(struct sockaddr_in6 *sa6)
214033841545SHajimu UMEMOTO {
214133841545SHajimu UMEMOTO 	struct in6_ifaddr *ia;
214233841545SHajimu UMEMOTO 
2143d1da0a06SRobert Watson 	IN6_IFADDR_RLOCK();
214468eba526SAndrey V. Elsukov 	LIST_FOREACH(ia, IN6ADDR_HASH(&sa6->sin6_addr), ia6_hash) {
214568eba526SAndrey V. Elsukov 		if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), &sa6->sin6_addr)) {
214668eba526SAndrey V. Elsukov 			if (ia->ia6_flags & IN6_IFF_DEPRECATED) {
2147d1da0a06SRobert Watson 				IN6_IFADDR_RUNLOCK();
214833841545SHajimu UMEMOTO 				return (1); /* true */
2149d1da0a06SRobert Watson 			}
215068eba526SAndrey V. Elsukov 			break;
215168eba526SAndrey V. Elsukov 		}
215233841545SHajimu UMEMOTO 	}
2153d1da0a06SRobert Watson 	IN6_IFADDR_RUNLOCK();
215433841545SHajimu UMEMOTO 
215533841545SHajimu UMEMOTO 	return (0);		/* false */
215633841545SHajimu UMEMOTO }
215733841545SHajimu UMEMOTO 
215882cd038dSYoshinobu Inoue /*
215982cd038dSYoshinobu Inoue  * return length of part which dst and src are equal
216082cd038dSYoshinobu Inoue  * hard coding...
216182cd038dSYoshinobu Inoue  */
216282cd038dSYoshinobu Inoue int
21631272577eSXin LI in6_matchlen(struct in6_addr *src, struct in6_addr *dst)
216482cd038dSYoshinobu Inoue {
216582cd038dSYoshinobu Inoue 	int match = 0;
216682cd038dSYoshinobu Inoue 	u_char *s = (u_char *)src, *d = (u_char *)dst;
216782cd038dSYoshinobu Inoue 	u_char *lim = s + 16, r;
216882cd038dSYoshinobu Inoue 
216982cd038dSYoshinobu Inoue 	while (s < lim)
217082cd038dSYoshinobu Inoue 		if ((r = (*d++ ^ *s++)) != 0) {
217182cd038dSYoshinobu Inoue 			while (r < 128) {
217282cd038dSYoshinobu Inoue 				match++;
217382cd038dSYoshinobu Inoue 				r <<= 1;
217482cd038dSYoshinobu Inoue 			}
217582cd038dSYoshinobu Inoue 			break;
217682cd038dSYoshinobu Inoue 		} else
217782cd038dSYoshinobu Inoue 			match += 8;
217882cd038dSYoshinobu Inoue 	return match;
217982cd038dSYoshinobu Inoue }
218082cd038dSYoshinobu Inoue 
2181686cdd19SJun-ichiro itojun Hagino /* XXX: to be scope conscious */
218282cd038dSYoshinobu Inoue int
21831272577eSXin LI in6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len)
218482cd038dSYoshinobu Inoue {
218582cd038dSYoshinobu Inoue 	int bytelen, bitlen;
218682cd038dSYoshinobu Inoue 
218782cd038dSYoshinobu Inoue 	/* sanity check */
218882cd038dSYoshinobu Inoue 	if (0 > len || len > 128) {
218982cd038dSYoshinobu Inoue 		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
219082cd038dSYoshinobu Inoue 		    len);
219182cd038dSYoshinobu Inoue 		return (0);
219282cd038dSYoshinobu Inoue 	}
219382cd038dSYoshinobu Inoue 
219482cd038dSYoshinobu Inoue 	bytelen = len / 8;
219582cd038dSYoshinobu Inoue 	bitlen = len % 8;
219682cd038dSYoshinobu Inoue 
219782cd038dSYoshinobu Inoue 	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
219882cd038dSYoshinobu Inoue 		return (0);
219914135e2cSColin Percival 	if (bitlen != 0 &&
220014135e2cSColin Percival 	    p1->s6_addr[bytelen] >> (8 - bitlen) !=
220182cd038dSYoshinobu Inoue 	    p2->s6_addr[bytelen] >> (8 - bitlen))
220282cd038dSYoshinobu Inoue 		return (0);
220382cd038dSYoshinobu Inoue 
220482cd038dSYoshinobu Inoue 	return (1);
220582cd038dSYoshinobu Inoue }
220682cd038dSYoshinobu Inoue 
220782cd038dSYoshinobu Inoue void
22081272577eSXin LI in6_prefixlen2mask(struct in6_addr *maskp, int len)
220982cd038dSYoshinobu Inoue {
221082cd038dSYoshinobu Inoue 	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
221182cd038dSYoshinobu Inoue 	int bytelen, bitlen, i;
221282cd038dSYoshinobu Inoue 
221382cd038dSYoshinobu Inoue 	/* sanity check */
221482cd038dSYoshinobu Inoue 	if (0 > len || len > 128) {
221582cd038dSYoshinobu Inoue 		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
221682cd038dSYoshinobu Inoue 		    len);
221782cd038dSYoshinobu Inoue 		return;
221882cd038dSYoshinobu Inoue 	}
221982cd038dSYoshinobu Inoue 
222082cd038dSYoshinobu Inoue 	bzero(maskp, sizeof(*maskp));
222182cd038dSYoshinobu Inoue 	bytelen = len / 8;
222282cd038dSYoshinobu Inoue 	bitlen = len % 8;
222382cd038dSYoshinobu Inoue 	for (i = 0; i < bytelen; i++)
222482cd038dSYoshinobu Inoue 		maskp->s6_addr[i] = 0xff;
222582cd038dSYoshinobu Inoue 	if (bitlen)
222682cd038dSYoshinobu Inoue 		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
222782cd038dSYoshinobu Inoue }
222882cd038dSYoshinobu Inoue 
222982cd038dSYoshinobu Inoue /*
223082cd038dSYoshinobu Inoue  * return the best address out of the same scope. if no address was
223182cd038dSYoshinobu Inoue  * found, return the first valid address from designated IF.
223282cd038dSYoshinobu Inoue  */
223382cd038dSYoshinobu Inoue struct in6_ifaddr *
22341272577eSXin LI in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
223582cd038dSYoshinobu Inoue {
223682cd038dSYoshinobu Inoue 	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
223782cd038dSYoshinobu Inoue 	struct ifaddr *ifa;
223882cd038dSYoshinobu Inoue 	struct in6_ifaddr *besta = 0;
223982cd038dSYoshinobu Inoue 	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
224082cd038dSYoshinobu Inoue 
224182cd038dSYoshinobu Inoue 	dep[0] = dep[1] = NULL;
224282cd038dSYoshinobu Inoue 
224382cd038dSYoshinobu Inoue 	/*
224482cd038dSYoshinobu Inoue 	 * We first look for addresses in the same scope.
224582cd038dSYoshinobu Inoue 	 * If there is one, return it.
224682cd038dSYoshinobu Inoue 	 * If two or more, return one which matches the dst longest.
224782cd038dSYoshinobu Inoue 	 * If none, return one of global addresses assigned other ifs.
224882cd038dSYoshinobu Inoue 	 */
2249137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
2250c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
225182cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
225282cd038dSYoshinobu Inoue 			continue;
225382cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
225482cd038dSYoshinobu Inoue 			continue; /* XXX: is there any case to allow anycast? */
225582cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
225682cd038dSYoshinobu Inoue 			continue; /* don't use this interface */
225782cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
225882cd038dSYoshinobu Inoue 			continue;
225982cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2260603724d3SBjoern A. Zeeb 			if (V_ip6_use_deprecated)
226182cd038dSYoshinobu Inoue 				dep[0] = (struct in6_ifaddr *)ifa;
226282cd038dSYoshinobu Inoue 			continue;
226382cd038dSYoshinobu Inoue 		}
226482cd038dSYoshinobu Inoue 
226582cd038dSYoshinobu Inoue 		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
226682cd038dSYoshinobu Inoue 			/*
226782cd038dSYoshinobu Inoue 			 * call in6_matchlen() as few as possible
226882cd038dSYoshinobu Inoue 			 */
226982cd038dSYoshinobu Inoue 			if (besta) {
227082cd038dSYoshinobu Inoue 				if (blen == -1)
227182cd038dSYoshinobu Inoue 					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
227282cd038dSYoshinobu Inoue 				tlen = in6_matchlen(IFA_IN6(ifa), dst);
227382cd038dSYoshinobu Inoue 				if (tlen > blen) {
227482cd038dSYoshinobu Inoue 					blen = tlen;
227582cd038dSYoshinobu Inoue 					besta = (struct in6_ifaddr *)ifa;
227682cd038dSYoshinobu Inoue 				}
227782cd038dSYoshinobu Inoue 			} else
227882cd038dSYoshinobu Inoue 				besta = (struct in6_ifaddr *)ifa;
227982cd038dSYoshinobu Inoue 		}
228082cd038dSYoshinobu Inoue 	}
2281ac6ba962SRobert Watson 	if (besta) {
22828c0fec80SRobert Watson 		ifa_ref(&besta->ia_ifa);
2283137f91e8SJohn Baldwin 		IF_ADDR_RUNLOCK(ifp);
228482cd038dSYoshinobu Inoue 		return (besta);
2285ac6ba962SRobert Watson 	}
228682cd038dSYoshinobu Inoue 
2287c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
228882cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6)
228982cd038dSYoshinobu Inoue 			continue;
229082cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
229182cd038dSYoshinobu Inoue 			continue; /* XXX: is there any case to allow anycast? */
229282cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
229382cd038dSYoshinobu Inoue 			continue; /* don't use this interface */
229482cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
229582cd038dSYoshinobu Inoue 			continue;
229682cd038dSYoshinobu Inoue 		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2297603724d3SBjoern A. Zeeb 			if (V_ip6_use_deprecated)
229882cd038dSYoshinobu Inoue 				dep[1] = (struct in6_ifaddr *)ifa;
229982cd038dSYoshinobu Inoue 			continue;
230082cd038dSYoshinobu Inoue 		}
230182cd038dSYoshinobu Inoue 
23028c0fec80SRobert Watson 		if (ifa != NULL)
23038c0fec80SRobert Watson 			ifa_ref(ifa);
2304137f91e8SJohn Baldwin 		IF_ADDR_RUNLOCK(ifp);
230582cd038dSYoshinobu Inoue 		return (struct in6_ifaddr *)ifa;
230682cd038dSYoshinobu Inoue 	}
230782cd038dSYoshinobu Inoue 
230882cd038dSYoshinobu Inoue 	/* use the last-resort values, that are, deprecated addresses */
2309c784f9e5SMaksim Yevmenkin 	if (dep[0]) {
2310c784f9e5SMaksim Yevmenkin 		ifa_ref((struct ifaddr *)dep[0]);
2311c784f9e5SMaksim Yevmenkin 		IF_ADDR_RUNLOCK(ifp);
231282cd038dSYoshinobu Inoue 		return dep[0];
2313c784f9e5SMaksim Yevmenkin 	}
2314c784f9e5SMaksim Yevmenkin 	if (dep[1]) {
2315c784f9e5SMaksim Yevmenkin 		ifa_ref((struct ifaddr *)dep[1]);
2316c784f9e5SMaksim Yevmenkin 		IF_ADDR_RUNLOCK(ifp);
231782cd038dSYoshinobu Inoue 		return dep[1];
2318c784f9e5SMaksim Yevmenkin 	}
231982cd038dSYoshinobu Inoue 
2320c784f9e5SMaksim Yevmenkin 	IF_ADDR_RUNLOCK(ifp);
232182cd038dSYoshinobu Inoue 	return NULL;
232282cd038dSYoshinobu Inoue }
232382cd038dSYoshinobu Inoue 
232482cd038dSYoshinobu Inoue /*
232582cd038dSYoshinobu Inoue  * perform DAD when interface becomes IFF_UP.
232682cd038dSYoshinobu Inoue  */
232782cd038dSYoshinobu Inoue void
23281272577eSXin LI in6_if_up(struct ifnet *ifp)
232982cd038dSYoshinobu Inoue {
233082cd038dSYoshinobu Inoue 	struct ifaddr *ifa;
233182cd038dSYoshinobu Inoue 	struct in6_ifaddr *ia;
2332743eee66SSUZUKI Shinsuke 
2333137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
2334c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
2335743eee66SSUZUKI Shinsuke 		if (ifa->ifa_addr->sa_family != AF_INET6)
2336743eee66SSUZUKI Shinsuke 			continue;
2337743eee66SSUZUKI Shinsuke 		ia = (struct in6_ifaddr *)ifa;
2338743eee66SSUZUKI Shinsuke 		if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
2339743eee66SSUZUKI Shinsuke 			/*
2340743eee66SSUZUKI Shinsuke 			 * The TENTATIVE flag was likely set by hand
2341743eee66SSUZUKI Shinsuke 			 * beforehand, implicitly indicating the need for DAD.
2342743eee66SSUZUKI Shinsuke 			 * We may be able to skip the random delay in this
2343743eee66SSUZUKI Shinsuke 			 * case, but we impose delays just in case.
2344743eee66SSUZUKI Shinsuke 			 */
2345743eee66SSUZUKI Shinsuke 			nd6_dad_start(ifa,
2346743eee66SSUZUKI Shinsuke 			    arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
2347743eee66SSUZUKI Shinsuke 		}
2348743eee66SSUZUKI Shinsuke 	}
2349137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
235082cd038dSYoshinobu Inoue 
2351686cdd19SJun-ichiro itojun Hagino 	/*
2352686cdd19SJun-ichiro itojun Hagino 	 * special cases, like 6to4, are handled in in6_ifattach
2353686cdd19SJun-ichiro itojun Hagino 	 */
2354686cdd19SJun-ichiro itojun Hagino 	in6_ifattach(ifp, NULL);
235582cd038dSYoshinobu Inoue }
235682cd038dSYoshinobu Inoue 
235733841545SHajimu UMEMOTO int
23581272577eSXin LI in6if_do_dad(struct ifnet *ifp)
235933841545SHajimu UMEMOTO {
236033841545SHajimu UMEMOTO 	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
236133841545SHajimu UMEMOTO 		return (0);
236233841545SHajimu UMEMOTO 
2363a283298cSHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
2364a283298cSHiroki Sato 		return (0);
2365a283298cSHiroki Sato 
236633841545SHajimu UMEMOTO 	switch (ifp->if_type) {
236733841545SHajimu UMEMOTO #ifdef IFT_DUMMY
236833841545SHajimu UMEMOTO 	case IFT_DUMMY:
236933841545SHajimu UMEMOTO #endif
237033841545SHajimu UMEMOTO 	case IFT_FAITH:
237133841545SHajimu UMEMOTO 		/*
237233841545SHajimu UMEMOTO 		 * These interfaces do not have the IFF_LOOPBACK flag,
237333841545SHajimu UMEMOTO 		 * but loop packets back.  We do not have to do DAD on such
237433841545SHajimu UMEMOTO 		 * interfaces.  We should even omit it, because loop-backed
237533841545SHajimu UMEMOTO 		 * NS would confuse the DAD procedure.
237633841545SHajimu UMEMOTO 		 */
237733841545SHajimu UMEMOTO 		return (0);
237833841545SHajimu UMEMOTO 	default:
237933841545SHajimu UMEMOTO 		/*
238033841545SHajimu UMEMOTO 		 * Our DAD routine requires the interface up and running.
238133841545SHajimu UMEMOTO 		 * However, some interfaces can be up before the RUNNING
238233841545SHajimu UMEMOTO 		 * status.  Additionaly, users may try to assign addresses
238333841545SHajimu UMEMOTO 		 * before the interface becomes up (or running).
238433841545SHajimu UMEMOTO 		 * We simply skip DAD in such a case as a work around.
238533841545SHajimu UMEMOTO 		 * XXX: we should rather mark "tentative" on such addresses,
238633841545SHajimu UMEMOTO 		 * and do DAD after the interface becomes ready.
238733841545SHajimu UMEMOTO 		 */
238813f4c340SRobert Watson 		if (!((ifp->if_flags & IFF_UP) &&
238913f4c340SRobert Watson 		    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
239033841545SHajimu UMEMOTO 			return (0);
239133841545SHajimu UMEMOTO 
239233841545SHajimu UMEMOTO 		return (1);
239333841545SHajimu UMEMOTO 	}
239433841545SHajimu UMEMOTO }
239533841545SHajimu UMEMOTO 
239682cd038dSYoshinobu Inoue /*
239782cd038dSYoshinobu Inoue  * Calculate max IPv6 MTU through all the interfaces and store it
239882cd038dSYoshinobu Inoue  * to in6_maxmtu.
239982cd038dSYoshinobu Inoue  */
240082cd038dSYoshinobu Inoue void
24011272577eSXin LI in6_setmaxmtu(void)
240282cd038dSYoshinobu Inoue {
240382cd038dSYoshinobu Inoue 	unsigned long maxmtu = 0;
240482cd038dSYoshinobu Inoue 	struct ifnet *ifp;
240582cd038dSYoshinobu Inoue 
240677dfcdc4SRobert Watson 	IFNET_RLOCK_NOSLEEP();
24073b0b2840SJohn Baldwin 	TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
240831b3783cSHajimu UMEMOTO 		/* this function can be called during ifnet initialization */
240931b3783cSHajimu UMEMOTO 		if (!ifp->if_afdata[AF_INET6])
241031b3783cSHajimu UMEMOTO 			continue;
241182cd038dSYoshinobu Inoue 		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
241231b3783cSHajimu UMEMOTO 		    IN6_LINKMTU(ifp) > maxmtu)
241331b3783cSHajimu UMEMOTO 			maxmtu = IN6_LINKMTU(ifp);
241482cd038dSYoshinobu Inoue 	}
241577dfcdc4SRobert Watson 	IFNET_RUNLOCK_NOSLEEP();
241682cd038dSYoshinobu Inoue 	if (maxmtu)	/* update only when maxmtu is positive */
2417603724d3SBjoern A. Zeeb 		V_in6_maxmtu = maxmtu;
241882cd038dSYoshinobu Inoue }
241982cd038dSYoshinobu Inoue 
2420743eee66SSUZUKI Shinsuke /*
2421743eee66SSUZUKI Shinsuke  * Provide the length of interface identifiers to be used for the link attached
2422743eee66SSUZUKI Shinsuke  * to the given interface.  The length should be defined in "IPv6 over
2423743eee66SSUZUKI Shinsuke  * xxx-link" document.  Note that address architecture might also define
2424743eee66SSUZUKI Shinsuke  * the length for a particular set of address prefixes, regardless of the
2425743eee66SSUZUKI Shinsuke  * link type.  As clarified in rfc2462bis, those two definitions should be
2426743eee66SSUZUKI Shinsuke  * consistent, and those really are as of August 2004.
2427743eee66SSUZUKI Shinsuke  */
2428743eee66SSUZUKI Shinsuke int
24291272577eSXin LI in6_if2idlen(struct ifnet *ifp)
2430743eee66SSUZUKI Shinsuke {
2431743eee66SSUZUKI Shinsuke 	switch (ifp->if_type) {
2432743eee66SSUZUKI Shinsuke 	case IFT_ETHER:		/* RFC2464 */
2433743eee66SSUZUKI Shinsuke #ifdef IFT_PROPVIRTUAL
2434743eee66SSUZUKI Shinsuke 	case IFT_PROPVIRTUAL:	/* XXX: no RFC. treat it as ether */
2435743eee66SSUZUKI Shinsuke #endif
2436743eee66SSUZUKI Shinsuke #ifdef IFT_L2VLAN
2437743eee66SSUZUKI Shinsuke 	case IFT_L2VLAN:	/* ditto */
2438743eee66SSUZUKI Shinsuke #endif
2439743eee66SSUZUKI Shinsuke #ifdef IFT_IEEE80211
2440743eee66SSUZUKI Shinsuke 	case IFT_IEEE80211:	/* ditto */
2441743eee66SSUZUKI Shinsuke #endif
2442743eee66SSUZUKI Shinsuke #ifdef IFT_MIP
2443743eee66SSUZUKI Shinsuke 	case IFT_MIP:	/* ditto */
2444743eee66SSUZUKI Shinsuke #endif
2445e4cd31ddSJeff Roberson 	case IFT_INFINIBAND:
2446743eee66SSUZUKI Shinsuke 		return (64);
2447743eee66SSUZUKI Shinsuke 	case IFT_FDDI:		/* RFC2467 */
2448743eee66SSUZUKI Shinsuke 		return (64);
2449743eee66SSUZUKI Shinsuke 	case IFT_ISO88025:	/* RFC2470 (IPv6 over Token Ring) */
2450743eee66SSUZUKI Shinsuke 		return (64);
2451743eee66SSUZUKI Shinsuke 	case IFT_PPP:		/* RFC2472 */
2452743eee66SSUZUKI Shinsuke 		return (64);
2453743eee66SSUZUKI Shinsuke 	case IFT_ARCNET:	/* RFC2497 */
2454743eee66SSUZUKI Shinsuke 		return (64);
2455743eee66SSUZUKI Shinsuke 	case IFT_FRELAY:	/* RFC2590 */
2456743eee66SSUZUKI Shinsuke 		return (64);
2457743eee66SSUZUKI Shinsuke 	case IFT_IEEE1394:	/* RFC3146 */
2458743eee66SSUZUKI Shinsuke 		return (64);
2459743eee66SSUZUKI Shinsuke 	case IFT_GIF:
2460743eee66SSUZUKI Shinsuke 		return (64);	/* draft-ietf-v6ops-mech-v2-07 */
2461743eee66SSUZUKI Shinsuke 	case IFT_LOOP:
2462743eee66SSUZUKI Shinsuke 		return (64);	/* XXX: is this really correct? */
2463743eee66SSUZUKI Shinsuke 	default:
2464743eee66SSUZUKI Shinsuke 		/*
2465743eee66SSUZUKI Shinsuke 		 * Unknown link type:
2466743eee66SSUZUKI Shinsuke 		 * It might be controversial to use the today's common constant
2467743eee66SSUZUKI Shinsuke 		 * of 64 for these cases unconditionally.  For full compliance,
2468743eee66SSUZUKI Shinsuke 		 * we should return an error in this case.  On the other hand,
2469743eee66SSUZUKI Shinsuke 		 * if we simply miss the standard for the link type or a new
2470743eee66SSUZUKI Shinsuke 		 * standard is defined for a new link type, the IFID length
2471743eee66SSUZUKI Shinsuke 		 * is very likely to be the common constant.  As a compromise,
2472743eee66SSUZUKI Shinsuke 		 * we always use the constant, but make an explicit notice
2473743eee66SSUZUKI Shinsuke 		 * indicating the "unknown" case.
2474743eee66SSUZUKI Shinsuke 		 */
2475743eee66SSUZUKI Shinsuke 		printf("in6_if2idlen: unknown link type (%d)\n", ifp->if_type);
2476743eee66SSUZUKI Shinsuke 		return (64);
2477743eee66SSUZUKI Shinsuke 	}
2478743eee66SSUZUKI Shinsuke }
2479743eee66SSUZUKI Shinsuke 
24806e6b3f7cSQing Li #include <sys/sysctl.h>
24816e6b3f7cSQing Li 
24826e6b3f7cSQing Li struct in6_llentry {
24836e6b3f7cSQing Li 	struct llentry		base;
24846e6b3f7cSQing Li 	struct sockaddr_in6	l3_addr6;
24856e6b3f7cSQing Li };
24866e6b3f7cSQing Li 
24876e6b3f7cSQing Li /*
24886e6b3f7cSQing Li  * Deletes an address from the address table.
24896e6b3f7cSQing Li  * This function is called by the timer functions
24906e6b3f7cSQing Li  * such as arptimer() and nd6_llinfo_timer(), and
24916e6b3f7cSQing Li  * the caller does the locking.
24926e6b3f7cSQing Li  */
24936e6b3f7cSQing Li static void
24946e6b3f7cSQing Li in6_lltable_free(struct lltable *llt, struct llentry *lle)
24956e6b3f7cSQing Li {
2496fbc2ca1bSKip Macy 	LLE_WUNLOCK(lle);
2497fbc2ca1bSKip Macy 	LLE_LOCK_DESTROY(lle);
24986e6b3f7cSQing Li 	free(lle, M_LLTABLE);
24996e6b3f7cSQing Li }
25006e6b3f7cSQing Li 
2501a93cda78SKip Macy static struct llentry *
2502a93cda78SKip Macy in6_lltable_new(const struct sockaddr *l3addr, u_int flags)
2503a93cda78SKip Macy {
2504a93cda78SKip Macy 	struct in6_llentry *lle;
2505a93cda78SKip Macy 
2506ea50c13eSGleb Smirnoff 	lle = malloc(sizeof(struct in6_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
2507a93cda78SKip Macy 	if (lle == NULL)		/* NB: caller generates msg */
2508a93cda78SKip Macy 		return NULL;
2509a93cda78SKip Macy 
2510a93cda78SKip Macy 	lle->l3_addr6 = *(const struct sockaddr_in6 *)l3addr;
2511a93cda78SKip Macy 	lle->base.lle_refcnt = 1;
2512a93cda78SKip Macy 	lle->base.lle_free = in6_lltable_free;
2513a93cda78SKip Macy 	LLE_LOCK_INIT(&lle->base);
2514a93cda78SKip Macy 	callout_init_rw(&lle->base.ln_timer_ch, &lle->base.lle_lock,
2515a93cda78SKip Macy 	    CALLOUT_RETURNUNLOCKED);
2516a93cda78SKip Macy 
2517ea50c13eSGleb Smirnoff 	return (&lle->base);
2518a93cda78SKip Macy }
2519a93cda78SKip Macy 
2520c9d763bfSQing Li static void
2521ea50c13eSGleb Smirnoff in6_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
2522ea50c13eSGleb Smirnoff     const struct sockaddr *mask, u_int flags)
2523c9d763bfSQing Li {
2524c9d763bfSQing Li 	const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix;
2525c9d763bfSQing Li 	const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask;
2526c9d763bfSQing Li 	struct llentry *lle, *next;
2527ea50c13eSGleb Smirnoff 	int i;
2528c9d763bfSQing Li 
25295b84dc78SQing Li 	/*
25305b84dc78SQing Li 	 * (flags & LLE_STATIC) means deleting all entries
2531ea50c13eSGleb Smirnoff 	 * including static ND6 entries.
25325b84dc78SQing Li 	 */
2533ea537929SGleb Smirnoff 	IF_AFDATA_WLOCK(llt->llt_ifp);
2534c9d763bfSQing Li 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
2535c9d763bfSQing Li 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
2536c9d763bfSQing Li 			if (IN6_ARE_MASKED_ADDR_EQUAL(
2537ea537929SGleb Smirnoff 			    &satosin6(L3_ADDR(lle))->sin6_addr,
2538ea537929SGleb Smirnoff 			    &pfx->sin6_addr, &msk->sin6_addr) &&
2539ea537929SGleb Smirnoff 			    ((flags & LLE_STATIC) ||
2540ea537929SGleb Smirnoff 			    !(lle->la_flags & LLE_STATIC))) {
2541c9d763bfSQing Li 				LLE_WLOCK(lle);
2542ea537929SGleb Smirnoff 				if (callout_stop(&lle->la_timer))
2543becba438SBjoern A. Zeeb 					LLE_REMREF(lle);
2544c9d763bfSQing Li 				llentry_free(lle);
2545c9d763bfSQing Li 			}
2546c9d763bfSQing Li 		}
2547c9d763bfSQing Li 	}
2548ea537929SGleb Smirnoff 	IF_AFDATA_WUNLOCK(llt->llt_ifp);
2549c9d763bfSQing Li }
2550c9d763bfSQing Li 
25516e6b3f7cSQing Li static int
2552c7ab6602SQing Li in6_lltable_rtcheck(struct ifnet *ifp,
2553c7ab6602SQing Li 		    u_int flags,
2554c7ab6602SQing Li 		    const struct sockaddr *l3addr)
25556e6b3f7cSQing Li {
25566e6b3f7cSQing Li 	struct rtentry *rt;
25576e6b3f7cSQing Li 	char ip6buf[INET6_ADDRSTRLEN];
25586e6b3f7cSQing Li 
25596e6b3f7cSQing Li 	KASSERT(l3addr->sa_family == AF_INET6,
25606e6b3f7cSQing Li 	    ("sin_family %d", l3addr->sa_family));
25616e6b3f7cSQing Li 
256281d5d46bSBjoern A. Zeeb 	/* Our local addresses are always only installed on the default FIB. */
25636e6b3f7cSQing Li 	/* XXX rtalloc1 should take a const param */
256481d5d46bSBjoern A. Zeeb 	rt = in6_rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0,
256581d5d46bSBjoern A. Zeeb 	    RT_DEFAULT_FIB);
25666e6b3f7cSQing Li 	if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
25676e6b3f7cSQing Li 		struct ifaddr *ifa;
25686e6b3f7cSQing Li 		/*
25696e6b3f7cSQing Li 		 * Create an ND6 cache for an IPv6 neighbor
25706e6b3f7cSQing Li 		 * that is not covered by our own prefix.
25716e6b3f7cSQing Li 		 */
25726e6b3f7cSQing Li 		/* XXX ifaof_ifpforaddr should take a const param */
25736e6b3f7cSQing Li 		ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
25746e6b3f7cSQing Li 		if (ifa != NULL) {
25758c0fec80SRobert Watson 			ifa_free(ifa);
25766e6b3f7cSQing Li 			if (rt != NULL)
25772e730beaSBjoern A. Zeeb 				RTFREE_LOCKED(rt);
25786e6b3f7cSQing Li 			return 0;
25796e6b3f7cSQing Li 		}
25806e6b3f7cSQing Li 		log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
25816e6b3f7cSQing Li 		    ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
25826e6b3f7cSQing Li 		if (rt != NULL)
25832e730beaSBjoern A. Zeeb 			RTFREE_LOCKED(rt);
25846e6b3f7cSQing Li 		return EINVAL;
25856e6b3f7cSQing Li 	}
25862e730beaSBjoern A. Zeeb 	RTFREE_LOCKED(rt);
25876e6b3f7cSQing Li 	return 0;
25886e6b3f7cSQing Li }
25896e6b3f7cSQing Li 
25906e6b3f7cSQing Li static struct llentry *
25916e6b3f7cSQing Li in6_lltable_lookup(struct lltable *llt, u_int flags,
25926e6b3f7cSQing Li 	const struct sockaddr *l3addr)
25936e6b3f7cSQing Li {
25946e6b3f7cSQing Li 	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
25956e6b3f7cSQing Li 	struct ifnet *ifp = llt->llt_ifp;
25966e6b3f7cSQing Li 	struct llentry *lle;
25976e6b3f7cSQing Li 	struct llentries *lleh;
25986e6b3f7cSQing Li 	u_int hashkey;
25996e6b3f7cSQing Li 
26006e6b3f7cSQing Li 	IF_AFDATA_LOCK_ASSERT(ifp);
26016e6b3f7cSQing Li 	KASSERT(l3addr->sa_family == AF_INET6,
26026e6b3f7cSQing Li 	    ("sin_family %d", l3addr->sa_family));
26036e6b3f7cSQing Li 
26046e6b3f7cSQing Li 	hashkey = sin6->sin6_addr.s6_addr32[3];
26056e6b3f7cSQing Li 	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
26066e6b3f7cSQing Li 	LIST_FOREACH(lle, lleh, lle_next) {
2607dc495497SQing Li 		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)L3_ADDR(lle);
26086e6b3f7cSQing Li 		if (lle->la_flags & LLE_DELETED)
26096e6b3f7cSQing Li 			continue;
2610dc495497SQing Li 		if (bcmp(&sa6->sin6_addr, &sin6->sin6_addr,
2611dc495497SQing Li 		    sizeof(struct in6_addr)) == 0)
26126e6b3f7cSQing Li 			break;
26136e6b3f7cSQing Li 	}
26146e6b3f7cSQing Li 
26156e6b3f7cSQing Li 	if (lle == NULL) {
26166e6b3f7cSQing Li 		if (!(flags & LLE_CREATE))
26176e6b3f7cSQing Li 			return (NULL);
26186e6b3f7cSQing Li 		/*
26196e6b3f7cSQing Li 		 * A route that covers the given address must have
26206e6b3f7cSQing Li 		 * been installed 1st because we are doing a resolution,
26216e6b3f7cSQing Li 		 * verify this.
26226e6b3f7cSQing Li 		 */
26236e6b3f7cSQing Li 		if (!(flags & LLE_IFADDR) &&
2624c7ab6602SQing Li 		    in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
26256e6b3f7cSQing Li 			return NULL;
26266e6b3f7cSQing Li 
26276e6b3f7cSQing Li 		lle = in6_lltable_new(l3addr, flags);
26286e6b3f7cSQing Li 		if (lle == NULL) {
26296e6b3f7cSQing Li 			log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
26306e6b3f7cSQing Li 			return NULL;
26316e6b3f7cSQing Li 		}
26326e6b3f7cSQing Li 		lle->la_flags = flags & ~LLE_CREATE;
26336e6b3f7cSQing Li 		if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
26346e6b3f7cSQing Li 			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
26356e6b3f7cSQing Li 			lle->la_flags |= (LLE_VALID | LLE_STATIC);
26366e6b3f7cSQing Li 		}
26376e6b3f7cSQing Li 
26386e6b3f7cSQing Li 		lle->lle_tbl  = llt;
26396e6b3f7cSQing Li 		lle->lle_head = lleh;
2640ea537929SGleb Smirnoff 		lle->la_flags |= LLE_LINKED;
26416e6b3f7cSQing Li 		LIST_INSERT_HEAD(lleh, lle, lle_next);
26426e6b3f7cSQing Li 	} else if (flags & LLE_DELETE) {
2643ebf1c744SQing Li 		if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
26446e6b3f7cSQing Li 			LLE_WLOCK(lle);
2645ea537929SGleb Smirnoff 			lle->la_flags |= LLE_DELETED;
26466cb2b4e7SQing Li #ifdef DIAGNOSTIC
26476e6b3f7cSQing Li 			log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
26486e6b3f7cSQing Li #endif
26491571132fSOleg Bulyzhin 			if ((lle->la_flags &
26501571132fSOleg Bulyzhin 			    (LLE_STATIC | LLE_IFADDR)) == LLE_STATIC)
26511571132fSOleg Bulyzhin 				llentry_free(lle);
26521571132fSOleg Bulyzhin 			else
26531571132fSOleg Bulyzhin 				LLE_WUNLOCK(lle);
2654ebf1c744SQing Li 		}
26556e6b3f7cSQing Li 		lle = (void *)-1;
26566e6b3f7cSQing Li 	}
26576e6b3f7cSQing Li 	if (LLE_IS_VALID(lle)) {
26586e6b3f7cSQing Li 		if (flags & LLE_EXCLUSIVE)
26596e6b3f7cSQing Li 			LLE_WLOCK(lle);
26606e6b3f7cSQing Li 		else
26616e6b3f7cSQing Li 			LLE_RLOCK(lle);
26626e6b3f7cSQing Li 	}
26636e6b3f7cSQing Li 	return (lle);
26646e6b3f7cSQing Li }
26656e6b3f7cSQing Li 
26666e6b3f7cSQing Li static int
26676e6b3f7cSQing Li in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
26686e6b3f7cSQing Li {
26696e6b3f7cSQing Li 	struct ifnet *ifp = llt->llt_ifp;
26706e6b3f7cSQing Li 	struct llentry *lle;
26716e6b3f7cSQing Li 	/* XXX stack use */
26726e6b3f7cSQing Li 	struct {
26736e6b3f7cSQing Li 		struct rt_msghdr	rtm;
26746e6b3f7cSQing Li 		struct sockaddr_in6	sin6;
26756e6b3f7cSQing Li 		/*
26766e6b3f7cSQing Li 		 * ndp.c assumes that sdl is word aligned
26776e6b3f7cSQing Li 		 */
26786e6b3f7cSQing Li #ifdef __LP64__
26796e6b3f7cSQing Li 		uint32_t		pad;
26806e6b3f7cSQing Li #endif
26816e6b3f7cSQing Li 		struct sockaddr_dl	sdl;
26826e6b3f7cSQing Li 	} ndpc;
26836e6b3f7cSQing Li 	int i, error;
26846e6b3f7cSQing Li 
26859452b0d2SQing Li 	if (ifp->if_flags & IFF_LOOPBACK)
26869452b0d2SQing Li 		return 0;
26879452b0d2SQing Li 
2688dc56e98fSRobert Watson 	LLTABLE_LOCK_ASSERT();
26896e6b3f7cSQing Li 
26906e6b3f7cSQing Li 	error = 0;
26916e6b3f7cSQing Li 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
26926e6b3f7cSQing Li 		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
26936e6b3f7cSQing Li 			struct sockaddr_dl *sdl;
26946e6b3f7cSQing Li 
26956e6b3f7cSQing Li 			/* skip deleted or invalid entries */
26966e6b3f7cSQing Li 			if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
26976e6b3f7cSQing Li 				continue;
2698813dd6aeSBjoern A. Zeeb 			/* Skip if jailed and not a valid IP of the prison. */
2699b89e82ddSJamie Gritton 			if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
2700813dd6aeSBjoern A. Zeeb 				continue;
27016e6b3f7cSQing Li 			/*
27026e6b3f7cSQing Li 			 * produce a msg made of:
27036e6b3f7cSQing Li 			 *  struct rt_msghdr;
27046e6b3f7cSQing Li 			 *  struct sockaddr_in6 (IPv6)
27056e6b3f7cSQing Li 			 *  struct sockaddr_dl;
27066e6b3f7cSQing Li 			 */
27076e6b3f7cSQing Li 			bzero(&ndpc, sizeof(ndpc));
27086e6b3f7cSQing Li 			ndpc.rtm.rtm_msglen = sizeof(ndpc);
270914981d80SQing Li 			ndpc.rtm.rtm_version = RTM_VERSION;
271014981d80SQing Li 			ndpc.rtm.rtm_type = RTM_GET;
271114981d80SQing Li 			ndpc.rtm.rtm_flags = RTF_UP;
271214981d80SQing Li 			ndpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
27136e6b3f7cSQing Li 			ndpc.sin6.sin6_family = AF_INET6;
27146e6b3f7cSQing Li 			ndpc.sin6.sin6_len = sizeof(ndpc.sin6);
27156e6b3f7cSQing Li 			bcopy(L3_ADDR(lle), &ndpc.sin6, L3_ADDR_LEN(lle));
27160bebb544SHiroki Sato 			if (V_deembed_scopeid)
27170bebb544SHiroki Sato 				sa6_recoverscope(&ndpc.sin6);
27186e6b3f7cSQing Li 
27196e6b3f7cSQing Li 			/* publish */
27206e6b3f7cSQing Li 			if (lle->la_flags & LLE_PUB)
27216e6b3f7cSQing Li 				ndpc.rtm.rtm_flags |= RTF_ANNOUNCE;
27226e6b3f7cSQing Li 
27236e6b3f7cSQing Li 			sdl = &ndpc.sdl;
27246e6b3f7cSQing Li 			sdl->sdl_family = AF_LINK;
27256e6b3f7cSQing Li 			sdl->sdl_len = sizeof(*sdl);
27266e6b3f7cSQing Li 			sdl->sdl_alen = ifp->if_addrlen;
27276e6b3f7cSQing Li 			sdl->sdl_index = ifp->if_index;
27286e6b3f7cSQing Li 			sdl->sdl_type = ifp->if_type;
27296e6b3f7cSQing Li 			bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
27306e6b3f7cSQing Li 			ndpc.rtm.rtm_rmx.rmx_expire =
27316e6b3f7cSQing Li 			    lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
27328eca593cSQing Li 			ndpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
27336e6b3f7cSQing Li 			if (lle->la_flags & LLE_STATIC)
27346e6b3f7cSQing Li 				ndpc.rtm.rtm_flags |= RTF_STATIC;
27356e6b3f7cSQing Li 			ndpc.rtm.rtm_index = ifp->if_index;
27366e6b3f7cSQing Li 			error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc));
27376e6b3f7cSQing Li 			if (error)
27386e6b3f7cSQing Li 				break;
27396e6b3f7cSQing Li 		}
27406e6b3f7cSQing Li 	}
27416e6b3f7cSQing Li 	return error;
27426e6b3f7cSQing Li }
27436e6b3f7cSQing Li 
274431b1bfe1SHajimu UMEMOTO void *
27451272577eSXin LI in6_domifattach(struct ifnet *ifp)
274631b1bfe1SHajimu UMEMOTO {
274731b1bfe1SHajimu UMEMOTO 	struct in6_ifextra *ext;
274831b1bfe1SHajimu UMEMOTO 
27490de0dd9bSHiroki Sato 	/* There are not IPv6-capable interfaces. */
27500de0dd9bSHiroki Sato 	switch (ifp->if_type) {
27510de0dd9bSHiroki Sato 	case IFT_PFLOG:
27520de0dd9bSHiroki Sato 	case IFT_PFSYNC:
27530de0dd9bSHiroki Sato 	case IFT_USB:
27540de0dd9bSHiroki Sato 		return (NULL);
27550de0dd9bSHiroki Sato 	}
275631b1bfe1SHajimu UMEMOTO 	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
275731b1bfe1SHajimu UMEMOTO 	bzero(ext, sizeof(*ext));
275831b1bfe1SHajimu UMEMOTO 
27599f0f032dSAndrey V. Elsukov 	ext->in6_ifstat = malloc(sizeof(counter_u64_t) *
27609f0f032dSAndrey V. Elsukov 	    sizeof(struct in6_ifstat) / sizeof(uint64_t), M_IFADDR, M_WAITOK);
27612841260cSAndrey V. Elsukov 	COUNTER_ARRAY_ALLOC(ext->in6_ifstat,
27622841260cSAndrey V. Elsukov 	    sizeof(struct in6_ifstat) / sizeof(uint64_t), M_WAITOK);
276331b1bfe1SHajimu UMEMOTO 
27649f0f032dSAndrey V. Elsukov 	ext->icmp6_ifstat = malloc(sizeof(counter_u64_t) *
27659f0f032dSAndrey V. Elsukov 	    sizeof(struct icmp6_ifstat) / sizeof(uint64_t), M_IFADDR,
27662841260cSAndrey V. Elsukov 	    M_WAITOK);
27672841260cSAndrey V. Elsukov 	COUNTER_ARRAY_ALLOC(ext->icmp6_ifstat,
27682841260cSAndrey V. Elsukov 	    sizeof(struct icmp6_ifstat) / sizeof(uint64_t), M_WAITOK);
276931b1bfe1SHajimu UMEMOTO 
277031b1bfe1SHajimu UMEMOTO 	ext->nd_ifinfo = nd6_ifattach(ifp);
277131b1bfe1SHajimu UMEMOTO 	ext->scope6_id = scope6_ifattach(ifp);
27726e6b3f7cSQing Li 	ext->lltable = lltable_init(ifp, AF_INET6);
27736e6b3f7cSQing Li 	if (ext->lltable != NULL) {
2774c9d763bfSQing Li 		ext->lltable->llt_prefix_free = in6_lltable_prefix_free;
27756e6b3f7cSQing Li 		ext->lltable->llt_lookup = in6_lltable_lookup;
27766e6b3f7cSQing Li 		ext->lltable->llt_dump = in6_lltable_dump;
27776e6b3f7cSQing Li 	}
277833cde130SBruce M Simpson 
277933cde130SBruce M Simpson 	ext->mld_ifinfo = mld_domifattach(ifp);
278033cde130SBruce M Simpson 
278131b1bfe1SHajimu UMEMOTO 	return ext;
278231b1bfe1SHajimu UMEMOTO }
278331b1bfe1SHajimu UMEMOTO 
278431b1bfe1SHajimu UMEMOTO void
27851272577eSXin LI in6_domifdetach(struct ifnet *ifp, void *aux)
278631b1bfe1SHajimu UMEMOTO {
278731b1bfe1SHajimu UMEMOTO 	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
278831b1bfe1SHajimu UMEMOTO 
278933cde130SBruce M Simpson 	mld_domifdetach(ifp);
279031b1bfe1SHajimu UMEMOTO 	scope6_ifdetach(ext->scope6_id);
279131b1bfe1SHajimu UMEMOTO 	nd6_ifdetach(ext->nd_ifinfo);
27926e6b3f7cSQing Li 	lltable_free(ext->lltable);
27932841260cSAndrey V. Elsukov 	COUNTER_ARRAY_FREE(ext->in6_ifstat,
27942841260cSAndrey V. Elsukov 	    sizeof(struct in6_ifstat) / sizeof(uint64_t));
279531b1bfe1SHajimu UMEMOTO 	free(ext->in6_ifstat, M_IFADDR);
27962841260cSAndrey V. Elsukov 	COUNTER_ARRAY_FREE(ext->icmp6_ifstat,
27972841260cSAndrey V. Elsukov 	    sizeof(struct icmp6_ifstat) / sizeof(uint64_t));
279831b1bfe1SHajimu UMEMOTO 	free(ext->icmp6_ifstat, M_IFADDR);
279931b1bfe1SHajimu UMEMOTO 	free(ext, M_IFADDR);
280031b1bfe1SHajimu UMEMOTO }
280131b1bfe1SHajimu UMEMOTO 
280282cd038dSYoshinobu Inoue /*
280382cd038dSYoshinobu Inoue  * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
280482cd038dSYoshinobu Inoue  * v4 mapped addr or v4 compat addr
280582cd038dSYoshinobu Inoue  */
280682cd038dSYoshinobu Inoue void
280782cd038dSYoshinobu Inoue in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
280882cd038dSYoshinobu Inoue {
28091272577eSXin LI 
281082cd038dSYoshinobu Inoue 	bzero(sin, sizeof(*sin));
281182cd038dSYoshinobu Inoue 	sin->sin_len = sizeof(struct sockaddr_in);
281282cd038dSYoshinobu Inoue 	sin->sin_family = AF_INET;
281382cd038dSYoshinobu Inoue 	sin->sin_port = sin6->sin6_port;
281482cd038dSYoshinobu Inoue 	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
281582cd038dSYoshinobu Inoue }
281682cd038dSYoshinobu Inoue 
281782cd038dSYoshinobu Inoue /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
281882cd038dSYoshinobu Inoue void
281982cd038dSYoshinobu Inoue in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
282082cd038dSYoshinobu Inoue {
282182cd038dSYoshinobu Inoue 	bzero(sin6, sizeof(*sin6));
282282cd038dSYoshinobu Inoue 	sin6->sin6_len = sizeof(struct sockaddr_in6);
282382cd038dSYoshinobu Inoue 	sin6->sin6_family = AF_INET6;
282482cd038dSYoshinobu Inoue 	sin6->sin6_port = sin->sin_port;
282582cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[0] = 0;
282682cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[1] = 0;
282782cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
282882cd038dSYoshinobu Inoue 	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
282982cd038dSYoshinobu Inoue }
283082cd038dSYoshinobu Inoue 
283182cd038dSYoshinobu Inoue /* Convert sockaddr_in6 into sockaddr_in. */
283282cd038dSYoshinobu Inoue void
283382cd038dSYoshinobu Inoue in6_sin6_2_sin_in_sock(struct sockaddr *nam)
283482cd038dSYoshinobu Inoue {
283582cd038dSYoshinobu Inoue 	struct sockaddr_in *sin_p;
283682cd038dSYoshinobu Inoue 	struct sockaddr_in6 sin6;
283782cd038dSYoshinobu Inoue 
283882cd038dSYoshinobu Inoue 	/*
283982cd038dSYoshinobu Inoue 	 * Save original sockaddr_in6 addr and convert it
284082cd038dSYoshinobu Inoue 	 * to sockaddr_in.
284182cd038dSYoshinobu Inoue 	 */
284282cd038dSYoshinobu Inoue 	sin6 = *(struct sockaddr_in6 *)nam;
284382cd038dSYoshinobu Inoue 	sin_p = (struct sockaddr_in *)nam;
284482cd038dSYoshinobu Inoue 	in6_sin6_2_sin(sin_p, &sin6);
284582cd038dSYoshinobu Inoue }
284682cd038dSYoshinobu Inoue 
284782cd038dSYoshinobu Inoue /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
284882cd038dSYoshinobu Inoue void
284982cd038dSYoshinobu Inoue in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
285082cd038dSYoshinobu Inoue {
285182cd038dSYoshinobu Inoue 	struct sockaddr_in *sin_p;
285282cd038dSYoshinobu Inoue 	struct sockaddr_in6 *sin6_p;
285382cd038dSYoshinobu Inoue 
2854ea50c13eSGleb Smirnoff 	sin6_p = malloc(sizeof *sin6_p, M_SONAME, M_WAITOK);
285582cd038dSYoshinobu Inoue 	sin_p = (struct sockaddr_in *)*nam;
285682cd038dSYoshinobu Inoue 	in6_sin_2_v4mapsin6(sin_p, sin6_p);
28571ede983cSDag-Erling Smørgrav 	free(*nam, M_SONAME);
285882cd038dSYoshinobu Inoue 	*nam = (struct sockaddr *)sin6_p;
285982cd038dSYoshinobu Inoue }
2860