1139826Simp/*-
253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
353541Sshin * All rights reserved.
453541Sshin *
553541Sshin * Redistribution and use in source and binary forms, with or without
653541Sshin * modification, are permitted provided that the following conditions
753541Sshin * are met:
853541Sshin * 1. Redistributions of source code must retain the above copyright
953541Sshin *    notice, this list of conditions and the following disclaimer.
1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1153541Sshin *    notice, this list of conditions and the following disclaimer in the
1253541Sshin *    documentation and/or other materials provided with the distribution.
1353541Sshin * 3. Neither the name of the project nor the names of its contributors
1453541Sshin *    may be used to endorse or promote products derived from this software
1553541Sshin *    without specific prior written permission.
1653541Sshin *
1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753541Sshin * SUCH DAMAGE.
28174510Sobrien *
29174510Sobrien *	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $
3053541Sshin */
3153541Sshin
32139826Simp/*-
3353541Sshin * Copyright (c) 1982, 1986, 1991, 1993
3453541Sshin *	The Regents of the University of California.  All rights reserved.
3553541Sshin *
3653541Sshin * Redistribution and use in source and binary forms, with or without
3753541Sshin * modification, are permitted provided that the following conditions
3853541Sshin * are met:
3953541Sshin * 1. Redistributions of source code must retain the above copyright
4053541Sshin *    notice, this list of conditions and the following disclaimer.
4153541Sshin * 2. Redistributions in binary form must reproduce the above copyright
4253541Sshin *    notice, this list of conditions and the following disclaimer in the
4353541Sshin *    documentation and/or other materials provided with the distribution.
4453541Sshin * 4. Neither the name of the University nor the names of its contributors
4553541Sshin *    may be used to endorse or promote products derived from this software
4653541Sshin *    without specific prior written permission.
4753541Sshin *
4853541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4953541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5053541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5153541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5253541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5353541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5453541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5553541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5653541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5753541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5853541Sshin * SUCH DAMAGE.
5953541Sshin *
6053541Sshin *	@(#)in.c	8.2 (Berkeley) 11/15/93
6153541Sshin */
6253541Sshin
63174510Sobrien#include <sys/cdefs.h>
64174510Sobrien__FBSDID("$FreeBSD$");
65174510Sobrien
66207268Skib#include "opt_compat.h"
6762587Sitojun#include "opt_inet.h"
6862587Sitojun#include "opt_inet6.h"
6962587Sitojun
7053541Sshin#include <sys/param.h>
7153541Sshin#include <sys/errno.h>
72186948Sbz#include <sys/jail.h>
7353541Sshin#include <sys/malloc.h>
7453541Sshin#include <sys/socket.h>
7553541Sshin#include <sys/socketvar.h>
7653541Sshin#include <sys/sockio.h>
7753541Sshin#include <sys/systm.h>
78164033Srwatson#include <sys/priv.h>
7953541Sshin#include <sys/proc.h>
8053541Sshin#include <sys/time.h>
8153541Sshin#include <sys/kernel.h>
8253541Sshin#include <sys/syslog.h>
8353541Sshin
8453541Sshin#include <net/if.h>
85197227Sqingli#include <net/if_var.h>
8653541Sshin#include <net/if_types.h>
8753541Sshin#include <net/route.h>
8853541Sshin#include <net/if_dl.h>
89185571Sbz#include <net/vnet.h>
9053541Sshin
9153541Sshin#include <netinet/in.h>
9253541Sshin#include <netinet/in_var.h>
93186119Sqingli#include <net/if_llatbl.h>
9453541Sshin#include <netinet/if_ether.h>
9578064Sume#include <netinet/in_systm.h>
9678064Sume#include <netinet/ip.h>
9778064Sume#include <netinet/in_pcb.h>
9853541Sshin
9962587Sitojun#include <netinet/ip6.h>
10053541Sshin#include <netinet6/ip6_var.h>
10195023Ssuz#include <netinet6/nd6.h>
10253541Sshin#include <netinet6/mld6_var.h>
10362587Sitojun#include <netinet6/ip6_mroute.h>
10453541Sshin#include <netinet6/in6_ifattach.h>
10562587Sitojun#include <netinet6/scope6_var.h>
10678064Sume#include <netinet6/in6_pcb.h>
10762587Sitojun
108252021ShrsVNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix);
109252021Shrs#define V_icmp6_nodeinfo_oldmcprefix	VNET(icmp6_nodeinfo_oldmcprefix)
110252021Shrs
11153541Sshin/*
11253541Sshin * Definitions of some costant IP6 addresses.
11353541Sshin */
11462587Sitojunconst struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
11562587Sitojunconst struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
11662587Sitojunconst struct in6_addr in6addr_nodelocal_allnodes =
11753541Sshin	IN6ADDR_NODELOCAL_ALLNODES_INIT;
11862587Sitojunconst struct in6_addr in6addr_linklocal_allnodes =
11953541Sshin	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
12062587Sitojunconst struct in6_addr in6addr_linklocal_allrouters =
12153541Sshin	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
122191672Sbmsconst struct in6_addr in6addr_linklocal_allv2routers =
123191672Sbms	IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT;
12453541Sshin
12562587Sitojunconst struct in6_addr in6mask0 = IN6MASK0;
12662587Sitojunconst struct in6_addr in6mask32 = IN6MASK32;
12762587Sitojunconst struct in6_addr in6mask64 = IN6MASK64;
12862587Sitojunconst struct in6_addr in6mask96 = IN6MASK96;
12962587Sitojunconst struct in6_addr in6mask128 = IN6MASK128;
13053541Sshin
131126552Sumeconst struct sockaddr_in6 sa6_any =
132126552Sume	{ sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 };
13378064Sume
134244524Sdelphijstatic int in6_lifaddr_ioctl(struct socket *, u_long, caddr_t,
135244524Sdelphij	struct ifnet *, struct thread *);
136244524Sdelphijstatic int in6_ifinit(struct ifnet *, struct in6_ifaddr *,
137244524Sdelphij	struct sockaddr_in6 *, int);
138175162Sobrienstatic void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
13953541Sshin
14083934Sbrooksint	(*faithprefix_p)(struct in6_addr *);
14183934Sbrooks
142226570Sglebius#define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
143226570Sglebius#define ia62ifa(ia6)	(&((ia6)->ia_ifa))
144120891Sume
145226570Sglebiusvoid
146226570Sglebiusin6_ifaddloop(struct ifaddr *ifa)
147226570Sglebius{
148226570Sglebius	struct sockaddr_dl gateway;
149226570Sglebius	struct sockaddr_in6 mask, addr;
150226570Sglebius	struct rtentry rt;
151226570Sglebius	struct in6_ifaddr *ia;
152226570Sglebius	struct ifnet *ifp;
153226570Sglebius	struct llentry *ln;
15478064Sume
155226570Sglebius	ia = ifa2ia6(ifa);
156226570Sglebius	ifp = ifa->ifa_ifp;
157226570Sglebius	IF_AFDATA_LOCK(ifp);
158230604Sqingli	ifa->ifa_rtrequest = nd6_rtrequest;
159226570Sglebius	ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR |
160226570Sglebius	    LLE_EXCLUSIVE), (struct sockaddr *)&ia->ia_addr);
161226570Sglebius	IF_AFDATA_UNLOCK(ifp);
162226570Sglebius	if (ln != NULL) {
163226570Sglebius		ln->la_expire = 0;  /* for IPv6 this means permanent */
164226570Sglebius		ln->ln_state = ND6_LLINFO_REACHABLE;
165226570Sglebius		/*
166226570Sglebius		 * initialize for rtmsg generation
167226570Sglebius		 */
168226570Sglebius		bzero(&gateway, sizeof(gateway));
169226570Sglebius		gateway.sdl_len = sizeof(gateway);
170226570Sglebius		gateway.sdl_family = AF_LINK;
171226570Sglebius		gateway.sdl_nlen = 0;
172226570Sglebius		gateway.sdl_alen = 6;
173226570Sglebius		memcpy(gateway.sdl_data, &ln->ll_addr.mac_aligned,
174226570Sglebius		    sizeof(ln->ll_addr));
175226570Sglebius		LLE_WUNLOCK(ln);
176226570Sglebius	}
177226570Sglebius
178226570Sglebius	bzero(&rt, sizeof(rt));
179226570Sglebius	rt.rt_gateway = (struct sockaddr *)&gateway;
180226570Sglebius	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
181226570Sglebius	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
182226570Sglebius	rt_mask(&rt) = (struct sockaddr *)&mask;
183226570Sglebius	rt_key(&rt) = (struct sockaddr *)&addr;
184226570Sglebius	rt.rt_flags = RTF_UP | RTF_HOST | RTF_STATIC;
185232292Sbz	/* Announce arrival of local address to all FIBs. */
186226570Sglebius	rt_newaddrmsg(RTM_ADD, ifa, 0, &rt);
187226570Sglebius}
188226570Sglebius
189226570Sglebiusvoid
190226570Sglebiusin6_ifremloop(struct ifaddr *ifa)
191226570Sglebius{
192226570Sglebius	struct sockaddr_dl gateway;
193226570Sglebius	struct sockaddr_in6 mask, addr;
194226570Sglebius	struct rtentry rt0;
195226570Sglebius	struct in6_ifaddr *ia;
196226570Sglebius	struct ifnet *ifp;
197226570Sglebius
198226570Sglebius	ia = ifa2ia6(ifa);
199226570Sglebius	ifp = ifa->ifa_ifp;
200250927Soleg	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
201250927Soleg	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
202250927Soleg	lltable_prefix_free(AF_INET6, (struct sockaddr *)&addr,
203250927Soleg	            (struct sockaddr *)&mask, LLE_STATIC);
204226570Sglebius
205226570Sglebius	/*
206226570Sglebius	 * initialize for rtmsg generation
207226570Sglebius	 */
208226570Sglebius	bzero(&gateway, sizeof(gateway));
209226570Sglebius	gateway.sdl_len = sizeof(gateway);
210226570Sglebius	gateway.sdl_family = AF_LINK;
211226570Sglebius	gateway.sdl_nlen = 0;
212226570Sglebius	gateway.sdl_alen = ifp->if_addrlen;
213226570Sglebius	bzero(&rt0, sizeof(rt0));
214226570Sglebius	rt0.rt_gateway = (struct sockaddr *)&gateway;
215226570Sglebius	rt_mask(&rt0) = (struct sockaddr *)&mask;
216226570Sglebius	rt_key(&rt0) = (struct sockaddr *)&addr;
217226570Sglebius	rt0.rt_flags = RTF_HOST | RTF_STATIC;
218232292Sbz	/* Announce removal of local address to all FIBs. */
219226570Sglebius	rt_newaddrmsg(RTM_DELETE, ifa, 0, &rt0);
220226570Sglebius}
221226570Sglebius
22253541Sshinint
223171259Sdelphijin6_mask2len(struct in6_addr *mask, u_char *lim0)
22453541Sshin{
22578064Sume	int x = 0, y;
22678064Sume	u_char *lim = lim0, *p;
22753541Sshin
228120891Sume	/* ignore the scope_id part */
229120891Sume	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
23078064Sume		lim = (u_char *)mask + sizeof(*mask);
23178064Sume	for (p = (u_char *)mask; p < lim; x++, p++) {
23278064Sume		if (*p != 0xff)
23353541Sshin			break;
23453541Sshin	}
23553541Sshin	y = 0;
23678064Sume	if (p < lim) {
23753541Sshin		for (y = 0; y < 8; y++) {
23878064Sume			if ((*p & (0x80 >> y)) == 0)
23953541Sshin				break;
24053541Sshin		}
24153541Sshin	}
24278064Sume
24378064Sume	/*
24478064Sume	 * when the limit pointer is given, do a stricter check on the
24578064Sume	 * remaining bits.
24678064Sume	 */
24778064Sume	if (p < lim) {
24878064Sume		if (y != 0 && (*p & (0x00ff >> y)) != 0)
249120856Sume			return (-1);
25078064Sume		for (p = p + 1; p < lim; p++)
25178064Sume			if (*p != 0)
252120856Sume				return (-1);
25378064Sume	}
254120891Sume
25553541Sshin	return x * 8 + y;
25653541Sshin}
25753541Sshin
258207268Skib#ifdef COMPAT_FREEBSD32
259207268Skibstruct in6_ndifreq32 {
260240310Sglebius	char ifname[IFNAMSIZ];
261240310Sglebius	uint32_t ifindex;
262207268Skib};
263240310Sglebius#define	SIOCGDEFIFACE32_IN6	_IOWR('i', 86, struct in6_ndifreq32)
264207268Skib#endif
265207268Skib
26653541Sshinint
267171259Sdelphijin6_control(struct socket *so, u_long cmd, caddr_t data,
268171259Sdelphij    struct ifnet *ifp, struct thread *td)
26953541Sshin{
27053541Sshin	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
27178064Sume	struct	in6_ifaddr *ia = NULL;
27253541Sshin	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
273151539Ssuz	struct sockaddr_in6 *sa6;
274164033Srwatson	int error;
27553541Sshin
27662587Sitojun	switch (cmd) {
27762587Sitojun	case SIOCGETSGCNT_IN6:
27862587Sitojun	case SIOCGETMIFCNT_IN6:
279240310Sglebius		/*
280232292Sbz		 * XXX mrt_ioctl has a 3rd, unused, FIB argument in route.c.
281232292Sbz		 * We cannot see how that would be needed, so do not adjust the
282232292Sbz		 * KPI blindly; more likely should clean up the IPv4 variant.
283232292Sbz		 */
284166938Sbms		return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP);
28562587Sitojun	}
28653541Sshin
287121742Sume	switch(cmd) {
288121742Sume	case SIOCAADDRCTL_POLICY:
289121742Sume	case SIOCDADDRCTL_POLICY:
290164033Srwatson		if (td != NULL) {
291164033Srwatson			error = priv_check(td, PRIV_NETINET_ADDRCTRL6);
292164033Srwatson			if (error)
293164033Srwatson				return (error);
294164033Srwatson		}
295121742Sume		return (in6_src_ioctl(cmd, data));
296121742Sume	}
297121742Sume
29862587Sitojun	if (ifp == NULL)
299120856Sume		return (EOPNOTSUPP);
30053541Sshin
30153541Sshin	switch (cmd) {
30253541Sshin	case SIOCSNDFLUSH_IN6:
30353541Sshin	case SIOCSPFXFLUSH_IN6:
30453541Sshin	case SIOCSRTRFLUSH_IN6:
30562587Sitojun	case SIOCSDEFIFACE_IN6:
30662587Sitojun	case SIOCSIFINFO_FLAGS:
307193893Scperciva	case SIOCSIFINFO_IN6:
308164033Srwatson		if (td != NULL) {
309164033Srwatson			error = priv_check(td, PRIV_NETINET_ND6);
310164033Srwatson			if (error)
311164033Srwatson				return (error);
312164033Srwatson		}
313120891Sume		/* FALLTHROUGH */
31478064Sume	case OSIOCGIFINFO_IN6:
31553541Sshin	case SIOCGIFINFO_IN6:
31653541Sshin	case SIOCGDRLST_IN6:
31753541Sshin	case SIOCGPRLST_IN6:
31853541Sshin	case SIOCGNBRINFO_IN6:
31962587Sitojun	case SIOCGDEFIFACE_IN6:
320120856Sume		return (nd6_ioctl(cmd, data, ifp));
321207268Skib
322207268Skib#ifdef COMPAT_FREEBSD32
323207268Skib	case SIOCGDEFIFACE32_IN6:
324207268Skib		{
325207268Skib			struct in6_ndifreq ndif;
326207268Skib			struct in6_ndifreq32 *ndif32;
327207268Skib
328207268Skib			error = nd6_ioctl(SIOCGDEFIFACE_IN6, (caddr_t)&ndif,
329207268Skib			    ifp);
330207268Skib			if (error)
331207268Skib				return (error);
332207268Skib			ndif32 = (struct in6_ndifreq32 *)data;
333207268Skib			ndif32->ifindex = ndif.ifindex;
334207268Skib			return (0);
335207268Skib		}
336207268Skib#endif
33753541Sshin	}
33853541Sshin
33953541Sshin	switch (cmd) {
34053541Sshin	case SIOCSIFPREFIX_IN6:
34153541Sshin	case SIOCDIFPREFIX_IN6:
34253541Sshin	case SIOCAIFPREFIX_IN6:
34353541Sshin	case SIOCCIFPREFIX_IN6:
34453541Sshin	case SIOCSGIFPREFIX_IN6:
34553541Sshin	case SIOCGIFPREFIX_IN6:
34678064Sume		log(LOG_NOTICE,
34778064Sume		    "prefix ioctls are now invalidated. "
34878064Sume		    "please use ifconfig.\n");
349120856Sume		return (EOPNOTSUPP);
35053541Sshin	}
35153541Sshin
35295023Ssuz	switch (cmd) {
35362587Sitojun	case SIOCSSCOPE6:
354164033Srwatson		if (td != NULL) {
355164033Srwatson			error = priv_check(td, PRIV_NETINET_SCOPE6);
356164033Srwatson			if (error)
357164033Srwatson				return (error);
358164033Srwatson		}
359121161Sume		return (scope6_set(ifp,
360121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
36162587Sitojun	case SIOCGSCOPE6:
362121161Sume		return (scope6_get(ifp,
363121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
36462587Sitojun	case SIOCGSCOPE6DEF:
365121161Sume		return (scope6_get_default((struct scope6_id *)
366121161Sume		    ifr->ifr_ifru.ifru_scope_id));
36762587Sitojun	}
36862587Sitojun
36953541Sshin	switch (cmd) {
37053541Sshin	case SIOCALIFADDR:
371175630Sbz		if (td != NULL) {
372175630Sbz			error = priv_check(td, PRIV_NET_ADDIFADDR);
373175630Sbz			if (error)
374175630Sbz				return (error);
375175630Sbz		}
376175630Sbz		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
377175630Sbz
37853541Sshin	case SIOCDLIFADDR:
379164033Srwatson		if (td != NULL) {
380175630Sbz			error = priv_check(td, PRIV_NET_DELIFADDR);
381164033Srwatson			if (error)
382164033Srwatson				return (error);
383164033Srwatson		}
384120891Sume		/* FALLTHROUGH */
38553541Sshin	case SIOCGLIFADDR:
38683366Sjulian		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
38753541Sshin	}
38853541Sshin
38953541Sshin	/*
39053541Sshin	 * Find address for this interface, if it exists.
391151539Ssuz	 *
392151539Ssuz	 * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
393151539Ssuz	 * only, and used the first interface address as the target of other
394151539Ssuz	 * operations (without checking ifra_addr).  This was because netinet
395151539Ssuz	 * code/API assumed at most 1 interface address per interface.
396151539Ssuz	 * Since IPv6 allows a node to assign multiple addresses
397151539Ssuz	 * on a single interface, we almost always look and check the
398151539Ssuz	 * presence of ifra_addr, and reject invalid ones here.
399151539Ssuz	 * It also decreases duplicated code among SIOC*_IN6 operations.
40053541Sshin	 */
401151539Ssuz	switch (cmd) {
402151539Ssuz	case SIOCAIFADDR_IN6:
403151539Ssuz	case SIOCSIFPHYADDR_IN6:
404151539Ssuz		sa6 = &ifra->ifra_addr;
405151539Ssuz		break;
406151539Ssuz	case SIOCSIFADDR_IN6:
407151539Ssuz	case SIOCGIFADDR_IN6:
408151539Ssuz	case SIOCSIFDSTADDR_IN6:
409151539Ssuz	case SIOCSIFNETMASK_IN6:
410151539Ssuz	case SIOCGIFDSTADDR_IN6:
411151539Ssuz	case SIOCGIFNETMASK_IN6:
412151539Ssuz	case SIOCDIFADDR_IN6:
413151539Ssuz	case SIOCGIFPSRCADDR_IN6:
414151539Ssuz	case SIOCGIFPDSTADDR_IN6:
415151539Ssuz	case SIOCGIFAFLAG_IN6:
416151539Ssuz	case SIOCSNDFLUSH_IN6:
417151539Ssuz	case SIOCSPFXFLUSH_IN6:
418151539Ssuz	case SIOCSRTRFLUSH_IN6:
419151539Ssuz	case SIOCGIFALIFETIME_IN6:
420151539Ssuz	case SIOCSIFALIFETIME_IN6:
421151539Ssuz	case SIOCGIFSTAT_IN6:
422151539Ssuz	case SIOCGIFSTAT_ICMP6:
423151539Ssuz		sa6 = &ifr->ifr_addr;
424151539Ssuz		break;
425255443Sdes	case SIOCSIFADDR:
426255443Sdes	case SIOCSIFBRDADDR:
427255443Sdes	case SIOCSIFDSTADDR:
428255443Sdes	case SIOCSIFNETMASK:
429255443Sdes		/*
430255443Sdes		 * Although we should pass any non-INET6 ioctl requests
431255443Sdes		 * down to driver, we filter some legacy INET requests.
432255443Sdes		 * Drivers trust SIOCSIFADDR et al to come from an already
433255443Sdes		 * privileged layer, and do not perform any credentials
434255443Sdes		 * checks or input validation.
435255443Sdes		 */
436255443Sdes		return (EINVAL);
437151539Ssuz	default:
438151539Ssuz		sa6 = NULL;
439151539Ssuz		break;
440151539Ssuz	}
441151539Ssuz	if (sa6 && sa6->sin6_family == AF_INET6) {
442151539Ssuz		if (sa6->sin6_scope_id != 0)
443151539Ssuz			error = sa6_embedscope(sa6, 0);
444148385Sume		else
445151539Ssuz			error = in6_setscope(&sa6->sin6_addr, ifp, NULL);
446148385Sume		if (error != 0)
447148385Sume			return (error);
448188144Sjamie		if (td != NULL && (error = prison_check_ip6(td->td_ucred,
449188144Sjamie		    &sa6->sin6_addr)) != 0)
450188144Sjamie			return (error);
451151539Ssuz		ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
452151539Ssuz	} else
453151539Ssuz		ia = NULL;
45453541Sshin
45553541Sshin	switch (cmd) {
45678064Sume	case SIOCSIFADDR_IN6:
45778064Sume	case SIOCSIFDSTADDR_IN6:
45878064Sume	case SIOCSIFNETMASK_IN6:
45978064Sume		/*
46078064Sume		 * Since IPv6 allows a node to assign multiple addresses
461151465Ssuz		 * on a single interface, SIOCSIFxxx ioctls are deprecated.
46278064Sume		 */
46378064Sume		/* we decided to obsolete this command (20000704) */
464194760Srwatson		error = EINVAL;
465194760Srwatson		goto out;
46653541Sshin
46753541Sshin	case SIOCDIFADDR_IN6:
46862587Sitojun		/*
46978064Sume		 * for IPv4, we look for existing in_ifaddr here to allow
470151465Ssuz		 * "ifconfig if0 delete" to remove the first IPv4 address on
471151465Ssuz		 * the interface.  For IPv6, as the spec allows multiple
472151465Ssuz		 * interface address from the day one, we consider "remove the
473151465Ssuz		 * first one" semantics to be not preferable.
47462587Sitojun		 */
475194760Srwatson		if (ia == NULL) {
476194760Srwatson			error = EADDRNOTAVAIL;
477194760Srwatson			goto out;
478194760Srwatson		}
47953541Sshin		/* FALLTHROUGH */
48053541Sshin	case SIOCAIFADDR_IN6:
48162587Sitojun		/*
48278064Sume		 * We always require users to specify a valid IPv6 address for
48378064Sume		 * the corresponding operation.
48462587Sitojun		 */
48578064Sume		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
486194760Srwatson		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) {
487194760Srwatson			error = EAFNOSUPPORT;
488194760Srwatson			goto out;
489194760Srwatson		}
49053541Sshin
491164033Srwatson		if (td != NULL) {
492240310Sglebius			error = priv_check(td, (cmd == SIOCDIFADDR_IN6) ?
493175630Sbz			    PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR);
494164033Srwatson			if (error)
495194760Srwatson				goto out;
496164033Srwatson		}
49753541Sshin		break;
49853541Sshin
49953541Sshin	case SIOCGIFADDR_IN6:
50053541Sshin		/* This interface is basically deprecated. use SIOCGIFCONF. */
501120891Sume		/* FALLTHROUGH */
50253541Sshin	case SIOCGIFAFLAG_IN6:
50353541Sshin	case SIOCGIFNETMASK_IN6:
50453541Sshin	case SIOCGIFDSTADDR_IN6:
50553541Sshin	case SIOCGIFALIFETIME_IN6:
50653541Sshin		/* must think again about its semantics */
507194760Srwatson		if (ia == NULL) {
508194760Srwatson			error = EADDRNOTAVAIL;
509194760Srwatson			goto out;
510194760Srwatson		}
51153541Sshin		break;
512194760Srwatson
51353541Sshin	case SIOCSIFALIFETIME_IN6:
51453541Sshin	    {
51553541Sshin		struct in6_addrlifetime *lt;
51653541Sshin
517164033Srwatson		if (td != NULL) {
518164033Srwatson			error = priv_check(td, PRIV_NETINET_ALIFETIME6);
519164033Srwatson			if (error)
520194760Srwatson				goto out;
521164033Srwatson		}
522194760Srwatson		if (ia == NULL) {
523194760Srwatson			error = EADDRNOTAVAIL;
524194760Srwatson			goto out;
525194760Srwatson		}
52653541Sshin		/* sanity for overflow - beware unsigned */
52753541Sshin		lt = &ifr->ifr_ifru.ifru_lifetime;
528126552Sume		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
529126552Sume		    lt->ia6t_vltime + time_second < time_second) {
530194760Srwatson			error = EINVAL;
531194760Srwatson			goto out;
53253541Sshin		}
533126552Sume		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
534126552Sume		    lt->ia6t_pltime + time_second < time_second) {
535194760Srwatson			error = EINVAL;
536194760Srwatson			goto out;
53753541Sshin		}
53853541Sshin		break;
53953541Sshin	    }
54053541Sshin	}
54153541Sshin
54253541Sshin	switch (cmd) {
54353541Sshin	case SIOCGIFADDR_IN6:
54453541Sshin		ifr->ifr_addr = ia->ia_addr;
545148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
546194760Srwatson			goto out;
54753541Sshin		break;
54853541Sshin
54953541Sshin	case SIOCGIFDSTADDR_IN6:
550194760Srwatson		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
551194760Srwatson			error = EINVAL;
552194760Srwatson			goto out;
553194760Srwatson		}
55462587Sitojun		/*
55562587Sitojun		 * XXX: should we check if ifa_dstaddr is NULL and return
55662587Sitojun		 * an error?
55762587Sitojun		 */
55853541Sshin		ifr->ifr_dstaddr = ia->ia_dstaddr;
559148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
560194760Srwatson			goto out;
56153541Sshin		break;
56253541Sshin
56353541Sshin	case SIOCGIFNETMASK_IN6:
56453541Sshin		ifr->ifr_addr = ia->ia_prefixmask;
56553541Sshin		break;
56653541Sshin
56753541Sshin	case SIOCGIFAFLAG_IN6:
56853541Sshin		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
56953541Sshin		break;
57053541Sshin
57153541Sshin	case SIOCGIFSTAT_IN6:
572194760Srwatson		if (ifp == NULL) {
573194760Srwatson			error = EINVAL;
574194760Srwatson			goto out;
575194760Srwatson		}
576121161Sume		bzero(&ifr->ifr_ifru.ifru_stat,
577121161Sume		    sizeof(ifr->ifr_ifru.ifru_stat));
578121161Sume		ifr->ifr_ifru.ifru_stat =
579121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
58053541Sshin		break;
58153541Sshin
58253541Sshin	case SIOCGIFSTAT_ICMP6:
583194760Srwatson		if (ifp == NULL) {
584194760Srwatson			error = EINVAL;
585194760Srwatson			goto out;
586194760Srwatson		}
587155454Sgnn		bzero(&ifr->ifr_ifru.ifru_icmp6stat,
588121161Sume		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
589121161Sume		ifr->ifr_ifru.ifru_icmp6stat =
590121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
59153541Sshin		break;
59253541Sshin
59353541Sshin	case SIOCGIFALIFETIME_IN6:
59453541Sshin		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
595151539Ssuz		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
596151539Ssuz			time_t maxexpire;
597151539Ssuz			struct in6_addrlifetime *retlt =
598151539Ssuz			    &ifr->ifr_ifru.ifru_lifetime;
599151539Ssuz
600151539Ssuz			/*
601151539Ssuz			 * XXX: adjust expiration time assuming time_t is
602151539Ssuz			 * signed.
603151539Ssuz			 */
604151539Ssuz			maxexpire = (-1) &
605151546Ssuz			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
606151539Ssuz			if (ia->ia6_lifetime.ia6t_vltime <
607151539Ssuz			    maxexpire - ia->ia6_updatetime) {
608151539Ssuz				retlt->ia6t_expire = ia->ia6_updatetime +
609151539Ssuz				    ia->ia6_lifetime.ia6t_vltime;
610151539Ssuz			} else
611151539Ssuz				retlt->ia6t_expire = maxexpire;
612151539Ssuz		}
613151539Ssuz		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
614151539Ssuz			time_t maxexpire;
615151539Ssuz			struct in6_addrlifetime *retlt =
616151539Ssuz			    &ifr->ifr_ifru.ifru_lifetime;
617151539Ssuz
618151539Ssuz			/*
619151539Ssuz			 * XXX: adjust expiration time assuming time_t is
620151539Ssuz			 * signed.
621151539Ssuz			 */
622151539Ssuz			maxexpire = (-1) &
623151546Ssuz			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
624151539Ssuz			if (ia->ia6_lifetime.ia6t_pltime <
625151539Ssuz			    maxexpire - ia->ia6_updatetime) {
626151539Ssuz				retlt->ia6t_preferred = ia->ia6_updatetime +
627151539Ssuz				    ia->ia6_lifetime.ia6t_pltime;
628151539Ssuz			} else
629151539Ssuz				retlt->ia6t_preferred = maxexpire;
630151539Ssuz		}
63153541Sshin		break;
63253541Sshin
63353541Sshin	case SIOCSIFALIFETIME_IN6:
63453541Sshin		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
63553541Sshin		/* for sanity */
63653541Sshin		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
63753541Sshin			ia->ia6_lifetime.ia6t_expire =
63853541Sshin				time_second + ia->ia6_lifetime.ia6t_vltime;
63953541Sshin		} else
64053541Sshin			ia->ia6_lifetime.ia6t_expire = 0;
64153541Sshin		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
64253541Sshin			ia->ia6_lifetime.ia6t_preferred =
64353541Sshin				time_second + ia->ia6_lifetime.ia6t_pltime;
64453541Sshin		} else
64553541Sshin			ia->ia6_lifetime.ia6t_preferred = 0;
64653541Sshin		break;
64753541Sshin
64878064Sume	case SIOCAIFADDR_IN6:
64978064Sume	{
650194760Srwatson		int i;
651151539Ssuz		struct nd_prefixctl pr0;
652151539Ssuz		struct nd_prefix *pr;
65378064Sume
65462587Sitojun		/*
65578064Sume		 * first, make or update the interface address structure,
65678064Sume		 * and link it to the list.
65762587Sitojun		 */
658151539Ssuz		if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
659194760Srwatson			goto out;
660194760Srwatson		if (ia != NULL)
661194760Srwatson			ifa_free(&ia->ia_ifa);
662151915Ssuz		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
663151915Ssuz		    == NULL) {
664171260Sdelphij			/*
665151915Ssuz			 * this can happen when the user specify the 0 valid
666151915Ssuz			 * lifetime.
667151915Ssuz			 */
668151915Ssuz			break;
669151915Ssuz		}
67053541Sshin
67178064Sume		/*
67278064Sume		 * then, make the prefix on-link on the interface.
67378064Sume		 * XXX: we'd rather create the prefix before the address, but
67478064Sume		 * we need at least one address to install the corresponding
67578064Sume		 * interface route, so we configure the address first.
67678064Sume		 */
67778064Sume
67878064Sume		/*
67978064Sume		 * convert mask to prefix length (prefixmask has already
68078064Sume		 * been validated in in6_update_ifa().
68178064Sume		 */
68278064Sume		bzero(&pr0, sizeof(pr0));
68378064Sume		pr0.ndpr_ifp = ifp;
68478064Sume		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
685120891Sume		    NULL);
686120891Sume		if (pr0.ndpr_plen == 128) {
68778064Sume			break;	/* we don't need to install a host route. */
688120891Sume		}
68978064Sume		pr0.ndpr_prefix = ifra->ifra_addr;
69078064Sume		/* apply the mask for safety. */
69178064Sume		for (i = 0; i < 4; i++) {
69278064Sume			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
693120891Sume			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
69478064Sume		}
69578064Sume		/*
69695023Ssuz		 * XXX: since we don't have an API to set prefix (not address)
69795023Ssuz		 * lifetimes, we just use the same lifetimes as addresses.
69895023Ssuz		 * The (temporarily) installed lifetimes can be overridden by
69995023Ssuz		 * later advertised RAs (when accept_rtadv is non 0), which is
70095023Ssuz		 * an intended behavior.
70178064Sume		 */
70278064Sume		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
70378064Sume		pr0.ndpr_raf_auto =
704120891Sume		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
70578064Sume		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
70678064Sume		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
70778064Sume
708120891Sume		/* add the prefix if not yet. */
70978064Sume		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
71078064Sume			/*
71178064Sume			 * nd6_prelist_add will install the corresponding
71278064Sume			 * interface route.
71378064Sume			 */
71478064Sume			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
715194760Srwatson				goto out;
71678064Sume			if (pr == NULL) {
717120891Sume				log(LOG_ERR, "nd6_prelist_add succeeded but "
71878064Sume				    "no prefix\n");
719194760Srwatson				error = EINVAL;
720194760Srwatson				goto out;
72178064Sume			}
72278064Sume		}
72378064Sume
724151915Ssuz		/* relate the address to the prefix */
725151915Ssuz		if (ia->ia6_ndpr == NULL) {
726151915Ssuz			ia->ia6_ndpr = pr;
727151915Ssuz			pr->ndpr_refcnt++;
72878064Sume
72978064Sume			/*
730151915Ssuz			 * If this is the first autoconf address from the
731151915Ssuz			 * prefix, create a temporary address as well
732151915Ssuz			 * (when required).
73378064Sume			 */
734151915Ssuz			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) &&
735181803Sbz			    V_ip6_use_tempaddr && pr->ndpr_refcnt == 1) {
736151915Ssuz				int e;
737151915Ssuz				if ((e = in6_tmpifadd(ia, 1, 0)) != 0) {
738151915Ssuz					log(LOG_NOTICE, "in6_control: failed "
739151915Ssuz					    "to create a temporary address, "
740151915Ssuz					    "errno=%d\n", e);
741151915Ssuz				}
742151915Ssuz			}
74362587Sitojun		}
744151915Ssuz
745151915Ssuz		/*
746151915Ssuz		 * this might affect the status of autoconfigured addresses,
747151915Ssuz		 * that is, this address might make other addresses detached.
748151915Ssuz		 */
749151915Ssuz		pfxlist_onlink_check();
750222730Shrs		if (error == 0 && ia) {
751222730Shrs			if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
752222730Shrs				/*
753222730Shrs				 * Try to clear the flag when a new
754222730Shrs				 * IPv6 address is added onto an
755222730Shrs				 * IFDISABLED interface and it
756222730Shrs				 * succeeds.
757222730Shrs				 */
758222730Shrs				struct in6_ndireq nd;
759222730Shrs
760222730Shrs				memset(&nd, 0, sizeof(nd));
761222730Shrs				nd.ndi.flags = ND_IFINFO(ifp)->flags;
762222730Shrs				nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
763222730Shrs				if (nd6_ioctl(SIOCSIFINFO_FLAGS,
764222730Shrs				    (caddr_t)&nd, ifp) < 0)
765222730Shrs					log(LOG_NOTICE, "SIOCAIFADDR_IN6: "
766222730Shrs					    "SIOCSIFINFO_FLAGS for -ifdisabled "
767222730Shrs					    "failed.");
768222730Shrs				/*
769222730Shrs				 * Ignore failure of clearing the flag
770222730Shrs				 * intentionally.  The failure means
771222730Shrs				 * address duplication was detected.
772222730Shrs				 */
773222730Shrs			}
774126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
775222730Shrs		}
77678064Sume		break;
77778064Sume	}
77862587Sitojun
77978064Sume	case SIOCDIFADDR_IN6:
78078064Sume	{
781151539Ssuz		struct nd_prefix *pr;
78278064Sume
78378064Sume		/*
78478064Sume		 * If the address being deleted is the only one that owns
78578064Sume		 * the corresponding prefix, expire the prefix as well.
786120891Sume		 * XXX: theoretically, we don't have to worry about such
78778064Sume		 * relationship, since we separate the address management
78878064Sume		 * and the prefix management.  We do this, however, to provide
78978064Sume		 * as much backward compatibility as possible in terms of
79078064Sume		 * the ioctl operation.
791151915Ssuz		 * Note that in6_purgeaddr() will decrement ndpr_refcnt.
79278064Sume		 */
793151915Ssuz		pr = ia->ia6_ndpr;
79478064Sume		in6_purgeaddr(&ia->ia_ifa);
795151915Ssuz		if (pr && pr->ndpr_refcnt == 0)
796151915Ssuz			prelist_remove(pr);
797126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
79853541Sshin		break;
79978064Sume	}
80053541Sshin
80178064Sume	default:
802194760Srwatson		if (ifp == NULL || ifp->if_ioctl == 0) {
803194760Srwatson			error = EOPNOTSUPP;
804194760Srwatson			goto out;
805194760Srwatson		}
806194760Srwatson		error = (*ifp->if_ioctl)(ifp, cmd, data);
807194760Srwatson		goto out;
80878064Sume	}
80953541Sshin
810194760Srwatson	error = 0;
811194760Srwatsonout:
812194760Srwatson	if (ia != NULL)
813194760Srwatson		ifa_free(&ia->ia_ifa);
814194760Srwatson	return (error);
81578064Sume}
81653541Sshin
817232292Sbz
81878064Sume/*
819232292Sbz * Join necessary multicast groups.  Factored out from in6_update_ifa().
820232292Sbz * This entire work should only be done once, for the default FIB.
821232292Sbz */
822232292Sbzstatic int
823232292Sbzin6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra,
824232292Sbz    struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol)
825232292Sbz{
826232292Sbz	char ip6buf[INET6_ADDRSTRLEN];
827232292Sbz	struct sockaddr_in6 mltaddr, mltmask;
828232292Sbz	struct in6_addr llsol;
829232292Sbz	struct in6_multi_mship *imm;
830232292Sbz	struct rtentry *rt;
831232292Sbz	int delay, error;
832232292Sbz
833232292Sbz	KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__));
834232292Sbz
835232292Sbz	/* Join solicited multicast addr for new host id. */
836232292Sbz	bzero(&llsol, sizeof(struct in6_addr));
837232292Sbz	llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
838232292Sbz	llsol.s6_addr32[1] = 0;
839232292Sbz	llsol.s6_addr32[2] = htonl(1);
840232292Sbz	llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
841232292Sbz	llsol.s6_addr8[12] = 0xff;
842232292Sbz	if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
843232292Sbz		/* XXX: should not happen */
844232292Sbz		log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
845232292Sbz		goto cleanup;
846232292Sbz	}
847232292Sbz	delay = 0;
848232292Sbz	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
849232292Sbz		/*
850232292Sbz		 * We need a random delay for DAD on the address being
851232292Sbz		 * configured.  It also means delaying transmission of the
852232292Sbz		 * corresponding MLD report to avoid report collision.
853232292Sbz		 * [RFC 4861, Section 6.3.7]
854232292Sbz		 */
855232292Sbz		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
856232292Sbz	}
857232292Sbz	imm = in6_joingroup(ifp, &llsol, &error, delay);
858232292Sbz	if (imm == NULL) {
859232292Sbz		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
860232292Sbz		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &llsol),
861232292Sbz		    if_name(ifp), error));
862232292Sbz		goto cleanup;
863232292Sbz	}
864232292Sbz	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
865232292Sbz	*in6m_sol = imm->i6mm_maddr;
866232292Sbz
867232292Sbz	bzero(&mltmask, sizeof(mltmask));
868232292Sbz	mltmask.sin6_len = sizeof(struct sockaddr_in6);
869232292Sbz	mltmask.sin6_family = AF_INET6;
870232292Sbz	mltmask.sin6_addr = in6mask32;
871232292Sbz#define	MLTMASK_LEN  4	/* mltmask's masklen (=32bit=4octet) */
872232292Sbz
873232292Sbz	/*
874232292Sbz	 * Join link-local all-nodes address.
875232292Sbz	 */
876232292Sbz	bzero(&mltaddr, sizeof(mltaddr));
877232292Sbz	mltaddr.sin6_len = sizeof(struct sockaddr_in6);
878232292Sbz	mltaddr.sin6_family = AF_INET6;
879232292Sbz	mltaddr.sin6_addr = in6addr_linklocal_allnodes;
880232292Sbz	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
881232292Sbz		goto cleanup; /* XXX: should not fail */
882232292Sbz
883232292Sbz	/*
884232292Sbz	 * XXX: do we really need this automatic routes?  We should probably
885232292Sbz	 * reconsider this stuff.  Most applications actually do not need the
886232292Sbz	 * routes, since they usually specify the outgoing interface.
887232292Sbz	 */
888232292Sbz	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
889232292Sbz	if (rt != NULL) {
890232292Sbz		/* XXX: only works in !SCOPEDROUTING case. */
891232292Sbz		if (memcmp(&mltaddr.sin6_addr,
892232292Sbz		    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
893232292Sbz		    MLTMASK_LEN)) {
894232292Sbz			RTFREE_LOCKED(rt);
895232292Sbz			rt = NULL;
896232292Sbz		}
897232292Sbz	}
898232292Sbz	if (rt == NULL) {
899232292Sbz		error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
900232292Sbz		    (struct sockaddr *)&ia->ia_addr,
901232292Sbz		    (struct sockaddr *)&mltmask, RTF_UP,
902232292Sbz		    (struct rtentry **)0, RT_DEFAULT_FIB);
903232292Sbz		if (error)
904232292Sbz			goto cleanup;
905232292Sbz	} else
906232292Sbz		RTFREE_LOCKED(rt);
907232292Sbz
908232292Sbz	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
909232292Sbz	if (imm == NULL) {
910232292Sbz		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
911232292Sbz		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
912232292Sbz		    &mltaddr.sin6_addr), if_name(ifp), error));
913232292Sbz		goto cleanup;
914232292Sbz	}
915232292Sbz	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
916232292Sbz
917232292Sbz	/*
918232292Sbz	 * Join node information group address.
919232292Sbz	 */
920232292Sbz	delay = 0;
921232292Sbz	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
922232292Sbz		/*
923232292Sbz		 * The spec does not say anything about delay for this group,
924232292Sbz		 * but the same logic should apply.
925232292Sbz		 */
926232292Sbz		delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz);
927232292Sbz	}
928232292Sbz	if (in6_nigroup(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) {
929232292Sbz		/* XXX jinmei */
930232292Sbz		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay);
931232292Sbz		if (imm == NULL)
932232292Sbz			nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
933232292Sbz			    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
934232292Sbz			    &mltaddr.sin6_addr), if_name(ifp), error));
935232292Sbz			/* XXX not very fatal, go on... */
936232292Sbz		else
937232292Sbz			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
938232292Sbz	}
939252021Shrs	if (V_icmp6_nodeinfo_oldmcprefix &&
940252021Shrs	     in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) {
941252021Shrs		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay);
942252021Shrs		if (imm == NULL)
943252021Shrs			nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
944252021Shrs			    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
945252021Shrs			    &mltaddr.sin6_addr), if_name(ifp), error));
946252021Shrs			/* XXX not very fatal, go on... */
947252021Shrs		else
948252021Shrs			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
949252021Shrs	}
950232292Sbz
951232292Sbz	/*
952232292Sbz	 * Join interface-local all-nodes address.
953232292Sbz	 * (ff01::1%ifN, and ff01::%ifN/32)
954232292Sbz	 */
955232292Sbz	mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
956232292Sbz	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
957232292Sbz		goto cleanup; /* XXX: should not fail */
958232292Sbz	/* XXX: again, do we really need the route? */
959232292Sbz	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
960232292Sbz	if (rt != NULL) {
961232292Sbz		if (memcmp(&mltaddr.sin6_addr,
962232292Sbz		    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
963232292Sbz		    MLTMASK_LEN)) {
964232292Sbz			RTFREE_LOCKED(rt);
965232292Sbz			rt = NULL;
966232292Sbz		}
967232292Sbz	}
968232292Sbz	if (rt == NULL) {
969232292Sbz		error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
970232292Sbz		    (struct sockaddr *)&ia->ia_addr,
971232292Sbz		    (struct sockaddr *)&mltmask, RTF_UP,
972232292Sbz		    (struct rtentry **)0, RT_DEFAULT_FIB);
973232292Sbz		if (error)
974232292Sbz			goto cleanup;
975232292Sbz	} else
976232292Sbz		RTFREE_LOCKED(rt);
977232292Sbz
978232292Sbz	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
979232292Sbz	if (imm == NULL) {
980232292Sbz		nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s "
981232292Sbz		    "(errno=%d)\n", __func__, ip6_sprintf(ip6buf,
982232292Sbz		    &mltaddr.sin6_addr), if_name(ifp), error));
983232292Sbz		goto cleanup;
984232292Sbz	}
985232292Sbz	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
986232292Sbz#undef	MLTMASK_LEN
987232292Sbz
988232292Sbzcleanup:
989232292Sbz	return (error);
990232292Sbz}
991232292Sbz
992232292Sbz/*
99378064Sume * Update parameters of an IPv6 interface address.
99478064Sume * If necessary, a new entry is created and linked into address chains.
99578064Sume * This function is separated from in6_control().
99678064Sume * XXX: should this be performed under splnet()?
99778064Sume */
99878064Sumeint
999171259Sdelphijin6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
1000171259Sdelphij    struct in6_ifaddr *ia, int flags)
100178064Sume{
100278064Sume	int error = 0, hostIsNew = 0, plen = -1;
100378064Sume	struct sockaddr_in6 dst6;
100478064Sume	struct in6_addrlifetime *lt;
1005151539Ssuz	struct in6_multi *in6m_sol;
1006151539Ssuz	int delay;
1007165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
100878064Sume
100978064Sume	/* Validate parameters */
101078064Sume	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
1011120856Sume		return (EINVAL);
101278064Sume
101378064Sume	/*
101478064Sume	 * The destination address for a p2p link must have a family
101578064Sume	 * of AF_UNSPEC or AF_INET6.
101678064Sume	 */
101778064Sume	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
101878064Sume	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
101978064Sume	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
1020120856Sume		return (EAFNOSUPPORT);
102178064Sume	/*
102278064Sume	 * validate ifra_prefixmask.  don't check sin6_family, netmask
102378064Sume	 * does not carry fields other than sin6_len.
102478064Sume	 */
102578064Sume	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
1026120856Sume		return (EINVAL);
102778064Sume	/*
102878064Sume	 * Because the IPv6 address architecture is classless, we require
102978064Sume	 * users to specify a (non 0) prefix length (mask) for a new address.
103078064Sume	 * We also require the prefix (when specified) mask is valid, and thus
103178064Sume	 * reject a non-consecutive mask.
103278064Sume	 */
103378064Sume	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
1034120856Sume		return (EINVAL);
103578064Sume	if (ifra->ifra_prefixmask.sin6_len != 0) {
103678064Sume		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
1037120891Sume		    (u_char *)&ifra->ifra_prefixmask +
1038120891Sume		    ifra->ifra_prefixmask.sin6_len);
103978064Sume		if (plen <= 0)
1040120856Sume			return (EINVAL);
1041120891Sume	} else {
104262587Sitojun		/*
104395023Ssuz		 * In this case, ia must not be NULL.  We just use its prefix
104478064Sume		 * length.
104562587Sitojun		 */
104678064Sume		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
104778064Sume	}
104878064Sume	/*
104978064Sume	 * If the destination address on a p2p interface is specified,
105078064Sume	 * and the address is a scoped one, validate/set the scope
105178064Sume	 * zone identifier.
105278064Sume	 */
105378064Sume	dst6 = ifra->ifra_dstaddr;
1054120891Sume	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
105578064Sume	    (dst6.sin6_family == AF_INET6)) {
1056148385Sume		struct in6_addr in6_tmp;
1057126552Sume		u_int32_t zoneid;
105878064Sume
1059148385Sume		in6_tmp = dst6.sin6_addr;
1060148385Sume		if (in6_setscope(&in6_tmp, ifp, &zoneid))
1061148385Sume			return (EINVAL); /* XXX: should be impossible */
1062148385Sume
1063148385Sume		if (dst6.sin6_scope_id != 0) {
1064148385Sume			if (dst6.sin6_scope_id != zoneid)
1065148385Sume				return (EINVAL);
1066148385Sume		} else		/* user omit to specify the ID. */
1067126552Sume			dst6.sin6_scope_id = zoneid;
1068148385Sume
1069148385Sume		/* convert into the internal form */
1070148385Sume		if (sa6_embedscope(&dst6, 0))
1071148385Sume			return (EINVAL); /* XXX: should be impossible */
107278064Sume	}
107378064Sume	/*
107478064Sume	 * The destination address can be specified only for a p2p or a
107578064Sume	 * loopback interface.  If specified, the corresponding prefix length
107678064Sume	 * must be 128.
107778064Sume	 */
107878064Sume	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
107978064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
1080126552Sume			/* XXX: noisy message */
1081122059Sume			nd6log((LOG_INFO, "in6_update_ifa: a destination can "
1082122059Sume			    "be specified for a p2p or a loopback IF only\n"));
1083120856Sume			return (EINVAL);
108478064Sume		}
108578064Sume		if (plen != 128) {
1086122059Sume			nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
1087122059Sume			    "be 128 when dstaddr is specified\n"));
1088120856Sume			return (EINVAL);
108978064Sume		}
109078064Sume	}
109178064Sume	/* lifetime consistency check */
109278064Sume	lt = &ifra->ifra_lifetime;
1093151539Ssuz	if (lt->ia6t_pltime > lt->ia6t_vltime)
1094151539Ssuz		return (EINVAL);
109578064Sume	if (lt->ia6t_vltime == 0) {
109662587Sitojun		/*
109778064Sume		 * the following log might be noisy, but this is a typical
109878064Sume		 * configuration mistake or a tool's bug.
109962587Sitojun		 */
1100122059Sume		nd6log((LOG_INFO,
110178064Sume		    "in6_update_ifa: valid lifetime is 0 for %s\n",
1102165118Sbz		    ip6_sprintf(ip6buf, &ifra->ifra_addr.sin6_addr)));
1103151539Ssuz
1104151539Ssuz		if (ia == NULL)
1105151539Ssuz			return (0); /* there's nothing to do */
110678064Sume	}
110762587Sitojun
110878064Sume	/*
110978064Sume	 * If this is a new address, allocate a new ifaddr and link it
111078064Sume	 * into chains.
111178064Sume	 */
111278064Sume	if (ia == NULL) {
111378064Sume		hostIsNew = 1;
111479763Sume		/*
111579763Sume		 * When in6_update_ifa() is called in a process of a received
1116120891Sume		 * RA, it is called under an interrupt context.  So, we should
1117120891Sume		 * call malloc with M_NOWAIT.
111879763Sume		 */
1119120891Sume		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
1120120891Sume		    M_NOWAIT);
112178064Sume		if (ia == NULL)
112278064Sume			return (ENOBUFS);
112378064Sume		bzero((caddr_t)ia, sizeof(*ia));
1124194602Srwatson		ifa_init(&ia->ia_ifa);
1125170202Sjinmei		LIST_INIT(&ia->ia6_memberships);
1126151539Ssuz		/* Initialize the address and masks, and put time stamp */
112778064Sume		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
112878064Sume		ia->ia_addr.sin6_family = AF_INET6;
112978064Sume		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
1130151539Ssuz		ia->ia6_createtime = time_second;
113178064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
113278064Sume			/*
113378064Sume			 * XXX: some functions expect that ifa_dstaddr is not
113478064Sume			 * NULL for p2p interfaces.
113578064Sume			 */
1136120891Sume			ia->ia_ifa.ifa_dstaddr =
1137120891Sume			    (struct sockaddr *)&ia->ia_dstaddr;
113878064Sume		} else {
113978064Sume			ia->ia_ifa.ifa_dstaddr = NULL;
114053541Sshin		}
1141108033Shsu		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
114278064Sume		ia->ia_ifp = ifp;
1143194760Srwatson		ifa_ref(&ia->ia_ifa);			/* if_addrhead */
1144233200Sjhb		IF_ADDR_WLOCK(ifp);
1145191340Srwatson		TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
1146233200Sjhb		IF_ADDR_WUNLOCK(ifp);
1147194907Srwatson
1148194971Srwatson		ifa_ref(&ia->ia_ifa);			/* in6_ifaddrhead */
1149194971Srwatson		IN6_IFADDR_WLOCK();
1150194907Srwatson		TAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link);
1151194971Srwatson		IN6_IFADDR_WUNLOCK();
115278064Sume	}
115378064Sume
1154151539Ssuz	/* update timestamp */
1155151539Ssuz	ia->ia6_updatetime = time_second;
1156151539Ssuz
115778064Sume	/* set prefix mask */
115878064Sume	if (ifra->ifra_prefixmask.sin6_len) {
115978064Sume		/*
116078064Sume		 * We prohibit changing the prefix length of an existing
116178064Sume		 * address, because
116278064Sume		 * + such an operation should be rare in IPv6, and
116378064Sume		 * + the operation would confuse prefix management.
116478064Sume		 */
116578064Sume		if (ia->ia_prefixmask.sin6_len &&
116678064Sume		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
1167122059Sume			nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
116878064Sume			    " existing (%s) address should not be changed\n",
1169165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
117078064Sume			error = EINVAL;
117178064Sume			goto unlink;
117253541Sshin		}
117378064Sume		ia->ia_prefixmask = ifra->ifra_prefixmask;
117478064Sume	}
117578064Sume
117678064Sume	/*
117778064Sume	 * If a new destination address is specified, scrub the old one and
117878064Sume	 * install the new destination.  Note that the interface must be
1179120891Sume	 * p2p or loopback (see the check above.)
118078064Sume	 */
118178064Sume	if (dst6.sin6_family == AF_INET6 &&
1182120891Sume	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
118378064Sume		int e;
118478064Sume
118578064Sume		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
1186120891Sume		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
1187122059Sume			nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
118878064Sume			    "a route to the old destination: %s\n",
1189165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
119078064Sume			/* proceed anyway... */
1191120891Sume		} else
119278064Sume			ia->ia_flags &= ~IFA_ROUTE;
119378064Sume		ia->ia_dstaddr = dst6;
119478064Sume	}
119553541Sshin
1196148385Sume	/*
1197148385Sume	 * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
1198148385Sume	 * to see if the address is deprecated or invalidated, but initialize
1199148385Sume	 * these members for applications.
1200148385Sume	 */
1201148385Sume	ia->ia6_lifetime = ifra->ifra_lifetime;
1202148385Sume	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
1203148385Sume		ia->ia6_lifetime.ia6t_expire =
1204148385Sume		    time_second + ia->ia6_lifetime.ia6t_vltime;
1205148385Sume	} else
1206148385Sume		ia->ia6_lifetime.ia6t_expire = 0;
1207148385Sume	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
1208148385Sume		ia->ia6_lifetime.ia6t_preferred =
1209148385Sume		    time_second + ia->ia6_lifetime.ia6t_pltime;
1210148385Sume	} else
1211148385Sume		ia->ia6_lifetime.ia6t_preferred = 0;
1212148385Sume
121378064Sume	/* reset the interface and routing table appropriately. */
121478064Sume	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
121578064Sume		goto unlink;
121678064Sume
121778064Sume	/*
1218148385Sume	 * configure address flags.
1219148385Sume	 */
1220148385Sume	ia->ia6_flags = ifra->ifra_flags;
1221148385Sume	/*
1222148385Sume	 * backward compatibility - if IN6_IFF_DEPRECATED is set from the
1223148385Sume	 * userland, make it deprecated.
1224148385Sume	 */
1225148385Sume	if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
1226148385Sume		ia->ia6_lifetime.ia6t_pltime = 0;
1227148385Sume		ia->ia6_lifetime.ia6t_preferred = time_second;
1228148385Sume	}
1229148385Sume	/*
1230151539Ssuz	 * Make the address tentative before joining multicast addresses,
1231151539Ssuz	 * so that corresponding MLD responses would not have a tentative
1232151539Ssuz	 * source address.
1233148385Sume	 */
1234151539Ssuz	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/* safety */
1235151539Ssuz	if (hostIsNew && in6if_do_dad(ifp))
1236148385Sume		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1237148385Sume
1238197138Shrs	/* DAD should be performed after ND6_IFF_IFDISABLED is cleared. */
1239197138Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
1240197138Shrs		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1241197138Shrs
1242148385Sume	/*
1243148385Sume	 * We are done if we have simply modified an existing address.
1244148385Sume	 */
1245148385Sume	if (!hostIsNew)
1246148385Sume		return (error);
1247148385Sume
1248148385Sume	/*
124978064Sume	 * Beyond this point, we should call in6_purgeaddr upon an error,
1250120891Sume	 * not just go to unlink.
125178064Sume	 */
125278064Sume
1253232292Sbz	/* Join necessary multicast groups. */
1254151539Ssuz	in6m_sol = NULL;
125578064Sume	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
1256232292Sbz		error = in6_update_ifa_join_mc(ifp, ifra, ia, flags, &in6m_sol);
1257232292Sbz		if (error)
1258148385Sume			goto cleanup;
125978064Sume	}
126053541Sshin
1261151539Ssuz	/*
1262151539Ssuz	 * Perform DAD, if needed.
1263232292Sbz	 * XXX It may be of use, if we can administratively disable DAD.
1264151539Ssuz	 */
1265194760Srwatson	if (in6if_do_dad(ifp) && ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
1266151539Ssuz	    (ia->ia6_flags & IN6_IFF_TENTATIVE))
1267151539Ssuz	{
1268151539Ssuz		int mindelay, maxdelay;
1269151539Ssuz
1270151539Ssuz		delay = 0;
1271151539Ssuz		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1272151539Ssuz			/*
1273151539Ssuz			 * We need to impose a delay before sending an NS
1274151539Ssuz			 * for DAD.  Check if we also needed a delay for the
1275151539Ssuz			 * corresponding MLD message.  If we did, the delay
1276151539Ssuz			 * should be larger than the MLD delay (this could be
1277151539Ssuz			 * relaxed a bit, but this simple logic is at least
1278151539Ssuz			 * safe).
1279191672Sbms			 * XXX: Break data hiding guidelines and look at
1280191672Sbms			 * state for the solicited multicast group.
1281151539Ssuz			 */
1282151539Ssuz			mindelay = 0;
1283151539Ssuz			if (in6m_sol != NULL &&
1284191672Sbms			    in6m_sol->in6m_state == MLD_REPORTING_MEMBER) {
1285151539Ssuz				mindelay = in6m_sol->in6m_timer;
1286151539Ssuz			}
1287151539Ssuz			maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
1288151539Ssuz			if (maxdelay - mindelay == 0)
1289151539Ssuz				delay = 0;
1290151539Ssuz			else {
1291151539Ssuz				delay =
1292151539Ssuz				    (arc4random() % (maxdelay - mindelay)) +
1293151539Ssuz				    mindelay;
1294151539Ssuz			}
1295151539Ssuz		}
1296151539Ssuz		nd6_dad_start((struct ifaddr *)ia, delay);
1297151539Ssuz	}
1298151539Ssuz
1299194760Srwatson	KASSERT(hostIsNew, ("in6_update_ifa: !hostIsNew"));
1300194760Srwatson	ifa_free(&ia->ia_ifa);
1301120856Sume	return (error);
130278064Sume
130378064Sume  unlink:
130478064Sume	/*
130578064Sume	 * XXX: if a change of an existing address failed, keep the entry
130678064Sume	 * anyway.
130778064Sume	 */
1308194760Srwatson	if (hostIsNew) {
1309194943Srwatson		in6_unlink_ifa(ia, ifp);
1310194760Srwatson		ifa_free(&ia->ia_ifa);
1311194760Srwatson	}
1312120856Sume	return (error);
1313148385Sume
1314148385Sume  cleanup:
1315194760Srwatson	KASSERT(hostIsNew, ("in6_update_ifa: cleanup: !hostIsNew"));
1316194760Srwatson	ifa_free(&ia->ia_ifa);
1317148385Sume	in6_purgeaddr(&ia->ia_ifa);
1318148385Sume	return error;
131953541Sshin}
132053541Sshin
1321232292Sbz/*
1322232292Sbz * Leave multicast groups.  Factored out from in6_purgeaddr().
1323232292Sbz * This entire work should only be done once, for the default FIB.
1324232292Sbz */
1325232292Sbzstatic int
1326232292Sbzin6_purgeaddr_mc(struct ifnet *ifp, struct in6_ifaddr *ia, struct ifaddr *ifa0)
132762587Sitojun{
1328232292Sbz	struct sockaddr_in6 mltaddr, mltmask;
1329170202Sjinmei	struct in6_multi_mship *imm;
1330192282Sqingli	struct rtentry *rt;
1331237945Sdelphij	struct sockaddr_in6 sin6;
1332232292Sbz	int error;
133362587Sitojun
1334192282Sqingli	/*
1335232292Sbz	 * Leave from multicast groups we have joined for the interface.
1336192282Sqingli	 */
1337233046Sjhb	while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
1338170202Sjinmei		LIST_REMOVE(imm, i6mm_chain);
1339170202Sjinmei		in6_leavegroup(imm);
134062587Sitojun	}
134162587Sitojun
1342192282Sqingli	/*
1343232292Sbz	 * Remove the link-local all-nodes address.
1344192282Sqingli	 */
1345192282Sqingli	bzero(&mltmask, sizeof(mltmask));
1346192282Sqingli	mltmask.sin6_len = sizeof(struct sockaddr_in6);
1347192282Sqingli	mltmask.sin6_family = AF_INET6;
1348192282Sqingli	mltmask.sin6_addr = in6mask32;
1349192282Sqingli
1350192282Sqingli	bzero(&mltaddr, sizeof(mltaddr));
1351192282Sqingli	mltaddr.sin6_len = sizeof(struct sockaddr_in6);
1352192282Sqingli	mltaddr.sin6_family = AF_INET6;
1353192282Sqingli	mltaddr.sin6_addr = in6addr_linklocal_allnodes;
1354192282Sqingli
1355231319Sbz	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
1356232292Sbz		return (error);
1357192282Sqingli
1358237945Sdelphij	/*
1359237945Sdelphij	 * As for the mltaddr above, proactively prepare the sin6 to avoid
1360237945Sdelphij	 * rtentry un- and re-locking.
1361237945Sdelphij	 */
1362237945Sdelphij	if (ifa0 != NULL) {
1363237945Sdelphij		bzero(&sin6, sizeof(sin6));
1364237945Sdelphij		sin6.sin6_len = sizeof(sin6);
1365237945Sdelphij		sin6.sin6_family = AF_INET6;
1366240310Sglebius		memcpy(&sin6.sin6_addr, &satosin6(ifa0->ifa_addr)->sin6_addr,
1367237945Sdelphij		    sizeof(sin6.sin6_addr));
1368238476Sbz		error = in6_setscope(&sin6.sin6_addr, ifa0->ifa_ifp, NULL);
1369238476Sbz		if (error != 0)
1370238476Sbz			return (error);
1371237945Sdelphij	}
1372237945Sdelphij
1373232292Sbz	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
1374192282Sqingli	if (rt != NULL && rt->rt_gateway != NULL &&
1375240310Sglebius	    (memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
1376192282Sqingli		    &ia->ia_addr.sin6_addr,
1377192282Sqingli		    sizeof(ia->ia_addr.sin6_addr)) == 0)) {
1378240310Sglebius		/*
1379232292Sbz		 * If no more IPv6 address exists on this interface then
1380232292Sbz		 * remove the multicast address route.
1381192282Sqingli		 */
1382192282Sqingli		if (ifa0 == NULL) {
1383240310Sglebius			memcpy(&mltaddr.sin6_addr,
1384240310Sglebius			    &satosin6(rt_key(rt))->sin6_addr,
1385240310Sglebius			    sizeof(mltaddr.sin6_addr));
1386192282Sqingli			RTFREE_LOCKED(rt);
1387232292Sbz			error = in6_rtrequest(RTM_DELETE,
1388232292Sbz			    (struct sockaddr *)&mltaddr,
1389232292Sbz			    (struct sockaddr *)&ia->ia_addr,
1390232292Sbz			    (struct sockaddr *)&mltmask, RTF_UP,
1391232292Sbz			    (struct rtentry **)0, RT_DEFAULT_FIB);
1392192282Sqingli			if (error)
1393232292Sbz				log(LOG_INFO, "%s: link-local all-nodes "
1394232292Sbz				    "multicast address deletion error\n",
1395232292Sbz				    __func__);
1396192282Sqingli		} else {
1397192282Sqingli			/*
1398232292Sbz			 * Replace the gateway of the route.
1399192282Sqingli			 */
1400237945Sdelphij			memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
1401192282Sqingli			RTFREE_LOCKED(rt);
1402192282Sqingli		}
1403192282Sqingli	} else {
1404192282Sqingli		if (rt != NULL)
1405192282Sqingli			RTFREE_LOCKED(rt);
1406192282Sqingli	}
1407192282Sqingli
1408192282Sqingli	/*
1409232292Sbz	 * Remove the node-local all-nodes address.
1410192282Sqingli	 */
1411192282Sqingli	mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
1412232292Sbz	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
1413232292Sbz		return (error);
1414192282Sqingli
1415232292Sbz	rt = in6_rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL, RT_DEFAULT_FIB);
1416192282Sqingli	if (rt != NULL && rt->rt_gateway != NULL &&
1417240310Sglebius	    (memcmp(&satosin6(rt->rt_gateway)->sin6_addr,
1418192282Sqingli		    &ia->ia_addr.sin6_addr,
1419192282Sqingli		    sizeof(ia->ia_addr.sin6_addr)) == 0)) {
1420240310Sglebius		/*
1421232292Sbz		 * If no more IPv6 address exists on this interface then
1422232292Sbz		 * remove the multicast address route.
1423192282Sqingli		 */
1424192282Sqingli		if (ifa0 == NULL) {
1425240310Sglebius			memcpy(&mltaddr.sin6_addr,
1426240310Sglebius			    &satosin6(rt_key(rt))->sin6_addr,
1427240310Sglebius			    sizeof(mltaddr.sin6_addr));
1428192282Sqingli
1429192282Sqingli			RTFREE_LOCKED(rt);
1430232292Sbz			error = in6_rtrequest(RTM_DELETE,
1431232292Sbz			    (struct sockaddr *)&mltaddr,
1432232292Sbz			    (struct sockaddr *)&ia->ia_addr,
1433232292Sbz			    (struct sockaddr *)&mltmask, RTF_UP,
1434232292Sbz			    (struct rtentry **)0, RT_DEFAULT_FIB);
1435192282Sqingli			if (error)
1436232292Sbz				log(LOG_INFO, "%s: node-local all-nodes"
1437232292Sbz				    "multicast address deletion error\n",
1438232292Sbz				    __func__);
1439192282Sqingli		} else {
1440192282Sqingli			/*
1441232292Sbz			 * Replace the gateway of the route.
1442192282Sqingli			 */
1443237945Sdelphij			memcpy(rt->rt_gateway, &sin6, sizeof(sin6));
1444192282Sqingli			RTFREE_LOCKED(rt);
1445192282Sqingli		}
1446192282Sqingli	} else {
1447192282Sqingli		if (rt != NULL)
1448192282Sqingli			RTFREE_LOCKED(rt);
1449192282Sqingli	}
1450192282Sqingli
1451232292Sbz	return (0);
1452232292Sbz}
1453232292Sbz
1454232292Sbzvoid
1455232292Sbzin6_purgeaddr(struct ifaddr *ifa)
1456232292Sbz{
1457232292Sbz	struct ifnet *ifp = ifa->ifa_ifp;
1458232292Sbz	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
1459232292Sbz	int plen, error;
1460232292Sbz	struct ifaddr *ifa0;
1461232292Sbz
1462232292Sbz	/*
1463232292Sbz	 * find another IPv6 address as the gateway for the
1464232292Sbz	 * link-local and node-local all-nodes multicast
1465232292Sbz	 * address routes
1466232292Sbz	 */
1467233200Sjhb	IF_ADDR_RLOCK(ifp);
1468232292Sbz	TAILQ_FOREACH(ifa0, &ifp->if_addrhead, ifa_link) {
1469232292Sbz		if ((ifa0->ifa_addr->sa_family != AF_INET6) ||
1470232292Sbz		    memcmp(&satosin6(ifa0->ifa_addr)->sin6_addr,
1471240310Sglebius		    &ia->ia_addr.sin6_addr, sizeof(struct in6_addr)) == 0)
1472232292Sbz			continue;
1473232292Sbz		else
1474232292Sbz			break;
1475232292Sbz	}
1476231324Sbz	if (ifa0 != NULL)
1477232292Sbz		ifa_ref(ifa0);
1478233200Sjhb	IF_ADDR_RUNLOCK(ifp);
1479232292Sbz
1480232292Sbz	/*
1481232292Sbz	 * Remove the loopback route to the interface address.
1482240310Sglebius	 * The check for the current setting of "nd6_useloopback"
1483232292Sbz	 * is not needed.
1484232292Sbz	 */
1485232292Sbz	if (ia->ia_flags & IFA_RTSELF) {
1486232292Sbz		error = ifa_del_loopback_route((struct ifaddr *)ia,
1487240310Sglebius		    (struct sockaddr *)&ia->ia_addr);
1488232292Sbz		if (error == 0)
1489232292Sbz			ia->ia_flags &= ~IFA_RTSELF;
1490232292Sbz	}
1491232292Sbz
1492232292Sbz	/* stop DAD processing */
1493232292Sbz	nd6_dad_stop(ifa);
1494232292Sbz
1495232292Sbz	/* Remove local address entry from lltable. */
1496232292Sbz	in6_ifremloop(ifa);
1497232292Sbz
1498232292Sbz	/* Leave multicast groups. */
1499232292Sbz	error = in6_purgeaddr_mc(ifp, ia, ifa0);
1500232292Sbz
1501232292Sbz	if (ifa0 != NULL)
1502231324Sbz		ifa_free(ifa0);
1503192282Sqingli
1504192282Sqingli	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1505192282Sqingli	if ((ia->ia_flags & IFA_ROUTE) && plen == 128) {
1506232292Sbz		error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags |
1507232292Sbz		    (ia->ia_dstaddr.sin6_family == AF_INET6) ? RTF_HOST : 0);
1508192282Sqingli		if (error != 0)
1509232292Sbz			log(LOG_INFO, "%s: err=%d, destination address delete "
1510232292Sbz			    "failed\n", __func__, error);
1511192282Sqingli		ia->ia_flags &= ~IFA_ROUTE;
1512192282Sqingli	}
1513192282Sqingli
151478064Sume	in6_unlink_ifa(ia, ifp);
151578064Sume}
151678064Sume
151778064Sumestatic void
1518171259Sdelphijin6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
151978064Sume{
152078064Sume	int	s = splnet();
152178064Sume
1522233200Sjhb	IF_ADDR_WLOCK(ifp);
1523191340Srwatson	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
1524233200Sjhb	IF_ADDR_WUNLOCK(ifp);
1525194760Srwatson	ifa_free(&ia->ia_ifa);			/* if_addrhead */
152662587Sitojun
1527195102Srwatson	/*
1528195102Srwatson	 * Defer the release of what might be the last reference to the
1529195102Srwatson	 * in6_ifaddr so that it can't be freed before the remainder of the
1530195102Srwatson	 * cleanup.
1531195102Srwatson	 */
1532194971Srwatson	IN6_IFADDR_WLOCK();
1533194907Srwatson	TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link);
1534194971Srwatson	IN6_IFADDR_WUNLOCK();
153562587Sitojun
153662587Sitojun	/*
1537151915Ssuz	 * Release the reference to the base prefix.  There should be a
1538151915Ssuz	 * positive reference.
153962587Sitojun	 */
1540194907Srwatson	if (ia->ia6_ndpr == NULL) {
1541151915Ssuz		nd6log((LOG_NOTICE,
1542151915Ssuz		    "in6_unlink_ifa: autoconf'ed address "
1543194907Srwatson		    "%p has no prefix\n", ia));
1544151915Ssuz	} else {
1545194907Srwatson		ia->ia6_ndpr->ndpr_refcnt--;
1546194907Srwatson		ia->ia6_ndpr = NULL;
1547151915Ssuz	}
154862587Sitojun
1549151915Ssuz	/*
1550151915Ssuz	 * Also, if the address being removed is autoconf'ed, call
1551151915Ssuz	 * pfxlist_onlink_check() since the release might affect the status of
1552171260Sdelphij	 * other (detached) addresses.
1553151915Ssuz	 */
1554194907Srwatson	if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) {
155578064Sume		pfxlist_onlink_check();
155662587Sitojun	}
1557195102Srwatson	ifa_free(&ia->ia_ifa);			/* in6_ifaddrhead */
155878064Sume	splx(s);
155962587Sitojun}
156062587Sitojun
156178064Sumevoid
1562171259Sdelphijin6_purgeif(struct ifnet *ifp)
156378064Sume{
156478064Sume	struct ifaddr *ifa, *nifa;
156578064Sume
1566191340Srwatson	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, nifa) {
156778064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
156878064Sume			continue;
156978064Sume		in6_purgeaddr(ifa);
157078064Sume	}
157178064Sume
157278064Sume	in6_ifdetach(ifp);
157378064Sume}
157478064Sume
157553541Sshin/*
157653541Sshin * SIOC[GAD]LIFADDR.
157762744Sgrog *	SIOCGLIFADDR: get first address. (?)
157853541Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
157953541Sshin *		get first address that matches the specified prefix.
158053541Sshin *	SIOCALIFADDR: add the specified address.
158153541Sshin *	SIOCALIFADDR with IFLR_PREFIX:
158253541Sshin *		add the specified prefix, filling hostid part from
158353541Sshin *		the first link-local address.  prefixlen must be <= 64.
158453541Sshin *	SIOCDLIFADDR: delete the specified address.
158553541Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
158653541Sshin *		delete the first address that matches the specified prefix.
158753541Sshin * return values:
158853541Sshin *	EINVAL on invalid parameters
158953541Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
159053541Sshin *	other values may be returned from in6_ioctl()
159153541Sshin *
159253541Sshin * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
159353541Sshin * this is to accomodate address naming scheme other than RFC2374,
159453541Sshin * in the future.
159553541Sshin * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
159653541Sshin * address encoding scheme. (see figure on page 8)
159753541Sshin */
159853541Sshinstatic int
1599171259Sdelphijin6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
1600171259Sdelphij    struct ifnet *ifp, struct thread *td)
160153541Sshin{
160253541Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
160353541Sshin	struct ifaddr *ifa;
160462587Sitojun	struct sockaddr *sa;
160553541Sshin
160653541Sshin	/* sanity checks */
160753541Sshin	if (!data || !ifp) {
160853541Sshin		panic("invalid argument to in6_lifaddr_ioctl");
1609120891Sume		/* NOTREACHED */
161053541Sshin	}
161153541Sshin
161253541Sshin	switch (cmd) {
161353541Sshin	case SIOCGLIFADDR:
161453541Sshin		/* address must be specified on GET with IFLR_PREFIX */
161553541Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
161653541Sshin			break;
161795023Ssuz		/* FALLTHROUGH */
161853541Sshin	case SIOCALIFADDR:
161953541Sshin	case SIOCDLIFADDR:
162053541Sshin		/* address must be specified on ADD and DELETE */
162162587Sitojun		sa = (struct sockaddr *)&iflr->addr;
162262587Sitojun		if (sa->sa_family != AF_INET6)
162353541Sshin			return EINVAL;
162462587Sitojun		if (sa->sa_len != sizeof(struct sockaddr_in6))
162553541Sshin			return EINVAL;
162653541Sshin		/* XXX need improvement */
162762587Sitojun		sa = (struct sockaddr *)&iflr->dstaddr;
162862587Sitojun		if (sa->sa_family && sa->sa_family != AF_INET6)
162953541Sshin			return EINVAL;
163062587Sitojun		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
163153541Sshin			return EINVAL;
163253541Sshin		break;
163395023Ssuz	default: /* shouldn't happen */
163462587Sitojun#if 0
163562587Sitojun		panic("invalid cmd to in6_lifaddr_ioctl");
163695023Ssuz		/* NOTREACHED */
163762587Sitojun#else
163853541Sshin		return EOPNOTSUPP;
163962587Sitojun#endif
164053541Sshin	}
164153541Sshin	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
164253541Sshin		return EINVAL;
164353541Sshin
164453541Sshin	switch (cmd) {
164553541Sshin	case SIOCALIFADDR:
164653541Sshin	    {
164753541Sshin		struct in6_aliasreq ifra;
164853541Sshin		struct in6_addr *hostid = NULL;
164953541Sshin		int prefixlen;
165053541Sshin
1651194760Srwatson		ifa = NULL;
165253541Sshin		if ((iflr->flags & IFLR_PREFIX) != 0) {
165353541Sshin			struct sockaddr_in6 *sin6;
165453541Sshin
165553541Sshin			/*
165653541Sshin			 * hostid is to fill in the hostid part of the
165753541Sshin			 * address.  hostid points to the first link-local
165853541Sshin			 * address attached to the interface.
165953541Sshin			 */
166062587Sitojun			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
166153541Sshin			if (!ifa)
166253541Sshin				return EADDRNOTAVAIL;
166353541Sshin			hostid = IFA_IN6(ifa);
166453541Sshin
1665171260Sdelphij			/* prefixlen must be <= 64. */
1666236826Sbz			if (64 < iflr->prefixlen) {
1667236826Sbz				if (ifa != NULL)
1668236826Sbz					ifa_free(ifa);
166953541Sshin				return EINVAL;
1670236826Sbz			}
167153541Sshin			prefixlen = iflr->prefixlen;
167253541Sshin
167353541Sshin			/* hostid part must be zero. */
167453541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1675126552Sume			if (sin6->sin6_addr.s6_addr32[2] != 0 ||
1676126552Sume			    sin6->sin6_addr.s6_addr32[3] != 0) {
1677236826Sbz				if (ifa != NULL)
1678236826Sbz					ifa_free(ifa);
167953541Sshin				return EINVAL;
168053541Sshin			}
168153541Sshin		} else
168253541Sshin			prefixlen = iflr->prefixlen;
168353541Sshin
168453541Sshin		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
168553541Sshin		bzero(&ifra, sizeof(ifra));
1686120891Sume		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
168753541Sshin
168862587Sitojun		bcopy(&iflr->addr, &ifra.ifra_addr,
1689120891Sume		    ((struct sockaddr *)&iflr->addr)->sa_len);
169053541Sshin		if (hostid) {
169153541Sshin			/* fill in hostid part */
169253541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1693120891Sume			    hostid->s6_addr32[2];
169453541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1695120891Sume			    hostid->s6_addr32[3];
169653541Sshin		}
169753541Sshin
1698120891Sume		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
169953541Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1700120891Sume			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
170153541Sshin			if (hostid) {
170253541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1703120891Sume				    hostid->s6_addr32[2];
170453541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1705120891Sume				    hostid->s6_addr32[3];
170653541Sshin			}
170753541Sshin		}
1708194760Srwatson		if (ifa != NULL)
1709194760Srwatson			ifa_free(ifa);
171053541Sshin
171153541Sshin		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1712121168Sume		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
171353541Sshin
171453541Sshin		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
171583366Sjulian		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
171653541Sshin	    }
171753541Sshin	case SIOCGLIFADDR:
171853541Sshin	case SIOCDLIFADDR:
171953541Sshin	    {
172053541Sshin		struct in6_ifaddr *ia;
172153541Sshin		struct in6_addr mask, candidate, match;
172253541Sshin		struct sockaddr_in6 *sin6;
172353541Sshin		int cmp;
172453541Sshin
172553541Sshin		bzero(&mask, sizeof(mask));
172653541Sshin		if (iflr->flags & IFLR_PREFIX) {
172753541Sshin			/* lookup a prefix rather than address. */
1728121168Sume			in6_prefixlen2mask(&mask, iflr->prefixlen);
172953541Sshin
173053541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
173153541Sshin			bcopy(&sin6->sin6_addr, &match, sizeof(match));
173253541Sshin			match.s6_addr32[0] &= mask.s6_addr32[0];
173353541Sshin			match.s6_addr32[1] &= mask.s6_addr32[1];
173453541Sshin			match.s6_addr32[2] &= mask.s6_addr32[2];
173553541Sshin			match.s6_addr32[3] &= mask.s6_addr32[3];
173653541Sshin
173753541Sshin			/* if you set extra bits, that's wrong */
173853541Sshin			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
173953541Sshin				return EINVAL;
174053541Sshin
174153541Sshin			cmp = 1;
174253541Sshin		} else {
174353541Sshin			if (cmd == SIOCGLIFADDR) {
174453541Sshin				/* on getting an address, take the 1st match */
174595023Ssuz				cmp = 0;	/* XXX */
174653541Sshin			} else {
174753541Sshin				/* on deleting an address, do exact match */
1748121168Sume				in6_prefixlen2mask(&mask, 128);
174953541Sshin				sin6 = (struct sockaddr_in6 *)&iflr->addr;
175053541Sshin				bcopy(&sin6->sin6_addr, &match, sizeof(match));
175153541Sshin
175253541Sshin				cmp = 1;
175353541Sshin			}
175453541Sshin		}
175553541Sshin
1756233200Sjhb		IF_ADDR_RLOCK(ifp);
1757191340Srwatson		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
175853541Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
175953541Sshin				continue;
176053541Sshin			if (!cmp)
176153541Sshin				break;
176278064Sume
176378064Sume			/*
176478064Sume			 * XXX: this is adhoc, but is necessary to allow
176578064Sume			 * a user to specify fe80::/64 (not /10) for a
176678064Sume			 * link-local address.
176778064Sume			 */
1768148385Sume			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1769148385Sume			in6_clearscope(&candidate);
177053541Sshin			candidate.s6_addr32[0] &= mask.s6_addr32[0];
177153541Sshin			candidate.s6_addr32[1] &= mask.s6_addr32[1];
177253541Sshin			candidate.s6_addr32[2] &= mask.s6_addr32[2];
177353541Sshin			candidate.s6_addr32[3] &= mask.s6_addr32[3];
177453541Sshin			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
177553541Sshin				break;
177653541Sshin		}
1777230074Sjhb		if (ifa != NULL)
1778230074Sjhb			ifa_ref(ifa);
1779233200Sjhb		IF_ADDR_RUNLOCK(ifp);
178053541Sshin		if (!ifa)
178153541Sshin			return EADDRNOTAVAIL;
178253541Sshin		ia = ifa2ia6(ifa);
178353541Sshin
178453541Sshin		if (cmd == SIOCGLIFADDR) {
1785148385Sume			int error;
178678064Sume
178753541Sshin			/* fill in the if_laddrreq structure */
178853541Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1789148385Sume			error = sa6_recoverscope(
1790148385Sume			    (struct sockaddr_in6 *)&iflr->addr);
1791230074Sjhb			if (error != 0) {
1792230074Sjhb				ifa_free(ifa);
1793148385Sume				return (error);
1794230074Sjhb			}
1795148385Sume
179653541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
179753541Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1798120891Sume				    ia->ia_dstaddr.sin6_len);
1799148385Sume				error = sa6_recoverscope(
1800148385Sume				    (struct sockaddr_in6 *)&iflr->dstaddr);
1801230074Sjhb				if (error != 0) {
1802230074Sjhb					ifa_free(ifa);
1803148385Sume					return (error);
1804230074Sjhb				}
180553541Sshin			} else
180653541Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
180753541Sshin
180853541Sshin			iflr->prefixlen =
1809120891Sume			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
181053541Sshin
181195023Ssuz			iflr->flags = ia->ia6_flags;	/* XXX */
1812230074Sjhb			ifa_free(ifa);
181353541Sshin
181453541Sshin			return 0;
181553541Sshin		} else {
181653541Sshin			struct in6_aliasreq ifra;
181753541Sshin
181853541Sshin			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
181953541Sshin			bzero(&ifra, sizeof(ifra));
182053541Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
1821120891Sume			    sizeof(ifra.ifra_name));
182253541Sshin
182353541Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
1824120891Sume			    ia->ia_addr.sin6_len);
182553541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
182653541Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1827120891Sume				    ia->ia_dstaddr.sin6_len);
182862587Sitojun			} else {
182962587Sitojun				bzero(&ifra.ifra_dstaddr,
183062587Sitojun				    sizeof(ifra.ifra_dstaddr));
183153541Sshin			}
183253541Sshin			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1833120891Sume			    ia->ia_prefixmask.sin6_len);
183453541Sshin
183553541Sshin			ifra.ifra_flags = ia->ia6_flags;
1836230074Sjhb			ifa_free(ifa);
183753541Sshin			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1838120891Sume			    ifp, td);
183953541Sshin		}
184053541Sshin	    }
184153541Sshin	}
184253541Sshin
184395023Ssuz	return EOPNOTSUPP;	/* just for safety */
184453541Sshin}
184553541Sshin
184653541Sshin/*
1847232292Sbz * Initialize an interface's IPv6 address and routing table entry.
184853541Sshin */
184978064Sumestatic int
1850171259Sdelphijin6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
1851171259Sdelphij    struct sockaddr_in6 *sin6, int newhost)
185253541Sshin{
185378064Sume	int	error = 0, plen, ifacount = 0;
185453541Sshin	int	s = splimp();
185578064Sume	struct ifaddr *ifa;
185653541Sshin
185753541Sshin	/*
185853541Sshin	 * Give the interface a chance to initialize
185953541Sshin	 * if this is its first address,
186053541Sshin	 * and to validate the address if necessary.
186153541Sshin	 */
1862233200Sjhb	IF_ADDR_RLOCK(ifp);
1863191340Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
186478064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
186578064Sume			continue;
186678064Sume		ifacount++;
186778064Sume	}
1868233200Sjhb	IF_ADDR_RUNLOCK(ifp);
186978064Sume
187078064Sume	ia->ia_addr = *sin6;
187178064Sume
1872146883Siedowse	if (ifacount <= 1 && ifp->if_ioctl) {
1873146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
1874146883Siedowse		if (error) {
1875146883Siedowse			splx(s);
1876146883Siedowse			return (error);
1877146883Siedowse		}
187853541Sshin	}
187978064Sume	splx(s);
188053541Sshin
188178064Sume	ia->ia_ifa.ifa_metric = ifp->if_metric;
188253541Sshin
188378064Sume	/* we could do in(6)_socktrim here, but just omit it at this moment. */
188478064Sume
188553541Sshin	/*
188678064Sume	 * Special case:
1887124337Sume	 * If a new destination address is specified for a point-to-point
188878064Sume	 * interface, install a route to the destination as an interface
1889240310Sglebius	 * direct route.
1890124337Sume	 * XXX: the logic below rejects assigning multiple addresses on a p2p
1891159390Sgnn	 * interface that share the same destination.
189253541Sshin	 */
189378064Sume	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1894196152Sqingli	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
1895196152Sqingli	    ia->ia_dstaddr.sin6_family == AF_INET6) {
1896159390Sgnn		int rtflags = RTF_UP | RTF_HOST;
1897232292Sbz		error = rtinit(&ia->ia_ifa, RTM_ADD, ia->ia_flags | rtflags);
1898232292Sbz		if (error)
1899120856Sume			return (error);
190078064Sume		ia->ia_flags |= IFA_ROUTE;
1901226455Sqingli		/*
1902226455Sqingli		 * Handle the case for ::1 .
1903226455Sqingli		 */
1904226455Sqingli		if (ifp->if_flags & IFF_LOOPBACK)
1905226455Sqingli			ia->ia_flags |= IFA_RTSELF;
190653541Sshin	}
190753541Sshin
1908195643Sqingli	/*
1909195643Sqingli	 * add a loopback route to self
1910195643Sqingli	 */
1911226455Sqingli	if (!(ia->ia_flags & IFA_RTSELF) && V_nd6_useloopback) {
1912197227Sqingli		error = ifa_add_loopback_route((struct ifaddr *)ia,
1913240310Sglebius		    (struct sockaddr *)&ia->ia_addr);
1914201282Sqingli		if (error == 0)
1915201282Sqingli			ia->ia_flags |= IFA_RTSELF;
1916195643Sqingli	}
1917195643Sqingli
1918232292Sbz	/* Add local address to lltable, if necessary (ex. on p2p link). */
1919226570Sglebius	if (newhost)
1920226570Sglebius		in6_ifaddloop(&(ia->ia_ifa));
192153541Sshin
1922120856Sume	return (error);
192353541Sshin}
192453541Sshin
192553541Sshin/*
192653541Sshin * Find an IPv6 interface link-local address specific to an interface.
1927194760Srwatson * ifaddr is returned referenced.
192853541Sshin */
192953541Sshinstruct in6_ifaddr *
1930171259Sdelphijin6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
193153541Sshin{
193278064Sume	struct ifaddr *ifa;
193353541Sshin
1934233200Sjhb	IF_ADDR_RLOCK(ifp);
1935191340Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
193653541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
193753541Sshin			continue;
193862587Sitojun		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
193962587Sitojun			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
1940240310Sglebius			    ignoreflags) != 0)
194162587Sitojun				continue;
1942194760Srwatson			ifa_ref(ifa);
194353541Sshin			break;
194462587Sitojun		}
194553541Sshin	}
1946233200Sjhb	IF_ADDR_RUNLOCK(ifp);
194753541Sshin
1948120856Sume	return ((struct in6_ifaddr *)ifa);
194953541Sshin}
195053541Sshin
195153541Sshin
195253541Sshin/*
195353541Sshin * find the internet address corresponding to a given interface and address.
1954194760Srwatson * ifaddr is returned referenced.
195553541Sshin */
195653541Sshinstruct in6_ifaddr *
1957171259Sdelphijin6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
195853541Sshin{
195978064Sume	struct ifaddr *ifa;
196053541Sshin
1961233200Sjhb	IF_ADDR_RLOCK(ifp);
1962191340Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
196353541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
196453541Sshin			continue;
1965194760Srwatson		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) {
1966194760Srwatson			ifa_ref(ifa);
196753541Sshin			break;
1968194760Srwatson		}
196953541Sshin	}
1970233200Sjhb	IF_ADDR_RUNLOCK(ifp);
197153541Sshin
1972120856Sume	return ((struct in6_ifaddr *)ifa);
197353541Sshin}
197453541Sshin
197553541Sshin/*
1976253239Shrs * Find a link-local scoped address on ifp and return it if any.
1977253239Shrs */
1978253239Shrsstruct in6_ifaddr *
1979253239Shrsin6ifa_llaonifp(struct ifnet *ifp)
1980253239Shrs{
1981253239Shrs	struct sockaddr_in6 *sin6;
1982253239Shrs	struct ifaddr *ifa;
1983253239Shrs
1984253239Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
1985253239Shrs		return (NULL);
1986253239Shrs	if_addr_rlock(ifp);
1987253239Shrs	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1988253239Shrs		if (ifa->ifa_addr->sa_family != AF_INET6)
1989253239Shrs			continue;
1990253239Shrs		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1991253239Shrs		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
1992253239Shrs		    IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr) ||
1993253239Shrs		    IN6_IS_ADDR_MC_NODELOCAL(&sin6->sin6_addr))
1994253239Shrs			break;
1995253239Shrs	}
1996253239Shrs	if_addr_runlock(ifp);
1997253239Shrs
1998253239Shrs	return ((struct in6_ifaddr *)ifa);
1999253239Shrs}
2000253239Shrs
2001253239Shrs/*
2002165118Sbz * Convert IP6 address to printable (loggable) representation. Caller
2003165118Sbz * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long.
200453541Sshin */
200553541Sshinstatic char digits[] = "0123456789abcdef";
200653541Sshinchar *
2007165118Sbzip6_sprintf(char *ip6buf, const struct in6_addr *addr)
200853541Sshin{
2009208284Salfred	int i, cnt = 0, maxcnt = 0, idx = 0, index = 0;
201078064Sume	char *cp;
2011126552Sume	const u_int16_t *a = (const u_int16_t *)addr;
2012126552Sume	const u_int8_t *d;
2013165287Sbz	int dcolon = 0, zero = 0;
201453541Sshin
2015165118Sbz	cp = ip6buf;
201653541Sshin
201753541Sshin	for (i = 0; i < 8; i++) {
2018208284Salfred		if (*(a + i) == 0) {
2019208284Salfred			cnt++;
2020208284Salfred			if (cnt == 1)
2021208284Salfred				idx = i;
2022208284Salfred		}
2023208284Salfred		else if (maxcnt < cnt) {
2024208284Salfred			maxcnt = cnt;
2025208284Salfred			index = idx;
2026208284Salfred			cnt = 0;
2027208284Salfred		}
2028208284Salfred	}
2029208284Salfred	if (maxcnt < cnt) {
2030208284Salfred		maxcnt = cnt;
2031208284Salfred		index = idx;
2032208284Salfred	}
2033208284Salfred
2034208284Salfred	for (i = 0; i < 8; i++) {
203553541Sshin		if (dcolon == 1) {
203653541Sshin			if (*a == 0) {
203753541Sshin				if (i == 7)
203853541Sshin					*cp++ = ':';
203953541Sshin				a++;
204053541Sshin				continue;
204153541Sshin			} else
204253541Sshin				dcolon = 2;
204353541Sshin		}
204453541Sshin		if (*a == 0) {
2045208284Salfred			if (dcolon == 0 && *(a + 1) == 0 && i == index) {
204653541Sshin				if (i == 0)
204753541Sshin					*cp++ = ':';
204853541Sshin				*cp++ = ':';
204953541Sshin				dcolon = 1;
205053541Sshin			} else {
205153541Sshin				*cp++ = '0';
205253541Sshin				*cp++ = ':';
205353541Sshin			}
205453541Sshin			a++;
205553541Sshin			continue;
205653541Sshin		}
205791346Salfred		d = (const u_char *)a;
2058165287Sbz		/* Try to eliminate leading zeros in printout like in :0001. */
2059165287Sbz		zero = 1;
2060165287Sbz		*cp = digits[*d >> 4];
2061165287Sbz		if (*cp != '0') {
2062165287Sbz			zero = 0;
2063165287Sbz			cp++;
2064165287Sbz		}
2065165287Sbz		*cp = digits[*d++ & 0xf];
2066165287Sbz		if (zero == 0 || (*cp != '0')) {
2067165287Sbz			zero = 0;
2068165287Sbz			cp++;
2069165287Sbz		}
2070165287Sbz		*cp = digits[*d >> 4];
2071165287Sbz		if (zero == 0 || (*cp != '0')) {
2072165287Sbz			zero = 0;
2073165287Sbz			cp++;
2074165287Sbz		}
207553541Sshin		*cp++ = digits[*d & 0xf];
207653541Sshin		*cp++ = ':';
207753541Sshin		a++;
207853541Sshin	}
2079165118Sbz	*--cp = '\0';
2080165118Sbz	return (ip6buf);
208153541Sshin}
208253541Sshin
208353541Sshinint
2084171259Sdelphijin6_localaddr(struct in6_addr *in6)
208553541Sshin{
208653541Sshin	struct in6_ifaddr *ia;
208753541Sshin
208853541Sshin	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
208953541Sshin		return 1;
209053541Sshin
2091194971Srwatson	IN6_IFADDR_RLOCK();
2092194907Srwatson	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
209353541Sshin		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
2094120891Sume		    &ia->ia_prefixmask.sin6_addr)) {
2095194971Srwatson			IN6_IFADDR_RUNLOCK();
209653541Sshin			return 1;
2097120891Sume		}
2098120891Sume	}
2099194971Srwatson	IN6_IFADDR_RUNLOCK();
210053541Sshin
210153541Sshin	return (0);
210253541Sshin}
210353541Sshin
2104225043Sbz/*
2105225043Sbz * Return 1 if an internet address is for the local host and configured
2106225043Sbz * on one of its interfaces.
2107225043Sbz */
210878064Sumeint
2109225043Sbzin6_localip(struct in6_addr *in6)
2110225043Sbz{
2111225043Sbz	struct in6_ifaddr *ia;
2112225043Sbz
2113225043Sbz	IN6_IFADDR_RLOCK();
2114225043Sbz	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
2115225043Sbz		if (IN6_ARE_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr)) {
2116225043Sbz			IN6_IFADDR_RUNLOCK();
2117225043Sbz			return (1);
2118225043Sbz		}
2119225043Sbz	}
2120225043Sbz	IN6_IFADDR_RUNLOCK();
2121225043Sbz	return (0);
2122225043Sbz}
2123225043Sbz
2124225043Sbz
2125225043Sbzint
2126171259Sdelphijin6_is_addr_deprecated(struct sockaddr_in6 *sa6)
212778064Sume{
212878064Sume	struct in6_ifaddr *ia;
212978064Sume
2130194971Srwatson	IN6_IFADDR_RLOCK();
2131194907Srwatson	TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
213278064Sume		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
2133240310Sglebius		    &sa6->sin6_addr) &&
2134194971Srwatson		    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
2135194971Srwatson			IN6_IFADDR_RUNLOCK();
2136120856Sume			return (1); /* true */
2137194971Srwatson		}
213878064Sume
213978064Sume		/* XXX: do we still have to go thru the rest of the list? */
214078064Sume	}
2141194971Srwatson	IN6_IFADDR_RUNLOCK();
214278064Sume
2143120856Sume	return (0);		/* false */
214478064Sume}
214578064Sume
214653541Sshin/*
214753541Sshin * return length of part which dst and src are equal
214853541Sshin * hard coding...
214953541Sshin */
215053541Sshinint
2151171259Sdelphijin6_matchlen(struct in6_addr *src, struct in6_addr *dst)
215253541Sshin{
215353541Sshin	int match = 0;
215453541Sshin	u_char *s = (u_char *)src, *d = (u_char *)dst;
215553541Sshin	u_char *lim = s + 16, r;
215653541Sshin
215753541Sshin	while (s < lim)
215853541Sshin		if ((r = (*d++ ^ *s++)) != 0) {
215953541Sshin			while (r < 128) {
216053541Sshin				match++;
216153541Sshin				r <<= 1;
216253541Sshin			}
216353541Sshin			break;
216453541Sshin		} else
216553541Sshin			match += 8;
216653541Sshin	return match;
216753541Sshin}
216853541Sshin
216962587Sitojun/* XXX: to be scope conscious */
217053541Sshinint
2171171259Sdelphijin6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len)
217253541Sshin{
217353541Sshin	int bytelen, bitlen;
217453541Sshin
217553541Sshin	/* sanity check */
217653541Sshin	if (0 > len || len > 128) {
217753541Sshin		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
217853541Sshin		    len);
2179120856Sume		return (0);
218053541Sshin	}
218153541Sshin
218253541Sshin	bytelen = len / 8;
218353541Sshin	bitlen = len % 8;
218453541Sshin
218553541Sshin	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
2186120856Sume		return (0);
2187126184Scperciva	if (bitlen != 0 &&
2188126184Scperciva	    p1->s6_addr[bytelen] >> (8 - bitlen) !=
218953541Sshin	    p2->s6_addr[bytelen] >> (8 - bitlen))
2190120856Sume		return (0);
219153541Sshin
2192120856Sume	return (1);
219353541Sshin}
219453541Sshin
219553541Sshinvoid
2196171259Sdelphijin6_prefixlen2mask(struct in6_addr *maskp, int len)
219753541Sshin{
219853541Sshin	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
219953541Sshin	int bytelen, bitlen, i;
220053541Sshin
220153541Sshin	/* sanity check */
220253541Sshin	if (0 > len || len > 128) {
220353541Sshin		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
220453541Sshin		    len);
220553541Sshin		return;
220653541Sshin	}
220753541Sshin
220853541Sshin	bzero(maskp, sizeof(*maskp));
220953541Sshin	bytelen = len / 8;
221053541Sshin	bitlen = len % 8;
221153541Sshin	for (i = 0; i < bytelen; i++)
221253541Sshin		maskp->s6_addr[i] = 0xff;
221353541Sshin	if (bitlen)
221453541Sshin		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
221553541Sshin}
221653541Sshin
221753541Sshin/*
221853541Sshin * return the best address out of the same scope. if no address was
221953541Sshin * found, return the first valid address from designated IF.
222053541Sshin */
222153541Sshinstruct in6_ifaddr *
2222171259Sdelphijin6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
222353541Sshin{
222453541Sshin	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
222553541Sshin	struct ifaddr *ifa;
222653541Sshin	struct in6_ifaddr *besta = 0;
222795023Ssuz	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
222853541Sshin
222953541Sshin	dep[0] = dep[1] = NULL;
223053541Sshin
223153541Sshin	/*
223253541Sshin	 * We first look for addresses in the same scope.
223353541Sshin	 * If there is one, return it.
223453541Sshin	 * If two or more, return one which matches the dst longest.
223553541Sshin	 * If none, return one of global addresses assigned other ifs.
223653541Sshin	 */
2237233200Sjhb	IF_ADDR_RLOCK(ifp);
2238191340Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
223953541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
224053541Sshin			continue;
224153541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
224253541Sshin			continue; /* XXX: is there any case to allow anycast? */
224353541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
224453541Sshin			continue; /* don't use this interface */
224553541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
224653541Sshin			continue;
224753541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2248181803Sbz			if (V_ip6_use_deprecated)
224953541Sshin				dep[0] = (struct in6_ifaddr *)ifa;
225053541Sshin			continue;
225153541Sshin		}
225253541Sshin
225353541Sshin		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
225453541Sshin			/*
225553541Sshin			 * call in6_matchlen() as few as possible
225653541Sshin			 */
225753541Sshin			if (besta) {
225853541Sshin				if (blen == -1)
225953541Sshin					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
226053541Sshin				tlen = in6_matchlen(IFA_IN6(ifa), dst);
226153541Sshin				if (tlen > blen) {
226253541Sshin					blen = tlen;
226353541Sshin					besta = (struct in6_ifaddr *)ifa;
226453541Sshin				}
226553541Sshin			} else
226653541Sshin				besta = (struct in6_ifaddr *)ifa;
226753541Sshin		}
226853541Sshin	}
2269191323Srwatson	if (besta) {
2270194760Srwatson		ifa_ref(&besta->ia_ifa);
2271233200Sjhb		IF_ADDR_RUNLOCK(ifp);
2272120856Sume		return (besta);
2273191323Srwatson	}
227453541Sshin
2275191340Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
227653541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
227753541Sshin			continue;
227853541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
227953541Sshin			continue; /* XXX: is there any case to allow anycast? */
228053541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
228153541Sshin			continue; /* don't use this interface */
228253541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
228353541Sshin			continue;
228453541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2285181803Sbz			if (V_ip6_use_deprecated)
228653541Sshin				dep[1] = (struct in6_ifaddr *)ifa;
228753541Sshin			continue;
228853541Sshin		}
228953541Sshin
2290194760Srwatson		if (ifa != NULL)
2291194760Srwatson			ifa_ref(ifa);
2292233200Sjhb		IF_ADDR_RUNLOCK(ifp);
229353541Sshin		return (struct in6_ifaddr *)ifa;
229453541Sshin	}
229553541Sshin
229653541Sshin	/* use the last-resort values, that are, deprecated addresses */
2297236606Sbz	if (dep[0]) {
2298236606Sbz		ifa_ref((struct ifaddr *)dep[0]);
2299236606Sbz		IF_ADDR_RUNLOCK(ifp);
230053541Sshin		return dep[0];
2301236606Sbz	}
2302236606Sbz	if (dep[1]) {
2303236606Sbz		ifa_ref((struct ifaddr *)dep[1]);
2304236606Sbz		IF_ADDR_RUNLOCK(ifp);
230553541Sshin		return dep[1];
2306236606Sbz	}
230753541Sshin
2308236606Sbz	IF_ADDR_RUNLOCK(ifp);
230953541Sshin	return NULL;
231053541Sshin}
231153541Sshin
231253541Sshin/*
231353541Sshin * perform DAD when interface becomes IFF_UP.
231453541Sshin */
231553541Sshinvoid
2316171259Sdelphijin6_if_up(struct ifnet *ifp)
231753541Sshin{
231853541Sshin	struct ifaddr *ifa;
231953541Sshin	struct in6_ifaddr *ia;
232053541Sshin
2321233200Sjhb	IF_ADDR_RLOCK(ifp);
2322191340Srwatson	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
232353541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
232453541Sshin			continue;
232553541Sshin		ia = (struct in6_ifaddr *)ifa;
2326151539Ssuz		if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
2327151539Ssuz			/*
2328151539Ssuz			 * The TENTATIVE flag was likely set by hand
2329151539Ssuz			 * beforehand, implicitly indicating the need for DAD.
2330151539Ssuz			 * We may be able to skip the random delay in this
2331151539Ssuz			 * case, but we impose delays just in case.
2332151539Ssuz			 */
2333151539Ssuz			nd6_dad_start(ifa,
2334151539Ssuz			    arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
2335151539Ssuz		}
233653541Sshin	}
2337233200Sjhb	IF_ADDR_RUNLOCK(ifp);
2338151539Ssuz
2339151539Ssuz	/*
2340151539Ssuz	 * special cases, like 6to4, are handled in in6_ifattach
2341151539Ssuz	 */
2342151539Ssuz	in6_ifattach(ifp, NULL);
234353541Sshin}
234453541Sshin
234578064Sumeint
2346171259Sdelphijin6if_do_dad(struct ifnet *ifp)
234778064Sume{
234878064Sume	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
2349120856Sume		return (0);
235078064Sume
2351197138Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
2352197138Shrs		return (0);
2353197138Shrs
235478064Sume	switch (ifp->if_type) {
235578064Sume#ifdef IFT_DUMMY
235678064Sume	case IFT_DUMMY:
235778064Sume#endif
235878064Sume	case IFT_FAITH:
235978064Sume		/*
236078064Sume		 * These interfaces do not have the IFF_LOOPBACK flag,
236178064Sume		 * but loop packets back.  We do not have to do DAD on such
236278064Sume		 * interfaces.  We should even omit it, because loop-backed
236378064Sume		 * NS would confuse the DAD procedure.
236478064Sume		 */
2365120856Sume		return (0);
236678064Sume	default:
236778064Sume		/*
236878064Sume		 * Our DAD routine requires the interface up and running.
236978064Sume		 * However, some interfaces can be up before the RUNNING
237078064Sume		 * status.  Additionaly, users may try to assign addresses
237178064Sume		 * before the interface becomes up (or running).
237278064Sume		 * We simply skip DAD in such a case as a work around.
237378064Sume		 * XXX: we should rather mark "tentative" on such addresses,
237478064Sume		 * and do DAD after the interface becomes ready.
237578064Sume		 */
2376148887Srwatson		if (!((ifp->if_flags & IFF_UP) &&
2377148887Srwatson		    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
2378120856Sume			return (0);
237978064Sume
2380120856Sume		return (1);
238178064Sume	}
238278064Sume}
238378064Sume
238453541Sshin/*
238553541Sshin * Calculate max IPv6 MTU through all the interfaces and store it
238653541Sshin * to in6_maxmtu.
238753541Sshin */
238853541Sshinvoid
2389171259Sdelphijin6_setmaxmtu(void)
239053541Sshin{
239153541Sshin	unsigned long maxmtu = 0;
239253541Sshin	struct ifnet *ifp;
239353541Sshin
2394196481Srwatson	IFNET_RLOCK_NOSLEEP();
2395233046Sjhb	TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
2396121283Sume		/* this function can be called during ifnet initialization */
2397121283Sume		if (!ifp->if_afdata[AF_INET6])
2398121283Sume			continue;
239953541Sshin		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2400121283Sume		    IN6_LINKMTU(ifp) > maxmtu)
2401121283Sume			maxmtu = IN6_LINKMTU(ifp);
240253541Sshin	}
2403196481Srwatson	IFNET_RUNLOCK_NOSLEEP();
2404240310Sglebius	if (maxmtu)	/* update only when maxmtu is positive */
2405181803Sbz		V_in6_maxmtu = maxmtu;
240653541Sshin}
240753541Sshin
2408151539Ssuz/*
2409151539Ssuz * Provide the length of interface identifiers to be used for the link attached
2410151539Ssuz * to the given interface.  The length should be defined in "IPv6 over
2411151539Ssuz * xxx-link" document.  Note that address architecture might also define
2412151539Ssuz * the length for a particular set of address prefixes, regardless of the
2413151539Ssuz * link type.  As clarified in rfc2462bis, those two definitions should be
2414151539Ssuz * consistent, and those really are as of August 2004.
2415151539Ssuz */
2416151539Ssuzint
2417171259Sdelphijin6_if2idlen(struct ifnet *ifp)
2418151539Ssuz{
2419151539Ssuz	switch (ifp->if_type) {
2420151539Ssuz	case IFT_ETHER:		/* RFC2464 */
2421151539Ssuz#ifdef IFT_PROPVIRTUAL
2422151539Ssuz	case IFT_PROPVIRTUAL:	/* XXX: no RFC. treat it as ether */
2423151539Ssuz#endif
2424151539Ssuz#ifdef IFT_L2VLAN
2425151539Ssuz	case IFT_L2VLAN:	/* ditto */
2426151539Ssuz#endif
2427151539Ssuz#ifdef IFT_IEEE80211
2428151539Ssuz	case IFT_IEEE80211:	/* ditto */
2429151539Ssuz#endif
2430151539Ssuz#ifdef IFT_MIP
2431151539Ssuz	case IFT_MIP:	/* ditto */
2432151539Ssuz#endif
2433219819Sjeff	case IFT_INFINIBAND:
2434151539Ssuz		return (64);
2435151539Ssuz	case IFT_FDDI:		/* RFC2467 */
2436151539Ssuz		return (64);
2437151539Ssuz	case IFT_ISO88025:	/* RFC2470 (IPv6 over Token Ring) */
2438151539Ssuz		return (64);
2439151539Ssuz	case IFT_PPP:		/* RFC2472 */
2440151539Ssuz		return (64);
2441151539Ssuz	case IFT_ARCNET:	/* RFC2497 */
2442151539Ssuz		return (64);
2443151539Ssuz	case IFT_FRELAY:	/* RFC2590 */
2444151539Ssuz		return (64);
2445151539Ssuz	case IFT_IEEE1394:	/* RFC3146 */
2446151539Ssuz		return (64);
2447151539Ssuz	case IFT_GIF:
2448151539Ssuz		return (64);	/* draft-ietf-v6ops-mech-v2-07 */
2449151539Ssuz	case IFT_LOOP:
2450151539Ssuz		return (64);	/* XXX: is this really correct? */
2451151539Ssuz	default:
2452151539Ssuz		/*
2453151539Ssuz		 * Unknown link type:
2454151539Ssuz		 * It might be controversial to use the today's common constant
2455151539Ssuz		 * of 64 for these cases unconditionally.  For full compliance,
2456151539Ssuz		 * we should return an error in this case.  On the other hand,
2457151539Ssuz		 * if we simply miss the standard for the link type or a new
2458151539Ssuz		 * standard is defined for a new link type, the IFID length
2459151539Ssuz		 * is very likely to be the common constant.  As a compromise,
2460151539Ssuz		 * we always use the constant, but make an explicit notice
2461151539Ssuz		 * indicating the "unknown" case.
2462151539Ssuz		 */
2463151539Ssuz		printf("in6_if2idlen: unknown link type (%d)\n", ifp->if_type);
2464151539Ssuz		return (64);
2465151539Ssuz	}
2466151539Ssuz}
2467151539Ssuz
2468186119Sqingli#include <sys/sysctl.h>
2469186119Sqingli
2470186119Sqinglistruct in6_llentry {
2471186119Sqingli	struct llentry		base;
2472186119Sqingli	struct sockaddr_in6	l3_addr6;
2473186119Sqingli};
2474186119Sqingli
2475240309Sglebius/*
2476240309Sglebius * Deletes an address from the address table.
2477240309Sglebius * This function is called by the timer functions
2478240309Sglebius * such as arptimer() and nd6_llinfo_timer(), and
2479240309Sglebius * the caller does the locking.
2480240309Sglebius */
2481240309Sglebiusstatic void
2482240309Sglebiusin6_lltable_free(struct lltable *llt, struct llentry *lle)
2483240309Sglebius{
2484240309Sglebius	LLE_WUNLOCK(lle);
2485240309Sglebius	LLE_LOCK_DESTROY(lle);
2486240309Sglebius	free(lle, M_LLTABLE);
2487240309Sglebius}
2488240309Sglebius
2489186119Sqinglistatic struct llentry *
2490186119Sqingliin6_lltable_new(const struct sockaddr *l3addr, u_int flags)
2491186119Sqingli{
2492186119Sqingli	struct in6_llentry *lle;
2493186119Sqingli
2494240310Sglebius	lle = malloc(sizeof(struct in6_llentry), M_LLTABLE, M_NOWAIT | M_ZERO);
2495186119Sqingli	if (lle == NULL)		/* NB: caller generates msg */
2496186119Sqingli		return NULL;
2497186119Sqingli
2498186119Sqingli	lle->l3_addr6 = *(const struct sockaddr_in6 *)l3addr;
2499186119Sqingli	lle->base.lle_refcnt = 1;
2500240309Sglebius	lle->base.lle_free = in6_lltable_free;
2501186119Sqingli	LLE_LOCK_INIT(&lle->base);
2502216022Sbz	callout_init_rw(&lle->base.ln_timer_ch, &lle->base.lle_lock,
2503216022Sbz	    CALLOUT_RETURNUNLOCKED);
2504216022Sbz
2505240310Sglebius	return (&lle->base);
2506186119Sqingli}
2507186119Sqingli
2508186119Sqinglistatic void
2509240310Sglebiusin6_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
2510240310Sglebius    const struct sockaddr *mask, u_int flags)
2511192476Sqingli{
2512192476Sqingli	const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix;
2513192476Sqingli	const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask;
2514192476Sqingli	struct llentry *lle, *next;
2515240310Sglebius	int i;
2516192476Sqingli
2517222143Sqingli	/*
2518240310Sglebius	 * (flags & LLE_STATIC) means deleting all entries
2519240310Sglebius	 * including static ND6 entries.
2520222143Sqingli	 */
2521240313Sglebius	IF_AFDATA_WLOCK(llt->llt_ifp);
2522240310Sglebius	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
2523192476Sqingli		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
2524192476Sqingli			if (IN6_ARE_MASKED_ADDR_EQUAL(
2525240313Sglebius			    &satosin6(L3_ADDR(lle))->sin6_addr,
2526240313Sglebius			    &pfx->sin6_addr, &msk->sin6_addr) &&
2527240313Sglebius			    ((flags & LLE_STATIC) ||
2528240313Sglebius			    !(lle->la_flags & LLE_STATIC))) {
2529192476Sqingli				LLE_WLOCK(lle);
2530240313Sglebius				if (callout_stop(&lle->la_timer))
2531206481Sbz					LLE_REMREF(lle);
2532192476Sqingli				llentry_free(lle);
2533192476Sqingli			}
2534192476Sqingli		}
2535192476Sqingli	}
2536240313Sglebius	IF_AFDATA_WUNLOCK(llt->llt_ifp);
2537192476Sqingli}
2538192476Sqingli
2539186119Sqinglistatic int
2540240310Sglebiusin6_lltable_rtcheck(struct ifnet *ifp,
2541240310Sglebius		    u_int flags,
2542201282Sqingli		    const struct sockaddr *l3addr)
2543186119Sqingli{
2544186119Sqingli	struct rtentry *rt;
2545186119Sqingli	char ip6buf[INET6_ADDRSTRLEN];
2546186119Sqingli
2547186119Sqingli	KASSERT(l3addr->sa_family == AF_INET6,
2548186119Sqingli	    ("sin_family %d", l3addr->sa_family));
2549186119Sqingli
2550232292Sbz	/* Our local addresses are always only installed on the default FIB. */
2551186119Sqingli	/* XXX rtalloc1 should take a const param */
2552232292Sbz	rt = in6_rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0,
2553232292Sbz	    RT_DEFAULT_FIB);
2554186119Sqingli	if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
2555186119Sqingli		struct ifaddr *ifa;
2556240310Sglebius		/*
2557240310Sglebius		 * Create an ND6 cache for an IPv6 neighbor
2558186119Sqingli		 * that is not covered by our own prefix.
2559186119Sqingli		 */
2560186119Sqingli		/* XXX ifaof_ifpforaddr should take a const param */
2561186119Sqingli		ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
2562186119Sqingli		if (ifa != NULL) {
2563194760Srwatson			ifa_free(ifa);
2564186119Sqingli			if (rt != NULL)
2565187946Sbz				RTFREE_LOCKED(rt);
2566186119Sqingli			return 0;
2567186119Sqingli		}
2568186119Sqingli		log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
2569186119Sqingli		    ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
2570186119Sqingli		if (rt != NULL)
2571187946Sbz			RTFREE_LOCKED(rt);
2572186119Sqingli		return EINVAL;
2573186119Sqingli	}
2574187946Sbz	RTFREE_LOCKED(rt);
2575186119Sqingli	return 0;
2576186119Sqingli}
2577186119Sqingli
2578186119Sqinglistatic struct llentry *
2579186119Sqingliin6_lltable_lookup(struct lltable *llt, u_int flags,
2580186119Sqingli	const struct sockaddr *l3addr)
2581186119Sqingli{
2582186119Sqingli	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
2583186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
2584186119Sqingli	struct llentry *lle;
2585186119Sqingli	struct llentries *lleh;
2586186119Sqingli	u_int hashkey;
2587186119Sqingli
2588186119Sqingli	IF_AFDATA_LOCK_ASSERT(ifp);
2589186119Sqingli	KASSERT(l3addr->sa_family == AF_INET6,
2590186119Sqingli	    ("sin_family %d", l3addr->sa_family));
2591186119Sqingli
2592186119Sqingli	hashkey = sin6->sin6_addr.s6_addr32[3];
2593186119Sqingli	lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
2594186119Sqingli	LIST_FOREACH(lle, lleh, lle_next) {
2595186708Sqingli		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)L3_ADDR(lle);
2596186119Sqingli		if (lle->la_flags & LLE_DELETED)
2597186119Sqingli			continue;
2598240310Sglebius		if (bcmp(&sa6->sin6_addr, &sin6->sin6_addr,
2599240310Sglebius		    sizeof(struct in6_addr)) == 0)
2600186119Sqingli			break;
2601186119Sqingli	}
2602186119Sqingli
2603186119Sqingli	if (lle == NULL) {
2604186119Sqingli		if (!(flags & LLE_CREATE))
2605186119Sqingli			return (NULL);
2606260510Sae		IF_AFDATA_WLOCK_ASSERT(ifp);
2607186119Sqingli		/*
2608186119Sqingli		 * A route that covers the given address must have
2609186119Sqingli		 * been installed 1st because we are doing a resolution,
2610186119Sqingli		 * verify this.
2611186119Sqingli		 */
2612186119Sqingli		if (!(flags & LLE_IFADDR) &&
2613201282Sqingli		    in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
2614186119Sqingli			return NULL;
2615186119Sqingli
2616186119Sqingli		lle = in6_lltable_new(l3addr, flags);
2617186119Sqingli		if (lle == NULL) {
2618186119Sqingli			log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
2619186119Sqingli			return NULL;
2620186119Sqingli		}
2621186119Sqingli		lle->la_flags = flags & ~LLE_CREATE;
2622186119Sqingli		if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
2623186119Sqingli			bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
2624186119Sqingli			lle->la_flags |= (LLE_VALID | LLE_STATIC);
2625186119Sqingli		}
2626186119Sqingli
2627186119Sqingli		lle->lle_tbl  = llt;
2628186119Sqingli		lle->lle_head = lleh;
2629240313Sglebius		lle->la_flags |= LLE_LINKED;
2630186119Sqingli		LIST_INSERT_HEAD(lleh, lle, lle_next);
2631186119Sqingli	} else if (flags & LLE_DELETE) {
2632186392Sqingli		if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
2633186392Sqingli			LLE_WLOCK(lle);
2634240313Sglebius			lle->la_flags |= LLE_DELETED;
2635198418Sqingli#ifdef DIAGNOSTIC
2636250927Soleg			log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
2637240310Sglebius#endif
2638250927Soleg			if ((lle->la_flags &
2639250927Soleg			    (LLE_STATIC | LLE_IFADDR)) == LLE_STATIC)
2640250927Soleg				llentry_free(lle);
2641250927Soleg			else
2642250927Soleg				LLE_WUNLOCK(lle);
2643186392Sqingli		}
2644186119Sqingli		lle = (void *)-1;
2645186119Sqingli	}
2646186119Sqingli	if (LLE_IS_VALID(lle)) {
2647186119Sqingli		if (flags & LLE_EXCLUSIVE)
2648186119Sqingli			LLE_WLOCK(lle);
2649186119Sqingli		else
2650186119Sqingli			LLE_RLOCK(lle);
2651186119Sqingli	}
2652186119Sqingli	return (lle);
2653186119Sqingli}
2654186119Sqingli
2655186119Sqinglistatic int
2656186119Sqingliin6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
2657186119Sqingli{
2658186119Sqingli	struct ifnet *ifp = llt->llt_ifp;
2659186119Sqingli	struct llentry *lle;
2660186119Sqingli	/* XXX stack use */
2661186119Sqingli	struct {
2662186119Sqingli		struct rt_msghdr	rtm;
2663186119Sqingli		struct sockaddr_in6	sin6;
2664186119Sqingli		/*
2665186119Sqingli		 * ndp.c assumes that sdl is word aligned
2666186119Sqingli		 */
2667186119Sqingli#ifdef __LP64__
2668186119Sqingli		uint32_t		pad;
2669186119Sqingli#endif
2670186119Sqingli		struct sockaddr_dl	sdl;
2671186119Sqingli	} ndpc;
2672186119Sqingli	int i, error;
2673186119Sqingli
2674196864Sqingli	if (ifp->if_flags & IFF_LOOPBACK)
2675196864Sqingli		return 0;
2676196864Sqingli
2677196535Srwatson	LLTABLE_LOCK_ASSERT();
2678186119Sqingli
2679186119Sqingli	error = 0;
2680186119Sqingli	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
2681186119Sqingli		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
2682186119Sqingli			struct sockaddr_dl *sdl;
2683186119Sqingli
2684186119Sqingli			/* skip deleted or invalid entries */
2685186119Sqingli			if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
2686186119Sqingli				continue;
2687186980Sbz			/* Skip if jailed and not a valid IP of the prison. */
2688188144Sjamie			if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
2689186980Sbz				continue;
2690186119Sqingli			/*
2691186119Sqingli			 * produce a msg made of:
2692186119Sqingli			 *  struct rt_msghdr;
2693186119Sqingli			 *  struct sockaddr_in6 (IPv6)
2694186119Sqingli			 *  struct sockaddr_dl;
2695186119Sqingli			 */
2696186119Sqingli			bzero(&ndpc, sizeof(ndpc));
2697186119Sqingli			ndpc.rtm.rtm_msglen = sizeof(ndpc);
2698187094Sqingli			ndpc.rtm.rtm_version = RTM_VERSION;
2699187094Sqingli			ndpc.rtm.rtm_type = RTM_GET;
2700187094Sqingli			ndpc.rtm.rtm_flags = RTF_UP;
2701187094Sqingli			ndpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
2702186119Sqingli			ndpc.sin6.sin6_family = AF_INET6;
2703186119Sqingli			ndpc.sin6.sin6_len = sizeof(ndpc.sin6);
2704186119Sqingli			bcopy(L3_ADDR(lle), &ndpc.sin6, L3_ADDR_LEN(lle));
2705186119Sqingli
2706186119Sqingli			/* publish */
2707186119Sqingli			if (lle->la_flags & LLE_PUB)
2708186119Sqingli				ndpc.rtm.rtm_flags |= RTF_ANNOUNCE;
2709186119Sqingli
2710186119Sqingli			sdl = &ndpc.sdl;
2711186119Sqingli			sdl->sdl_family = AF_LINK;
2712186119Sqingli			sdl->sdl_len = sizeof(*sdl);
2713186119Sqingli			sdl->sdl_alen = ifp->if_addrlen;
2714186119Sqingli			sdl->sdl_index = ifp->if_index;
2715186119Sqingli			sdl->sdl_type = ifp->if_type;
2716186119Sqingli			bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
2717186119Sqingli			ndpc.rtm.rtm_rmx.rmx_expire =
2718186119Sqingli			    lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
2719186500Sqingli			ndpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
2720186119Sqingli			if (lle->la_flags & LLE_STATIC)
2721186119Sqingli				ndpc.rtm.rtm_flags |= RTF_STATIC;
2722186119Sqingli			ndpc.rtm.rtm_index = ifp->if_index;
2723186119Sqingli			error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc));
2724186119Sqingli			if (error)
2725186119Sqingli				break;
2726186119Sqingli		}
2727186119Sqingli	}
2728186119Sqingli	return error;
2729186119Sqingli}
2730186119Sqingli
2731121161Sumevoid *
2732171259Sdelphijin6_domifattach(struct ifnet *ifp)
2733121161Sume{
2734121161Sume	struct in6_ifextra *ext;
2735121161Sume
2736121161Sume	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
2737121161Sume	bzero(ext, sizeof(*ext));
2738121161Sume
2739121161Sume	ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
2740121161Sume	    M_IFADDR, M_WAITOK);
2741121161Sume	bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
2742121161Sume
2743121161Sume	ext->icmp6_ifstat =
2744121161Sume	    (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
2745121161Sume	    M_IFADDR, M_WAITOK);
2746121161Sume	bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
2747121161Sume
2748121161Sume	ext->nd_ifinfo = nd6_ifattach(ifp);
2749121161Sume	ext->scope6_id = scope6_ifattach(ifp);
2750186119Sqingli	ext->lltable = lltable_init(ifp, AF_INET6);
2751186119Sqingli	if (ext->lltable != NULL) {
2752192476Sqingli		ext->lltable->llt_prefix_free = in6_lltable_prefix_free;
2753186119Sqingli		ext->lltable->llt_lookup = in6_lltable_lookup;
2754186119Sqingli		ext->lltable->llt_dump = in6_lltable_dump;
2755186119Sqingli	}
2756191672Sbms
2757191672Sbms	ext->mld_ifinfo = mld_domifattach(ifp);
2758191672Sbms
2759121161Sume	return ext;
2760121161Sume}
2761121161Sume
2762121161Sumevoid
2763171259Sdelphijin6_domifdetach(struct ifnet *ifp, void *aux)
2764121161Sume{
2765121161Sume	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
2766121161Sume
2767191672Sbms	mld_domifdetach(ifp);
2768121161Sume	scope6_ifdetach(ext->scope6_id);
2769121161Sume	nd6_ifdetach(ext->nd_ifinfo);
2770186119Sqingli	lltable_free(ext->lltable);
2771121161Sume	free(ext->in6_ifstat, M_IFADDR);
2772121161Sume	free(ext->icmp6_ifstat, M_IFADDR);
2773121161Sume	free(ext, M_IFADDR);
2774121161Sume}
2775121161Sume
277653541Sshin/*
277795023Ssuz * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
277853541Sshin * v4 mapped addr or v4 compat addr
277953541Sshin */
278053541Sshinvoid
278153541Sshinin6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
278253541Sshin{
2783171259Sdelphij
278453541Sshin	bzero(sin, sizeof(*sin));
278553541Sshin	sin->sin_len = sizeof(struct sockaddr_in);
278653541Sshin	sin->sin_family = AF_INET;
278753541Sshin	sin->sin_port = sin6->sin6_port;
2788120891Sume	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
278953541Sshin}
279053541Sshin
279153541Sshin/* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
279253541Sshinvoid
279353541Sshinin6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
279453541Sshin{
279553541Sshin	bzero(sin6, sizeof(*sin6));
279653541Sshin	sin6->sin6_len = sizeof(struct sockaddr_in6);
279753541Sshin	sin6->sin6_family = AF_INET6;
279853541Sshin	sin6->sin6_port = sin->sin_port;
279953541Sshin	sin6->sin6_addr.s6_addr32[0] = 0;
280053541Sshin	sin6->sin6_addr.s6_addr32[1] = 0;
280153541Sshin	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
280253541Sshin	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
280353541Sshin}
280453541Sshin
280553541Sshin/* Convert sockaddr_in6 into sockaddr_in. */
280653541Sshinvoid
280753541Sshinin6_sin6_2_sin_in_sock(struct sockaddr *nam)
280853541Sshin{
280953541Sshin	struct sockaddr_in *sin_p;
281053541Sshin	struct sockaddr_in6 sin6;
281153541Sshin
281253541Sshin	/*
281353541Sshin	 * Save original sockaddr_in6 addr and convert it
281453541Sshin	 * to sockaddr_in.
281553541Sshin	 */
281653541Sshin	sin6 = *(struct sockaddr_in6 *)nam;
281753541Sshin	sin_p = (struct sockaddr_in *)nam;
281853541Sshin	in6_sin6_2_sin(sin_p, &sin6);
281953541Sshin}
282053541Sshin
282153541Sshin/* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
282253541Sshinvoid
282353541Sshinin6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
282453541Sshin{
282553541Sshin	struct sockaddr_in *sin_p;
282653541Sshin	struct sockaddr_in6 *sin6_p;
282753541Sshin
2828240310Sglebius	sin6_p = malloc(sizeof *sin6_p, M_SONAME, M_WAITOK);
282953541Sshin	sin_p = (struct sockaddr_in *)*nam;
283053541Sshin	in6_sin_2_v4mapsin6(sin_p, sin6_p);
2831184205Sdes	free(*nam, M_SONAME);
283253541Sshin	*nam = (struct sockaddr *)sin6_p;
283353541Sshin}
2834