in6.c revision 146883
162587Sitojun/*	$FreeBSD: head/sys/netinet6/in6.c 146883 2005-06-02 00:04:08Z iedowse $	*/
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;
33353541Sshin	int 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 */
41553541Sshin		struct sockaddr_in6 *sa6 =
41653541Sshin			(struct sockaddr_in6 *)&ifra->ifra_addr;
41753541Sshin
41853541Sshin		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
41953541Sshin			if (sa6->sin6_addr.s6_addr16[1] == 0) {
42078064Sume				/* link ID is not embedded by the user */
42153541Sshin				sa6->sin6_addr.s6_addr16[1] =
422120891Sume				    htons(ifp->if_index);
42362587Sitojun			} else if (sa6->sin6_addr.s6_addr16[1] !=
424120891Sume			    htons(ifp->if_index)) {
425120856Sume				return (EINVAL);	/* link ID contradicts */
42662587Sitojun			}
42753541Sshin			if (sa6->sin6_scope_id) {
42853541Sshin				if (sa6->sin6_scope_id !=
42953541Sshin				    (u_int32_t)ifp->if_index)
430120856Sume					return (EINVAL);
43153541Sshin				sa6->sin6_scope_id = 0; /* XXX: good way? */
43253541Sshin			}
43353541Sshin		}
43462587Sitojun		ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
43553541Sshin	}
43653541Sshin
43753541Sshin	switch (cmd) {
43878064Sume	case SIOCSIFADDR_IN6:
43978064Sume	case SIOCSIFDSTADDR_IN6:
44078064Sume	case SIOCSIFNETMASK_IN6:
44178064Sume		/*
44278064Sume		 * Since IPv6 allows a node to assign multiple addresses
44378064Sume		 * on a single interface, SIOCSIFxxx ioctls are not suitable
44478064Sume		 * and should be unused.
44578064Sume		 */
44678064Sume		/* we decided to obsolete this command (20000704) */
447120856Sume		return (EINVAL);
44853541Sshin
44953541Sshin	case SIOCDIFADDR_IN6:
45062587Sitojun		/*
45178064Sume		 * for IPv4, we look for existing in_ifaddr here to allow
45262587Sitojun		 * "ifconfig if0 delete" to remove first IPv4 address on the
45362587Sitojun		 * interface.  For IPv6, as the spec allow multiple interface
45462587Sitojun		 * address from the day one, we consider "remove the first one"
45578064Sume		 * semantics to be not preferable.
45662587Sitojun		 */
45762587Sitojun		if (ia == NULL)
458120856Sume			return (EADDRNOTAVAIL);
45953541Sshin		/* FALLTHROUGH */
46053541Sshin	case SIOCAIFADDR_IN6:
46162587Sitojun		/*
46278064Sume		 * We always require users to specify a valid IPv6 address for
46378064Sume		 * the corresponding operation.
46462587Sitojun		 */
46578064Sume		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
46678064Sume		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
467120856Sume			return (EAFNOSUPPORT);
46853541Sshin		if (!privileged)
469120856Sume			return (EPERM);
47053541Sshin
47153541Sshin		break;
47253541Sshin
47353541Sshin	case SIOCGIFADDR_IN6:
47453541Sshin		/* This interface is basically deprecated. use SIOCGIFCONF. */
475120891Sume		/* FALLTHROUGH */
47653541Sshin	case SIOCGIFAFLAG_IN6:
47753541Sshin	case SIOCGIFNETMASK_IN6:
47853541Sshin	case SIOCGIFDSTADDR_IN6:
47953541Sshin	case SIOCGIFALIFETIME_IN6:
48053541Sshin		/* must think again about its semantics */
48162587Sitojun		if (ia == NULL)
482120856Sume			return (EADDRNOTAVAIL);
48353541Sshin		break;
48453541Sshin	case SIOCSIFALIFETIME_IN6:
48553541Sshin	    {
48653541Sshin		struct in6_addrlifetime *lt;
48753541Sshin
48853541Sshin		if (!privileged)
489120856Sume			return (EPERM);
49062587Sitojun		if (ia == NULL)
491120856Sume			return (EADDRNOTAVAIL);
49253541Sshin		/* sanity for overflow - beware unsigned */
49353541Sshin		lt = &ifr->ifr_ifru.ifru_lifetime;
494126552Sume		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
495126552Sume		    lt->ia6t_vltime + time_second < time_second) {
49653541Sshin			return EINVAL;
49753541Sshin		}
498126552Sume		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
499126552Sume		    lt->ia6t_pltime + time_second < time_second) {
50053541Sshin			return EINVAL;
50153541Sshin		}
50253541Sshin		break;
50353541Sshin	    }
50453541Sshin	}
50553541Sshin
50653541Sshin	switch (cmd) {
50753541Sshin
50853541Sshin	case SIOCGIFADDR_IN6:
50953541Sshin		ifr->ifr_addr = ia->ia_addr;
51053541Sshin		break;
51153541Sshin
51253541Sshin	case SIOCGIFDSTADDR_IN6:
51353541Sshin		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
514120856Sume			return (EINVAL);
51562587Sitojun		/*
51662587Sitojun		 * XXX: should we check if ifa_dstaddr is NULL and return
51762587Sitojun		 * an error?
51862587Sitojun		 */
51953541Sshin		ifr->ifr_dstaddr = ia->ia_dstaddr;
52053541Sshin		break;
52153541Sshin
52253541Sshin	case SIOCGIFNETMASK_IN6:
52353541Sshin		ifr->ifr_addr = ia->ia_prefixmask;
52453541Sshin		break;
52553541Sshin
52653541Sshin	case SIOCGIFAFLAG_IN6:
52753541Sshin		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
52853541Sshin		break;
52953541Sshin
53053541Sshin	case SIOCGIFSTAT_IN6:
531121167Sume		if (ifp == NULL)
532121167Sume			return EINVAL;
533121161Sume		bzero(&ifr->ifr_ifru.ifru_stat,
534121161Sume		    sizeof(ifr->ifr_ifru.ifru_stat));
535121161Sume		ifr->ifr_ifru.ifru_stat =
536121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
53753541Sshin		break;
53853541Sshin
53953541Sshin	case SIOCGIFSTAT_ICMP6:
54053541Sshin		if (ifp == NULL)
54153541Sshin			return EINVAL;
542121161Sume		bzero(&ifr->ifr_ifru.ifru_stat,
543121161Sume		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
544121161Sume		ifr->ifr_ifru.ifru_icmp6stat =
545121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
54653541Sshin		break;
54753541Sshin
54853541Sshin	case SIOCGIFALIFETIME_IN6:
54953541Sshin		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
55053541Sshin		break;
55153541Sshin
55253541Sshin	case SIOCSIFALIFETIME_IN6:
55353541Sshin		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
55453541Sshin		/* for sanity */
55553541Sshin		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
55653541Sshin			ia->ia6_lifetime.ia6t_expire =
55753541Sshin				time_second + ia->ia6_lifetime.ia6t_vltime;
55853541Sshin		} else
55953541Sshin			ia->ia6_lifetime.ia6t_expire = 0;
56053541Sshin		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
56153541Sshin			ia->ia6_lifetime.ia6t_preferred =
56253541Sshin				time_second + ia->ia6_lifetime.ia6t_pltime;
56353541Sshin		} else
56453541Sshin			ia->ia6_lifetime.ia6t_preferred = 0;
56553541Sshin		break;
56653541Sshin
56778064Sume	case SIOCAIFADDR_IN6:
56878064Sume	{
56978064Sume		int i, error = 0;
57078064Sume		struct nd_prefix pr0, *pr;
57178064Sume
57262587Sitojun		/*
57378064Sume		 * first, make or update the interface address structure,
57478064Sume		 * and link it to the list.
57562587Sitojun		 */
57678064Sume		if ((error = in6_update_ifa(ifp, ifra, ia)) != 0)
577120856Sume			return (error);
57853541Sshin
57978064Sume		/*
58078064Sume		 * then, make the prefix on-link on the interface.
58178064Sume		 * XXX: we'd rather create the prefix before the address, but
58278064Sume		 * we need at least one address to install the corresponding
58378064Sume		 * interface route, so we configure the address first.
58478064Sume		 */
58578064Sume
58678064Sume		/*
58778064Sume		 * convert mask to prefix length (prefixmask has already
58878064Sume		 * been validated in in6_update_ifa().
58978064Sume		 */
59078064Sume		bzero(&pr0, sizeof(pr0));
59178064Sume		pr0.ndpr_ifp = ifp;
59278064Sume		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
593120891Sume		    NULL);
594120891Sume		if (pr0.ndpr_plen == 128) {
59578064Sume			break;	/* we don't need to install a host route. */
596120891Sume		}
59778064Sume		pr0.ndpr_prefix = ifra->ifra_addr;
59878064Sume		pr0.ndpr_mask = ifra->ifra_prefixmask.sin6_addr;
59978064Sume		/* apply the mask for safety. */
60078064Sume		for (i = 0; i < 4; i++) {
60178064Sume			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
602120891Sume			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
60378064Sume		}
60478064Sume		/*
60595023Ssuz		 * XXX: since we don't have an API to set prefix (not address)
60695023Ssuz		 * lifetimes, we just use the same lifetimes as addresses.
60795023Ssuz		 * The (temporarily) installed lifetimes can be overridden by
60895023Ssuz		 * later advertised RAs (when accept_rtadv is non 0), which is
60995023Ssuz		 * an intended behavior.
61078064Sume		 */
61178064Sume		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
61278064Sume		pr0.ndpr_raf_auto =
613120891Sume		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
61478064Sume		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
61578064Sume		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
61678064Sume
617120891Sume		/* add the prefix if not yet. */
61878064Sume		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
61978064Sume			/*
62078064Sume			 * nd6_prelist_add will install the corresponding
62178064Sume			 * interface route.
62278064Sume			 */
62378064Sume			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
624120856Sume				return (error);
62578064Sume			if (pr == NULL) {
626120891Sume				log(LOG_ERR, "nd6_prelist_add succeeded but "
62778064Sume				    "no prefix\n");
628120856Sume				return (EINVAL); /* XXX panic here? */
62978064Sume			}
63078064Sume		}
63178064Sume		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
63278064Sume		    == NULL) {
63378064Sume		    	/* XXX: this should not happen! */
63478064Sume			log(LOG_ERR, "in6_control: addition succeeded, but"
63578064Sume			    " no ifaddr\n");
63678064Sume		} else {
63778064Sume			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
63878064Sume			    ia->ia6_ndpr == NULL) { /* new autoconfed addr */
63978064Sume				ia->ia6_ndpr = pr;
64078064Sume				pr->ndpr_refcnt++;
64178064Sume
64278064Sume				/*
64378064Sume				 * If this is the first autoconf address from
64478064Sume				 * the prefix, create a temporary address
64578064Sume				 * as well (when specified).
64678064Sume				 */
64778064Sume				if (ip6_use_tempaddr &&
64878064Sume				    pr->ndpr_refcnt == 1) {
64978064Sume					int e;
65078064Sume					if ((e = in6_tmpifadd(ia, 1)) != 0) {
65178064Sume						log(LOG_NOTICE, "in6_control: "
65278064Sume						    "failed to create a "
65378064Sume						    "temporary address, "
654122059Sume						    "errno=%d\n", e);
65578064Sume					}
65662587Sitojun				}
65762587Sitojun			}
65878064Sume
65978064Sume			/*
66078064Sume			 * this might affect the status of autoconfigured
66178064Sume			 * addresses, that is, this address might make
66278064Sume			 * other addresses detached.
66378064Sume			 */
66478064Sume			pfxlist_onlink_check();
66562587Sitojun		}
666126264Smlaier		if (error == 0 && ia)
667126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
66878064Sume		break;
66978064Sume	}
67062587Sitojun
67178064Sume	case SIOCDIFADDR_IN6:
67278064Sume	{
67378064Sume		int i = 0;
67478064Sume		struct nd_prefix pr0, *pr;
67578064Sume
67678064Sume		/*
67778064Sume		 * If the address being deleted is the only one that owns
67878064Sume		 * the corresponding prefix, expire the prefix as well.
679120891Sume		 * XXX: theoretically, we don't have to worry about such
68078064Sume		 * relationship, since we separate the address management
68178064Sume		 * and the prefix management.  We do this, however, to provide
68278064Sume		 * as much backward compatibility as possible in terms of
68378064Sume		 * the ioctl operation.
68478064Sume		 */
68578064Sume		bzero(&pr0, sizeof(pr0));
68678064Sume		pr0.ndpr_ifp = ifp;
68778064Sume		pr0.ndpr_plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr,
68878064Sume					     NULL);
68978064Sume		if (pr0.ndpr_plen == 128)
69078064Sume			goto purgeaddr;
69178064Sume		pr0.ndpr_prefix = ia->ia_addr;
69278064Sume		pr0.ndpr_mask = ia->ia_prefixmask.sin6_addr;
69378064Sume		for (i = 0; i < 4; i++) {
69478064Sume			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
69578064Sume				ia->ia_prefixmask.sin6_addr.s6_addr32[i];
69678064Sume		}
69778064Sume		/*
69878064Sume		 * The logic of the following condition is a bit complicated.
69978064Sume		 * We expire the prefix when
70078064Sume		 * 1. the address obeys autoconfiguration and it is the
70178064Sume		 *    only owner of the associated prefix, or
70278064Sume		 * 2. the address does not obey autoconf and there is no
70378064Sume		 *    other owner of the prefix.
70478064Sume		 */
70578064Sume		if ((pr = nd6_prefix_lookup(&pr0)) != NULL &&
70678064Sume		    (((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
70778064Sume		      pr->ndpr_refcnt == 1) ||
70878064Sume		     ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0 &&
70978064Sume		      pr->ndpr_refcnt == 0))) {
71078064Sume			pr->ndpr_expire = 1; /* XXX: just for expiration */
71178064Sume		}
71278064Sume
71378064Sume	  purgeaddr:
71478064Sume		in6_purgeaddr(&ia->ia_ifa);
715126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
71653541Sshin		break;
71778064Sume	}
71853541Sshin
71978064Sume	default:
72078064Sume		if (ifp == NULL || ifp->if_ioctl == 0)
721120856Sume			return (EOPNOTSUPP);
722120856Sume		return ((*ifp->if_ioctl)(ifp, cmd, data));
72378064Sume	}
72453541Sshin
725120856Sume	return (0);
72678064Sume}
72753541Sshin
72878064Sume/*
72978064Sume * Update parameters of an IPv6 interface address.
73078064Sume * If necessary, a new entry is created and linked into address chains.
73178064Sume * This function is separated from in6_control().
73278064Sume * XXX: should this be performed under splnet()?
73378064Sume */
73478064Sumeint
73578064Sumein6_update_ifa(ifp, ifra, ia)
73678064Sume	struct ifnet *ifp;
73778064Sume	struct in6_aliasreq *ifra;
73878064Sume	struct in6_ifaddr *ia;
73978064Sume{
74078064Sume	int error = 0, hostIsNew = 0, plen = -1;
74178064Sume	struct in6_ifaddr *oia;
74278064Sume	struct sockaddr_in6 dst6;
74378064Sume	struct in6_addrlifetime *lt;
74478064Sume
74578064Sume	/* Validate parameters */
74678064Sume	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
747120856Sume		return (EINVAL);
74878064Sume
74978064Sume	/*
75078064Sume	 * The destination address for a p2p link must have a family
75178064Sume	 * of AF_UNSPEC or AF_INET6.
75278064Sume	 */
75378064Sume	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
75478064Sume	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
75578064Sume	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
756120856Sume		return (EAFNOSUPPORT);
75778064Sume	/*
75878064Sume	 * validate ifra_prefixmask.  don't check sin6_family, netmask
75978064Sume	 * does not carry fields other than sin6_len.
76078064Sume	 */
76178064Sume	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
762120856Sume		return (EINVAL);
76378064Sume	/*
76478064Sume	 * Because the IPv6 address architecture is classless, we require
76578064Sume	 * users to specify a (non 0) prefix length (mask) for a new address.
76678064Sume	 * We also require the prefix (when specified) mask is valid, and thus
76778064Sume	 * reject a non-consecutive mask.
76878064Sume	 */
76978064Sume	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
770120856Sume		return (EINVAL);
77178064Sume	if (ifra->ifra_prefixmask.sin6_len != 0) {
77278064Sume		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
773120891Sume		    (u_char *)&ifra->ifra_prefixmask +
774120891Sume		    ifra->ifra_prefixmask.sin6_len);
77578064Sume		if (plen <= 0)
776120856Sume			return (EINVAL);
777120891Sume	} else {
77862587Sitojun		/*
77995023Ssuz		 * In this case, ia must not be NULL.  We just use its prefix
78078064Sume		 * length.
78162587Sitojun		 */
78278064Sume		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
78378064Sume	}
78478064Sume	/*
78578064Sume	 * If the destination address on a p2p interface is specified,
78678064Sume	 * and the address is a scoped one, validate/set the scope
78778064Sume	 * zone identifier.
78878064Sume	 */
78978064Sume	dst6 = ifra->ifra_dstaddr;
790120891Sume	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
79178064Sume	    (dst6.sin6_family == AF_INET6)) {
792126552Sume		u_int32_t zoneid;
79378064Sume
79478064Sume		if ((error = in6_recoverscope(&dst6,
795120891Sume		    &ifra->ifra_dstaddr.sin6_addr, ifp)) != 0)
796120856Sume			return (error);
797126552Sume		if (in6_addr2zoneid(ifp, &dst6.sin6_addr, &zoneid))
798121315Sume			return (EINVAL);
79978064Sume		if (dst6.sin6_scope_id == 0) /* user omit to specify the ID. */
800126552Sume			dst6.sin6_scope_id = zoneid;
801126552Sume		else if (dst6.sin6_scope_id != zoneid)
802120856Sume			return (EINVAL); /* scope ID mismatch. */
80378064Sume		if ((error = in6_embedscope(&dst6.sin6_addr, &dst6, NULL, NULL))
80478064Sume		    != 0)
805120856Sume			return (error);
80678064Sume		dst6.sin6_scope_id = 0; /* XXX */
80778064Sume	}
80878064Sume	/*
80978064Sume	 * The destination address can be specified only for a p2p or a
81078064Sume	 * loopback interface.  If specified, the corresponding prefix length
81178064Sume	 * must be 128.
81278064Sume	 */
81378064Sume	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
81478064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
815126552Sume			/* XXX: noisy message */
816122059Sume			nd6log((LOG_INFO, "in6_update_ifa: a destination can "
817122059Sume			    "be specified for a p2p or a loopback IF only\n"));
818120856Sume			return (EINVAL);
81978064Sume		}
82078064Sume		if (plen != 128) {
821122059Sume			nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
822122059Sume			    "be 128 when dstaddr is specified\n"));
823120856Sume			return (EINVAL);
82478064Sume		}
82578064Sume	}
82678064Sume	/* lifetime consistency check */
82778064Sume	lt = &ifra->ifra_lifetime;
82878064Sume	if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
82978064Sume	    && lt->ia6t_vltime + time_second < time_second) {
83078064Sume		return EINVAL;
83178064Sume	}
83278064Sume	if (lt->ia6t_vltime == 0) {
83362587Sitojun		/*
83478064Sume		 * the following log might be noisy, but this is a typical
83578064Sume		 * configuration mistake or a tool's bug.
83662587Sitojun		 */
837122059Sume		nd6log((LOG_INFO,
83878064Sume		    "in6_update_ifa: valid lifetime is 0 for %s\n",
839122059Sume		    ip6_sprintf(&ifra->ifra_addr.sin6_addr)));
84078064Sume	}
84178064Sume	if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
84278064Sume	    && lt->ia6t_pltime + time_second < time_second) {
84378064Sume		return EINVAL;
84478064Sume	}
84562587Sitojun
84678064Sume	/*
84778064Sume	 * If this is a new address, allocate a new ifaddr and link it
84878064Sume	 * into chains.
84978064Sume	 */
85078064Sume	if (ia == NULL) {
85178064Sume		hostIsNew = 1;
85279763Sume		/*
85379763Sume		 * When in6_update_ifa() is called in a process of a received
854120891Sume		 * RA, it is called under an interrupt context.  So, we should
855120891Sume		 * call malloc with M_NOWAIT.
85679763Sume		 */
857120891Sume		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
858120891Sume		    M_NOWAIT);
85978064Sume		if (ia == NULL)
86078064Sume			return (ENOBUFS);
86178064Sume		bzero((caddr_t)ia, sizeof(*ia));
86278064Sume		/* Initialize the address and masks */
863108033Shsu		IFA_LOCK_INIT(&ia->ia_ifa);
86478064Sume		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
86578064Sume		ia->ia_addr.sin6_family = AF_INET6;
86678064Sume		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
86778064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
86878064Sume			/*
86978064Sume			 * XXX: some functions expect that ifa_dstaddr is not
87078064Sume			 * NULL for p2p interfaces.
87178064Sume			 */
872120891Sume			ia->ia_ifa.ifa_dstaddr =
873120891Sume			    (struct sockaddr *)&ia->ia_dstaddr;
87478064Sume		} else {
87578064Sume			ia->ia_ifa.ifa_dstaddr = NULL;
87653541Sshin		}
877108033Shsu		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
87878064Sume
87978064Sume		ia->ia_ifp = ifp;
88078064Sume		if ((oia = in6_ifaddr) != NULL) {
88178064Sume			for ( ; oia->ia_next; oia = oia->ia_next)
88278064Sume				continue;
88378064Sume			oia->ia_next = ia;
88478064Sume		} else
88578064Sume			in6_ifaddr = ia;
88678064Sume
887108033Shsu		ia->ia_ifa.ifa_refcnt = 1;
888108033Shsu		TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
88978064Sume	}
89078064Sume
89178064Sume	/* set prefix mask */
89278064Sume	if (ifra->ifra_prefixmask.sin6_len) {
89378064Sume		/*
89478064Sume		 * We prohibit changing the prefix length of an existing
89578064Sume		 * address, because
89678064Sume		 * + such an operation should be rare in IPv6, and
89778064Sume		 * + the operation would confuse prefix management.
89878064Sume		 */
89978064Sume		if (ia->ia_prefixmask.sin6_len &&
90078064Sume		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
901122059Sume			nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
90278064Sume			    " existing (%s) address should not be changed\n",
903122059Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr)));
90478064Sume			error = EINVAL;
90578064Sume			goto unlink;
90653541Sshin		}
90778064Sume		ia->ia_prefixmask = ifra->ifra_prefixmask;
90878064Sume	}
90978064Sume
91078064Sume	/*
91178064Sume	 * If a new destination address is specified, scrub the old one and
91278064Sume	 * install the new destination.  Note that the interface must be
913120891Sume	 * p2p or loopback (see the check above.)
91478064Sume	 */
91578064Sume	if (dst6.sin6_family == AF_INET6 &&
916120891Sume	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
91778064Sume		int e;
91878064Sume
91978064Sume		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
920120891Sume		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
921122059Sume			nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
92278064Sume			    "a route to the old destination: %s\n",
923122059Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr)));
92478064Sume			/* proceed anyway... */
925120891Sume		} else
92678064Sume			ia->ia_flags &= ~IFA_ROUTE;
92778064Sume		ia->ia_dstaddr = dst6;
92878064Sume	}
92953541Sshin
93078064Sume	/* reset the interface and routing table appropriately. */
93178064Sume	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
93278064Sume		goto unlink;
93378064Sume
93478064Sume	/*
93578064Sume	 * Beyond this point, we should call in6_purgeaddr upon an error,
936120891Sume	 * not just go to unlink.
93778064Sume	 */
93878064Sume
93978064Sume	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
94078064Sume		struct sockaddr_in6 mltaddr, mltmask;
94178064Sume		struct in6_multi *in6m;
94278064Sume
94378064Sume		if (hostIsNew) {
944120891Sume			/* join solicited multicast addr for new host id */
94553541Sshin			struct in6_addr llsol;
946120891Sume
94753541Sshin			bzero(&llsol, sizeof(struct in6_addr));
94853541Sshin			llsol.s6_addr16[0] = htons(0xff02);
94953541Sshin			llsol.s6_addr16[1] = htons(ifp->if_index);
95053541Sshin			llsol.s6_addr32[1] = 0;
95153541Sshin			llsol.s6_addr32[2] = htonl(1);
95253541Sshin			llsol.s6_addr32[3] =
95353541Sshin				ifra->ifra_addr.sin6_addr.s6_addr32[3];
95453541Sshin			llsol.s6_addr8[12] = 0xff;
95578064Sume			(void)in6_addmulti(&llsol, ifp, &error);
95678064Sume			if (error != 0) {
957122059Sume				nd6log((LOG_WARNING,
95878064Sume				    "in6_update_ifa: addmulti failed for "
95978064Sume				    "%s on %s (errno=%d)\n",
96078064Sume				    ip6_sprintf(&llsol), if_name(ifp),
961122059Sume				    error));
96278064Sume				in6_purgeaddr((struct ifaddr *)ia);
963120856Sume				return (error);
96478064Sume			}
96553541Sshin		}
96653541Sshin
96778064Sume		bzero(&mltmask, sizeof(mltmask));
96878064Sume		mltmask.sin6_len = sizeof(struct sockaddr_in6);
96978064Sume		mltmask.sin6_family = AF_INET6;
97078064Sume		mltmask.sin6_addr = in6mask32;
97153541Sshin
97253541Sshin		/*
97378064Sume		 * join link-local all-nodes address
97471207Sitojun		 */
97578064Sume		bzero(&mltaddr, sizeof(mltaddr));
97678064Sume		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
97778064Sume		mltaddr.sin6_family = AF_INET6;
97878064Sume		mltaddr.sin6_addr = in6addr_linklocal_allnodes;
97978064Sume		mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
98071207Sitojun
98178064Sume		IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
98278064Sume		if (in6m == NULL) {
98378064Sume			rtrequest(RTM_ADD,
98478064Sume				  (struct sockaddr *)&mltaddr,
98578064Sume				  (struct sockaddr *)&ia->ia_addr,
98678064Sume				  (struct sockaddr *)&mltmask,
98778064Sume				  RTF_UP|RTF_CLONING,  /* xxx */
98878064Sume				  (struct rtentry **)0);
98978064Sume			(void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
99078064Sume			if (error != 0) {
991122059Sume				nd6log((LOG_WARNING,
99278064Sume				    "in6_update_ifa: addmulti failed for "
99378064Sume				    "%s on %s (errno=%d)\n",
994122059Sume				    ip6_sprintf(&mltaddr.sin6_addr),
995122059Sume				    if_name(ifp), error));
99678064Sume			}
99778064Sume		}
99878064Sume
99971207Sitojun		/*
100078064Sume		 * join node information group address
100153541Sshin		 */
100278064Sume#define hostnamelen	strlen(hostname)
100378064Sume		if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr)
100478064Sume		    == 0) {
100578064Sume			IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
100678064Sume			if (in6m == NULL && ia != NULL) {
100778064Sume				(void)in6_addmulti(&mltaddr.sin6_addr,
100878064Sume				    ifp, &error);
100978064Sume				if (error != 0) {
1010122059Sume					nd6log((LOG_WARNING, "in6_update_ifa: "
101178064Sume					    "addmulti failed for "
101278064Sume					    "%s on %s (errno=%d)\n",
1013122059Sume					    ip6_sprintf(&mltaddr.sin6_addr),
1014122059Sume					    if_name(ifp), error));
101578064Sume				}
101662587Sitojun			}
101753541Sshin		}
101878064Sume#undef hostnamelen
101953541Sshin
102078064Sume		/*
102178064Sume		 * join node-local all-nodes address, on loopback.
102278064Sume		 * XXX: since "node-local" is obsoleted by interface-local,
102378064Sume		 *      we have to join the group on every interface with
102478064Sume		 *      some interface-boundary restriction.
102578064Sume		 */
102678064Sume		if (ifp->if_flags & IFF_LOOPBACK) {
102781115Sume			struct in6_ifaddr *ia_loop;
102881115Sume
102978064Sume			struct in6_addr loop6 = in6addr_loopback;
103081115Sume			ia_loop = in6ifa_ifpwithaddr(ifp, &loop6);
103153541Sshin
103278064Sume			mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
103378064Sume
103478064Sume			IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
103581115Sume			if (in6m == NULL && ia_loop != NULL) {
103678064Sume				rtrequest(RTM_ADD,
103778064Sume					  (struct sockaddr *)&mltaddr,
103881115Sume					  (struct sockaddr *)&ia_loop->ia_addr,
103978064Sume					  (struct sockaddr *)&mltmask,
104078064Sume					  RTF_UP,
104178064Sume					  (struct rtentry **)0);
104278064Sume				(void)in6_addmulti(&mltaddr.sin6_addr, ifp,
104378064Sume						   &error);
104478064Sume				if (error != 0) {
1045122059Sume					nd6log((LOG_WARNING, "in6_update_ifa: "
104678064Sume					    "addmulti failed for %s on %s "
104778064Sume					    "(errno=%d)\n",
1048122059Sume					    ip6_sprintf(&mltaddr.sin6_addr),
1049122059Sume					    if_name(ifp), error));
105078064Sume				}
105178064Sume			}
105253541Sshin		}
105378064Sume	}
105453541Sshin
105578064Sume	ia->ia6_flags = ifra->ifra_flags;
105678064Sume	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/*safety*/
105778064Sume	ia->ia6_flags &= ~IN6_IFF_NODAD;	/* Mobile IPv6 */
105853541Sshin
105978064Sume	ia->ia6_lifetime = ifra->ifra_lifetime;
106078064Sume	/* for sanity */
106178064Sume	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
106278064Sume		ia->ia6_lifetime.ia6t_expire =
106378064Sume			time_second + ia->ia6_lifetime.ia6t_vltime;
106478064Sume	} else
106578064Sume		ia->ia6_lifetime.ia6t_expire = 0;
106678064Sume	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
106778064Sume		ia->ia6_lifetime.ia6t_preferred =
106878064Sume			time_second + ia->ia6_lifetime.ia6t_pltime;
106978064Sume	} else
107078064Sume		ia->ia6_lifetime.ia6t_preferred = 0;
107153541Sshin
107278064Sume	/*
107378064Sume	 * Perform DAD, if needed.
107478064Sume	 * XXX It may be of use, if we can administratively
107578064Sume	 * disable DAD.
107678064Sume	 */
107778064Sume	if (in6if_do_dad(ifp) && (ifra->ifra_flags & IN6_IFF_NODAD) == 0) {
107878064Sume		ia->ia6_flags |= IN6_IFF_TENTATIVE;
107978064Sume		nd6_dad_start((struct ifaddr *)ia, NULL);
108053541Sshin	}
108178064Sume
1082120856Sume	return (error);
108378064Sume
108478064Sume  unlink:
108578064Sume	/*
108678064Sume	 * XXX: if a change of an existing address failed, keep the entry
108778064Sume	 * anyway.
108878064Sume	 */
108978064Sume	if (hostIsNew)
109078064Sume		in6_unlink_ifa(ia, ifp);
1091120856Sume	return (error);
109253541Sshin}
109353541Sshin
109462587Sitojunvoid
109578064Sumein6_purgeaddr(ifa)
109662587Sitojun	struct ifaddr *ifa;
109762587Sitojun{
109878064Sume	struct ifnet *ifp = ifa->ifa_ifp;
109978064Sume	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
110062587Sitojun
110178064Sume	/* stop DAD processing */
110278064Sume	nd6_dad_stop(ifa);
110362587Sitojun
110478064Sume	/*
110578064Sume	 * delete route to the destination of the address being purged.
110678064Sume	 * The interface must be p2p or loopback in this case.
110778064Sume	 */
110878064Sume	if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
110978064Sume		int e;
111078064Sume
111178064Sume		if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
111278064Sume		    != 0) {
111378064Sume			log(LOG_ERR, "in6_purgeaddr: failed to remove "
111478064Sume			    "a route to the p2p destination: %s on %s, "
111578064Sume			    "errno=%d\n",
111678064Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp),
111778064Sume			    e);
111878064Sume			/* proceed anyway... */
1119120891Sume		} else
112078064Sume			ia->ia_flags &= ~IFA_ROUTE;
112178064Sume	}
112278064Sume
112378064Sume	/* Remove ownaddr's loopback rtentry, if it exists. */
112478064Sume	in6_ifremloop(&(ia->ia_ifa));
112578064Sume
112662587Sitojun	if (ifp->if_flags & IFF_MULTICAST) {
112762587Sitojun		/*
112862587Sitojun		 * delete solicited multicast addr for deleting host id
112962587Sitojun		 */
113062587Sitojun		struct in6_multi *in6m;
113162587Sitojun		struct in6_addr llsol;
113262587Sitojun		bzero(&llsol, sizeof(struct in6_addr));
113362587Sitojun		llsol.s6_addr16[0] = htons(0xff02);
113462587Sitojun		llsol.s6_addr16[1] = htons(ifp->if_index);
113562587Sitojun		llsol.s6_addr32[1] = 0;
113662587Sitojun		llsol.s6_addr32[2] = htonl(1);
113762587Sitojun		llsol.s6_addr32[3] =
113862587Sitojun			ia->ia_addr.sin6_addr.s6_addr32[3];
113962587Sitojun		llsol.s6_addr8[12] = 0xff;
114062587Sitojun
114162587Sitojun		IN6_LOOKUP_MULTI(llsol, ifp, in6m);
114262587Sitojun		if (in6m)
114362587Sitojun			in6_delmulti(in6m);
114462587Sitojun	}
114562587Sitojun
114678064Sume	in6_unlink_ifa(ia, ifp);
114778064Sume}
114878064Sume
114978064Sumestatic void
115078064Sumein6_unlink_ifa(ia, ifp)
115178064Sume	struct in6_ifaddr *ia;
115278064Sume	struct ifnet *ifp;
115378064Sume{
115478064Sume	struct in6_ifaddr *oia;
115578064Sume	int	s = splnet();
115678064Sume
115762587Sitojun	TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
115862587Sitojun
115962587Sitojun	oia = ia;
116062587Sitojun	if (oia == (ia = in6_ifaddr))
116162587Sitojun		in6_ifaddr = ia->ia_next;
116262587Sitojun	else {
116362587Sitojun		while (ia->ia_next && (ia->ia_next != oia))
116462587Sitojun			ia = ia->ia_next;
116562587Sitojun		if (ia->ia_next)
116662587Sitojun			ia->ia_next = oia->ia_next;
116778064Sume		else {
116878064Sume			/* search failed */
116978064Sume			printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
117078064Sume		}
117162587Sitojun	}
117262587Sitojun
117362587Sitojun	/*
117478064Sume	 * When an autoconfigured address is being removed, release the
117578064Sume	 * reference to the base prefix.  Also, since the release might
117678064Sume	 * affect the status of other (detached) addresses, call
117778064Sume	 * pfxlist_onlink_check().
117862587Sitojun	 */
117978064Sume	if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
118078064Sume		if (oia->ia6_ndpr == NULL) {
1181122059Sume			nd6log((LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "
1182122059Sume			    "%p has no prefix\n", oia));
118378064Sume		} else {
118478064Sume			oia->ia6_ndpr->ndpr_refcnt--;
118578064Sume			oia->ia6_flags &= ~IN6_IFF_AUTOCONF;
118678064Sume			oia->ia6_ndpr = NULL;
118778064Sume		}
118862587Sitojun
118978064Sume		pfxlist_onlink_check();
119062587Sitojun	}
119178064Sume
119278064Sume	/*
119378064Sume	 * release another refcnt for the link from in6_ifaddr.
119478064Sume	 * Note that we should decrement the refcnt at least once for all *BSD.
119578064Sume	 */
119662587Sitojun	IFAFREE(&oia->ia_ifa);
119778064Sume
119878064Sume	splx(s);
119962587Sitojun}
120062587Sitojun
120178064Sumevoid
120278064Sumein6_purgeif(ifp)
120378064Sume	struct ifnet *ifp;
120478064Sume{
120578064Sume	struct ifaddr *ifa, *nifa;
120678064Sume
1207120891Sume	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
120878064Sume		nifa = TAILQ_NEXT(ifa, ifa_list);
120978064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
121078064Sume			continue;
121178064Sume		in6_purgeaddr(ifa);
121278064Sume	}
121378064Sume
121478064Sume	in6_ifdetach(ifp);
121578064Sume}
121678064Sume
121753541Sshin/*
121853541Sshin * SIOC[GAD]LIFADDR.
121962744Sgrog *	SIOCGLIFADDR: get first address. (?)
122053541Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
122153541Sshin *		get first address that matches the specified prefix.
122253541Sshin *	SIOCALIFADDR: add the specified address.
122353541Sshin *	SIOCALIFADDR with IFLR_PREFIX:
122453541Sshin *		add the specified prefix, filling hostid part from
122553541Sshin *		the first link-local address.  prefixlen must be <= 64.
122653541Sshin *	SIOCDLIFADDR: delete the specified address.
122753541Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
122853541Sshin *		delete the first address that matches the specified prefix.
122953541Sshin * return values:
123053541Sshin *	EINVAL on invalid parameters
123153541Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
123253541Sshin *	other values may be returned from in6_ioctl()
123353541Sshin *
123453541Sshin * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
123553541Sshin * this is to accomodate address naming scheme other than RFC2374,
123653541Sshin * in the future.
123753541Sshin * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
123853541Sshin * address encoding scheme. (see figure on page 8)
123953541Sshin */
124053541Sshinstatic int
124183366Sjulianin6_lifaddr_ioctl(so, cmd, data, ifp, td)
124253541Sshin	struct socket *so;
124353541Sshin	u_long cmd;
124453541Sshin	caddr_t	data;
124553541Sshin	struct ifnet *ifp;
124683366Sjulian	struct thread *td;
124753541Sshin{
124853541Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
124953541Sshin	struct ifaddr *ifa;
125062587Sitojun	struct sockaddr *sa;
125153541Sshin
125253541Sshin	/* sanity checks */
125353541Sshin	if (!data || !ifp) {
125453541Sshin		panic("invalid argument to in6_lifaddr_ioctl");
1255120891Sume		/* NOTREACHED */
125653541Sshin	}
125753541Sshin
125853541Sshin	switch (cmd) {
125953541Sshin	case SIOCGLIFADDR:
126053541Sshin		/* address must be specified on GET with IFLR_PREFIX */
126153541Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
126253541Sshin			break;
126395023Ssuz		/* FALLTHROUGH */
126453541Sshin	case SIOCALIFADDR:
126553541Sshin	case SIOCDLIFADDR:
126653541Sshin		/* address must be specified on ADD and DELETE */
126762587Sitojun		sa = (struct sockaddr *)&iflr->addr;
126862587Sitojun		if (sa->sa_family != AF_INET6)
126953541Sshin			return EINVAL;
127062587Sitojun		if (sa->sa_len != sizeof(struct sockaddr_in6))
127153541Sshin			return EINVAL;
127253541Sshin		/* XXX need improvement */
127362587Sitojun		sa = (struct sockaddr *)&iflr->dstaddr;
127462587Sitojun		if (sa->sa_family && sa->sa_family != AF_INET6)
127553541Sshin			return EINVAL;
127662587Sitojun		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
127753541Sshin			return EINVAL;
127853541Sshin		break;
127995023Ssuz	default: /* shouldn't happen */
128062587Sitojun#if 0
128162587Sitojun		panic("invalid cmd to in6_lifaddr_ioctl");
128295023Ssuz		/* NOTREACHED */
128362587Sitojun#else
128453541Sshin		return EOPNOTSUPP;
128562587Sitojun#endif
128653541Sshin	}
128753541Sshin	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
128853541Sshin		return EINVAL;
128953541Sshin
129053541Sshin	switch (cmd) {
129153541Sshin	case SIOCALIFADDR:
129253541Sshin	    {
129353541Sshin		struct in6_aliasreq ifra;
129453541Sshin		struct in6_addr *hostid = NULL;
129553541Sshin		int prefixlen;
129653541Sshin
129753541Sshin		if ((iflr->flags & IFLR_PREFIX) != 0) {
129853541Sshin			struct sockaddr_in6 *sin6;
129953541Sshin
130053541Sshin			/*
130153541Sshin			 * hostid is to fill in the hostid part of the
130253541Sshin			 * address.  hostid points to the first link-local
130353541Sshin			 * address attached to the interface.
130453541Sshin			 */
130562587Sitojun			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
130653541Sshin			if (!ifa)
130753541Sshin				return EADDRNOTAVAIL;
130853541Sshin			hostid = IFA_IN6(ifa);
130953541Sshin
131053541Sshin		 	/* prefixlen must be <= 64. */
131153541Sshin			if (64 < iflr->prefixlen)
131253541Sshin				return EINVAL;
131353541Sshin			prefixlen = iflr->prefixlen;
131453541Sshin
131553541Sshin			/* hostid part must be zero. */
131653541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1317126552Sume			if (sin6->sin6_addr.s6_addr32[2] != 0 ||
1318126552Sume			    sin6->sin6_addr.s6_addr32[3] != 0) {
131953541Sshin				return EINVAL;
132053541Sshin			}
132153541Sshin		} else
132253541Sshin			prefixlen = iflr->prefixlen;
132353541Sshin
132453541Sshin		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
132553541Sshin		bzero(&ifra, sizeof(ifra));
1326120891Sume		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
132753541Sshin
132862587Sitojun		bcopy(&iflr->addr, &ifra.ifra_addr,
1329120891Sume		    ((struct sockaddr *)&iflr->addr)->sa_len);
133053541Sshin		if (hostid) {
133153541Sshin			/* fill in hostid part */
133253541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1333120891Sume			    hostid->s6_addr32[2];
133453541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1335120891Sume			    hostid->s6_addr32[3];
133653541Sshin		}
133753541Sshin
1338120891Sume		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
133953541Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1340120891Sume			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
134153541Sshin			if (hostid) {
134253541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1343120891Sume				    hostid->s6_addr32[2];
134453541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1345120891Sume				    hostid->s6_addr32[3];
134653541Sshin			}
134753541Sshin		}
134853541Sshin
134953541Sshin		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1350121168Sume		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
135153541Sshin
135253541Sshin		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
135383366Sjulian		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
135453541Sshin	    }
135553541Sshin	case SIOCGLIFADDR:
135653541Sshin	case SIOCDLIFADDR:
135753541Sshin	    {
135853541Sshin		struct in6_ifaddr *ia;
135953541Sshin		struct in6_addr mask, candidate, match;
136053541Sshin		struct sockaddr_in6 *sin6;
136153541Sshin		int cmp;
136253541Sshin
136353541Sshin		bzero(&mask, sizeof(mask));
136453541Sshin		if (iflr->flags & IFLR_PREFIX) {
136553541Sshin			/* lookup a prefix rather than address. */
1366121168Sume			in6_prefixlen2mask(&mask, iflr->prefixlen);
136753541Sshin
136853541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
136953541Sshin			bcopy(&sin6->sin6_addr, &match, sizeof(match));
137053541Sshin			match.s6_addr32[0] &= mask.s6_addr32[0];
137153541Sshin			match.s6_addr32[1] &= mask.s6_addr32[1];
137253541Sshin			match.s6_addr32[2] &= mask.s6_addr32[2];
137353541Sshin			match.s6_addr32[3] &= mask.s6_addr32[3];
137453541Sshin
137553541Sshin			/* if you set extra bits, that's wrong */
137653541Sshin			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
137753541Sshin				return EINVAL;
137853541Sshin
137953541Sshin			cmp = 1;
138053541Sshin		} else {
138153541Sshin			if (cmd == SIOCGLIFADDR) {
138253541Sshin				/* on getting an address, take the 1st match */
138395023Ssuz				cmp = 0;	/* XXX */
138453541Sshin			} else {
138553541Sshin				/* on deleting an address, do exact match */
1386121168Sume				in6_prefixlen2mask(&mask, 128);
138753541Sshin				sin6 = (struct sockaddr_in6 *)&iflr->addr;
138853541Sshin				bcopy(&sin6->sin6_addr, &match, sizeof(match));
138953541Sshin
139053541Sshin				cmp = 1;
139153541Sshin			}
139253541Sshin		}
139353541Sshin
1394120891Sume		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
139553541Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
139653541Sshin				continue;
139753541Sshin			if (!cmp)
139853541Sshin				break;
139978064Sume
140053541Sshin			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
140178064Sume			/*
140278064Sume			 * XXX: this is adhoc, but is necessary to allow
140378064Sume			 * a user to specify fe80::/64 (not /10) for a
140478064Sume			 * link-local address.
140578064Sume			 */
140678064Sume			if (IN6_IS_ADDR_LINKLOCAL(&candidate))
140778064Sume				candidate.s6_addr16[1] = 0;
140853541Sshin			candidate.s6_addr32[0] &= mask.s6_addr32[0];
140953541Sshin			candidate.s6_addr32[1] &= mask.s6_addr32[1];
141053541Sshin			candidate.s6_addr32[2] &= mask.s6_addr32[2];
141153541Sshin			candidate.s6_addr32[3] &= mask.s6_addr32[3];
141253541Sshin			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
141353541Sshin				break;
141453541Sshin		}
141553541Sshin		if (!ifa)
141653541Sshin			return EADDRNOTAVAIL;
141753541Sshin		ia = ifa2ia6(ifa);
141853541Sshin
141953541Sshin		if (cmd == SIOCGLIFADDR) {
142078064Sume			struct sockaddr_in6 *s6;
142178064Sume
142253541Sshin			/* fill in the if_laddrreq structure */
142353541Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
142478064Sume			s6 = (struct sockaddr_in6 *)&iflr->addr;
142578064Sume			if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {
142678064Sume				s6->sin6_addr.s6_addr16[1] = 0;
1427121315Sume				if (in6_addr2zoneid(ifp, &s6->sin6_addr,
1428121315Sume				    &s6->sin6_scope_id))
1429126552Sume					return (EINVAL);	/* XXX */
143078064Sume			}
143153541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
143253541Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1433120891Sume				    ia->ia_dstaddr.sin6_len);
143478064Sume				s6 = (struct sockaddr_in6 *)&iflr->dstaddr;
143578064Sume				if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {
143678064Sume					s6->sin6_addr.s6_addr16[1] = 0;
1437121315Sume					if (in6_addr2zoneid(ifp,
1438121315Sume					    &s6->sin6_addr, &s6->sin6_scope_id))
1439121315Sume						return (EINVAL); /* EINVAL */
144078064Sume				}
144153541Sshin			} else
144253541Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
144353541Sshin
144453541Sshin			iflr->prefixlen =
1445120891Sume			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
144653541Sshin
144795023Ssuz			iflr->flags = ia->ia6_flags;	/* XXX */
144853541Sshin
144953541Sshin			return 0;
145053541Sshin		} else {
145153541Sshin			struct in6_aliasreq ifra;
145253541Sshin
145353541Sshin			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
145453541Sshin			bzero(&ifra, sizeof(ifra));
145553541Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
1456120891Sume			    sizeof(ifra.ifra_name));
145753541Sshin
145853541Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
1459120891Sume			    ia->ia_addr.sin6_len);
146053541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
146153541Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1462120891Sume				    ia->ia_dstaddr.sin6_len);
146362587Sitojun			} else {
146462587Sitojun				bzero(&ifra.ifra_dstaddr,
146562587Sitojun				    sizeof(ifra.ifra_dstaddr));
146653541Sshin			}
146753541Sshin			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1468120891Sume			    ia->ia_prefixmask.sin6_len);
146953541Sshin
147053541Sshin			ifra.ifra_flags = ia->ia6_flags;
147153541Sshin			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1472120891Sume			    ifp, td);
147353541Sshin		}
147453541Sshin	    }
147553541Sshin	}
147653541Sshin
147795023Ssuz	return EOPNOTSUPP;	/* just for safety */
147853541Sshin}
147953541Sshin
148053541Sshin/*
148153541Sshin * Initialize an interface's intetnet6 address
148253541Sshin * and routing table entry.
148353541Sshin */
148478064Sumestatic int
148578064Sumein6_ifinit(ifp, ia, sin6, newhost)
148653541Sshin	struct ifnet *ifp;
148753541Sshin	struct in6_ifaddr *ia;
148853541Sshin	struct sockaddr_in6 *sin6;
148978064Sume	int newhost;
149053541Sshin{
149178064Sume	int	error = 0, plen, ifacount = 0;
149253541Sshin	int	s = splimp();
149378064Sume	struct ifaddr *ifa;
149453541Sshin
149553541Sshin	/*
149653541Sshin	 * Give the interface a chance to initialize
149753541Sshin	 * if this is its first address,
149853541Sshin	 * and to validate the address if necessary.
149953541Sshin	 */
1500120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
150178064Sume		if (ifa->ifa_addr == NULL)
150278064Sume			continue;	/* just for safety */
150378064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
150478064Sume			continue;
150578064Sume		ifacount++;
150678064Sume	}
150778064Sume
150878064Sume	ia->ia_addr = *sin6;
150978064Sume
1510146883Siedowse	if (ifacount <= 1 && ifp->if_ioctl) {
1511146883Siedowse		IFF_LOCKGIANT(ifp);
1512146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
1513146883Siedowse		IFF_UNLOCKGIANT(ifp);
1514146883Siedowse		if (error) {
1515146883Siedowse			splx(s);
1516146883Siedowse			return (error);
1517146883Siedowse		}
151853541Sshin	}
151978064Sume	splx(s);
152053541Sshin
152178064Sume	ia->ia_ifa.ifa_metric = ifp->if_metric;
152253541Sshin
152378064Sume	/* we could do in(6)_socktrim here, but just omit it at this moment. */
152478064Sume
152553541Sshin	/*
152678064Sume	 * Special case:
1527124337Sume	 * If a new destination address is specified for a point-to-point
152878064Sume	 * interface, install a route to the destination as an interface
152978064Sume	 * direct route.
1530124337Sume	 * XXX: the logic below rejects assigning multiple addresses on a p2p
1531124337Sume	 * interface that share a same destination.
153253541Sshin	 */
153378064Sume	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1534124337Sume	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
1535124337Sume	    ia->ia_dstaddr.sin6_family == AF_INET6) {
153678064Sume		if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
153778064Sume				    RTF_UP | RTF_HOST)) != 0)
1538120856Sume			return (error);
153978064Sume		ia->ia_flags |= IFA_ROUTE;
154053541Sshin	}
154178064Sume	if (plen < 128) {
154278064Sume		/*
154378064Sume		 * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
154478064Sume		 */
154578064Sume		ia->ia_ifa.ifa_flags |= RTF_CLONING;
154678064Sume	}
154753541Sshin
154895023Ssuz	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
154978064Sume	if (newhost) {
155078064Sume		/* set the rtrequest function to create llinfo */
155178064Sume		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
155278064Sume		in6_ifaddloop(&(ia->ia_ifa));
155378064Sume	}
155453541Sshin
1555120856Sume	return (error);
155653541Sshin}
155753541Sshin
1558142215Sglebiusstruct in6_multi_mship *
1559142215Sglebiusin6_joingroup(ifp, addr, errorp)
1560142215Sglebius	struct ifnet *ifp;
1561142215Sglebius	struct in6_addr *addr;
1562142215Sglebius	int *errorp;
1563142215Sglebius{
1564142215Sglebius	struct in6_multi_mship *imm;
1565142215Sglebius
1566142215Sglebius	imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT);
1567142215Sglebius	if (!imm) {
1568142215Sglebius		*errorp = ENOBUFS;
1569142215Sglebius		return NULL;
1570142215Sglebius	}
1571142215Sglebius	imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp);
1572142215Sglebius	if (!imm->i6mm_maddr) {
1573142215Sglebius		/* *errorp is alrady set */
1574142215Sglebius		free(imm, M_IPMADDR);
1575142215Sglebius		return NULL;
1576142215Sglebius	}
1577142215Sglebius	return imm;
1578142215Sglebius}
1579142215Sglebius
1580142215Sglebiusint
1581142215Sglebiusin6_leavegroup(imm)
1582142215Sglebius	struct in6_multi_mship *imm;
1583142215Sglebius{
1584142215Sglebius
1585142215Sglebius	if (imm->i6mm_maddr)
1586142215Sglebius		in6_delmulti(imm->i6mm_maddr);
1587142215Sglebius	free(imm,  M_IPMADDR);
1588142215Sglebius	return 0;
1589142215Sglebius}
1590142215Sglebius
159153541Sshin/*
159253541Sshin * Find an IPv6 interface link-local address specific to an interface.
159353541Sshin */
159453541Sshinstruct in6_ifaddr *
159562587Sitojunin6ifa_ifpforlinklocal(ifp, ignoreflags)
159653541Sshin	struct ifnet *ifp;
159762587Sitojun	int ignoreflags;
159853541Sshin{
159978064Sume	struct ifaddr *ifa;
160053541Sshin
1601120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
160253541Sshin		if (ifa->ifa_addr == NULL)
160353541Sshin			continue;	/* just for safety */
160453541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
160553541Sshin			continue;
160662587Sitojun		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
160762587Sitojun			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
160862587Sitojun			     ignoreflags) != 0)
160962587Sitojun				continue;
161053541Sshin			break;
161162587Sitojun		}
161253541Sshin	}
161353541Sshin
1614120856Sume	return ((struct in6_ifaddr *)ifa);
161553541Sshin}
161653541Sshin
161753541Sshin
161853541Sshin/*
161953541Sshin * find the internet address corresponding to a given interface and address.
162053541Sshin */
162153541Sshinstruct in6_ifaddr *
162253541Sshinin6ifa_ifpwithaddr(ifp, addr)
162353541Sshin	struct ifnet *ifp;
162453541Sshin	struct in6_addr *addr;
162553541Sshin{
162678064Sume	struct ifaddr *ifa;
162753541Sshin
1628120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
162953541Sshin		if (ifa->ifa_addr == NULL)
163053541Sshin			continue;	/* just for safety */
163153541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
163253541Sshin			continue;
163353541Sshin		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
163453541Sshin			break;
163553541Sshin	}
163653541Sshin
1637120856Sume	return ((struct in6_ifaddr *)ifa);
163853541Sshin}
163953541Sshin
164053541Sshin/*
164153541Sshin * Convert IP6 address to printable (loggable) representation.
164253541Sshin */
164353541Sshinstatic char digits[] = "0123456789abcdef";
164453541Sshinstatic int ip6round = 0;
164553541Sshinchar *
164653541Sshinip6_sprintf(addr)
164778064Sume	const struct in6_addr *addr;
164853541Sshin{
164953541Sshin	static char ip6buf[8][48];
165078064Sume	int i;
165178064Sume	char *cp;
1652126552Sume	const u_int16_t *a = (const u_int16_t *)addr;
1653126552Sume	const u_int8_t *d;
165453541Sshin	int dcolon = 0;
165553541Sshin
165653541Sshin	ip6round = (ip6round + 1) & 7;
165753541Sshin	cp = ip6buf[ip6round];
165853541Sshin
165953541Sshin	for (i = 0; i < 8; i++) {
166053541Sshin		if (dcolon == 1) {
166153541Sshin			if (*a == 0) {
166253541Sshin				if (i == 7)
166353541Sshin					*cp++ = ':';
166453541Sshin				a++;
166553541Sshin				continue;
166653541Sshin			} else
166753541Sshin				dcolon = 2;
166853541Sshin		}
166953541Sshin		if (*a == 0) {
167053541Sshin			if (dcolon == 0 && *(a + 1) == 0) {
167153541Sshin				if (i == 0)
167253541Sshin					*cp++ = ':';
167353541Sshin				*cp++ = ':';
167453541Sshin				dcolon = 1;
167553541Sshin			} else {
167653541Sshin				*cp++ = '0';
167753541Sshin				*cp++ = ':';
167853541Sshin			}
167953541Sshin			a++;
168053541Sshin			continue;
168153541Sshin		}
168291346Salfred		d = (const u_char *)a;
168353541Sshin		*cp++ = digits[*d >> 4];
168453541Sshin		*cp++ = digits[*d++ & 0xf];
168553541Sshin		*cp++ = digits[*d >> 4];
168653541Sshin		*cp++ = digits[*d & 0xf];
168753541Sshin		*cp++ = ':';
168853541Sshin		a++;
168953541Sshin	}
169053541Sshin	*--cp = 0;
1691120856Sume	return (ip6buf[ip6round]);
169253541Sshin}
169353541Sshin
169453541Sshinint
169553541Sshinin6_localaddr(in6)
169653541Sshin	struct in6_addr *in6;
169753541Sshin{
169853541Sshin	struct in6_ifaddr *ia;
169953541Sshin
170053541Sshin	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
170153541Sshin		return 1;
170253541Sshin
1703120891Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
170453541Sshin		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1705120891Sume		    &ia->ia_prefixmask.sin6_addr)) {
170653541Sshin			return 1;
1707120891Sume		}
1708120891Sume	}
170953541Sshin
171053541Sshin	return (0);
171153541Sshin}
171253541Sshin
171378064Sumeint
171478064Sumein6_is_addr_deprecated(sa6)
171578064Sume	struct sockaddr_in6 *sa6;
171678064Sume{
171778064Sume	struct in6_ifaddr *ia;
171878064Sume
171978064Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
172078064Sume		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
172178064Sume				       &sa6->sin6_addr) &&
172278064Sume		    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
1723120856Sume			return (1); /* true */
172478064Sume
172578064Sume		/* XXX: do we still have to go thru the rest of the list? */
172678064Sume	}
172778064Sume
1728120856Sume	return (0);		/* false */
172978064Sume}
173078064Sume
173153541Sshin/*
173253541Sshin * return length of part which dst and src are equal
173353541Sshin * hard coding...
173453541Sshin */
173553541Sshinint
173653541Sshinin6_matchlen(src, dst)
173753541Sshinstruct in6_addr *src, *dst;
173853541Sshin{
173953541Sshin	int match = 0;
174053541Sshin	u_char *s = (u_char *)src, *d = (u_char *)dst;
174153541Sshin	u_char *lim = s + 16, r;
174253541Sshin
174353541Sshin	while (s < lim)
174453541Sshin		if ((r = (*d++ ^ *s++)) != 0) {
174553541Sshin			while (r < 128) {
174653541Sshin				match++;
174753541Sshin				r <<= 1;
174853541Sshin			}
174953541Sshin			break;
175053541Sshin		} else
175153541Sshin			match += 8;
175253541Sshin	return match;
175353541Sshin}
175453541Sshin
175562587Sitojun/* XXX: to be scope conscious */
175653541Sshinint
175753541Sshinin6_are_prefix_equal(p1, p2, len)
175853541Sshin	struct in6_addr *p1, *p2;
175953541Sshin	int len;
176053541Sshin{
176153541Sshin	int bytelen, bitlen;
176253541Sshin
176353541Sshin	/* sanity check */
176453541Sshin	if (0 > len || len > 128) {
176553541Sshin		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
176653541Sshin		    len);
1767120856Sume		return (0);
176853541Sshin	}
176953541Sshin
177053541Sshin	bytelen = len / 8;
177153541Sshin	bitlen = len % 8;
177253541Sshin
177353541Sshin	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
1774120856Sume		return (0);
1775126184Scperciva	if (bitlen != 0 &&
1776126184Scperciva	    p1->s6_addr[bytelen] >> (8 - bitlen) !=
177753541Sshin	    p2->s6_addr[bytelen] >> (8 - bitlen))
1778120856Sume		return (0);
177953541Sshin
1780120856Sume	return (1);
178153541Sshin}
178253541Sshin
178353541Sshinvoid
178453541Sshinin6_prefixlen2mask(maskp, len)
178553541Sshin	struct in6_addr *maskp;
178653541Sshin	int len;
178753541Sshin{
178853541Sshin	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
178953541Sshin	int bytelen, bitlen, i;
179053541Sshin
179153541Sshin	/* sanity check */
179253541Sshin	if (0 > len || len > 128) {
179353541Sshin		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
179453541Sshin		    len);
179553541Sshin		return;
179653541Sshin	}
179753541Sshin
179853541Sshin	bzero(maskp, sizeof(*maskp));
179953541Sshin	bytelen = len / 8;
180053541Sshin	bitlen = len % 8;
180153541Sshin	for (i = 0; i < bytelen; i++)
180253541Sshin		maskp->s6_addr[i] = 0xff;
180353541Sshin	if (bitlen)
180453541Sshin		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
180553541Sshin}
180653541Sshin
180753541Sshin/*
180853541Sshin * return the best address out of the same scope. if no address was
180953541Sshin * found, return the first valid address from designated IF.
181053541Sshin */
181153541Sshinstruct in6_ifaddr *
181253541Sshinin6_ifawithifp(ifp, dst)
181378064Sume	struct ifnet *ifp;
181478064Sume	struct in6_addr *dst;
181553541Sshin{
181653541Sshin	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
181753541Sshin	struct ifaddr *ifa;
181853541Sshin	struct in6_ifaddr *besta = 0;
181995023Ssuz	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
182053541Sshin
182153541Sshin	dep[0] = dep[1] = NULL;
182253541Sshin
182353541Sshin	/*
182453541Sshin	 * We first look for addresses in the same scope.
182553541Sshin	 * If there is one, return it.
182653541Sshin	 * If two or more, return one which matches the dst longest.
182753541Sshin	 * If none, return one of global addresses assigned other ifs.
182853541Sshin	 */
1829120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
183053541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
183153541Sshin			continue;
183253541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
183353541Sshin			continue; /* XXX: is there any case to allow anycast? */
183453541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
183553541Sshin			continue; /* don't use this interface */
183653541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
183753541Sshin			continue;
183853541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
183953541Sshin			if (ip6_use_deprecated)
184053541Sshin				dep[0] = (struct in6_ifaddr *)ifa;
184153541Sshin			continue;
184253541Sshin		}
184353541Sshin
184453541Sshin		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
184553541Sshin			/*
184653541Sshin			 * call in6_matchlen() as few as possible
184753541Sshin			 */
184853541Sshin			if (besta) {
184953541Sshin				if (blen == -1)
185053541Sshin					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
185153541Sshin				tlen = in6_matchlen(IFA_IN6(ifa), dst);
185253541Sshin				if (tlen > blen) {
185353541Sshin					blen = tlen;
185453541Sshin					besta = (struct in6_ifaddr *)ifa;
185553541Sshin				}
185653541Sshin			} else
185753541Sshin				besta = (struct in6_ifaddr *)ifa;
185853541Sshin		}
185953541Sshin	}
186053541Sshin	if (besta)
1861120856Sume		return (besta);
186253541Sshin
1863120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
186453541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
186553541Sshin			continue;
186653541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
186753541Sshin			continue; /* XXX: is there any case to allow anycast? */
186853541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
186953541Sshin			continue; /* don't use this interface */
187053541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
187153541Sshin			continue;
187253541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
187353541Sshin			if (ip6_use_deprecated)
187453541Sshin				dep[1] = (struct in6_ifaddr *)ifa;
187553541Sshin			continue;
187653541Sshin		}
187753541Sshin
187853541Sshin		return (struct in6_ifaddr *)ifa;
187953541Sshin	}
188053541Sshin
188153541Sshin	/* use the last-resort values, that are, deprecated addresses */
188253541Sshin	if (dep[0])
188353541Sshin		return dep[0];
188453541Sshin	if (dep[1])
188553541Sshin		return dep[1];
188653541Sshin
188753541Sshin	return NULL;
188853541Sshin}
188953541Sshin
189053541Sshin/*
189153541Sshin * perform DAD when interface becomes IFF_UP.
189253541Sshin */
189353541Sshinvoid
189453541Sshinin6_if_up(ifp)
189553541Sshin	struct ifnet *ifp;
189653541Sshin{
189753541Sshin	struct ifaddr *ifa;
189853541Sshin	struct in6_ifaddr *ia;
189953541Sshin	int dad_delay;		/* delay ticks before DAD output */
190053541Sshin
190162587Sitojun	/*
190262587Sitojun	 * special cases, like 6to4, are handled in in6_ifattach
190362587Sitojun	 */
190462587Sitojun	in6_ifattach(ifp, NULL);
190553541Sshin
190653541Sshin	dad_delay = 0;
1907120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
190853541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
190953541Sshin			continue;
191053541Sshin		ia = (struct in6_ifaddr *)ifa;
191153541Sshin		if (ia->ia6_flags & IN6_IFF_TENTATIVE)
191253541Sshin			nd6_dad_start(ifa, &dad_delay);
191353541Sshin	}
191453541Sshin}
191553541Sshin
191678064Sumeint
191778064Sumein6if_do_dad(ifp)
191878064Sume	struct ifnet *ifp;
191978064Sume{
192078064Sume	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
1921120856Sume		return (0);
192278064Sume
192378064Sume	switch (ifp->if_type) {
192478064Sume#ifdef IFT_DUMMY
192578064Sume	case IFT_DUMMY:
192678064Sume#endif
192778064Sume	case IFT_FAITH:
192878064Sume		/*
192978064Sume		 * These interfaces do not have the IFF_LOOPBACK flag,
193078064Sume		 * but loop packets back.  We do not have to do DAD on such
193178064Sume		 * interfaces.  We should even omit it, because loop-backed
193278064Sume		 * NS would confuse the DAD procedure.
193378064Sume		 */
1934120856Sume		return (0);
193578064Sume	default:
193678064Sume		/*
193778064Sume		 * Our DAD routine requires the interface up and running.
193878064Sume		 * However, some interfaces can be up before the RUNNING
193978064Sume		 * status.  Additionaly, users may try to assign addresses
194078064Sume		 * before the interface becomes up (or running).
194178064Sume		 * We simply skip DAD in such a case as a work around.
194278064Sume		 * XXX: we should rather mark "tentative" on such addresses,
194378064Sume		 * and do DAD after the interface becomes ready.
194478064Sume		 */
194578064Sume		if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) !=
194678064Sume		    (IFF_UP|IFF_RUNNING))
1947120856Sume			return (0);
194878064Sume
1949120856Sume		return (1);
195078064Sume	}
195178064Sume}
195278064Sume
195353541Sshin/*
195453541Sshin * Calculate max IPv6 MTU through all the interfaces and store it
195553541Sshin * to in6_maxmtu.
195653541Sshin */
195753541Sshinvoid
195853541Sshinin6_setmaxmtu()
195953541Sshin{
196053541Sshin	unsigned long maxmtu = 0;
196153541Sshin	struct ifnet *ifp;
196253541Sshin
1963108172Shsu	IFNET_RLOCK();
1964120891Sume	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
1965121283Sume		/* this function can be called during ifnet initialization */
1966121283Sume		if (!ifp->if_afdata[AF_INET6])
1967121283Sume			continue;
196853541Sshin		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
1969121283Sume		    IN6_LINKMTU(ifp) > maxmtu)
1970121283Sume			maxmtu = IN6_LINKMTU(ifp);
197153541Sshin	}
1972108172Shsu	IFNET_RUNLOCK();
1973120891Sume	if (maxmtu)	     /* update only when maxmtu is positive */
197453541Sshin		in6_maxmtu = maxmtu;
197553541Sshin}
197653541Sshin
1977121161Sumevoid *
1978121161Sumein6_domifattach(ifp)
1979121161Sume	struct ifnet *ifp;
1980121161Sume{
1981121161Sume	struct in6_ifextra *ext;
1982121161Sume
1983121161Sume	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
1984121161Sume	bzero(ext, sizeof(*ext));
1985121161Sume
1986121161Sume	ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
1987121161Sume	    M_IFADDR, M_WAITOK);
1988121161Sume	bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
1989121161Sume
1990121161Sume	ext->icmp6_ifstat =
1991121161Sume	    (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
1992121161Sume	    M_IFADDR, M_WAITOK);
1993121161Sume	bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
1994121161Sume
1995121161Sume	ext->nd_ifinfo = nd6_ifattach(ifp);
1996121161Sume	ext->scope6_id = scope6_ifattach(ifp);
1997121161Sume	return ext;
1998121161Sume}
1999121161Sume
2000121161Sumevoid
2001121161Sumein6_domifdetach(ifp, aux)
2002121161Sume	struct ifnet *ifp;
2003121161Sume	void *aux;
2004121161Sume{
2005121161Sume	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
2006121161Sume
2007121161Sume	scope6_ifdetach(ext->scope6_id);
2008121161Sume	nd6_ifdetach(ext->nd_ifinfo);
2009121161Sume	free(ext->in6_ifstat, M_IFADDR);
2010121161Sume	free(ext->icmp6_ifstat, M_IFADDR);
2011121161Sume	free(ext, M_IFADDR);
2012121161Sume}
2013121161Sume
201453541Sshin/*
201595023Ssuz * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
201653541Sshin * v4 mapped addr or v4 compat addr
201753541Sshin */
201853541Sshinvoid
201953541Sshinin6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
202053541Sshin{
202153541Sshin	bzero(sin, sizeof(*sin));
202253541Sshin	sin->sin_len = sizeof(struct sockaddr_in);
202353541Sshin	sin->sin_family = AF_INET;
202453541Sshin	sin->sin_port = sin6->sin6_port;
2025120891Sume	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
202653541Sshin}
202753541Sshin
202853541Sshin/* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
202953541Sshinvoid
203053541Sshinin6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
203153541Sshin{
203253541Sshin	bzero(sin6, sizeof(*sin6));
203353541Sshin	sin6->sin6_len = sizeof(struct sockaddr_in6);
203453541Sshin	sin6->sin6_family = AF_INET6;
203553541Sshin	sin6->sin6_port = sin->sin_port;
203653541Sshin	sin6->sin6_addr.s6_addr32[0] = 0;
203753541Sshin	sin6->sin6_addr.s6_addr32[1] = 0;
203853541Sshin	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
203953541Sshin	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
204053541Sshin}
204153541Sshin
204253541Sshin/* Convert sockaddr_in6 into sockaddr_in. */
204353541Sshinvoid
204453541Sshinin6_sin6_2_sin_in_sock(struct sockaddr *nam)
204553541Sshin{
204653541Sshin	struct sockaddr_in *sin_p;
204753541Sshin	struct sockaddr_in6 sin6;
204853541Sshin
204953541Sshin	/*
205053541Sshin	 * Save original sockaddr_in6 addr and convert it
205153541Sshin	 * to sockaddr_in.
205253541Sshin	 */
205353541Sshin	sin6 = *(struct sockaddr_in6 *)nam;
205453541Sshin	sin_p = (struct sockaddr_in *)nam;
205553541Sshin	in6_sin6_2_sin(sin_p, &sin6);
205653541Sshin}
205753541Sshin
205853541Sshin/* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
205953541Sshinvoid
206053541Sshinin6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
206153541Sshin{
206253541Sshin	struct sockaddr_in *sin_p;
206353541Sshin	struct sockaddr_in6 *sin6_p;
206453541Sshin
206553541Sshin	MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
2066111119Simp	       M_WAITOK);
206753541Sshin	sin_p = (struct sockaddr_in *)*nam;
206853541Sshin	in6_sin_2_v4mapsin6(sin_p, sin6_p);
206953541Sshin	FREE(*nam, M_SONAME);
207053541Sshin	*nam = (struct sockaddr *)sin6_p;
207153541Sshin}
2072