in6.c revision 148887
162587Sitojun/*	$FreeBSD: head/sys/netinet6/in6.c 148887 2005-08-09 10:20:02Z rwatson $	*/
295023Ssuz/*	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $	*/
362587Sitojun
4139826Simp/*-
553541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
653541Sshin * All rights reserved.
753541Sshin *
853541Sshin * Redistribution and use in source and binary forms, with or without
953541Sshin * modification, are permitted provided that the following conditions
1053541Sshin * are met:
1153541Sshin * 1. Redistributions of source code must retain the above copyright
1253541Sshin *    notice, this list of conditions and the following disclaimer.
1353541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1453541Sshin *    notice, this list of conditions and the following disclaimer in the
1553541Sshin *    documentation and/or other materials provided with the distribution.
1653541Sshin * 3. Neither the name of the project nor the names of its contributors
1753541Sshin *    may be used to endorse or promote products derived from this software
1853541Sshin *    without specific prior written permission.
1953541Sshin *
2053541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2153541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2253541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2353541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2453541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2553541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2653541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2753541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2853541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2953541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3053541Sshin * SUCH DAMAGE.
3153541Sshin */
3253541Sshin
33139826Simp/*-
3453541Sshin * Copyright (c) 1982, 1986, 1991, 1993
3553541Sshin *	The Regents of the University of California.  All rights reserved.
3653541Sshin *
3753541Sshin * Redistribution and use in source and binary forms, with or without
3853541Sshin * modification, are permitted provided that the following conditions
3953541Sshin * are met:
4053541Sshin * 1. Redistributions of source code must retain the above copyright
4153541Sshin *    notice, this list of conditions and the following disclaimer.
4253541Sshin * 2. Redistributions in binary form must reproduce the above copyright
4353541Sshin *    notice, this list of conditions and the following disclaimer in the
4453541Sshin *    documentation and/or other materials provided with the distribution.
4553541Sshin * 4. Neither the name of the University nor the names of its contributors
4653541Sshin *    may be used to endorse or promote products derived from this software
4753541Sshin *    without specific prior written permission.
4853541Sshin *
4953541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5053541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5153541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5253541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5353541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5453541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5553541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5653541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5753541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5853541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5953541Sshin * SUCH DAMAGE.
6053541Sshin *
6153541Sshin *	@(#)in.c	8.2 (Berkeley) 11/15/93
6253541Sshin */
6353541Sshin
6462587Sitojun#include "opt_inet.h"
6562587Sitojun#include "opt_inet6.h"
6662587Sitojun
6753541Sshin#include <sys/param.h>
6853541Sshin#include <sys/errno.h>
6953541Sshin#include <sys/malloc.h>
7053541Sshin#include <sys/socket.h>
7153541Sshin#include <sys/socketvar.h>
7253541Sshin#include <sys/sockio.h>
7353541Sshin#include <sys/systm.h>
7453541Sshin#include <sys/proc.h>
7553541Sshin#include <sys/time.h>
7653541Sshin#include <sys/kernel.h>
7753541Sshin#include <sys/syslog.h>
7853541Sshin
7953541Sshin#include <net/if.h>
8053541Sshin#include <net/if_types.h>
8153541Sshin#include <net/route.h>
8253541Sshin#include <net/if_dl.h>
8353541Sshin
8453541Sshin#include <netinet/in.h>
8553541Sshin#include <netinet/in_var.h>
8653541Sshin#include <netinet/if_ether.h>
8778064Sume#include <netinet/in_systm.h>
8878064Sume#include <netinet/ip.h>
8978064Sume#include <netinet/in_pcb.h>
9053541Sshin
9162587Sitojun#include <netinet/ip6.h>
9253541Sshin#include <netinet6/ip6_var.h>
9395023Ssuz#include <netinet6/nd6.h>
9453541Sshin#include <netinet6/mld6_var.h>
9562587Sitojun#include <netinet6/ip6_mroute.h>
9653541Sshin#include <netinet6/in6_ifattach.h>
9762587Sitojun#include <netinet6/scope6_var.h>
9878064Sume#include <netinet6/in6_pcb.h>
9962587Sitojun
10053541Sshin#include <net/net_osdep.h>
10153541Sshin
10253541SshinMALLOC_DEFINE(M_IPMADDR, "in6_multi", "internet multicast address");
10353541Sshin
10453541Sshin/*
10553541Sshin * Definitions of some costant IP6 addresses.
10653541Sshin */
10762587Sitojunconst struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
10862587Sitojunconst struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
10962587Sitojunconst struct in6_addr in6addr_nodelocal_allnodes =
11053541Sshin	IN6ADDR_NODELOCAL_ALLNODES_INIT;
11162587Sitojunconst struct in6_addr in6addr_linklocal_allnodes =
11253541Sshin	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
11362587Sitojunconst struct in6_addr in6addr_linklocal_allrouters =
11453541Sshin	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
11553541Sshin
11662587Sitojunconst struct in6_addr in6mask0 = IN6MASK0;
11762587Sitojunconst struct in6_addr in6mask32 = IN6MASK32;
11862587Sitojunconst struct in6_addr in6mask64 = IN6MASK64;
11962587Sitojunconst struct in6_addr in6mask96 = IN6MASK96;
12062587Sitojunconst struct in6_addr in6mask128 = IN6MASK128;
12153541Sshin
122126552Sumeconst struct sockaddr_in6 sa6_any =
123126552Sume	{ sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 };
12478064Sume
12562587Sitojunstatic int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
12683366Sjulian	struct ifnet *, struct thread *));
12778064Sumestatic int in6_ifinit __P((struct ifnet *, struct in6_ifaddr *,
128120891Sume	struct sockaddr_in6 *, int));
12978064Sumestatic void in6_unlink_ifa __P((struct in6_ifaddr *, struct ifnet *));
13053541Sshin
13162587Sitojunstruct in6_multihead in6_multihead;	/* XXX BSS initialization */
13283934Sbrooksint	(*faithprefix_p)(struct in6_addr *);
13383934Sbrooks
13453541Sshin/*
13553541Sshin * Subroutine for in6_ifaddloop() and in6_ifremloop().
13653541Sshin * This routine does actual work.
13753541Sshin */
13853541Sshinstatic void
13953541Sshinin6_ifloop_request(int cmd, struct ifaddr *ifa)
14053541Sshin{
14153541Sshin	struct sockaddr_in6 all1_sa;
14278064Sume	struct rtentry *nrt = NULL;
14378064Sume	int e;
144120891Sume
14553541Sshin	bzero(&all1_sa, sizeof(all1_sa));
14678064Sume	all1_sa.sin6_family = AF_INET6;
14778064Sume	all1_sa.sin6_len = sizeof(struct sockaddr_in6);
14853541Sshin	all1_sa.sin6_addr = in6mask128;
14978064Sume
15062587Sitojun	/*
15178064Sume	 * We specify the address itself as the gateway, and set the
15278064Sume	 * RTF_LLINFO flag, so that the corresponding host route would have
15378064Sume	 * the flag, and thus applications that assume traditional behavior
15478064Sume	 * would be happy.  Note that we assume the caller of the function
15578064Sume	 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
15678064Sume	 * which changes the outgoing interface to the loopback interface.
15762587Sitojun	 */
15878064Sume	e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
159120891Sume	    (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
16078064Sume	if (e != 0) {
161120891Sume		/* XXX need more descriptive message */
16278064Sume		log(LOG_ERR, "in6_ifloop_request: "
16378064Sume		    "%s operation failed for %s (errno=%d)\n",
16478064Sume		    cmd == RTM_ADD ? "ADD" : "DELETE",
16578064Sume		    ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
16678064Sume		    e);
16778064Sume	}
16853541Sshin
169120727Ssam	if (nrt) {
170120727Ssam		RT_LOCK(nrt);
171120727Ssam		/*
172120727Ssam		 * Make sure rt_ifa be equal to IFA, the second argument of
173120727Ssam		 * the function.  We need this because when we refer to
174120727Ssam		 * rt_ifa->ia6_flags in ip6_input, we assume that the rt_ifa
175120727Ssam		 * points to the address instead of the loopback address.
176120727Ssam		 */
177120727Ssam		if (cmd == RTM_ADD && ifa != nrt->rt_ifa) {
178120727Ssam			IFAFREE(nrt->rt_ifa);
179120727Ssam			IFAREF(ifa);
180120727Ssam			nrt->rt_ifa = ifa;
181120727Ssam		}
18278064Sume
183120727Ssam		/*
184120727Ssam		 * Report the addition/removal of the address to the routing
185120727Ssam		 * socket.
186120727Ssam		 *
187120727Ssam		 * XXX: since we called rtinit for a p2p interface with a
188120727Ssam		 *      destination, we end up reporting twice in such a case.
189120727Ssam		 *      Should we rather omit the second report?
190120727Ssam		 */
19178064Sume		rt_newaddrmsg(cmd, ifa, e, nrt);
19278064Sume		if (cmd == RTM_DELETE) {
193120727Ssam			rtfree(nrt);
19478064Sume		} else {
19578064Sume			/* the cmd must be RTM_ADD here */
196122334Ssam			RT_REMREF(nrt);
197120727Ssam			RT_UNLOCK(nrt);
19878064Sume		}
19978064Sume	}
20053541Sshin}
20153541Sshin
20253541Sshin/*
20378064Sume * Add ownaddr as loopback rtentry.  We previously add the route only if
20478064Sume * necessary (ex. on a p2p link).  However, since we now manage addresses
20578064Sume * separately from prefixes, we should always add the route.  We can't
20678064Sume * rely on the cloning mechanism from the corresponding interface route
20778064Sume * any more.
20853541Sshin */
209142215Sglebiusvoid
21053541Sshinin6_ifaddloop(struct ifaddr *ifa)
21153541Sshin{
21278064Sume	struct rtentry *rt;
213121716Ssam	int need_loop;
21453541Sshin
21578064Sume	/* If there is no loopback entry, allocate one. */
21678064Sume	rt = rtalloc1(ifa->ifa_addr, 0, 0);
217121716Ssam	need_loop = (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
218121716Ssam	    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0);
21978064Sume	if (rt)
220120727Ssam		rtfree(rt);
221121716Ssam	if (need_loop)
222121716Ssam		in6_ifloop_request(RTM_ADD, ifa);
22353541Sshin}
22453541Sshin
22553541Sshin/*
22653541Sshin * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
22753541Sshin * if it exists.
22853541Sshin */
229142215Sglebiusvoid
23053541Sshinin6_ifremloop(struct ifaddr *ifa)
23153541Sshin{
23262587Sitojun	struct in6_ifaddr *ia;
23378064Sume	struct rtentry *rt;
23462587Sitojun	int ia_count = 0;
23553541Sshin
23662587Sitojun	/*
23778064Sume	 * Some of BSD variants do not remove cloned routes
23862587Sitojun	 * from an interface direct route, when removing the direct route
23978064Sume	 * (see comments in net/net_osdep.h).  Even for variants that do remove
24078064Sume	 * cloned routes, they could fail to remove the cloned routes when
24178064Sume	 * we handle multple addresses that share a common prefix.
24278064Sume	 * So, we should remove the route corresponding to the deleted address
24362587Sitojun	 * regardless of the result of in6_is_ifloop_auto().
24462587Sitojun	 */
24578064Sume
24678064Sume	/*
24795023Ssuz	 * Delete the entry only if exact one ifa exists.  More than one ifa
24878064Sume	 * can exist if we assign a same single address to multiple
24978064Sume	 * (probably p2p) interfaces.
25078064Sume	 * XXX: we should avoid such a configuration in IPv6...
25178064Sume	 */
25278064Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
25378064Sume		if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
25478064Sume			ia_count++;
25578064Sume			if (ia_count > 1)
25678064Sume				break;
25753541Sshin		}
25878064Sume	}
25978064Sume
26078064Sume	if (ia_count == 1) {
26178064Sume		/*
26278064Sume		 * Before deleting, check if a corresponding loopbacked host
26395023Ssuz		 * route surely exists.  With this check, we can avoid to
26478064Sume		 * delete an interface direct route whose destination is same
265120891Sume		 * as the address being removed.  This can happen when removing
26678064Sume		 * a subnet-router anycast address on an interface attahced
26778064Sume		 * to a shared medium.
26878064Sume		 */
26978064Sume		rt = rtalloc1(ifa->ifa_addr, 0, 0);
270120727Ssam		if (rt != NULL) {
271120727Ssam			if ((rt->rt_flags & RTF_HOST) != 0 &&
272120727Ssam			    (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
273120727Ssam				rtfree(rt);
274120727Ssam				in6_ifloop_request(RTM_DELETE, ifa);
275120727Ssam			} else
276120727Ssam				RT_UNLOCK(rt);
27778064Sume		}
27853541Sshin	}
27953541Sshin}
28053541Sshin
28153541Sshinint
28278064Sumein6_mask2len(mask, lim0)
28353541Sshin	struct in6_addr *mask;
28478064Sume	u_char *lim0;
28553541Sshin{
28678064Sume	int x = 0, y;
28778064Sume	u_char *lim = lim0, *p;
28853541Sshin
289120891Sume	/* ignore the scope_id part */
290120891Sume	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
29178064Sume		lim = (u_char *)mask + sizeof(*mask);
29278064Sume	for (p = (u_char *)mask; p < lim; x++, p++) {
29378064Sume		if (*p != 0xff)
29453541Sshin			break;
29553541Sshin	}
29653541Sshin	y = 0;
29778064Sume	if (p < lim) {
29853541Sshin		for (y = 0; y < 8; y++) {
29978064Sume			if ((*p & (0x80 >> y)) == 0)
30053541Sshin				break;
30153541Sshin		}
30253541Sshin	}
30378064Sume
30478064Sume	/*
30578064Sume	 * when the limit pointer is given, do a stricter check on the
30678064Sume	 * remaining bits.
30778064Sume	 */
30878064Sume	if (p < lim) {
30978064Sume		if (y != 0 && (*p & (0x00ff >> y)) != 0)
310120856Sume			return (-1);
31178064Sume		for (p = p + 1; p < lim; p++)
31278064Sume			if (*p != 0)
313120856Sume				return (-1);
31478064Sume	}
315120891Sume
31653541Sshin	return x * 8 + y;
31753541Sshin}
31853541Sshin
31953541Sshin#define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
32062587Sitojun#define ia62ifa(ia6)	(&((ia6)->ia_ifa))
32153541Sshin
32253541Sshinint
32383366Sjulianin6_control(so, cmd, data, ifp, td)
32453541Sshin	struct	socket *so;
32553541Sshin	u_long cmd;
32653541Sshin	caddr_t	data;
32753541Sshin	struct ifnet *ifp;
32883366Sjulian	struct thread *td;
32953541Sshin{
33053541Sshin	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
33178064Sume	struct	in6_ifaddr *ia = NULL;
33253541Sshin	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
333148385Sume	int error, privileged;
33453541Sshin
33553541Sshin	privileged = 0;
33693593Sjhb	if (td == NULL || !suser(td))
33753541Sshin		privileged++;
33853541Sshin
33962587Sitojun	switch (cmd) {
34062587Sitojun	case SIOCGETSGCNT_IN6:
34162587Sitojun	case SIOCGETMIFCNT_IN6:
34262587Sitojun		return (mrt6_ioctl(cmd, data));
34362587Sitojun	}
34453541Sshin
345121742Sume	switch(cmd) {
346121742Sume	case SIOCAADDRCTL_POLICY:
347121742Sume	case SIOCDADDRCTL_POLICY:
348121742Sume		if (!privileged)
349121742Sume			return (EPERM);
350121742Sume		return (in6_src_ioctl(cmd, data));
351121742Sume	}
352121742Sume
35362587Sitojun	if (ifp == NULL)
354120856Sume		return (EOPNOTSUPP);
35553541Sshin
35653541Sshin	switch (cmd) {
35753541Sshin	case SIOCSNDFLUSH_IN6:
35853541Sshin	case SIOCSPFXFLUSH_IN6:
35953541Sshin	case SIOCSRTRFLUSH_IN6:
36062587Sitojun	case SIOCSDEFIFACE_IN6:
36162587Sitojun	case SIOCSIFINFO_FLAGS:
36253541Sshin		if (!privileged)
363120856Sume			return (EPERM);
364120891Sume		/* FALLTHROUGH */
36578064Sume	case OSIOCGIFINFO_IN6:
36653541Sshin	case SIOCGIFINFO_IN6:
36753541Sshin	case SIOCGDRLST_IN6:
36853541Sshin	case SIOCGPRLST_IN6:
36953541Sshin	case SIOCGNBRINFO_IN6:
37062587Sitojun	case SIOCGDEFIFACE_IN6:
371120856Sume		return (nd6_ioctl(cmd, data, ifp));
37253541Sshin	}
37353541Sshin
37453541Sshin	switch (cmd) {
37553541Sshin	case SIOCSIFPREFIX_IN6:
37653541Sshin	case SIOCDIFPREFIX_IN6:
37753541Sshin	case SIOCAIFPREFIX_IN6:
37853541Sshin	case SIOCCIFPREFIX_IN6:
37953541Sshin	case SIOCSGIFPREFIX_IN6:
38053541Sshin	case SIOCGIFPREFIX_IN6:
38178064Sume		log(LOG_NOTICE,
38278064Sume		    "prefix ioctls are now invalidated. "
38378064Sume		    "please use ifconfig.\n");
384120856Sume		return (EOPNOTSUPP);
38553541Sshin	}
38653541Sshin
38795023Ssuz	switch (cmd) {
38862587Sitojun	case SIOCSSCOPE6:
38962587Sitojun		if (!privileged)
390120856Sume			return (EPERM);
391121161Sume		return (scope6_set(ifp,
392121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
39362587Sitojun	case SIOCGSCOPE6:
394121161Sume		return (scope6_get(ifp,
395121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
39662587Sitojun	case SIOCGSCOPE6DEF:
397121161Sume		return (scope6_get_default((struct scope6_id *)
398121161Sume		    ifr->ifr_ifru.ifru_scope_id));
39962587Sitojun	}
40062587Sitojun
40153541Sshin	switch (cmd) {
40253541Sshin	case SIOCALIFADDR:
40353541Sshin	case SIOCDLIFADDR:
40453541Sshin		if (!privileged)
405120856Sume			return (EPERM);
406120891Sume		/* FALLTHROUGH */
40753541Sshin	case SIOCGLIFADDR:
40883366Sjulian		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
40953541Sshin	}
41053541Sshin
41153541Sshin	/*
41253541Sshin	 * Find address for this interface, if it exists.
41353541Sshin	 */
41462587Sitojun	if (ifra->ifra_addr.sin6_family == AF_INET6) { /* XXX */
415148385Sume		int error = 0;
41653541Sshin
417148385Sume		if (ifra->ifra_addr.sin6_scope_id != 0)
418148385Sume			error = sa6_embedscope(&ifra->ifra_addr, 0);
419148385Sume		else
420148385Sume			error = in6_setscope(&ifra->ifra_addr.sin6_addr,
421148385Sume			    ifp, NULL);
422148385Sume		if (error != 0)
423148385Sume			return (error);
42462587Sitojun		ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
42553541Sshin	}
42653541Sshin
42753541Sshin	switch (cmd) {
42878064Sume	case SIOCSIFADDR_IN6:
42978064Sume	case SIOCSIFDSTADDR_IN6:
43078064Sume	case SIOCSIFNETMASK_IN6:
43178064Sume		/*
43278064Sume		 * Since IPv6 allows a node to assign multiple addresses
43378064Sume		 * on a single interface, SIOCSIFxxx ioctls are not suitable
43478064Sume		 * and should be unused.
43578064Sume		 */
43678064Sume		/* we decided to obsolete this command (20000704) */
437120856Sume		return (EINVAL);
43853541Sshin
43953541Sshin	case SIOCDIFADDR_IN6:
44062587Sitojun		/*
44178064Sume		 * for IPv4, we look for existing in_ifaddr here to allow
44262587Sitojun		 * "ifconfig if0 delete" to remove first IPv4 address on the
44362587Sitojun		 * interface.  For IPv6, as the spec allow multiple interface
44462587Sitojun		 * address from the day one, we consider "remove the first one"
44578064Sume		 * semantics to be not preferable.
44662587Sitojun		 */
44762587Sitojun		if (ia == NULL)
448120856Sume			return (EADDRNOTAVAIL);
44953541Sshin		/* FALLTHROUGH */
45053541Sshin	case SIOCAIFADDR_IN6:
45162587Sitojun		/*
45278064Sume		 * We always require users to specify a valid IPv6 address for
45378064Sume		 * the corresponding operation.
45462587Sitojun		 */
45578064Sume		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
45678064Sume		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
457120856Sume			return (EAFNOSUPPORT);
45853541Sshin		if (!privileged)
459120856Sume			return (EPERM);
46053541Sshin
46153541Sshin		break;
46253541Sshin
46353541Sshin	case SIOCGIFADDR_IN6:
46453541Sshin		/* This interface is basically deprecated. use SIOCGIFCONF. */
465120891Sume		/* FALLTHROUGH */
46653541Sshin	case SIOCGIFAFLAG_IN6:
46753541Sshin	case SIOCGIFNETMASK_IN6:
46853541Sshin	case SIOCGIFDSTADDR_IN6:
46953541Sshin	case SIOCGIFALIFETIME_IN6:
47053541Sshin		/* must think again about its semantics */
47162587Sitojun		if (ia == NULL)
472120856Sume			return (EADDRNOTAVAIL);
47353541Sshin		break;
47453541Sshin	case SIOCSIFALIFETIME_IN6:
47553541Sshin	    {
47653541Sshin		struct in6_addrlifetime *lt;
47753541Sshin
47853541Sshin		if (!privileged)
479120856Sume			return (EPERM);
48062587Sitojun		if (ia == NULL)
481120856Sume			return (EADDRNOTAVAIL);
48253541Sshin		/* sanity for overflow - beware unsigned */
48353541Sshin		lt = &ifr->ifr_ifru.ifru_lifetime;
484126552Sume		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
485126552Sume		    lt->ia6t_vltime + time_second < time_second) {
48653541Sshin			return EINVAL;
48753541Sshin		}
488126552Sume		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
489126552Sume		    lt->ia6t_pltime + time_second < time_second) {
49053541Sshin			return EINVAL;
49153541Sshin		}
49253541Sshin		break;
49353541Sshin	    }
49453541Sshin	}
49553541Sshin
49653541Sshin	switch (cmd) {
49753541Sshin
49853541Sshin	case SIOCGIFADDR_IN6:
49953541Sshin		ifr->ifr_addr = ia->ia_addr;
500148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
501148385Sume			return (error);
50253541Sshin		break;
50353541Sshin
50453541Sshin	case SIOCGIFDSTADDR_IN6:
50553541Sshin		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
506120856Sume			return (EINVAL);
50762587Sitojun		/*
50862587Sitojun		 * XXX: should we check if ifa_dstaddr is NULL and return
50962587Sitojun		 * an error?
51062587Sitojun		 */
51153541Sshin		ifr->ifr_dstaddr = ia->ia_dstaddr;
512148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
513148385Sume			return (error);
51453541Sshin		break;
51553541Sshin
51653541Sshin	case SIOCGIFNETMASK_IN6:
51753541Sshin		ifr->ifr_addr = ia->ia_prefixmask;
51853541Sshin		break;
51953541Sshin
52053541Sshin	case SIOCGIFAFLAG_IN6:
52153541Sshin		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
52253541Sshin		break;
52353541Sshin
52453541Sshin	case SIOCGIFSTAT_IN6:
525121167Sume		if (ifp == NULL)
526121167Sume			return EINVAL;
527121161Sume		bzero(&ifr->ifr_ifru.ifru_stat,
528121161Sume		    sizeof(ifr->ifr_ifru.ifru_stat));
529121161Sume		ifr->ifr_ifru.ifru_stat =
530121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
53153541Sshin		break;
53253541Sshin
53353541Sshin	case SIOCGIFSTAT_ICMP6:
53453541Sshin		if (ifp == NULL)
53553541Sshin			return EINVAL;
536121161Sume		bzero(&ifr->ifr_ifru.ifru_stat,
537121161Sume		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
538121161Sume		ifr->ifr_ifru.ifru_icmp6stat =
539121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
54053541Sshin		break;
54153541Sshin
54253541Sshin	case SIOCGIFALIFETIME_IN6:
54353541Sshin		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
54453541Sshin		break;
54553541Sshin
54653541Sshin	case SIOCSIFALIFETIME_IN6:
54753541Sshin		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
54853541Sshin		/* for sanity */
54953541Sshin		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
55053541Sshin			ia->ia6_lifetime.ia6t_expire =
55153541Sshin				time_second + ia->ia6_lifetime.ia6t_vltime;
55253541Sshin		} else
55353541Sshin			ia->ia6_lifetime.ia6t_expire = 0;
55453541Sshin		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
55553541Sshin			ia->ia6_lifetime.ia6t_preferred =
55653541Sshin				time_second + ia->ia6_lifetime.ia6t_pltime;
55753541Sshin		} else
55853541Sshin			ia->ia6_lifetime.ia6t_preferred = 0;
55953541Sshin		break;
56053541Sshin
56178064Sume	case SIOCAIFADDR_IN6:
56278064Sume	{
56378064Sume		int i, error = 0;
56478064Sume		struct nd_prefix pr0, *pr;
56578064Sume
56662587Sitojun		/*
56778064Sume		 * first, make or update the interface address structure,
56878064Sume		 * and link it to the list.
56962587Sitojun		 */
57078064Sume		if ((error = in6_update_ifa(ifp, ifra, ia)) != 0)
571120856Sume			return (error);
57253541Sshin
57378064Sume		/*
57478064Sume		 * then, make the prefix on-link on the interface.
57578064Sume		 * XXX: we'd rather create the prefix before the address, but
57678064Sume		 * we need at least one address to install the corresponding
57778064Sume		 * interface route, so we configure the address first.
57878064Sume		 */
57978064Sume
58078064Sume		/*
58178064Sume		 * convert mask to prefix length (prefixmask has already
58278064Sume		 * been validated in in6_update_ifa().
58378064Sume		 */
58478064Sume		bzero(&pr0, sizeof(pr0));
58578064Sume		pr0.ndpr_ifp = ifp;
58678064Sume		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
587120891Sume		    NULL);
588120891Sume		if (pr0.ndpr_plen == 128) {
58978064Sume			break;	/* we don't need to install a host route. */
590120891Sume		}
59178064Sume		pr0.ndpr_prefix = ifra->ifra_addr;
59278064Sume		pr0.ndpr_mask = ifra->ifra_prefixmask.sin6_addr;
59378064Sume		/* apply the mask for safety. */
59478064Sume		for (i = 0; i < 4; i++) {
59578064Sume			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
596120891Sume			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
59778064Sume		}
59878064Sume		/*
59995023Ssuz		 * XXX: since we don't have an API to set prefix (not address)
60095023Ssuz		 * lifetimes, we just use the same lifetimes as addresses.
60195023Ssuz		 * The (temporarily) installed lifetimes can be overridden by
60295023Ssuz		 * later advertised RAs (when accept_rtadv is non 0), which is
60395023Ssuz		 * an intended behavior.
60478064Sume		 */
60578064Sume		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
60678064Sume		pr0.ndpr_raf_auto =
607120891Sume		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
60878064Sume		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
60978064Sume		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
61078064Sume
611120891Sume		/* add the prefix if not yet. */
61278064Sume		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
61378064Sume			/*
61478064Sume			 * nd6_prelist_add will install the corresponding
61578064Sume			 * interface route.
61678064Sume			 */
61778064Sume			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
618120856Sume				return (error);
61978064Sume			if (pr == NULL) {
620120891Sume				log(LOG_ERR, "nd6_prelist_add succeeded but "
62178064Sume				    "no prefix\n");
622120856Sume				return (EINVAL); /* XXX panic here? */
62378064Sume			}
62478064Sume		}
62578064Sume		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
62678064Sume		    == NULL) {
62778064Sume		    	/* XXX: this should not happen! */
62878064Sume			log(LOG_ERR, "in6_control: addition succeeded, but"
62978064Sume			    " no ifaddr\n");
63078064Sume		} else {
63178064Sume			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
63278064Sume			    ia->ia6_ndpr == NULL) { /* new autoconfed addr */
63378064Sume				ia->ia6_ndpr = pr;
63478064Sume				pr->ndpr_refcnt++;
63578064Sume
63678064Sume				/*
63778064Sume				 * If this is the first autoconf address from
63878064Sume				 * the prefix, create a temporary address
63978064Sume				 * as well (when specified).
64078064Sume				 */
64178064Sume				if (ip6_use_tempaddr &&
64278064Sume				    pr->ndpr_refcnt == 1) {
64378064Sume					int e;
64478064Sume					if ((e = in6_tmpifadd(ia, 1)) != 0) {
64578064Sume						log(LOG_NOTICE, "in6_control: "
64678064Sume						    "failed to create a "
64778064Sume						    "temporary address, "
648122059Sume						    "errno=%d\n", e);
64978064Sume					}
65062587Sitojun				}
65162587Sitojun			}
65278064Sume
65378064Sume			/*
65478064Sume			 * this might affect the status of autoconfigured
65578064Sume			 * addresses, that is, this address might make
65678064Sume			 * other addresses detached.
65778064Sume			 */
65878064Sume			pfxlist_onlink_check();
65962587Sitojun		}
660126264Smlaier		if (error == 0 && ia)
661126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
66278064Sume		break;
66378064Sume	}
66462587Sitojun
66578064Sume	case SIOCDIFADDR_IN6:
66678064Sume	{
66778064Sume		int i = 0;
66878064Sume		struct nd_prefix pr0, *pr;
66978064Sume
67078064Sume		/*
67178064Sume		 * If the address being deleted is the only one that owns
67278064Sume		 * the corresponding prefix, expire the prefix as well.
673120891Sume		 * XXX: theoretically, we don't have to worry about such
67478064Sume		 * relationship, since we separate the address management
67578064Sume		 * and the prefix management.  We do this, however, to provide
67678064Sume		 * as much backward compatibility as possible in terms of
67778064Sume		 * the ioctl operation.
67878064Sume		 */
67978064Sume		bzero(&pr0, sizeof(pr0));
68078064Sume		pr0.ndpr_ifp = ifp;
68178064Sume		pr0.ndpr_plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr,
68278064Sume					     NULL);
68378064Sume		if (pr0.ndpr_plen == 128)
68478064Sume			goto purgeaddr;
68578064Sume		pr0.ndpr_prefix = ia->ia_addr;
68678064Sume		pr0.ndpr_mask = ia->ia_prefixmask.sin6_addr;
68778064Sume		for (i = 0; i < 4; i++) {
68878064Sume			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
68978064Sume				ia->ia_prefixmask.sin6_addr.s6_addr32[i];
69078064Sume		}
69178064Sume		/*
69278064Sume		 * The logic of the following condition is a bit complicated.
69378064Sume		 * We expire the prefix when
69478064Sume		 * 1. the address obeys autoconfiguration and it is the
69578064Sume		 *    only owner of the associated prefix, or
69678064Sume		 * 2. the address does not obey autoconf and there is no
69778064Sume		 *    other owner of the prefix.
69878064Sume		 */
69978064Sume		if ((pr = nd6_prefix_lookup(&pr0)) != NULL &&
70078064Sume		    (((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
70178064Sume		      pr->ndpr_refcnt == 1) ||
70278064Sume		     ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0 &&
70378064Sume		      pr->ndpr_refcnt == 0))) {
70478064Sume			pr->ndpr_expire = 1; /* XXX: just for expiration */
70578064Sume		}
70678064Sume
70778064Sume	  purgeaddr:
70878064Sume		in6_purgeaddr(&ia->ia_ifa);
709126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
71053541Sshin		break;
71178064Sume	}
71253541Sshin
71378064Sume	default:
71478064Sume		if (ifp == NULL || ifp->if_ioctl == 0)
715120856Sume			return (EOPNOTSUPP);
716120856Sume		return ((*ifp->if_ioctl)(ifp, cmd, data));
71778064Sume	}
71853541Sshin
719120856Sume	return (0);
72078064Sume}
72153541Sshin
72278064Sume/*
72378064Sume * Update parameters of an IPv6 interface address.
72478064Sume * If necessary, a new entry is created and linked into address chains.
72578064Sume * This function is separated from in6_control().
72678064Sume * XXX: should this be performed under splnet()?
72778064Sume */
72878064Sumeint
72978064Sumein6_update_ifa(ifp, ifra, ia)
73078064Sume	struct ifnet *ifp;
73178064Sume	struct in6_aliasreq *ifra;
73278064Sume	struct in6_ifaddr *ia;
73378064Sume{
73478064Sume	int error = 0, hostIsNew = 0, plen = -1;
73578064Sume	struct in6_ifaddr *oia;
73678064Sume	struct sockaddr_in6 dst6;
73778064Sume	struct in6_addrlifetime *lt;
738148385Sume	struct rtentry *rt;
73978064Sume
74078064Sume	/* Validate parameters */
74178064Sume	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
742120856Sume		return (EINVAL);
74378064Sume
74478064Sume	/*
74578064Sume	 * The destination address for a p2p link must have a family
74678064Sume	 * of AF_UNSPEC or AF_INET6.
74778064Sume	 */
74878064Sume	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
74978064Sume	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
75078064Sume	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
751120856Sume		return (EAFNOSUPPORT);
75278064Sume	/*
75378064Sume	 * validate ifra_prefixmask.  don't check sin6_family, netmask
75478064Sume	 * does not carry fields other than sin6_len.
75578064Sume	 */
75678064Sume	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
757120856Sume		return (EINVAL);
75878064Sume	/*
75978064Sume	 * Because the IPv6 address architecture is classless, we require
76078064Sume	 * users to specify a (non 0) prefix length (mask) for a new address.
76178064Sume	 * We also require the prefix (when specified) mask is valid, and thus
76278064Sume	 * reject a non-consecutive mask.
76378064Sume	 */
76478064Sume	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
765120856Sume		return (EINVAL);
76678064Sume	if (ifra->ifra_prefixmask.sin6_len != 0) {
76778064Sume		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
768120891Sume		    (u_char *)&ifra->ifra_prefixmask +
769120891Sume		    ifra->ifra_prefixmask.sin6_len);
77078064Sume		if (plen <= 0)
771120856Sume			return (EINVAL);
772120891Sume	} else {
77362587Sitojun		/*
77495023Ssuz		 * In this case, ia must not be NULL.  We just use its prefix
77578064Sume		 * length.
77662587Sitojun		 */
77778064Sume		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
77878064Sume	}
77978064Sume	/*
78078064Sume	 * If the destination address on a p2p interface is specified,
78178064Sume	 * and the address is a scoped one, validate/set the scope
78278064Sume	 * zone identifier.
78378064Sume	 */
78478064Sume	dst6 = ifra->ifra_dstaddr;
785120891Sume	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
78678064Sume	    (dst6.sin6_family == AF_INET6)) {
787148385Sume		struct in6_addr in6_tmp;
788126552Sume		u_int32_t zoneid;
78978064Sume
790148385Sume		in6_tmp = dst6.sin6_addr;
791148385Sume		if (in6_setscope(&in6_tmp, ifp, &zoneid))
792148385Sume			return (EINVAL); /* XXX: should be impossible */
793148385Sume
794148385Sume		if (dst6.sin6_scope_id != 0) {
795148385Sume			if (dst6.sin6_scope_id != zoneid)
796148385Sume				return (EINVAL);
797148385Sume		} else		/* user omit to specify the ID. */
798126552Sume			dst6.sin6_scope_id = zoneid;
799148385Sume
800148385Sume		/* convert into the internal form */
801148385Sume		if (sa6_embedscope(&dst6, 0))
802148385Sume			return (EINVAL); /* XXX: should be impossible */
80378064Sume	}
80478064Sume	/*
80578064Sume	 * The destination address can be specified only for a p2p or a
80678064Sume	 * loopback interface.  If specified, the corresponding prefix length
80778064Sume	 * must be 128.
80878064Sume	 */
80978064Sume	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
81078064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
811126552Sume			/* XXX: noisy message */
812122059Sume			nd6log((LOG_INFO, "in6_update_ifa: a destination can "
813122059Sume			    "be specified for a p2p or a loopback IF only\n"));
814120856Sume			return (EINVAL);
81578064Sume		}
81678064Sume		if (plen != 128) {
817122059Sume			nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
818122059Sume			    "be 128 when dstaddr is specified\n"));
819120856Sume			return (EINVAL);
82078064Sume		}
82178064Sume	}
82278064Sume	/* lifetime consistency check */
82378064Sume	lt = &ifra->ifra_lifetime;
82478064Sume	if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
82578064Sume	    && lt->ia6t_vltime + time_second < time_second) {
82678064Sume		return EINVAL;
82778064Sume	}
82878064Sume	if (lt->ia6t_vltime == 0) {
82962587Sitojun		/*
83078064Sume		 * the following log might be noisy, but this is a typical
83178064Sume		 * configuration mistake or a tool's bug.
83262587Sitojun		 */
833122059Sume		nd6log((LOG_INFO,
83478064Sume		    "in6_update_ifa: valid lifetime is 0 for %s\n",
835122059Sume		    ip6_sprintf(&ifra->ifra_addr.sin6_addr)));
83678064Sume	}
83778064Sume	if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
83878064Sume	    && lt->ia6t_pltime + time_second < time_second) {
83978064Sume		return EINVAL;
84078064Sume	}
84162587Sitojun
84278064Sume	/*
84378064Sume	 * If this is a new address, allocate a new ifaddr and link it
84478064Sume	 * into chains.
84578064Sume	 */
84678064Sume	if (ia == NULL) {
84778064Sume		hostIsNew = 1;
84879763Sume		/*
84979763Sume		 * When in6_update_ifa() is called in a process of a received
850120891Sume		 * RA, it is called under an interrupt context.  So, we should
851120891Sume		 * call malloc with M_NOWAIT.
85279763Sume		 */
853120891Sume		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
854120891Sume		    M_NOWAIT);
85578064Sume		if (ia == NULL)
85678064Sume			return (ENOBUFS);
85778064Sume		bzero((caddr_t)ia, sizeof(*ia));
85878064Sume		/* Initialize the address and masks */
859108033Shsu		IFA_LOCK_INIT(&ia->ia_ifa);
86078064Sume		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
86178064Sume		ia->ia_addr.sin6_family = AF_INET6;
86278064Sume		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
86378064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
86478064Sume			/*
86578064Sume			 * XXX: some functions expect that ifa_dstaddr is not
86678064Sume			 * NULL for p2p interfaces.
86778064Sume			 */
868120891Sume			ia->ia_ifa.ifa_dstaddr =
869120891Sume			    (struct sockaddr *)&ia->ia_dstaddr;
87078064Sume		} else {
87178064Sume			ia->ia_ifa.ifa_dstaddr = NULL;
87253541Sshin		}
873108033Shsu		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
87478064Sume
87578064Sume		ia->ia_ifp = ifp;
87678064Sume		if ((oia = in6_ifaddr) != NULL) {
87778064Sume			for ( ; oia->ia_next; oia = oia->ia_next)
87878064Sume				continue;
87978064Sume			oia->ia_next = ia;
88078064Sume		} else
88178064Sume			in6_ifaddr = ia;
88278064Sume
883108033Shsu		ia->ia_ifa.ifa_refcnt = 1;
884108033Shsu		TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
88578064Sume	}
88678064Sume
88778064Sume	/* set prefix mask */
88878064Sume	if (ifra->ifra_prefixmask.sin6_len) {
88978064Sume		/*
89078064Sume		 * We prohibit changing the prefix length of an existing
89178064Sume		 * address, because
89278064Sume		 * + such an operation should be rare in IPv6, and
89378064Sume		 * + the operation would confuse prefix management.
89478064Sume		 */
89578064Sume		if (ia->ia_prefixmask.sin6_len &&
89678064Sume		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
897122059Sume			nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
89878064Sume			    " existing (%s) address should not be changed\n",
899122059Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr)));
90078064Sume			error = EINVAL;
90178064Sume			goto unlink;
90253541Sshin		}
90378064Sume		ia->ia_prefixmask = ifra->ifra_prefixmask;
90478064Sume	}
90578064Sume
90678064Sume	/*
90778064Sume	 * If a new destination address is specified, scrub the old one and
90878064Sume	 * install the new destination.  Note that the interface must be
909120891Sume	 * p2p or loopback (see the check above.)
91078064Sume	 */
91178064Sume	if (dst6.sin6_family == AF_INET6 &&
912120891Sume	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
91378064Sume		int e;
91478064Sume
91578064Sume		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
916120891Sume		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
917122059Sume			nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
91878064Sume			    "a route to the old destination: %s\n",
919122059Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr)));
92078064Sume			/* proceed anyway... */
921120891Sume		} else
92278064Sume			ia->ia_flags &= ~IFA_ROUTE;
92378064Sume		ia->ia_dstaddr = dst6;
92478064Sume	}
92553541Sshin
926148385Sume	/*
927148385Sume	 * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
928148385Sume	 * to see if the address is deprecated or invalidated, but initialize
929148385Sume	 * these members for applications.
930148385Sume	 */
931148385Sume	ia->ia6_lifetime = ifra->ifra_lifetime;
932148385Sume	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
933148385Sume		ia->ia6_lifetime.ia6t_expire =
934148385Sume		    time_second + ia->ia6_lifetime.ia6t_vltime;
935148385Sume	} else
936148385Sume		ia->ia6_lifetime.ia6t_expire = 0;
937148385Sume	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
938148385Sume		ia->ia6_lifetime.ia6t_preferred =
939148385Sume		    time_second + ia->ia6_lifetime.ia6t_pltime;
940148385Sume	} else
941148385Sume		ia->ia6_lifetime.ia6t_preferred = 0;
942148385Sume
94378064Sume	/* reset the interface and routing table appropriately. */
94478064Sume	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
94578064Sume		goto unlink;
94678064Sume
94778064Sume	/*
948148385Sume	 * configure address flags.
949148385Sume	 */
950148385Sume	ia->ia6_flags = ifra->ifra_flags;
951148385Sume	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/* safety */
952148385Sume	ia->ia6_flags &= ~IN6_IFF_NODAD;	/* Mobile IPv6 */
953148385Sume	/*
954148385Sume	 * backward compatibility - if IN6_IFF_DEPRECATED is set from the
955148385Sume	 * userland, make it deprecated.
956148385Sume	 */
957148385Sume	if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
958148385Sume		ia->ia6_lifetime.ia6t_pltime = 0;
959148385Sume		ia->ia6_lifetime.ia6t_preferred = time_second;
960148385Sume	}
961148385Sume
962148385Sume	/*
963148385Sume	 * Perform DAD, if needed.
964148385Sume	 * XXX It may be of use, if we can administratively
965148385Sume	 * disable DAD.
966148385Sume	 */
967148385Sume	if (in6if_do_dad(ifp) && hostIsNew &&
968148385Sume	    (ifra->ifra_flags & IN6_IFF_NODAD) == 0) {
969148385Sume		ia->ia6_flags |= IN6_IFF_TENTATIVE;
970148385Sume		nd6_dad_start((struct ifaddr *)ia, NULL);
971148385Sume	}
972148385Sume
973148385Sume	/*
974148385Sume	 * We are done if we have simply modified an existing address.
975148385Sume	 */
976148385Sume	if (!hostIsNew)
977148385Sume		return (error);
978148385Sume
979148385Sume	/*
98078064Sume	 * Beyond this point, we should call in6_purgeaddr upon an error,
981120891Sume	 * not just go to unlink.
98278064Sume	 */
98378064Sume
98478064Sume	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
98578064Sume		struct sockaddr_in6 mltaddr, mltmask;
98678064Sume		struct in6_multi *in6m;
987148385Sume		struct in6_addr llsol;
98878064Sume
989148385Sume		/* join solicited multicast addr for new host id */
990148385Sume		bzero(&llsol, sizeof(struct in6_addr));
991148385Sume		llsol.s6_addr16[0] = htons(0xff02);
992148385Sume		llsol.s6_addr32[1] = 0;
993148385Sume		llsol.s6_addr32[2] = htonl(1);
994148385Sume		llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
995148385Sume		llsol.s6_addr8[12] = 0xff;
996148385Sume		if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
997148385Sume			/* XXX: should not happen */
998148385Sume			log(LOG_ERR, "in6_update_ifa: "
999148385Sume			    "in6_setscope failed\n");
1000148385Sume			goto cleanup;
100153541Sshin		}
1002148385Sume		(void)in6_addmulti(&llsol, ifp, &error);
1003148385Sume		if (error != 0) {
1004148385Sume			nd6log((LOG_WARNING,
1005148385Sume			    "in6_update_ifa: addmulti failed for "
1006148385Sume			    "%s on %s (errno=%d)\n",
1007148385Sume			    ip6_sprintf(&llsol), if_name(ifp),
1008148385Sume			    error));
1009148385Sume			goto cleanup;
1010148385Sume		}
101153541Sshin
101278064Sume		bzero(&mltmask, sizeof(mltmask));
101378064Sume		mltmask.sin6_len = sizeof(struct sockaddr_in6);
101478064Sume		mltmask.sin6_family = AF_INET6;
101578064Sume		mltmask.sin6_addr = in6mask32;
101653541Sshin
101753541Sshin		/*
101878064Sume		 * join link-local all-nodes address
101971207Sitojun		 */
102078064Sume		bzero(&mltaddr, sizeof(mltaddr));
102178064Sume		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
102278064Sume		mltaddr.sin6_family = AF_INET6;
102378064Sume		mltaddr.sin6_addr = in6addr_linklocal_allnodes;
1024148385Sume		if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) !=
1025148385Sume		    0)
1026148385Sume			goto cleanup; /* XXX: should not fail */
102771207Sitojun
1028148385Sume		/*
1029148385Sume		 * XXX: do we really need this automatic routes?
1030148385Sume		 * We should probably reconsider this stuff.  Most applications
1031148385Sume		 * actually do not need the routes, since they usually specify
1032148385Sume		 * the outgoing interface.
1033148385Sume		 */
1034148385Sume		rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
1035148385Sume		if (rt) {
1036148385Sume			/*
1037148385Sume			 * 32bit came from "mltmask"
1038148385Sume			 */
1039148385Sume			if (memcmp(&mltaddr.sin6_addr,
1040148385Sume			    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1041148385Sume			    32 / 8)) {
1042148385Sume				RTFREE_LOCKED(rt);
1043148385Sume				rt = NULL;
1044148385Sume			}
1045148385Sume		}
1046148385Sume		if (!rt) {
1047148385Sume			/* XXX: we need RTF_CLONING to fake nd6_rtrequest */
1048148385Sume			error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
1049148385Sume			    (struct sockaddr *)&ia->ia_addr,
1050148385Sume			    (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
1051148385Sume			    (struct rtentry **)0);
1052148385Sume			if (error)
1053148385Sume				goto cleanup;
1054148385Sume		} else
1055148385Sume			RTFREE_LOCKED(rt);
1056148385Sume
105778064Sume		IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
105878064Sume		if (in6m == NULL) {
105978064Sume			(void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
106078064Sume			if (error != 0) {
1061122059Sume				nd6log((LOG_WARNING,
106278064Sume				    "in6_update_ifa: addmulti failed for "
106378064Sume				    "%s on %s (errno=%d)\n",
1064122059Sume				    ip6_sprintf(&mltaddr.sin6_addr),
1065122059Sume				    if_name(ifp), error));
1066148385Sume				goto cleanup;
106778064Sume			}
106878064Sume		}
106978064Sume
107071207Sitojun		/*
107178064Sume		 * join node information group address
107253541Sshin		 */
107378064Sume#define hostnamelen	strlen(hostname)
107478064Sume		if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr)
107578064Sume		    == 0) {
107678064Sume			IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
1077148385Sume			if (in6m == NULL) {
107878064Sume				(void)in6_addmulti(&mltaddr.sin6_addr,
107978064Sume				    ifp, &error);
108078064Sume				if (error != 0) {
1081122059Sume					nd6log((LOG_WARNING, "in6_update_ifa: "
108278064Sume					    "addmulti failed for "
108378064Sume					    "%s on %s (errno=%d)\n",
1084122059Sume					    ip6_sprintf(&mltaddr.sin6_addr),
1085122059Sume					    if_name(ifp), error));
1086148385Sume					goto cleanup;
108778064Sume				}
108862587Sitojun			}
108953541Sshin		}
109078064Sume#undef hostnamelen
109153541Sshin
109278064Sume		/*
1093148385Sume		 * join interface-local all-nodes address.
1094148385Sume		 * (ff01::1%ifN, and ff01::%ifN/32)
109578064Sume		 */
1096148385Sume		mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
1097148385Sume		if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL))
1098148385Sume		    != 0)
1099148385Sume			goto cleanup; /* XXX: should not fail */
1100148385Sume		/* XXX: again, do we really need the route? */
1101148385Sume		rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
1102148385Sume		if (rt) {
1103148385Sume			/* 32bit came from "mltmask" */
1104148385Sume			if (memcmp(&mltaddr.sin6_addr,
1105148385Sume			    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1106148385Sume			    32 / 8)) {
1107148385Sume				RTFREE_LOCKED(rt);
1108148385Sume				rt = NULL;
1109148385Sume			}
1110148385Sume		}
1111148385Sume		if (!rt) {
1112148385Sume			error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
1113148385Sume			    (struct sockaddr *)&ia->ia_addr,
1114148385Sume			    (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
1115148385Sume			    (struct rtentry **)0);
1116148385Sume			if (error)
1117148385Sume				goto cleanup;
1118148385Sume		} else
1119148385Sume			RTFREE_LOCKED(rt);
112081115Sume
1121148385Sume		IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
1122148385Sume		if (in6m == NULL) {
1123148385Sume			(void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
1124148385Sume			if (error != 0) {
1125148385Sume				nd6log((LOG_WARNING, "in6_update_ifa: "
1126148385Sume				    "addmulti failed for %s on %s "
1127148385Sume				    "(errno=%d)\n",
1128148385Sume				    ip6_sprintf(&mltaddr.sin6_addr),
1129148385Sume				    if_name(ifp), error));
1130148385Sume				goto cleanup;
113178064Sume			}
113253541Sshin		}
113378064Sume	}
113453541Sshin
1135120856Sume	return (error);
113678064Sume
113778064Sume  unlink:
113878064Sume	/*
113978064Sume	 * XXX: if a change of an existing address failed, keep the entry
114078064Sume	 * anyway.
114178064Sume	 */
114278064Sume	if (hostIsNew)
114378064Sume		in6_unlink_ifa(ia, ifp);
1144120856Sume	return (error);
1145148385Sume
1146148385Sume  cleanup:
1147148385Sume	in6_purgeaddr(&ia->ia_ifa);
1148148385Sume	return error;
114953541Sshin}
115053541Sshin
115162587Sitojunvoid
115278064Sumein6_purgeaddr(ifa)
115362587Sitojun	struct ifaddr *ifa;
115462587Sitojun{
115578064Sume	struct ifnet *ifp = ifa->ifa_ifp;
115678064Sume	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
115762587Sitojun
115878064Sume	/* stop DAD processing */
115978064Sume	nd6_dad_stop(ifa);
116062587Sitojun
116178064Sume	/*
116278064Sume	 * delete route to the destination of the address being purged.
116378064Sume	 * The interface must be p2p or loopback in this case.
116478064Sume	 */
116578064Sume	if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
116678064Sume		int e;
116778064Sume
116878064Sume		if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
116978064Sume		    != 0) {
117078064Sume			log(LOG_ERR, "in6_purgeaddr: failed to remove "
117178064Sume			    "a route to the p2p destination: %s on %s, "
117278064Sume			    "errno=%d\n",
117378064Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp),
117478064Sume			    e);
117578064Sume			/* proceed anyway... */
1176120891Sume		} else
117778064Sume			ia->ia_flags &= ~IFA_ROUTE;
117878064Sume	}
117978064Sume
118078064Sume	/* Remove ownaddr's loopback rtentry, if it exists. */
118178064Sume	in6_ifremloop(&(ia->ia_ifa));
118278064Sume
118362587Sitojun	if (ifp->if_flags & IFF_MULTICAST) {
118462587Sitojun		/*
118562587Sitojun		 * delete solicited multicast addr for deleting host id
118662587Sitojun		 */
118762587Sitojun		struct in6_multi *in6m;
118862587Sitojun		struct in6_addr llsol;
118962587Sitojun		bzero(&llsol, sizeof(struct in6_addr));
119062587Sitojun		llsol.s6_addr16[0] = htons(0xff02);
119162587Sitojun		llsol.s6_addr32[1] = 0;
119262587Sitojun		llsol.s6_addr32[2] = htonl(1);
119362587Sitojun		llsol.s6_addr32[3] =
119462587Sitojun			ia->ia_addr.sin6_addr.s6_addr32[3];
119562587Sitojun		llsol.s6_addr8[12] = 0xff;
1196148385Sume		(void)in6_setscope(&llsol, ifp, NULL); /* XXX proceed anyway */
119762587Sitojun
119862587Sitojun		IN6_LOOKUP_MULTI(llsol, ifp, in6m);
119962587Sitojun		if (in6m)
120062587Sitojun			in6_delmulti(in6m);
120162587Sitojun	}
120262587Sitojun
120378064Sume	in6_unlink_ifa(ia, ifp);
120478064Sume}
120578064Sume
120678064Sumestatic void
120778064Sumein6_unlink_ifa(ia, ifp)
120878064Sume	struct in6_ifaddr *ia;
120978064Sume	struct ifnet *ifp;
121078064Sume{
121178064Sume	struct in6_ifaddr *oia;
121278064Sume	int	s = splnet();
121378064Sume
121462587Sitojun	TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
121562587Sitojun
121662587Sitojun	oia = ia;
121762587Sitojun	if (oia == (ia = in6_ifaddr))
121862587Sitojun		in6_ifaddr = ia->ia_next;
121962587Sitojun	else {
122062587Sitojun		while (ia->ia_next && (ia->ia_next != oia))
122162587Sitojun			ia = ia->ia_next;
122262587Sitojun		if (ia->ia_next)
122362587Sitojun			ia->ia_next = oia->ia_next;
122478064Sume		else {
122578064Sume			/* search failed */
122678064Sume			printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
122778064Sume		}
122862587Sitojun	}
122962587Sitojun
123062587Sitojun	/*
123178064Sume	 * When an autoconfigured address is being removed, release the
123278064Sume	 * reference to the base prefix.  Also, since the release might
123378064Sume	 * affect the status of other (detached) addresses, call
123478064Sume	 * pfxlist_onlink_check().
123562587Sitojun	 */
123678064Sume	if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
123778064Sume		if (oia->ia6_ndpr == NULL) {
1238122059Sume			nd6log((LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "
1239122059Sume			    "%p has no prefix\n", oia));
124078064Sume		} else {
124178064Sume			oia->ia6_ndpr->ndpr_refcnt--;
124278064Sume			oia->ia6_flags &= ~IN6_IFF_AUTOCONF;
124378064Sume			oia->ia6_ndpr = NULL;
124478064Sume		}
124562587Sitojun
124678064Sume		pfxlist_onlink_check();
124762587Sitojun	}
124878064Sume
124978064Sume	/*
125078064Sume	 * release another refcnt for the link from in6_ifaddr.
125178064Sume	 * Note that we should decrement the refcnt at least once for all *BSD.
125278064Sume	 */
125362587Sitojun	IFAFREE(&oia->ia_ifa);
125478064Sume
125578064Sume	splx(s);
125662587Sitojun}
125762587Sitojun
125878064Sumevoid
125978064Sumein6_purgeif(ifp)
126078064Sume	struct ifnet *ifp;
126178064Sume{
126278064Sume	struct ifaddr *ifa, *nifa;
126378064Sume
1264120891Sume	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
126578064Sume		nifa = TAILQ_NEXT(ifa, ifa_list);
126678064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
126778064Sume			continue;
126878064Sume		in6_purgeaddr(ifa);
126978064Sume	}
127078064Sume
127178064Sume	in6_ifdetach(ifp);
127278064Sume}
127378064Sume
127453541Sshin/*
127553541Sshin * SIOC[GAD]LIFADDR.
127662744Sgrog *	SIOCGLIFADDR: get first address. (?)
127753541Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
127853541Sshin *		get first address that matches the specified prefix.
127953541Sshin *	SIOCALIFADDR: add the specified address.
128053541Sshin *	SIOCALIFADDR with IFLR_PREFIX:
128153541Sshin *		add the specified prefix, filling hostid part from
128253541Sshin *		the first link-local address.  prefixlen must be <= 64.
128353541Sshin *	SIOCDLIFADDR: delete the specified address.
128453541Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
128553541Sshin *		delete the first address that matches the specified prefix.
128653541Sshin * return values:
128753541Sshin *	EINVAL on invalid parameters
128853541Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
128953541Sshin *	other values may be returned from in6_ioctl()
129053541Sshin *
129153541Sshin * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
129253541Sshin * this is to accomodate address naming scheme other than RFC2374,
129353541Sshin * in the future.
129453541Sshin * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
129553541Sshin * address encoding scheme. (see figure on page 8)
129653541Sshin */
129753541Sshinstatic int
129883366Sjulianin6_lifaddr_ioctl(so, cmd, data, ifp, td)
129953541Sshin	struct socket *so;
130053541Sshin	u_long cmd;
130153541Sshin	caddr_t	data;
130253541Sshin	struct ifnet *ifp;
130383366Sjulian	struct thread *td;
130453541Sshin{
130553541Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
130653541Sshin	struct ifaddr *ifa;
130762587Sitojun	struct sockaddr *sa;
130853541Sshin
130953541Sshin	/* sanity checks */
131053541Sshin	if (!data || !ifp) {
131153541Sshin		panic("invalid argument to in6_lifaddr_ioctl");
1312120891Sume		/* NOTREACHED */
131353541Sshin	}
131453541Sshin
131553541Sshin	switch (cmd) {
131653541Sshin	case SIOCGLIFADDR:
131753541Sshin		/* address must be specified on GET with IFLR_PREFIX */
131853541Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
131953541Sshin			break;
132095023Ssuz		/* FALLTHROUGH */
132153541Sshin	case SIOCALIFADDR:
132253541Sshin	case SIOCDLIFADDR:
132353541Sshin		/* address must be specified on ADD and DELETE */
132462587Sitojun		sa = (struct sockaddr *)&iflr->addr;
132562587Sitojun		if (sa->sa_family != AF_INET6)
132653541Sshin			return EINVAL;
132762587Sitojun		if (sa->sa_len != sizeof(struct sockaddr_in6))
132853541Sshin			return EINVAL;
132953541Sshin		/* XXX need improvement */
133062587Sitojun		sa = (struct sockaddr *)&iflr->dstaddr;
133162587Sitojun		if (sa->sa_family && sa->sa_family != AF_INET6)
133253541Sshin			return EINVAL;
133362587Sitojun		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
133453541Sshin			return EINVAL;
133553541Sshin		break;
133695023Ssuz	default: /* shouldn't happen */
133762587Sitojun#if 0
133862587Sitojun		panic("invalid cmd to in6_lifaddr_ioctl");
133995023Ssuz		/* NOTREACHED */
134062587Sitojun#else
134153541Sshin		return EOPNOTSUPP;
134262587Sitojun#endif
134353541Sshin	}
134453541Sshin	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
134553541Sshin		return EINVAL;
134653541Sshin
134753541Sshin	switch (cmd) {
134853541Sshin	case SIOCALIFADDR:
134953541Sshin	    {
135053541Sshin		struct in6_aliasreq ifra;
135153541Sshin		struct in6_addr *hostid = NULL;
135253541Sshin		int prefixlen;
135353541Sshin
135453541Sshin		if ((iflr->flags & IFLR_PREFIX) != 0) {
135553541Sshin			struct sockaddr_in6 *sin6;
135653541Sshin
135753541Sshin			/*
135853541Sshin			 * hostid is to fill in the hostid part of the
135953541Sshin			 * address.  hostid points to the first link-local
136053541Sshin			 * address attached to the interface.
136153541Sshin			 */
136262587Sitojun			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
136353541Sshin			if (!ifa)
136453541Sshin				return EADDRNOTAVAIL;
136553541Sshin			hostid = IFA_IN6(ifa);
136653541Sshin
136753541Sshin		 	/* prefixlen must be <= 64. */
136853541Sshin			if (64 < iflr->prefixlen)
136953541Sshin				return EINVAL;
137053541Sshin			prefixlen = iflr->prefixlen;
137153541Sshin
137253541Sshin			/* hostid part must be zero. */
137353541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1374126552Sume			if (sin6->sin6_addr.s6_addr32[2] != 0 ||
1375126552Sume			    sin6->sin6_addr.s6_addr32[3] != 0) {
137653541Sshin				return EINVAL;
137753541Sshin			}
137853541Sshin		} else
137953541Sshin			prefixlen = iflr->prefixlen;
138053541Sshin
138153541Sshin		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
138253541Sshin		bzero(&ifra, sizeof(ifra));
1383120891Sume		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
138453541Sshin
138562587Sitojun		bcopy(&iflr->addr, &ifra.ifra_addr,
1386120891Sume		    ((struct sockaddr *)&iflr->addr)->sa_len);
138753541Sshin		if (hostid) {
138853541Sshin			/* fill in hostid part */
138953541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1390120891Sume			    hostid->s6_addr32[2];
139153541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1392120891Sume			    hostid->s6_addr32[3];
139353541Sshin		}
139453541Sshin
1395120891Sume		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
139653541Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1397120891Sume			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
139853541Sshin			if (hostid) {
139953541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1400120891Sume				    hostid->s6_addr32[2];
140153541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1402120891Sume				    hostid->s6_addr32[3];
140353541Sshin			}
140453541Sshin		}
140553541Sshin
140653541Sshin		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1407121168Sume		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
140853541Sshin
140953541Sshin		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
141083366Sjulian		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
141153541Sshin	    }
141253541Sshin	case SIOCGLIFADDR:
141353541Sshin	case SIOCDLIFADDR:
141453541Sshin	    {
141553541Sshin		struct in6_ifaddr *ia;
141653541Sshin		struct in6_addr mask, candidate, match;
141753541Sshin		struct sockaddr_in6 *sin6;
141853541Sshin		int cmp;
141953541Sshin
142053541Sshin		bzero(&mask, sizeof(mask));
142153541Sshin		if (iflr->flags & IFLR_PREFIX) {
142253541Sshin			/* lookup a prefix rather than address. */
1423121168Sume			in6_prefixlen2mask(&mask, iflr->prefixlen);
142453541Sshin
142553541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
142653541Sshin			bcopy(&sin6->sin6_addr, &match, sizeof(match));
142753541Sshin			match.s6_addr32[0] &= mask.s6_addr32[0];
142853541Sshin			match.s6_addr32[1] &= mask.s6_addr32[1];
142953541Sshin			match.s6_addr32[2] &= mask.s6_addr32[2];
143053541Sshin			match.s6_addr32[3] &= mask.s6_addr32[3];
143153541Sshin
143253541Sshin			/* if you set extra bits, that's wrong */
143353541Sshin			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
143453541Sshin				return EINVAL;
143553541Sshin
143653541Sshin			cmp = 1;
143753541Sshin		} else {
143853541Sshin			if (cmd == SIOCGLIFADDR) {
143953541Sshin				/* on getting an address, take the 1st match */
144095023Ssuz				cmp = 0;	/* XXX */
144153541Sshin			} else {
144253541Sshin				/* on deleting an address, do exact match */
1443121168Sume				in6_prefixlen2mask(&mask, 128);
144453541Sshin				sin6 = (struct sockaddr_in6 *)&iflr->addr;
144553541Sshin				bcopy(&sin6->sin6_addr, &match, sizeof(match));
144653541Sshin
144753541Sshin				cmp = 1;
144853541Sshin			}
144953541Sshin		}
145053541Sshin
1451120891Sume		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
145253541Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
145353541Sshin				continue;
145453541Sshin			if (!cmp)
145553541Sshin				break;
145678064Sume
145778064Sume			/*
145878064Sume			 * XXX: this is adhoc, but is necessary to allow
145978064Sume			 * a user to specify fe80::/64 (not /10) for a
146078064Sume			 * link-local address.
146178064Sume			 */
1462148385Sume			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1463148385Sume			in6_clearscope(&candidate);
146453541Sshin			candidate.s6_addr32[0] &= mask.s6_addr32[0];
146553541Sshin			candidate.s6_addr32[1] &= mask.s6_addr32[1];
146653541Sshin			candidate.s6_addr32[2] &= mask.s6_addr32[2];
146753541Sshin			candidate.s6_addr32[3] &= mask.s6_addr32[3];
146853541Sshin			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
146953541Sshin				break;
147053541Sshin		}
147153541Sshin		if (!ifa)
147253541Sshin			return EADDRNOTAVAIL;
147353541Sshin		ia = ifa2ia6(ifa);
147453541Sshin
147553541Sshin		if (cmd == SIOCGLIFADDR) {
1476148385Sume			int error;
147778064Sume
147853541Sshin			/* fill in the if_laddrreq structure */
147953541Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1480148385Sume			error = sa6_recoverscope(
1481148385Sume			    (struct sockaddr_in6 *)&iflr->addr);
1482148385Sume			if (error != 0)
1483148385Sume				return (error);
1484148385Sume
148553541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
148653541Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1487120891Sume				    ia->ia_dstaddr.sin6_len);
1488148385Sume				error = sa6_recoverscope(
1489148385Sume				    (struct sockaddr_in6 *)&iflr->dstaddr);
1490148385Sume				if (error != 0)
1491148385Sume					return (error);
149253541Sshin			} else
149353541Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
149453541Sshin
149553541Sshin			iflr->prefixlen =
1496120891Sume			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
149753541Sshin
149895023Ssuz			iflr->flags = ia->ia6_flags;	/* XXX */
149953541Sshin
150053541Sshin			return 0;
150153541Sshin		} else {
150253541Sshin			struct in6_aliasreq ifra;
150353541Sshin
150453541Sshin			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
150553541Sshin			bzero(&ifra, sizeof(ifra));
150653541Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
1507120891Sume			    sizeof(ifra.ifra_name));
150853541Sshin
150953541Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
1510120891Sume			    ia->ia_addr.sin6_len);
151153541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
151253541Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1513120891Sume				    ia->ia_dstaddr.sin6_len);
151462587Sitojun			} else {
151562587Sitojun				bzero(&ifra.ifra_dstaddr,
151662587Sitojun				    sizeof(ifra.ifra_dstaddr));
151753541Sshin			}
151853541Sshin			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1519120891Sume			    ia->ia_prefixmask.sin6_len);
152053541Sshin
152153541Sshin			ifra.ifra_flags = ia->ia6_flags;
152253541Sshin			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1523120891Sume			    ifp, td);
152453541Sshin		}
152553541Sshin	    }
152653541Sshin	}
152753541Sshin
152895023Ssuz	return EOPNOTSUPP;	/* just for safety */
152953541Sshin}
153053541Sshin
153153541Sshin/*
153253541Sshin * Initialize an interface's intetnet6 address
153353541Sshin * and routing table entry.
153453541Sshin */
153578064Sumestatic int
153678064Sumein6_ifinit(ifp, ia, sin6, newhost)
153753541Sshin	struct ifnet *ifp;
153853541Sshin	struct in6_ifaddr *ia;
153953541Sshin	struct sockaddr_in6 *sin6;
154078064Sume	int newhost;
154153541Sshin{
154278064Sume	int	error = 0, plen, ifacount = 0;
154353541Sshin	int	s = splimp();
154478064Sume	struct ifaddr *ifa;
154553541Sshin
154653541Sshin	/*
154753541Sshin	 * Give the interface a chance to initialize
154853541Sshin	 * if this is its first address,
154953541Sshin	 * and to validate the address if necessary.
155053541Sshin	 */
1551120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
155278064Sume		if (ifa->ifa_addr == NULL)
155378064Sume			continue;	/* just for safety */
155478064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
155578064Sume			continue;
155678064Sume		ifacount++;
155778064Sume	}
155878064Sume
155978064Sume	ia->ia_addr = *sin6;
156078064Sume
1561146883Siedowse	if (ifacount <= 1 && ifp->if_ioctl) {
1562146883Siedowse		IFF_LOCKGIANT(ifp);
1563146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
1564146883Siedowse		IFF_UNLOCKGIANT(ifp);
1565146883Siedowse		if (error) {
1566146883Siedowse			splx(s);
1567146883Siedowse			return (error);
1568146883Siedowse		}
156953541Sshin	}
157078064Sume	splx(s);
157153541Sshin
157278064Sume	ia->ia_ifa.ifa_metric = ifp->if_metric;
157353541Sshin
157478064Sume	/* we could do in(6)_socktrim here, but just omit it at this moment. */
157578064Sume
157653541Sshin	/*
157778064Sume	 * Special case:
1578124337Sume	 * If a new destination address is specified for a point-to-point
157978064Sume	 * interface, install a route to the destination as an interface
158078064Sume	 * direct route.
1581124337Sume	 * XXX: the logic below rejects assigning multiple addresses on a p2p
1582124337Sume	 * interface that share a same destination.
158353541Sshin	 */
158478064Sume	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1585124337Sume	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
1586124337Sume	    ia->ia_dstaddr.sin6_family == AF_INET6) {
158778064Sume		if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
158878064Sume				    RTF_UP | RTF_HOST)) != 0)
1589120856Sume			return (error);
159078064Sume		ia->ia_flags |= IFA_ROUTE;
159153541Sshin	}
159278064Sume	if (plen < 128) {
159378064Sume		/*
159478064Sume		 * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
159578064Sume		 */
159678064Sume		ia->ia_ifa.ifa_flags |= RTF_CLONING;
159778064Sume	}
159853541Sshin
159995023Ssuz	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
160078064Sume	if (newhost) {
160178064Sume		/* set the rtrequest function to create llinfo */
160278064Sume		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
160378064Sume		in6_ifaddloop(&(ia->ia_ifa));
160478064Sume	}
160553541Sshin
1606120856Sume	return (error);
160753541Sshin}
160853541Sshin
1609142215Sglebiusstruct in6_multi_mship *
1610142215Sglebiusin6_joingroup(ifp, addr, errorp)
1611142215Sglebius	struct ifnet *ifp;
1612142215Sglebius	struct in6_addr *addr;
1613142215Sglebius	int *errorp;
1614142215Sglebius{
1615142215Sglebius	struct in6_multi_mship *imm;
1616142215Sglebius
1617142215Sglebius	imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT);
1618142215Sglebius	if (!imm) {
1619142215Sglebius		*errorp = ENOBUFS;
1620142215Sglebius		return NULL;
1621142215Sglebius	}
1622142215Sglebius	imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp);
1623142215Sglebius	if (!imm->i6mm_maddr) {
1624142215Sglebius		/* *errorp is alrady set */
1625142215Sglebius		free(imm, M_IPMADDR);
1626142215Sglebius		return NULL;
1627142215Sglebius	}
1628142215Sglebius	return imm;
1629142215Sglebius}
1630142215Sglebius
1631142215Sglebiusint
1632142215Sglebiusin6_leavegroup(imm)
1633142215Sglebius	struct in6_multi_mship *imm;
1634142215Sglebius{
1635142215Sglebius
1636142215Sglebius	if (imm->i6mm_maddr)
1637142215Sglebius		in6_delmulti(imm->i6mm_maddr);
1638142215Sglebius	free(imm,  M_IPMADDR);
1639142215Sglebius	return 0;
1640142215Sglebius}
1641142215Sglebius
164253541Sshin/*
164353541Sshin * Find an IPv6 interface link-local address specific to an interface.
164453541Sshin */
164553541Sshinstruct in6_ifaddr *
164662587Sitojunin6ifa_ifpforlinklocal(ifp, ignoreflags)
164753541Sshin	struct ifnet *ifp;
164862587Sitojun	int ignoreflags;
164953541Sshin{
165078064Sume	struct ifaddr *ifa;
165153541Sshin
1652120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
165353541Sshin		if (ifa->ifa_addr == NULL)
165453541Sshin			continue;	/* just for safety */
165553541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
165653541Sshin			continue;
165762587Sitojun		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
165862587Sitojun			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
165962587Sitojun			     ignoreflags) != 0)
166062587Sitojun				continue;
166153541Sshin			break;
166262587Sitojun		}
166353541Sshin	}
166453541Sshin
1665120856Sume	return ((struct in6_ifaddr *)ifa);
166653541Sshin}
166753541Sshin
166853541Sshin
166953541Sshin/*
167053541Sshin * find the internet address corresponding to a given interface and address.
167153541Sshin */
167253541Sshinstruct in6_ifaddr *
167353541Sshinin6ifa_ifpwithaddr(ifp, addr)
167453541Sshin	struct ifnet *ifp;
167553541Sshin	struct in6_addr *addr;
167653541Sshin{
167778064Sume	struct ifaddr *ifa;
167853541Sshin
1679120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
168053541Sshin		if (ifa->ifa_addr == NULL)
168153541Sshin			continue;	/* just for safety */
168253541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
168353541Sshin			continue;
168453541Sshin		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
168553541Sshin			break;
168653541Sshin	}
168753541Sshin
1688120856Sume	return ((struct in6_ifaddr *)ifa);
168953541Sshin}
169053541Sshin
169153541Sshin/*
169253541Sshin * Convert IP6 address to printable (loggable) representation.
169353541Sshin */
169453541Sshinstatic char digits[] = "0123456789abcdef";
169553541Sshinstatic int ip6round = 0;
169653541Sshinchar *
169753541Sshinip6_sprintf(addr)
169878064Sume	const struct in6_addr *addr;
169953541Sshin{
170053541Sshin	static char ip6buf[8][48];
170178064Sume	int i;
170278064Sume	char *cp;
1703126552Sume	const u_int16_t *a = (const u_int16_t *)addr;
1704126552Sume	const u_int8_t *d;
170553541Sshin	int dcolon = 0;
170653541Sshin
170753541Sshin	ip6round = (ip6round + 1) & 7;
170853541Sshin	cp = ip6buf[ip6round];
170953541Sshin
171053541Sshin	for (i = 0; i < 8; i++) {
171153541Sshin		if (dcolon == 1) {
171253541Sshin			if (*a == 0) {
171353541Sshin				if (i == 7)
171453541Sshin					*cp++ = ':';
171553541Sshin				a++;
171653541Sshin				continue;
171753541Sshin			} else
171853541Sshin				dcolon = 2;
171953541Sshin		}
172053541Sshin		if (*a == 0) {
172153541Sshin			if (dcolon == 0 && *(a + 1) == 0) {
172253541Sshin				if (i == 0)
172353541Sshin					*cp++ = ':';
172453541Sshin				*cp++ = ':';
172553541Sshin				dcolon = 1;
172653541Sshin			} else {
172753541Sshin				*cp++ = '0';
172853541Sshin				*cp++ = ':';
172953541Sshin			}
173053541Sshin			a++;
173153541Sshin			continue;
173253541Sshin		}
173391346Salfred		d = (const u_char *)a;
173453541Sshin		*cp++ = digits[*d >> 4];
173553541Sshin		*cp++ = digits[*d++ & 0xf];
173653541Sshin		*cp++ = digits[*d >> 4];
173753541Sshin		*cp++ = digits[*d & 0xf];
173853541Sshin		*cp++ = ':';
173953541Sshin		a++;
174053541Sshin	}
174153541Sshin	*--cp = 0;
1742120856Sume	return (ip6buf[ip6round]);
174353541Sshin}
174453541Sshin
174553541Sshinint
174653541Sshinin6_localaddr(in6)
174753541Sshin	struct in6_addr *in6;
174853541Sshin{
174953541Sshin	struct in6_ifaddr *ia;
175053541Sshin
175153541Sshin	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
175253541Sshin		return 1;
175353541Sshin
1754120891Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
175553541Sshin		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1756120891Sume		    &ia->ia_prefixmask.sin6_addr)) {
175753541Sshin			return 1;
1758120891Sume		}
1759120891Sume	}
176053541Sshin
176153541Sshin	return (0);
176253541Sshin}
176353541Sshin
176478064Sumeint
176578064Sumein6_is_addr_deprecated(sa6)
176678064Sume	struct sockaddr_in6 *sa6;
176778064Sume{
176878064Sume	struct in6_ifaddr *ia;
176978064Sume
177078064Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
177178064Sume		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
177278064Sume				       &sa6->sin6_addr) &&
177378064Sume		    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
1774120856Sume			return (1); /* true */
177578064Sume
177678064Sume		/* XXX: do we still have to go thru the rest of the list? */
177778064Sume	}
177878064Sume
1779120856Sume	return (0);		/* false */
178078064Sume}
178178064Sume
178253541Sshin/*
178353541Sshin * return length of part which dst and src are equal
178453541Sshin * hard coding...
178553541Sshin */
178653541Sshinint
178753541Sshinin6_matchlen(src, dst)
178853541Sshinstruct in6_addr *src, *dst;
178953541Sshin{
179053541Sshin	int match = 0;
179153541Sshin	u_char *s = (u_char *)src, *d = (u_char *)dst;
179253541Sshin	u_char *lim = s + 16, r;
179353541Sshin
179453541Sshin	while (s < lim)
179553541Sshin		if ((r = (*d++ ^ *s++)) != 0) {
179653541Sshin			while (r < 128) {
179753541Sshin				match++;
179853541Sshin				r <<= 1;
179953541Sshin			}
180053541Sshin			break;
180153541Sshin		} else
180253541Sshin			match += 8;
180353541Sshin	return match;
180453541Sshin}
180553541Sshin
180662587Sitojun/* XXX: to be scope conscious */
180753541Sshinint
180853541Sshinin6_are_prefix_equal(p1, p2, len)
180953541Sshin	struct in6_addr *p1, *p2;
181053541Sshin	int len;
181153541Sshin{
181253541Sshin	int bytelen, bitlen;
181353541Sshin
181453541Sshin	/* sanity check */
181553541Sshin	if (0 > len || len > 128) {
181653541Sshin		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
181753541Sshin		    len);
1818120856Sume		return (0);
181953541Sshin	}
182053541Sshin
182153541Sshin	bytelen = len / 8;
182253541Sshin	bitlen = len % 8;
182353541Sshin
182453541Sshin	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
1825120856Sume		return (0);
1826126184Scperciva	if (bitlen != 0 &&
1827126184Scperciva	    p1->s6_addr[bytelen] >> (8 - bitlen) !=
182853541Sshin	    p2->s6_addr[bytelen] >> (8 - bitlen))
1829120856Sume		return (0);
183053541Sshin
1831120856Sume	return (1);
183253541Sshin}
183353541Sshin
183453541Sshinvoid
183553541Sshinin6_prefixlen2mask(maskp, len)
183653541Sshin	struct in6_addr *maskp;
183753541Sshin	int len;
183853541Sshin{
183953541Sshin	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
184053541Sshin	int bytelen, bitlen, i;
184153541Sshin
184253541Sshin	/* sanity check */
184353541Sshin	if (0 > len || len > 128) {
184453541Sshin		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
184553541Sshin		    len);
184653541Sshin		return;
184753541Sshin	}
184853541Sshin
184953541Sshin	bzero(maskp, sizeof(*maskp));
185053541Sshin	bytelen = len / 8;
185153541Sshin	bitlen = len % 8;
185253541Sshin	for (i = 0; i < bytelen; i++)
185353541Sshin		maskp->s6_addr[i] = 0xff;
185453541Sshin	if (bitlen)
185553541Sshin		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
185653541Sshin}
185753541Sshin
185853541Sshin/*
185953541Sshin * return the best address out of the same scope. if no address was
186053541Sshin * found, return the first valid address from designated IF.
186153541Sshin */
186253541Sshinstruct in6_ifaddr *
186353541Sshinin6_ifawithifp(ifp, dst)
186478064Sume	struct ifnet *ifp;
186578064Sume	struct in6_addr *dst;
186653541Sshin{
186753541Sshin	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
186853541Sshin	struct ifaddr *ifa;
186953541Sshin	struct in6_ifaddr *besta = 0;
187095023Ssuz	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
187153541Sshin
187253541Sshin	dep[0] = dep[1] = NULL;
187353541Sshin
187453541Sshin	/*
187553541Sshin	 * We first look for addresses in the same scope.
187653541Sshin	 * If there is one, return it.
187753541Sshin	 * If two or more, return one which matches the dst longest.
187853541Sshin	 * If none, return one of global addresses assigned other ifs.
187953541Sshin	 */
1880120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
188153541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
188253541Sshin			continue;
188353541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
188453541Sshin			continue; /* XXX: is there any case to allow anycast? */
188553541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
188653541Sshin			continue; /* don't use this interface */
188753541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
188853541Sshin			continue;
188953541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
189053541Sshin			if (ip6_use_deprecated)
189153541Sshin				dep[0] = (struct in6_ifaddr *)ifa;
189253541Sshin			continue;
189353541Sshin		}
189453541Sshin
189553541Sshin		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
189653541Sshin			/*
189753541Sshin			 * call in6_matchlen() as few as possible
189853541Sshin			 */
189953541Sshin			if (besta) {
190053541Sshin				if (blen == -1)
190153541Sshin					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
190253541Sshin				tlen = in6_matchlen(IFA_IN6(ifa), dst);
190353541Sshin				if (tlen > blen) {
190453541Sshin					blen = tlen;
190553541Sshin					besta = (struct in6_ifaddr *)ifa;
190653541Sshin				}
190753541Sshin			} else
190853541Sshin				besta = (struct in6_ifaddr *)ifa;
190953541Sshin		}
191053541Sshin	}
191153541Sshin	if (besta)
1912120856Sume		return (besta);
191353541Sshin
1914120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
191553541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
191653541Sshin			continue;
191753541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
191853541Sshin			continue; /* XXX: is there any case to allow anycast? */
191953541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
192053541Sshin			continue; /* don't use this interface */
192153541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
192253541Sshin			continue;
192353541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
192453541Sshin			if (ip6_use_deprecated)
192553541Sshin				dep[1] = (struct in6_ifaddr *)ifa;
192653541Sshin			continue;
192753541Sshin		}
192853541Sshin
192953541Sshin		return (struct in6_ifaddr *)ifa;
193053541Sshin	}
193153541Sshin
193253541Sshin	/* use the last-resort values, that are, deprecated addresses */
193353541Sshin	if (dep[0])
193453541Sshin		return dep[0];
193553541Sshin	if (dep[1])
193653541Sshin		return dep[1];
193753541Sshin
193853541Sshin	return NULL;
193953541Sshin}
194053541Sshin
194153541Sshin/*
194253541Sshin * perform DAD when interface becomes IFF_UP.
194353541Sshin */
194453541Sshinvoid
194553541Sshinin6_if_up(ifp)
194653541Sshin	struct ifnet *ifp;
194753541Sshin{
194853541Sshin	struct ifaddr *ifa;
194953541Sshin	struct in6_ifaddr *ia;
195053541Sshin	int dad_delay;		/* delay ticks before DAD output */
195153541Sshin
195262587Sitojun	/*
195362587Sitojun	 * special cases, like 6to4, are handled in in6_ifattach
195462587Sitojun	 */
195562587Sitojun	in6_ifattach(ifp, NULL);
195653541Sshin
195753541Sshin	dad_delay = 0;
1958120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
195953541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
196053541Sshin			continue;
196153541Sshin		ia = (struct in6_ifaddr *)ifa;
196253541Sshin		if (ia->ia6_flags & IN6_IFF_TENTATIVE)
196353541Sshin			nd6_dad_start(ifa, &dad_delay);
196453541Sshin	}
196553541Sshin}
196653541Sshin
196778064Sumeint
196878064Sumein6if_do_dad(ifp)
196978064Sume	struct ifnet *ifp;
197078064Sume{
197178064Sume	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
1972120856Sume		return (0);
197378064Sume
197478064Sume	switch (ifp->if_type) {
197578064Sume#ifdef IFT_DUMMY
197678064Sume	case IFT_DUMMY:
197778064Sume#endif
197878064Sume	case IFT_FAITH:
197978064Sume		/*
198078064Sume		 * These interfaces do not have the IFF_LOOPBACK flag,
198178064Sume		 * but loop packets back.  We do not have to do DAD on such
198278064Sume		 * interfaces.  We should even omit it, because loop-backed
198378064Sume		 * NS would confuse the DAD procedure.
198478064Sume		 */
1985120856Sume		return (0);
198678064Sume	default:
198778064Sume		/*
198878064Sume		 * Our DAD routine requires the interface up and running.
198978064Sume		 * However, some interfaces can be up before the RUNNING
199078064Sume		 * status.  Additionaly, users may try to assign addresses
199178064Sume		 * before the interface becomes up (or running).
199278064Sume		 * We simply skip DAD in such a case as a work around.
199378064Sume		 * XXX: we should rather mark "tentative" on such addresses,
199478064Sume		 * and do DAD after the interface becomes ready.
199578064Sume		 */
1996148887Srwatson		if (!((ifp->if_flags & IFF_UP) &&
1997148887Srwatson		    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
1998120856Sume			return (0);
199978064Sume
2000120856Sume		return (1);
200178064Sume	}
200278064Sume}
200378064Sume
200453541Sshin/*
200553541Sshin * Calculate max IPv6 MTU through all the interfaces and store it
200653541Sshin * to in6_maxmtu.
200753541Sshin */
200853541Sshinvoid
200953541Sshinin6_setmaxmtu()
201053541Sshin{
201153541Sshin	unsigned long maxmtu = 0;
201253541Sshin	struct ifnet *ifp;
201353541Sshin
2014108172Shsu	IFNET_RLOCK();
2015120891Sume	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
2016121283Sume		/* this function can be called during ifnet initialization */
2017121283Sume		if (!ifp->if_afdata[AF_INET6])
2018121283Sume			continue;
201953541Sshin		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2020121283Sume		    IN6_LINKMTU(ifp) > maxmtu)
2021121283Sume			maxmtu = IN6_LINKMTU(ifp);
202253541Sshin	}
2023108172Shsu	IFNET_RUNLOCK();
2024120891Sume	if (maxmtu)	     /* update only when maxmtu is positive */
202553541Sshin		in6_maxmtu = maxmtu;
202653541Sshin}
202753541Sshin
2028121161Sumevoid *
2029121161Sumein6_domifattach(ifp)
2030121161Sume	struct ifnet *ifp;
2031121161Sume{
2032121161Sume	struct in6_ifextra *ext;
2033121161Sume
2034121161Sume	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
2035121161Sume	bzero(ext, sizeof(*ext));
2036121161Sume
2037121161Sume	ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
2038121161Sume	    M_IFADDR, M_WAITOK);
2039121161Sume	bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
2040121161Sume
2041121161Sume	ext->icmp6_ifstat =
2042121161Sume	    (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
2043121161Sume	    M_IFADDR, M_WAITOK);
2044121161Sume	bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
2045121161Sume
2046121161Sume	ext->nd_ifinfo = nd6_ifattach(ifp);
2047121161Sume	ext->scope6_id = scope6_ifattach(ifp);
2048121161Sume	return ext;
2049121161Sume}
2050121161Sume
2051121161Sumevoid
2052121161Sumein6_domifdetach(ifp, aux)
2053121161Sume	struct ifnet *ifp;
2054121161Sume	void *aux;
2055121161Sume{
2056121161Sume	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
2057121161Sume
2058121161Sume	scope6_ifdetach(ext->scope6_id);
2059121161Sume	nd6_ifdetach(ext->nd_ifinfo);
2060121161Sume	free(ext->in6_ifstat, M_IFADDR);
2061121161Sume	free(ext->icmp6_ifstat, M_IFADDR);
2062121161Sume	free(ext, M_IFADDR);
2063121161Sume}
2064121161Sume
206553541Sshin/*
206695023Ssuz * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
206753541Sshin * v4 mapped addr or v4 compat addr
206853541Sshin */
206953541Sshinvoid
207053541Sshinin6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
207153541Sshin{
207253541Sshin	bzero(sin, sizeof(*sin));
207353541Sshin	sin->sin_len = sizeof(struct sockaddr_in);
207453541Sshin	sin->sin_family = AF_INET;
207553541Sshin	sin->sin_port = sin6->sin6_port;
2076120891Sume	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
207753541Sshin}
207853541Sshin
207953541Sshin/* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
208053541Sshinvoid
208153541Sshinin6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
208253541Sshin{
208353541Sshin	bzero(sin6, sizeof(*sin6));
208453541Sshin	sin6->sin6_len = sizeof(struct sockaddr_in6);
208553541Sshin	sin6->sin6_family = AF_INET6;
208653541Sshin	sin6->sin6_port = sin->sin_port;
208753541Sshin	sin6->sin6_addr.s6_addr32[0] = 0;
208853541Sshin	sin6->sin6_addr.s6_addr32[1] = 0;
208953541Sshin	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
209053541Sshin	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
209153541Sshin}
209253541Sshin
209353541Sshin/* Convert sockaddr_in6 into sockaddr_in. */
209453541Sshinvoid
209553541Sshinin6_sin6_2_sin_in_sock(struct sockaddr *nam)
209653541Sshin{
209753541Sshin	struct sockaddr_in *sin_p;
209853541Sshin	struct sockaddr_in6 sin6;
209953541Sshin
210053541Sshin	/*
210153541Sshin	 * Save original sockaddr_in6 addr and convert it
210253541Sshin	 * to sockaddr_in.
210353541Sshin	 */
210453541Sshin	sin6 = *(struct sockaddr_in6 *)nam;
210553541Sshin	sin_p = (struct sockaddr_in *)nam;
210653541Sshin	in6_sin6_2_sin(sin_p, &sin6);
210753541Sshin}
210853541Sshin
210953541Sshin/* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
211053541Sshinvoid
211153541Sshinin6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
211253541Sshin{
211353541Sshin	struct sockaddr_in *sin_p;
211453541Sshin	struct sockaddr_in6 *sin6_p;
211553541Sshin
211653541Sshin	MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
2117111119Simp	       M_WAITOK);
211853541Sshin	sin_p = (struct sockaddr_in *)*nam;
211953541Sshin	in6_sin_2_v4mapsin6(sin_p, sin6_p);
212053541Sshin	FREE(*nam, M_SONAME);
212153541Sshin	*nam = (struct sockaddr *)sin6_p;
212253541Sshin}
2123