in6.c revision 175162
1139826Simp/*-
253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
353541Sshin * All rights reserved.
453541Sshin *
553541Sshin * Redistribution and use in source and binary forms, with or without
653541Sshin * modification, are permitted provided that the following conditions
753541Sshin * are met:
853541Sshin * 1. Redistributions of source code must retain the above copyright
953541Sshin *    notice, this list of conditions and the following disclaimer.
1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1153541Sshin *    notice, this list of conditions and the following disclaimer in the
1253541Sshin *    documentation and/or other materials provided with the distribution.
1353541Sshin * 3. Neither the name of the project nor the names of its contributors
1453541Sshin *    may be used to endorse or promote products derived from this software
1553541Sshin *    without specific prior written permission.
1653541Sshin *
1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753541Sshin * SUCH DAMAGE.
28174510Sobrien *
29174510Sobrien *	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $
3053541Sshin */
3153541Sshin
32139826Simp/*-
3353541Sshin * Copyright (c) 1982, 1986, 1991, 1993
3453541Sshin *	The Regents of the University of California.  All rights reserved.
3553541Sshin *
3653541Sshin * Redistribution and use in source and binary forms, with or without
3753541Sshin * modification, are permitted provided that the following conditions
3853541Sshin * are met:
3953541Sshin * 1. Redistributions of source code must retain the above copyright
4053541Sshin *    notice, this list of conditions and the following disclaimer.
4153541Sshin * 2. Redistributions in binary form must reproduce the above copyright
4253541Sshin *    notice, this list of conditions and the following disclaimer in the
4353541Sshin *    documentation and/or other materials provided with the distribution.
4453541Sshin * 4. Neither the name of the University nor the names of its contributors
4553541Sshin *    may be used to endorse or promote products derived from this software
4653541Sshin *    without specific prior written permission.
4753541Sshin *
4853541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4953541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5053541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5153541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5253541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5353541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5453541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5553541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5653541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5753541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5853541Sshin * SUCH DAMAGE.
5953541Sshin *
6053541Sshin *	@(#)in.c	8.2 (Berkeley) 11/15/93
6153541Sshin */
6253541Sshin
63174510Sobrien#include <sys/cdefs.h>
64174510Sobrien__FBSDID("$FreeBSD: head/sys/netinet6/in6.c 175162 2008-01-08 19:08:58Z obrien $");
65174510Sobrien
6662587Sitojun#include "opt_inet.h"
6762587Sitojun#include "opt_inet6.h"
6862587Sitojun
6953541Sshin#include <sys/param.h>
7053541Sshin#include <sys/errno.h>
7153541Sshin#include <sys/malloc.h>
7253541Sshin#include <sys/socket.h>
7353541Sshin#include <sys/socketvar.h>
7453541Sshin#include <sys/sockio.h>
7553541Sshin#include <sys/systm.h>
76164033Srwatson#include <sys/priv.h>
7753541Sshin#include <sys/proc.h>
7853541Sshin#include <sys/time.h>
7953541Sshin#include <sys/kernel.h>
8053541Sshin#include <sys/syslog.h>
8153541Sshin
8253541Sshin#include <net/if.h>
8353541Sshin#include <net/if_types.h>
8453541Sshin#include <net/route.h>
8553541Sshin#include <net/if_dl.h>
8653541Sshin
8753541Sshin#include <netinet/in.h>
8853541Sshin#include <netinet/in_var.h>
8953541Sshin#include <netinet/if_ether.h>
9078064Sume#include <netinet/in_systm.h>
9178064Sume#include <netinet/ip.h>
9278064Sume#include <netinet/in_pcb.h>
9353541Sshin
9462587Sitojun#include <netinet/ip6.h>
9553541Sshin#include <netinet6/ip6_var.h>
9695023Ssuz#include <netinet6/nd6.h>
9753541Sshin#include <netinet6/mld6_var.h>
9862587Sitojun#include <netinet6/ip6_mroute.h>
9953541Sshin#include <netinet6/in6_ifattach.h>
10062587Sitojun#include <netinet6/scope6_var.h>
10178064Sume#include <netinet6/in6_pcb.h>
10262587Sitojun
103149849SobrienMALLOC_DEFINE(M_IP6MADDR, "in6_multi", "internet multicast address");
10453541Sshin
10553541Sshin/*
10653541Sshin * Definitions of some costant IP6 addresses.
10753541Sshin */
10862587Sitojunconst struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
10962587Sitojunconst struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
11062587Sitojunconst struct in6_addr in6addr_nodelocal_allnodes =
11153541Sshin	IN6ADDR_NODELOCAL_ALLNODES_INIT;
11262587Sitojunconst struct in6_addr in6addr_linklocal_allnodes =
11353541Sshin	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
11462587Sitojunconst struct in6_addr in6addr_linklocal_allrouters =
11553541Sshin	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
11653541Sshin
11762587Sitojunconst struct in6_addr in6mask0 = IN6MASK0;
11862587Sitojunconst struct in6_addr in6mask32 = IN6MASK32;
11962587Sitojunconst struct in6_addr in6mask64 = IN6MASK64;
12062587Sitojunconst struct in6_addr in6mask96 = IN6MASK96;
12162587Sitojunconst struct in6_addr in6mask128 = IN6MASK128;
12253541Sshin
123126552Sumeconst struct sockaddr_in6 sa6_any =
124126552Sume	{ sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 };
12578064Sume
12662587Sitojunstatic int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
12783366Sjulian	struct ifnet *, struct thread *));
12878064Sumestatic int in6_ifinit __P((struct ifnet *, struct in6_ifaddr *,
129120891Sume	struct sockaddr_in6 *, int));
130175162Sobrienstatic void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
13153541Sshin
13262587Sitojunstruct in6_multihead in6_multihead;	/* XXX BSS initialization */
13383934Sbrooksint	(*faithprefix_p)(struct in6_addr *);
13483934Sbrooks
13553541Sshin/*
13653541Sshin * Subroutine for in6_ifaddloop() and in6_ifremloop().
13753541Sshin * This routine does actual work.
13853541Sshin */
13953541Sshinstatic void
14053541Sshinin6_ifloop_request(int cmd, struct ifaddr *ifa)
14153541Sshin{
14253541Sshin	struct sockaddr_in6 all1_sa;
14378064Sume	struct rtentry *nrt = NULL;
14478064Sume	int e;
145165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
146120891Sume
14753541Sshin	bzero(&all1_sa, sizeof(all1_sa));
14878064Sume	all1_sa.sin6_family = AF_INET6;
14978064Sume	all1_sa.sin6_len = sizeof(struct sockaddr_in6);
15053541Sshin	all1_sa.sin6_addr = in6mask128;
15178064Sume
15262587Sitojun	/*
15378064Sume	 * We specify the address itself as the gateway, and set the
15478064Sume	 * RTF_LLINFO flag, so that the corresponding host route would have
15578064Sume	 * the flag, and thus applications that assume traditional behavior
15678064Sume	 * would be happy.  Note that we assume the caller of the function
15778064Sume	 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
15878064Sume	 * which changes the outgoing interface to the loopback interface.
15962587Sitojun	 */
16078064Sume	e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
161120891Sume	    (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
16278064Sume	if (e != 0) {
163120891Sume		/* XXX need more descriptive message */
164165118Sbz
16578064Sume		log(LOG_ERR, "in6_ifloop_request: "
16678064Sume		    "%s operation failed for %s (errno=%d)\n",
16778064Sume		    cmd == RTM_ADD ? "ADD" : "DELETE",
168165118Sbz		    ip6_sprintf(ip6buf,
169165118Sbz			    &((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr), e);
17078064Sume	}
17153541Sshin
172151465Ssuz	/*
173151465Ssuz	 * Report the addition/removal of the address to the routing socket.
174151465Ssuz	 * XXX: since we called rtinit for a p2p interface with a destination,
175151465Ssuz	 *      we end up reporting twice in such a case.  Should we rather
176151465Ssuz	 *      omit the second report?
177151465Ssuz	 */
178120727Ssam	if (nrt) {
179120727Ssam		RT_LOCK(nrt);
180120727Ssam		/*
181120727Ssam		 * Make sure rt_ifa be equal to IFA, the second argument of
182120727Ssam		 * the function.  We need this because when we refer to
183120727Ssam		 * rt_ifa->ia6_flags in ip6_input, we assume that the rt_ifa
184120727Ssam		 * points to the address instead of the loopback address.
185120727Ssam		 */
186120727Ssam		if (cmd == RTM_ADD && ifa != nrt->rt_ifa) {
187120727Ssam			IFAFREE(nrt->rt_ifa);
188120727Ssam			IFAREF(ifa);
189120727Ssam			nrt->rt_ifa = ifa;
190120727Ssam		}
19178064Sume
19278064Sume		rt_newaddrmsg(cmd, ifa, e, nrt);
193169975Sjinmei		if (cmd == RTM_DELETE)
194169975Sjinmei			RTFREE_LOCKED(nrt);
195169975Sjinmei		else {
19678064Sume			/* the cmd must be RTM_ADD here */
197122334Ssam			RT_REMREF(nrt);
198120727Ssam			RT_UNLOCK(nrt);
19978064Sume		}
20078064Sume	}
20153541Sshin}
20253541Sshin
20353541Sshin/*
20478064Sume * Add ownaddr as loopback rtentry.  We previously add the route only if
20578064Sume * necessary (ex. on a p2p link).  However, since we now manage addresses
20678064Sume * separately from prefixes, we should always add the route.  We can't
20778064Sume * rely on the cloning mechanism from the corresponding interface route
20878064Sume * any more.
20953541Sshin */
210142215Sglebiusvoid
21153541Sshinin6_ifaddloop(struct ifaddr *ifa)
21253541Sshin{
21378064Sume	struct rtentry *rt;
214121716Ssam	int need_loop;
21553541Sshin
21678064Sume	/* If there is no loopback entry, allocate one. */
21778064Sume	rt = rtalloc1(ifa->ifa_addr, 0, 0);
218121716Ssam	need_loop = (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
219121716Ssam	    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0);
220170200Sjinmei	if (rt)
221170200Sjinmei		RTFREE_LOCKED(rt);
222121716Ssam	if (need_loop)
223121716Ssam		in6_ifloop_request(RTM_ADD, ifa);
22453541Sshin}
22553541Sshin
22653541Sshin/*
22753541Sshin * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
22853541Sshin * if it exists.
22953541Sshin */
230142215Sglebiusvoid
23153541Sshinin6_ifremloop(struct ifaddr *ifa)
23253541Sshin{
23362587Sitojun	struct in6_ifaddr *ia;
23478064Sume	struct rtentry *rt;
23562587Sitojun	int ia_count = 0;
23653541Sshin
23762587Sitojun	/*
23878064Sume	 * Some of BSD variants do not remove cloned routes
23962587Sitojun	 * from an interface direct route, when removing the direct route
24078064Sume	 * (see comments in net/net_osdep.h).  Even for variants that do remove
24178064Sume	 * cloned routes, they could fail to remove the cloned routes when
24278064Sume	 * we handle multple addresses that share a common prefix.
243151465Ssuz	 * So, we should remove the route corresponding to the deleted address.
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) {
273170200Sjinmei				RTFREE_LOCKED(rt);
274120727Ssam				in6_ifloop_request(RTM_DELETE, ifa);
275120727Ssam			} else
276120727Ssam				RT_UNLOCK(rt);
27778064Sume		}
27853541Sshin	}
27953541Sshin}
28053541Sshin
28153541Sshinint
282171259Sdelphijin6_mask2len(struct in6_addr *mask, u_char *lim0)
28353541Sshin{
28478064Sume	int x = 0, y;
28578064Sume	u_char *lim = lim0, *p;
28653541Sshin
287120891Sume	/* ignore the scope_id part */
288120891Sume	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
28978064Sume		lim = (u_char *)mask + sizeof(*mask);
29078064Sume	for (p = (u_char *)mask; p < lim; x++, p++) {
29178064Sume		if (*p != 0xff)
29253541Sshin			break;
29353541Sshin	}
29453541Sshin	y = 0;
29578064Sume	if (p < lim) {
29653541Sshin		for (y = 0; y < 8; y++) {
29778064Sume			if ((*p & (0x80 >> y)) == 0)
29853541Sshin				break;
29953541Sshin		}
30053541Sshin	}
30178064Sume
30278064Sume	/*
30378064Sume	 * when the limit pointer is given, do a stricter check on the
30478064Sume	 * remaining bits.
30578064Sume	 */
30678064Sume	if (p < lim) {
30778064Sume		if (y != 0 && (*p & (0x00ff >> y)) != 0)
308120856Sume			return (-1);
30978064Sume		for (p = p + 1; p < lim; p++)
31078064Sume			if (*p != 0)
311120856Sume				return (-1);
31278064Sume	}
313120891Sume
31453541Sshin	return x * 8 + y;
31553541Sshin}
31653541Sshin
31753541Sshin#define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
31862587Sitojun#define ia62ifa(ia6)	(&((ia6)->ia_ifa))
31953541Sshin
32053541Sshinint
321171259Sdelphijin6_control(struct socket *so, u_long cmd, caddr_t data,
322171259Sdelphij    struct ifnet *ifp, struct thread *td)
32353541Sshin{
32453541Sshin	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
32578064Sume	struct	in6_ifaddr *ia = NULL;
32653541Sshin	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
327151539Ssuz	struct sockaddr_in6 *sa6;
328164033Srwatson	int error;
32953541Sshin
33062587Sitojun	switch (cmd) {
33162587Sitojun	case SIOCGETSGCNT_IN6:
33262587Sitojun	case SIOCGETMIFCNT_IN6:
333166938Sbms		return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP);
33462587Sitojun	}
33553541Sshin
336121742Sume	switch(cmd) {
337121742Sume	case SIOCAADDRCTL_POLICY:
338121742Sume	case SIOCDADDRCTL_POLICY:
339164033Srwatson		if (td != NULL) {
340164033Srwatson			error = priv_check(td, PRIV_NETINET_ADDRCTRL6);
341164033Srwatson			if (error)
342164033Srwatson				return (error);
343164033Srwatson		}
344121742Sume		return (in6_src_ioctl(cmd, data));
345121742Sume	}
346121742Sume
34762587Sitojun	if (ifp == NULL)
348120856Sume		return (EOPNOTSUPP);
34953541Sshin
35053541Sshin	switch (cmd) {
35153541Sshin	case SIOCSNDFLUSH_IN6:
35253541Sshin	case SIOCSPFXFLUSH_IN6:
35353541Sshin	case SIOCSRTRFLUSH_IN6:
35462587Sitojun	case SIOCSDEFIFACE_IN6:
35562587Sitojun	case SIOCSIFINFO_FLAGS:
356164033Srwatson		if (td != NULL) {
357164033Srwatson			error = priv_check(td, PRIV_NETINET_ND6);
358164033Srwatson			if (error)
359164033Srwatson				return (error);
360164033Srwatson		}
361120891Sume		/* FALLTHROUGH */
36278064Sume	case OSIOCGIFINFO_IN6:
36353541Sshin	case SIOCGIFINFO_IN6:
364151468Ssuz	case SIOCSIFINFO_IN6:
36553541Sshin	case SIOCGDRLST_IN6:
36653541Sshin	case SIOCGPRLST_IN6:
36753541Sshin	case SIOCGNBRINFO_IN6:
36862587Sitojun	case SIOCGDEFIFACE_IN6:
369120856Sume		return (nd6_ioctl(cmd, data, ifp));
37053541Sshin	}
37153541Sshin
37253541Sshin	switch (cmd) {
37353541Sshin	case SIOCSIFPREFIX_IN6:
37453541Sshin	case SIOCDIFPREFIX_IN6:
37553541Sshin	case SIOCAIFPREFIX_IN6:
37653541Sshin	case SIOCCIFPREFIX_IN6:
37753541Sshin	case SIOCSGIFPREFIX_IN6:
37853541Sshin	case SIOCGIFPREFIX_IN6:
37978064Sume		log(LOG_NOTICE,
38078064Sume		    "prefix ioctls are now invalidated. "
38178064Sume		    "please use ifconfig.\n");
382120856Sume		return (EOPNOTSUPP);
38353541Sshin	}
38453541Sshin
38595023Ssuz	switch (cmd) {
38662587Sitojun	case SIOCSSCOPE6:
387164033Srwatson		if (td != NULL) {
388164033Srwatson			error = priv_check(td, PRIV_NETINET_SCOPE6);
389164033Srwatson			if (error)
390164033Srwatson				return (error);
391164033Srwatson		}
392121161Sume		return (scope6_set(ifp,
393121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
39462587Sitojun	case SIOCGSCOPE6:
395121161Sume		return (scope6_get(ifp,
396121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
39762587Sitojun	case SIOCGSCOPE6DEF:
398121161Sume		return (scope6_get_default((struct scope6_id *)
399121161Sume		    ifr->ifr_ifru.ifru_scope_id));
40062587Sitojun	}
40162587Sitojun
40253541Sshin	switch (cmd) {
40353541Sshin	case SIOCALIFADDR:
40453541Sshin	case SIOCDLIFADDR:
405164033Srwatson		/*
406164033Srwatson		 * XXXRW: Is this checked at another layer?  What priv to use
407164033Srwatson		 * here?
408164033Srwatson		 */
409164033Srwatson		if (td != NULL) {
410164033Srwatson			error = suser(td);
411164033Srwatson			if (error)
412164033Srwatson				return (error);
413164033Srwatson		}
414120891Sume		/* FALLTHROUGH */
41553541Sshin	case SIOCGLIFADDR:
41683366Sjulian		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
41753541Sshin	}
41853541Sshin
41953541Sshin	/*
42053541Sshin	 * Find address for this interface, if it exists.
421151539Ssuz	 *
422151539Ssuz	 * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
423151539Ssuz	 * only, and used the first interface address as the target of other
424151539Ssuz	 * operations (without checking ifra_addr).  This was because netinet
425151539Ssuz	 * code/API assumed at most 1 interface address per interface.
426151539Ssuz	 * Since IPv6 allows a node to assign multiple addresses
427151539Ssuz	 * on a single interface, we almost always look and check the
428151539Ssuz	 * presence of ifra_addr, and reject invalid ones here.
429151539Ssuz	 * It also decreases duplicated code among SIOC*_IN6 operations.
43053541Sshin	 */
431151539Ssuz	switch (cmd) {
432151539Ssuz	case SIOCAIFADDR_IN6:
433151539Ssuz	case SIOCSIFPHYADDR_IN6:
434151539Ssuz		sa6 = &ifra->ifra_addr;
435151539Ssuz		break;
436151539Ssuz	case SIOCSIFADDR_IN6:
437151539Ssuz	case SIOCGIFADDR_IN6:
438151539Ssuz	case SIOCSIFDSTADDR_IN6:
439151539Ssuz	case SIOCSIFNETMASK_IN6:
440151539Ssuz	case SIOCGIFDSTADDR_IN6:
441151539Ssuz	case SIOCGIFNETMASK_IN6:
442151539Ssuz	case SIOCDIFADDR_IN6:
443151539Ssuz	case SIOCGIFPSRCADDR_IN6:
444151539Ssuz	case SIOCGIFPDSTADDR_IN6:
445151539Ssuz	case SIOCGIFAFLAG_IN6:
446151539Ssuz	case SIOCSNDFLUSH_IN6:
447151539Ssuz	case SIOCSPFXFLUSH_IN6:
448151539Ssuz	case SIOCSRTRFLUSH_IN6:
449151539Ssuz	case SIOCGIFALIFETIME_IN6:
450151539Ssuz	case SIOCSIFALIFETIME_IN6:
451151539Ssuz	case SIOCGIFSTAT_IN6:
452151539Ssuz	case SIOCGIFSTAT_ICMP6:
453151539Ssuz		sa6 = &ifr->ifr_addr;
454151539Ssuz		break;
455151539Ssuz	default:
456151539Ssuz		sa6 = NULL;
457151539Ssuz		break;
458151539Ssuz	}
459151539Ssuz	if (sa6 && sa6->sin6_family == AF_INET6) {
460148385Sume		int error = 0;
46153541Sshin
462151539Ssuz		if (sa6->sin6_scope_id != 0)
463151539Ssuz			error = sa6_embedscope(sa6, 0);
464148385Sume		else
465151539Ssuz			error = in6_setscope(&sa6->sin6_addr, ifp, NULL);
466148385Sume		if (error != 0)
467148385Sume			return (error);
468151539Ssuz		ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
469151539Ssuz	} else
470151539Ssuz		ia = NULL;
47153541Sshin
47253541Sshin	switch (cmd) {
47378064Sume	case SIOCSIFADDR_IN6:
47478064Sume	case SIOCSIFDSTADDR_IN6:
47578064Sume	case SIOCSIFNETMASK_IN6:
47678064Sume		/*
47778064Sume		 * Since IPv6 allows a node to assign multiple addresses
478151465Ssuz		 * on a single interface, SIOCSIFxxx ioctls are deprecated.
47978064Sume		 */
48078064Sume		/* we decided to obsolete this command (20000704) */
481120856Sume		return (EINVAL);
48253541Sshin
48353541Sshin	case SIOCDIFADDR_IN6:
48462587Sitojun		/*
48578064Sume		 * for IPv4, we look for existing in_ifaddr here to allow
486151465Ssuz		 * "ifconfig if0 delete" to remove the first IPv4 address on
487151465Ssuz		 * the interface.  For IPv6, as the spec allows multiple
488151465Ssuz		 * interface address from the day one, we consider "remove the
489151465Ssuz		 * first one" semantics to be not preferable.
49062587Sitojun		 */
49162587Sitojun		if (ia == NULL)
492120856Sume			return (EADDRNOTAVAIL);
49353541Sshin		/* FALLTHROUGH */
49453541Sshin	case SIOCAIFADDR_IN6:
49562587Sitojun		/*
49678064Sume		 * We always require users to specify a valid IPv6 address for
49778064Sume		 * the corresponding operation.
49862587Sitojun		 */
49978064Sume		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
50078064Sume		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
501120856Sume			return (EAFNOSUPPORT);
50253541Sshin
503164033Srwatson		/*
504164033Srwatson		 * XXXRW: Is this checked at another layer?  What priv to use
505164033Srwatson		 * here?
506164033Srwatson		 */
507164033Srwatson		if (td != NULL) {
508164033Srwatson			error = suser(td);
509164033Srwatson			if (error)
510164033Srwatson				return (error);
511164033Srwatson		}
512164033Srwatson
51353541Sshin		break;
51453541Sshin
51553541Sshin	case SIOCGIFADDR_IN6:
51653541Sshin		/* This interface is basically deprecated. use SIOCGIFCONF. */
517120891Sume		/* FALLTHROUGH */
51853541Sshin	case SIOCGIFAFLAG_IN6:
51953541Sshin	case SIOCGIFNETMASK_IN6:
52053541Sshin	case SIOCGIFDSTADDR_IN6:
52153541Sshin	case SIOCGIFALIFETIME_IN6:
52253541Sshin		/* must think again about its semantics */
52362587Sitojun		if (ia == NULL)
524120856Sume			return (EADDRNOTAVAIL);
52553541Sshin		break;
52653541Sshin	case SIOCSIFALIFETIME_IN6:
52753541Sshin	    {
52853541Sshin		struct in6_addrlifetime *lt;
52953541Sshin
530164033Srwatson		if (td != NULL) {
531164033Srwatson			error = priv_check(td, PRIV_NETINET_ALIFETIME6);
532164033Srwatson			if (error)
533164033Srwatson				return (error);
534164033Srwatson		}
53562587Sitojun		if (ia == NULL)
536120856Sume			return (EADDRNOTAVAIL);
53753541Sshin		/* sanity for overflow - beware unsigned */
53853541Sshin		lt = &ifr->ifr_ifru.ifru_lifetime;
539126552Sume		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
540126552Sume		    lt->ia6t_vltime + time_second < time_second) {
54153541Sshin			return EINVAL;
54253541Sshin		}
543126552Sume		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
544126552Sume		    lt->ia6t_pltime + time_second < time_second) {
54553541Sshin			return EINVAL;
54653541Sshin		}
54753541Sshin		break;
54853541Sshin	    }
54953541Sshin	}
55053541Sshin
55153541Sshin	switch (cmd) {
55253541Sshin
55353541Sshin	case SIOCGIFADDR_IN6:
55453541Sshin		ifr->ifr_addr = ia->ia_addr;
555148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
556148385Sume			return (error);
55753541Sshin		break;
55853541Sshin
55953541Sshin	case SIOCGIFDSTADDR_IN6:
56053541Sshin		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
561120856Sume			return (EINVAL);
56262587Sitojun		/*
56362587Sitojun		 * XXX: should we check if ifa_dstaddr is NULL and return
56462587Sitojun		 * an error?
56562587Sitojun		 */
56653541Sshin		ifr->ifr_dstaddr = ia->ia_dstaddr;
567148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
568148385Sume			return (error);
56953541Sshin		break;
57053541Sshin
57153541Sshin	case SIOCGIFNETMASK_IN6:
57253541Sshin		ifr->ifr_addr = ia->ia_prefixmask;
57353541Sshin		break;
57453541Sshin
57553541Sshin	case SIOCGIFAFLAG_IN6:
57653541Sshin		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
57753541Sshin		break;
57853541Sshin
57953541Sshin	case SIOCGIFSTAT_IN6:
580121167Sume		if (ifp == NULL)
581121167Sume			return EINVAL;
582121161Sume		bzero(&ifr->ifr_ifru.ifru_stat,
583121161Sume		    sizeof(ifr->ifr_ifru.ifru_stat));
584121161Sume		ifr->ifr_ifru.ifru_stat =
585121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
58653541Sshin		break;
58753541Sshin
58853541Sshin	case SIOCGIFSTAT_ICMP6:
58953541Sshin		if (ifp == NULL)
59053541Sshin			return EINVAL;
591155454Sgnn		bzero(&ifr->ifr_ifru.ifru_icmp6stat,
592121161Sume		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
593121161Sume		ifr->ifr_ifru.ifru_icmp6stat =
594121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
59553541Sshin		break;
59653541Sshin
59753541Sshin	case SIOCGIFALIFETIME_IN6:
59853541Sshin		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
599151539Ssuz		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
600151539Ssuz			time_t maxexpire;
601151539Ssuz			struct in6_addrlifetime *retlt =
602151539Ssuz			    &ifr->ifr_ifru.ifru_lifetime;
603151539Ssuz
604151539Ssuz			/*
605151539Ssuz			 * XXX: adjust expiration time assuming time_t is
606151539Ssuz			 * signed.
607151539Ssuz			 */
608151539Ssuz			maxexpire = (-1) &
609151546Ssuz			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
610151539Ssuz			if (ia->ia6_lifetime.ia6t_vltime <
611151539Ssuz			    maxexpire - ia->ia6_updatetime) {
612151539Ssuz				retlt->ia6t_expire = ia->ia6_updatetime +
613151539Ssuz				    ia->ia6_lifetime.ia6t_vltime;
614151539Ssuz			} else
615151539Ssuz				retlt->ia6t_expire = maxexpire;
616151539Ssuz		}
617151539Ssuz		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
618151539Ssuz			time_t maxexpire;
619151539Ssuz			struct in6_addrlifetime *retlt =
620151539Ssuz			    &ifr->ifr_ifru.ifru_lifetime;
621151539Ssuz
622151539Ssuz			/*
623151539Ssuz			 * XXX: adjust expiration time assuming time_t is
624151539Ssuz			 * signed.
625151539Ssuz			 */
626151539Ssuz			maxexpire = (-1) &
627151546Ssuz			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
628151539Ssuz			if (ia->ia6_lifetime.ia6t_pltime <
629151539Ssuz			    maxexpire - ia->ia6_updatetime) {
630151539Ssuz				retlt->ia6t_preferred = ia->ia6_updatetime +
631151539Ssuz				    ia->ia6_lifetime.ia6t_pltime;
632151539Ssuz			} else
633151539Ssuz				retlt->ia6t_preferred = maxexpire;
634151539Ssuz		}
63553541Sshin		break;
63653541Sshin
63753541Sshin	case SIOCSIFALIFETIME_IN6:
63853541Sshin		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
63953541Sshin		/* for sanity */
64053541Sshin		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
64153541Sshin			ia->ia6_lifetime.ia6t_expire =
64253541Sshin				time_second + ia->ia6_lifetime.ia6t_vltime;
64353541Sshin		} else
64453541Sshin			ia->ia6_lifetime.ia6t_expire = 0;
64553541Sshin		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
64653541Sshin			ia->ia6_lifetime.ia6t_preferred =
64753541Sshin				time_second + ia->ia6_lifetime.ia6t_pltime;
64853541Sshin		} else
64953541Sshin			ia->ia6_lifetime.ia6t_preferred = 0;
65053541Sshin		break;
65153541Sshin
65278064Sume	case SIOCAIFADDR_IN6:
65378064Sume	{
65478064Sume		int i, error = 0;
655151539Ssuz		struct nd_prefixctl pr0;
656151539Ssuz		struct nd_prefix *pr;
65778064Sume
65862587Sitojun		/*
65978064Sume		 * first, make or update the interface address structure,
66078064Sume		 * and link it to the list.
66162587Sitojun		 */
662151539Ssuz		if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
663120856Sume			return (error);
664151915Ssuz		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
665151915Ssuz		    == NULL) {
666171260Sdelphij			/*
667151915Ssuz			 * this can happen when the user specify the 0 valid
668151915Ssuz			 * lifetime.
669151915Ssuz			 */
670151915Ssuz			break;
671151915Ssuz		}
67253541Sshin
67378064Sume		/*
67478064Sume		 * then, make the prefix on-link on the interface.
67578064Sume		 * XXX: we'd rather create the prefix before the address, but
67678064Sume		 * we need at least one address to install the corresponding
67778064Sume		 * interface route, so we configure the address first.
67878064Sume		 */
67978064Sume
68078064Sume		/*
68178064Sume		 * convert mask to prefix length (prefixmask has already
68278064Sume		 * been validated in in6_update_ifa().
68378064Sume		 */
68478064Sume		bzero(&pr0, sizeof(pr0));
68578064Sume		pr0.ndpr_ifp = ifp;
68678064Sume		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
687120891Sume		    NULL);
688120891Sume		if (pr0.ndpr_plen == 128) {
68978064Sume			break;	/* we don't need to install a host route. */
690120891Sume		}
69178064Sume		pr0.ndpr_prefix = ifra->ifra_addr;
69278064Sume		/* apply the mask for safety. */
69378064Sume		for (i = 0; i < 4; i++) {
69478064Sume			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
695120891Sume			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
69678064Sume		}
69778064Sume		/*
69895023Ssuz		 * XXX: since we don't have an API to set prefix (not address)
69995023Ssuz		 * lifetimes, we just use the same lifetimes as addresses.
70095023Ssuz		 * The (temporarily) installed lifetimes can be overridden by
70195023Ssuz		 * later advertised RAs (when accept_rtadv is non 0), which is
70295023Ssuz		 * an intended behavior.
70378064Sume		 */
70478064Sume		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
70578064Sume		pr0.ndpr_raf_auto =
706120891Sume		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
70778064Sume		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
70878064Sume		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
70978064Sume
710120891Sume		/* add the prefix if not yet. */
71178064Sume		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
71278064Sume			/*
71378064Sume			 * nd6_prelist_add will install the corresponding
71478064Sume			 * interface route.
71578064Sume			 */
71678064Sume			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
717120856Sume				return (error);
71878064Sume			if (pr == NULL) {
719120891Sume				log(LOG_ERR, "nd6_prelist_add succeeded but "
72078064Sume				    "no prefix\n");
721120856Sume				return (EINVAL); /* XXX panic here? */
72278064Sume			}
72378064Sume		}
72478064Sume
725151915Ssuz		/* relate the address to the prefix */
726151915Ssuz		if (ia->ia6_ndpr == NULL) {
727151915Ssuz			ia->ia6_ndpr = pr;
728151915Ssuz			pr->ndpr_refcnt++;
72978064Sume
73078064Sume			/*
731151915Ssuz			 * If this is the first autoconf address from the
732151915Ssuz			 * prefix, create a temporary address as well
733151915Ssuz			 * (when required).
73478064Sume			 */
735151915Ssuz			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) &&
736151915Ssuz			    ip6_use_tempaddr && pr->ndpr_refcnt == 1) {
737151915Ssuz				int e;
738151915Ssuz				if ((e = in6_tmpifadd(ia, 1, 0)) != 0) {
739151915Ssuz					log(LOG_NOTICE, "in6_control: failed "
740151915Ssuz					    "to create a temporary address, "
741151915Ssuz					    "errno=%d\n", e);
742151915Ssuz				}
743151915Ssuz			}
74462587Sitojun		}
745151915Ssuz
746151915Ssuz		/*
747151915Ssuz		 * this might affect the status of autoconfigured addresses,
748151915Ssuz		 * that is, this address might make other addresses detached.
749151915Ssuz		 */
750151915Ssuz		pfxlist_onlink_check();
751126264Smlaier		if (error == 0 && ia)
752126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
75378064Sume		break;
75478064Sume	}
75562587Sitojun
75678064Sume	case SIOCDIFADDR_IN6:
75778064Sume	{
758151539Ssuz		struct nd_prefix *pr;
75978064Sume
76078064Sume		/*
76178064Sume		 * If the address being deleted is the only one that owns
76278064Sume		 * the corresponding prefix, expire the prefix as well.
763120891Sume		 * XXX: theoretically, we don't have to worry about such
76478064Sume		 * relationship, since we separate the address management
76578064Sume		 * and the prefix management.  We do this, however, to provide
76678064Sume		 * as much backward compatibility as possible in terms of
76778064Sume		 * the ioctl operation.
768151915Ssuz		 * Note that in6_purgeaddr() will decrement ndpr_refcnt.
76978064Sume		 */
770151915Ssuz		pr = ia->ia6_ndpr;
77178064Sume		in6_purgeaddr(&ia->ia_ifa);
772151915Ssuz		if (pr && pr->ndpr_refcnt == 0)
773151915Ssuz			prelist_remove(pr);
774126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
77553541Sshin		break;
77678064Sume	}
77753541Sshin
77878064Sume	default:
77978064Sume		if (ifp == NULL || ifp->if_ioctl == 0)
780120856Sume			return (EOPNOTSUPP);
781120856Sume		return ((*ifp->if_ioctl)(ifp, cmd, data));
78278064Sume	}
78353541Sshin
784120856Sume	return (0);
78578064Sume}
78653541Sshin
78778064Sume/*
78878064Sume * Update parameters of an IPv6 interface address.
78978064Sume * If necessary, a new entry is created and linked into address chains.
79078064Sume * This function is separated from in6_control().
79178064Sume * XXX: should this be performed under splnet()?
79278064Sume */
79378064Sumeint
794171259Sdelphijin6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
795171259Sdelphij    struct in6_ifaddr *ia, int flags)
79678064Sume{
79778064Sume	int error = 0, hostIsNew = 0, plen = -1;
79878064Sume	struct in6_ifaddr *oia;
79978064Sume	struct sockaddr_in6 dst6;
80078064Sume	struct in6_addrlifetime *lt;
801151539Ssuz	struct in6_multi_mship *imm;
802151539Ssuz	struct in6_multi *in6m_sol;
803148385Sume	struct rtentry *rt;
804151539Ssuz	int delay;
805165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
80678064Sume
80778064Sume	/* Validate parameters */
80878064Sume	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
809120856Sume		return (EINVAL);
81078064Sume
81178064Sume	/*
81278064Sume	 * The destination address for a p2p link must have a family
81378064Sume	 * of AF_UNSPEC or AF_INET6.
81478064Sume	 */
81578064Sume	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
81678064Sume	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
81778064Sume	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
818120856Sume		return (EAFNOSUPPORT);
81978064Sume	/*
82078064Sume	 * validate ifra_prefixmask.  don't check sin6_family, netmask
82178064Sume	 * does not carry fields other than sin6_len.
82278064Sume	 */
82378064Sume	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
824120856Sume		return (EINVAL);
82578064Sume	/*
82678064Sume	 * Because the IPv6 address architecture is classless, we require
82778064Sume	 * users to specify a (non 0) prefix length (mask) for a new address.
82878064Sume	 * We also require the prefix (when specified) mask is valid, and thus
82978064Sume	 * reject a non-consecutive mask.
83078064Sume	 */
83178064Sume	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
832120856Sume		return (EINVAL);
83378064Sume	if (ifra->ifra_prefixmask.sin6_len != 0) {
83478064Sume		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
835120891Sume		    (u_char *)&ifra->ifra_prefixmask +
836120891Sume		    ifra->ifra_prefixmask.sin6_len);
83778064Sume		if (plen <= 0)
838120856Sume			return (EINVAL);
839120891Sume	} else {
84062587Sitojun		/*
84195023Ssuz		 * In this case, ia must not be NULL.  We just use its prefix
84278064Sume		 * length.
84362587Sitojun		 */
84478064Sume		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
84578064Sume	}
84678064Sume	/*
84778064Sume	 * If the destination address on a p2p interface is specified,
84878064Sume	 * and the address is a scoped one, validate/set the scope
84978064Sume	 * zone identifier.
85078064Sume	 */
85178064Sume	dst6 = ifra->ifra_dstaddr;
852120891Sume	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
85378064Sume	    (dst6.sin6_family == AF_INET6)) {
854148385Sume		struct in6_addr in6_tmp;
855126552Sume		u_int32_t zoneid;
85678064Sume
857148385Sume		in6_tmp = dst6.sin6_addr;
858148385Sume		if (in6_setscope(&in6_tmp, ifp, &zoneid))
859148385Sume			return (EINVAL); /* XXX: should be impossible */
860148385Sume
861148385Sume		if (dst6.sin6_scope_id != 0) {
862148385Sume			if (dst6.sin6_scope_id != zoneid)
863148385Sume				return (EINVAL);
864148385Sume		} else		/* user omit to specify the ID. */
865126552Sume			dst6.sin6_scope_id = zoneid;
866148385Sume
867148385Sume		/* convert into the internal form */
868148385Sume		if (sa6_embedscope(&dst6, 0))
869148385Sume			return (EINVAL); /* XXX: should be impossible */
87078064Sume	}
87178064Sume	/*
87278064Sume	 * The destination address can be specified only for a p2p or a
87378064Sume	 * loopback interface.  If specified, the corresponding prefix length
87478064Sume	 * must be 128.
87578064Sume	 */
87678064Sume	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
87778064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
878126552Sume			/* XXX: noisy message */
879122059Sume			nd6log((LOG_INFO, "in6_update_ifa: a destination can "
880122059Sume			    "be specified for a p2p or a loopback IF only\n"));
881120856Sume			return (EINVAL);
88278064Sume		}
88378064Sume		if (plen != 128) {
884122059Sume			nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
885122059Sume			    "be 128 when dstaddr is specified\n"));
886120856Sume			return (EINVAL);
88778064Sume		}
88878064Sume	}
88978064Sume	/* lifetime consistency check */
89078064Sume	lt = &ifra->ifra_lifetime;
891151539Ssuz	if (lt->ia6t_pltime > lt->ia6t_vltime)
892151539Ssuz		return (EINVAL);
89378064Sume	if (lt->ia6t_vltime == 0) {
89462587Sitojun		/*
89578064Sume		 * the following log might be noisy, but this is a typical
89678064Sume		 * configuration mistake or a tool's bug.
89762587Sitojun		 */
898122059Sume		nd6log((LOG_INFO,
89978064Sume		    "in6_update_ifa: valid lifetime is 0 for %s\n",
900165118Sbz		    ip6_sprintf(ip6buf, &ifra->ifra_addr.sin6_addr)));
901151539Ssuz
902151539Ssuz		if (ia == NULL)
903151539Ssuz			return (0); /* there's nothing to do */
90478064Sume	}
90562587Sitojun
90678064Sume	/*
90778064Sume	 * If this is a new address, allocate a new ifaddr and link it
90878064Sume	 * into chains.
90978064Sume	 */
91078064Sume	if (ia == NULL) {
91178064Sume		hostIsNew = 1;
91279763Sume		/*
91379763Sume		 * When in6_update_ifa() is called in a process of a received
914120891Sume		 * RA, it is called under an interrupt context.  So, we should
915120891Sume		 * call malloc with M_NOWAIT.
91679763Sume		 */
917120891Sume		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
918120891Sume		    M_NOWAIT);
91978064Sume		if (ia == NULL)
92078064Sume			return (ENOBUFS);
92178064Sume		bzero((caddr_t)ia, sizeof(*ia));
922170202Sjinmei		LIST_INIT(&ia->ia6_memberships);
923151539Ssuz		/* Initialize the address and masks, and put time stamp */
924108033Shsu		IFA_LOCK_INIT(&ia->ia_ifa);
92578064Sume		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
92678064Sume		ia->ia_addr.sin6_family = AF_INET6;
92778064Sume		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
928151539Ssuz		ia->ia6_createtime = time_second;
92978064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
93078064Sume			/*
93178064Sume			 * XXX: some functions expect that ifa_dstaddr is not
93278064Sume			 * NULL for p2p interfaces.
93378064Sume			 */
934120891Sume			ia->ia_ifa.ifa_dstaddr =
935120891Sume			    (struct sockaddr *)&ia->ia_dstaddr;
93678064Sume		} else {
93778064Sume			ia->ia_ifa.ifa_dstaddr = NULL;
93853541Sshin		}
939108033Shsu		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
94078064Sume
94178064Sume		ia->ia_ifp = ifp;
94278064Sume		if ((oia = in6_ifaddr) != NULL) {
94378064Sume			for ( ; oia->ia_next; oia = oia->ia_next)
94478064Sume				continue;
94578064Sume			oia->ia_next = ia;
94678064Sume		} else
94778064Sume			in6_ifaddr = ia;
94878064Sume
949108033Shsu		ia->ia_ifa.ifa_refcnt = 1;
950108033Shsu		TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
95178064Sume	}
95278064Sume
953151539Ssuz	/* update timestamp */
954151539Ssuz	ia->ia6_updatetime = time_second;
955151539Ssuz
95678064Sume	/* set prefix mask */
95778064Sume	if (ifra->ifra_prefixmask.sin6_len) {
95878064Sume		/*
95978064Sume		 * We prohibit changing the prefix length of an existing
96078064Sume		 * address, because
96178064Sume		 * + such an operation should be rare in IPv6, and
96278064Sume		 * + the operation would confuse prefix management.
96378064Sume		 */
96478064Sume		if (ia->ia_prefixmask.sin6_len &&
96578064Sume		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
966122059Sume			nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
96778064Sume			    " existing (%s) address should not be changed\n",
968165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
96978064Sume			error = EINVAL;
97078064Sume			goto unlink;
97153541Sshin		}
97278064Sume		ia->ia_prefixmask = ifra->ifra_prefixmask;
97378064Sume	}
97478064Sume
97578064Sume	/*
97678064Sume	 * If a new destination address is specified, scrub the old one and
97778064Sume	 * install the new destination.  Note that the interface must be
978120891Sume	 * p2p or loopback (see the check above.)
97978064Sume	 */
98078064Sume	if (dst6.sin6_family == AF_INET6 &&
981120891Sume	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
98278064Sume		int e;
98378064Sume
98478064Sume		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
985120891Sume		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
986122059Sume			nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
98778064Sume			    "a route to the old destination: %s\n",
988165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
98978064Sume			/* proceed anyway... */
990120891Sume		} else
99178064Sume			ia->ia_flags &= ~IFA_ROUTE;
99278064Sume		ia->ia_dstaddr = dst6;
99378064Sume	}
99453541Sshin
995148385Sume	/*
996148385Sume	 * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
997148385Sume	 * to see if the address is deprecated or invalidated, but initialize
998148385Sume	 * these members for applications.
999148385Sume	 */
1000148385Sume	ia->ia6_lifetime = ifra->ifra_lifetime;
1001148385Sume	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
1002148385Sume		ia->ia6_lifetime.ia6t_expire =
1003148385Sume		    time_second + ia->ia6_lifetime.ia6t_vltime;
1004148385Sume	} else
1005148385Sume		ia->ia6_lifetime.ia6t_expire = 0;
1006148385Sume	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
1007148385Sume		ia->ia6_lifetime.ia6t_preferred =
1008148385Sume		    time_second + ia->ia6_lifetime.ia6t_pltime;
1009148385Sume	} else
1010148385Sume		ia->ia6_lifetime.ia6t_preferred = 0;
1011148385Sume
101278064Sume	/* reset the interface and routing table appropriately. */
101378064Sume	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
101478064Sume		goto unlink;
101578064Sume
101678064Sume	/*
1017148385Sume	 * configure address flags.
1018148385Sume	 */
1019148385Sume	ia->ia6_flags = ifra->ifra_flags;
1020148385Sume	/*
1021148385Sume	 * backward compatibility - if IN6_IFF_DEPRECATED is set from the
1022148385Sume	 * userland, make it deprecated.
1023148385Sume	 */
1024148385Sume	if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
1025148385Sume		ia->ia6_lifetime.ia6t_pltime = 0;
1026148385Sume		ia->ia6_lifetime.ia6t_preferred = time_second;
1027148385Sume	}
1028148385Sume	/*
1029151539Ssuz	 * Make the address tentative before joining multicast addresses,
1030151539Ssuz	 * so that corresponding MLD responses would not have a tentative
1031151539Ssuz	 * source address.
1032148385Sume	 */
1033151539Ssuz	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/* safety */
1034151539Ssuz	if (hostIsNew && in6if_do_dad(ifp))
1035148385Sume		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1036148385Sume
1037148385Sume	/*
1038148385Sume	 * We are done if we have simply modified an existing address.
1039148385Sume	 */
1040148385Sume	if (!hostIsNew)
1041148385Sume		return (error);
1042148385Sume
1043148385Sume	/*
104478064Sume	 * Beyond this point, we should call in6_purgeaddr upon an error,
1045120891Sume	 * not just go to unlink.
104678064Sume	 */
104778064Sume
1048151465Ssuz	/* Join necessary multicast groups */
1049151539Ssuz	in6m_sol = NULL;
105078064Sume	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
105178064Sume		struct sockaddr_in6 mltaddr, mltmask;
1052148385Sume		struct in6_addr llsol;
105378064Sume
1054148385Sume		/* join solicited multicast addr for new host id */
1055148385Sume		bzero(&llsol, sizeof(struct in6_addr));
1056151465Ssuz		llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
1057148385Sume		llsol.s6_addr32[1] = 0;
1058148385Sume		llsol.s6_addr32[2] = htonl(1);
1059148385Sume		llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
1060148385Sume		llsol.s6_addr8[12] = 0xff;
1061148385Sume		if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
1062148385Sume			/* XXX: should not happen */
1063148385Sume			log(LOG_ERR, "in6_update_ifa: "
1064148385Sume			    "in6_setscope failed\n");
1065148385Sume			goto cleanup;
106653541Sshin		}
1067151539Ssuz		delay = 0;
1068151539Ssuz		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1069151539Ssuz			/*
1070151539Ssuz			 * We need a random delay for DAD on the address
1071151539Ssuz			 * being configured.  It also means delaying
1072151539Ssuz			 * transmission of the corresponding MLD report to
1073151539Ssuz			 * avoid report collision.
1074151539Ssuz			 * [draft-ietf-ipv6-rfc2462bis-02.txt]
1075151539Ssuz			 */
1076151539Ssuz			delay = arc4random() %
1077151539Ssuz			    (MAX_RTR_SOLICITATION_DELAY * hz);
1078151539Ssuz		}
1079151539Ssuz		imm = in6_joingroup(ifp, &llsol, &error, delay);
1080170202Sjinmei		if (imm == NULL) {
1081148385Sume			nd6log((LOG_WARNING,
1082148385Sume			    "in6_update_ifa: addmulti failed for "
1083148385Sume			    "%s on %s (errno=%d)\n",
1084165118Sbz			    ip6_sprintf(ip6buf, &llsol), if_name(ifp),
1085148385Sume			    error));
1086151539Ssuz			in6_purgeaddr((struct ifaddr *)ia);
1087151539Ssuz			return (error);
1088148385Sume		}
1089170202Sjinmei		LIST_INSERT_HEAD(&ia->ia6_memberships,
1090170202Sjinmei		    imm, i6mm_chain);
1091151539Ssuz		in6m_sol = imm->i6mm_maddr;
109253541Sshin
109378064Sume		bzero(&mltmask, sizeof(mltmask));
109478064Sume		mltmask.sin6_len = sizeof(struct sockaddr_in6);
109578064Sume		mltmask.sin6_family = AF_INET6;
109678064Sume		mltmask.sin6_addr = in6mask32;
1097151465Ssuz#define	MLTMASK_LEN  4	/* mltmask's masklen (=32bit=4octet) */
109853541Sshin
109953541Sshin		/*
110078064Sume		 * join link-local all-nodes address
110171207Sitojun		 */
110278064Sume		bzero(&mltaddr, sizeof(mltaddr));
110378064Sume		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
110478064Sume		mltaddr.sin6_family = AF_INET6;
110578064Sume		mltaddr.sin6_addr = in6addr_linklocal_allnodes;
1106148385Sume		if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) !=
1107148385Sume		    0)
1108148385Sume			goto cleanup; /* XXX: should not fail */
110971207Sitojun
1110148385Sume		/*
1111148385Sume		 * XXX: do we really need this automatic routes?
1112148385Sume		 * We should probably reconsider this stuff.  Most applications
1113148385Sume		 * actually do not need the routes, since they usually specify
1114148385Sume		 * the outgoing interface.
1115148385Sume		 */
1116148385Sume		rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
1117148385Sume		if (rt) {
1118174375Sjulian			/* XXX: only works in !SCOPEDROUTING case. */
1119148385Sume			if (memcmp(&mltaddr.sin6_addr,
1120148385Sume			    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1121151465Ssuz			    MLTMASK_LEN)) {
1122148385Sume				RTFREE_LOCKED(rt);
1123148385Sume				rt = NULL;
1124148385Sume			}
1125148385Sume		}
1126148385Sume		if (!rt) {
1127148385Sume			/* XXX: we need RTF_CLONING to fake nd6_rtrequest */
1128148385Sume			error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
1129148385Sume			    (struct sockaddr *)&ia->ia_addr,
1130148385Sume			    (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
1131148385Sume			    (struct rtentry **)0);
1132148385Sume			if (error)
1133148385Sume				goto cleanup;
1134151539Ssuz		} else {
1135151539Ssuz			RTFREE_LOCKED(rt);
1136151539Ssuz		}
113778064Sume
1138151539Ssuz		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
1139151539Ssuz		if (!imm) {
1140151539Ssuz			nd6log((LOG_WARNING,
1141151539Ssuz			    "in6_update_ifa: addmulti failed for "
1142151539Ssuz			    "%s on %s (errno=%d)\n",
1143165118Sbz			    ip6_sprintf(ip6buf, &mltaddr.sin6_addr),
1144151539Ssuz			    if_name(ifp), error));
1145151539Ssuz			goto cleanup;
1146151539Ssuz		}
1147170202Sjinmei		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
1148151539Ssuz
114971207Sitojun		/*
115078064Sume		 * join node information group address
115153541Sshin		 */
115278064Sume#define hostnamelen	strlen(hostname)
1153151539Ssuz		delay = 0;
1154151539Ssuz		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1155151539Ssuz			/*
1156151539Ssuz			 * The spec doesn't say anything about delay for this
1157151539Ssuz			 * group, but the same logic should apply.
1158151539Ssuz			 */
1159151539Ssuz			delay = arc4random() %
1160151539Ssuz			    (MAX_RTR_SOLICITATION_DELAY * hz);
1161151539Ssuz		}
116278064Sume		if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr)
116378064Sume		    == 0) {
1164151539Ssuz			imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error,
1165151539Ssuz			    delay); /* XXX jinmei */
1166151539Ssuz			if (!imm) {
1167151539Ssuz				nd6log((LOG_WARNING, "in6_update_ifa: "
1168151539Ssuz				    "addmulti failed for %s on %s "
1169151539Ssuz				    "(errno=%d)\n",
1170165118Sbz				    ip6_sprintf(ip6buf, &mltaddr.sin6_addr),
1171151539Ssuz				    if_name(ifp), error));
1172151539Ssuz				/* XXX not very fatal, go on... */
1173170202Sjinmei			} else {
1174170202Sjinmei				LIST_INSERT_HEAD(&ia->ia6_memberships,
1175170202Sjinmei				    imm, i6mm_chain);
117662587Sitojun			}
117753541Sshin		}
117878064Sume#undef hostnamelen
117953541Sshin
118078064Sume		/*
1181148385Sume		 * join interface-local all-nodes address.
1182148385Sume		 * (ff01::1%ifN, and ff01::%ifN/32)
118378064Sume		 */
1184148385Sume		mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
1185148385Sume		if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL))
1186148385Sume		    != 0)
1187148385Sume			goto cleanup; /* XXX: should not fail */
1188148385Sume		/* XXX: again, do we really need the route? */
1189148385Sume		rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
1190148385Sume		if (rt) {
1191148385Sume			if (memcmp(&mltaddr.sin6_addr,
1192148385Sume			    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1193151465Ssuz			    MLTMASK_LEN)) {
1194148385Sume				RTFREE_LOCKED(rt);
1195148385Sume				rt = NULL;
1196148385Sume			}
1197148385Sume		}
1198148385Sume		if (!rt) {
1199148385Sume			error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
1200148385Sume			    (struct sockaddr *)&ia->ia_addr,
1201148385Sume			    (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
1202148385Sume			    (struct rtentry **)0);
1203148385Sume			if (error)
1204148385Sume				goto cleanup;
1205148385Sume		} else
1206148385Sume			RTFREE_LOCKED(rt);
120781115Sume
1208151539Ssuz		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
1209151539Ssuz		if (!imm) {
1210151539Ssuz			nd6log((LOG_WARNING, "in6_update_ifa: "
1211151539Ssuz			    "addmulti failed for %s on %s "
1212151539Ssuz			    "(errno=%d)\n",
1213165118Sbz			    ip6_sprintf(ip6buf, &mltaddr.sin6_addr),
1214151539Ssuz			    if_name(ifp), error));
1215151539Ssuz			goto cleanup;
1216151539Ssuz		}
1217170202Sjinmei		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
1218151465Ssuz#undef	MLTMASK_LEN
121978064Sume	}
122053541Sshin
1221151539Ssuz	/*
1222151539Ssuz	 * Perform DAD, if needed.
1223151539Ssuz	 * XXX It may be of use, if we can administratively
1224151539Ssuz	 * disable DAD.
1225151539Ssuz	 */
1226151539Ssuz	if (hostIsNew && in6if_do_dad(ifp) &&
1227151539Ssuz	    ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
1228151539Ssuz	    (ia->ia6_flags & IN6_IFF_TENTATIVE))
1229151539Ssuz	{
1230151539Ssuz		int mindelay, maxdelay;
1231151539Ssuz
1232151539Ssuz		delay = 0;
1233151539Ssuz		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1234151539Ssuz			/*
1235151539Ssuz			 * We need to impose a delay before sending an NS
1236151539Ssuz			 * for DAD.  Check if we also needed a delay for the
1237151539Ssuz			 * corresponding MLD message.  If we did, the delay
1238151539Ssuz			 * should be larger than the MLD delay (this could be
1239151539Ssuz			 * relaxed a bit, but this simple logic is at least
1240151539Ssuz			 * safe).
1241151539Ssuz			 */
1242151539Ssuz			mindelay = 0;
1243151539Ssuz			if (in6m_sol != NULL &&
1244151539Ssuz			    in6m_sol->in6m_state == MLD_REPORTPENDING) {
1245151539Ssuz				mindelay = in6m_sol->in6m_timer;
1246151539Ssuz			}
1247151539Ssuz			maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
1248151539Ssuz			if (maxdelay - mindelay == 0)
1249151539Ssuz				delay = 0;
1250151539Ssuz			else {
1251151539Ssuz				delay =
1252151539Ssuz				    (arc4random() % (maxdelay - mindelay)) +
1253151539Ssuz				    mindelay;
1254151539Ssuz			}
1255151539Ssuz		}
1256151539Ssuz		nd6_dad_start((struct ifaddr *)ia, delay);
1257151539Ssuz	}
1258151539Ssuz
1259120856Sume	return (error);
126078064Sume
126178064Sume  unlink:
126278064Sume	/*
126378064Sume	 * XXX: if a change of an existing address failed, keep the entry
126478064Sume	 * anyway.
126578064Sume	 */
126678064Sume	if (hostIsNew)
126778064Sume		in6_unlink_ifa(ia, ifp);
1268120856Sume	return (error);
1269148385Sume
1270148385Sume  cleanup:
1271148385Sume	in6_purgeaddr(&ia->ia_ifa);
1272148385Sume	return error;
127353541Sshin}
127453541Sshin
127562587Sitojunvoid
1276171259Sdelphijin6_purgeaddr(struct ifaddr *ifa)
127762587Sitojun{
127878064Sume	struct ifnet *ifp = ifa->ifa_ifp;
127978064Sume	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
1280165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
1281170202Sjinmei	struct in6_multi_mship *imm;
128262587Sitojun
128378064Sume	/* stop DAD processing */
128478064Sume	nd6_dad_stop(ifa);
128562587Sitojun
128678064Sume	/*
128778064Sume	 * delete route to the destination of the address being purged.
128878064Sume	 * The interface must be p2p or loopback in this case.
128978064Sume	 */
129078064Sume	if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
129178064Sume		int e;
129278064Sume
129378064Sume		if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
129478064Sume		    != 0) {
129578064Sume			log(LOG_ERR, "in6_purgeaddr: failed to remove "
129678064Sume			    "a route to the p2p destination: %s on %s, "
129778064Sume			    "errno=%d\n",
1298165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
1299165118Sbz			    if_name(ifp), e);
130078064Sume			/* proceed anyway... */
1301120891Sume		} else
130278064Sume			ia->ia_flags &= ~IFA_ROUTE;
130378064Sume	}
130478064Sume
130578064Sume	/* Remove ownaddr's loopback rtentry, if it exists. */
130678064Sume	in6_ifremloop(&(ia->ia_ifa));
130778064Sume
1308170202Sjinmei	/*
1309170202Sjinmei	 * leave from multicast groups we have joined for the interface
1310170202Sjinmei	 */
1311170202Sjinmei	while ((imm = ia->ia6_memberships.lh_first) != NULL) {
1312170202Sjinmei		LIST_REMOVE(imm, i6mm_chain);
1313170202Sjinmei		in6_leavegroup(imm);
131462587Sitojun	}
131562587Sitojun
131678064Sume	in6_unlink_ifa(ia, ifp);
131778064Sume}
131878064Sume
131978064Sumestatic void
1320171259Sdelphijin6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
132178064Sume{
132278064Sume	struct in6_ifaddr *oia;
132378064Sume	int	s = splnet();
132478064Sume
132562587Sitojun	TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
132662587Sitojun
132762587Sitojun	oia = ia;
132862587Sitojun	if (oia == (ia = in6_ifaddr))
132962587Sitojun		in6_ifaddr = ia->ia_next;
133062587Sitojun	else {
133162587Sitojun		while (ia->ia_next && (ia->ia_next != oia))
133262587Sitojun			ia = ia->ia_next;
133362587Sitojun		if (ia->ia_next)
133462587Sitojun			ia->ia_next = oia->ia_next;
133578064Sume		else {
133678064Sume			/* search failed */
133778064Sume			printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
133878064Sume		}
133962587Sitojun	}
134062587Sitojun
134162587Sitojun	/*
1342151915Ssuz	 * Release the reference to the base prefix.  There should be a
1343151915Ssuz	 * positive reference.
134462587Sitojun	 */
1345151915Ssuz	if (oia->ia6_ndpr == NULL) {
1346151915Ssuz		nd6log((LOG_NOTICE,
1347151915Ssuz		    "in6_unlink_ifa: autoconf'ed address "
1348151915Ssuz		    "%p has no prefix\n", oia));
1349151915Ssuz	} else {
1350151915Ssuz		oia->ia6_ndpr->ndpr_refcnt--;
1351151915Ssuz		oia->ia6_ndpr = NULL;
1352151915Ssuz	}
135362587Sitojun
1354151915Ssuz	/*
1355151915Ssuz	 * Also, if the address being removed is autoconf'ed, call
1356151915Ssuz	 * pfxlist_onlink_check() since the release might affect the status of
1357171260Sdelphij	 * other (detached) addresses.
1358151915Ssuz	 */
1359151915Ssuz	if ((oia->ia6_flags & IN6_IFF_AUTOCONF)) {
136078064Sume		pfxlist_onlink_check();
136162587Sitojun	}
136278064Sume
136378064Sume	/*
136478064Sume	 * release another refcnt for the link from in6_ifaddr.
136578064Sume	 * Note that we should decrement the refcnt at least once for all *BSD.
136678064Sume	 */
136762587Sitojun	IFAFREE(&oia->ia_ifa);
136878064Sume
136978064Sume	splx(s);
137062587Sitojun}
137162587Sitojun
137278064Sumevoid
1373171259Sdelphijin6_purgeif(struct ifnet *ifp)
137478064Sume{
137578064Sume	struct ifaddr *ifa, *nifa;
137678064Sume
1377120891Sume	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
137878064Sume		nifa = TAILQ_NEXT(ifa, ifa_list);
137978064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
138078064Sume			continue;
138178064Sume		in6_purgeaddr(ifa);
138278064Sume	}
138378064Sume
138478064Sume	in6_ifdetach(ifp);
138578064Sume}
138678064Sume
138753541Sshin/*
138853541Sshin * SIOC[GAD]LIFADDR.
138962744Sgrog *	SIOCGLIFADDR: get first address. (?)
139053541Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
139153541Sshin *		get first address that matches the specified prefix.
139253541Sshin *	SIOCALIFADDR: add the specified address.
139353541Sshin *	SIOCALIFADDR with IFLR_PREFIX:
139453541Sshin *		add the specified prefix, filling hostid part from
139553541Sshin *		the first link-local address.  prefixlen must be <= 64.
139653541Sshin *	SIOCDLIFADDR: delete the specified address.
139753541Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
139853541Sshin *		delete the first address that matches the specified prefix.
139953541Sshin * return values:
140053541Sshin *	EINVAL on invalid parameters
140153541Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
140253541Sshin *	other values may be returned from in6_ioctl()
140353541Sshin *
140453541Sshin * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
140553541Sshin * this is to accomodate address naming scheme other than RFC2374,
140653541Sshin * in the future.
140753541Sshin * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
140853541Sshin * address encoding scheme. (see figure on page 8)
140953541Sshin */
141053541Sshinstatic int
1411171259Sdelphijin6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
1412171259Sdelphij    struct ifnet *ifp, struct thread *td)
141353541Sshin{
141453541Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
141553541Sshin	struct ifaddr *ifa;
141662587Sitojun	struct sockaddr *sa;
141753541Sshin
141853541Sshin	/* sanity checks */
141953541Sshin	if (!data || !ifp) {
142053541Sshin		panic("invalid argument to in6_lifaddr_ioctl");
1421120891Sume		/* NOTREACHED */
142253541Sshin	}
142353541Sshin
142453541Sshin	switch (cmd) {
142553541Sshin	case SIOCGLIFADDR:
142653541Sshin		/* address must be specified on GET with IFLR_PREFIX */
142753541Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
142853541Sshin			break;
142995023Ssuz		/* FALLTHROUGH */
143053541Sshin	case SIOCALIFADDR:
143153541Sshin	case SIOCDLIFADDR:
143253541Sshin		/* address must be specified on ADD and DELETE */
143362587Sitojun		sa = (struct sockaddr *)&iflr->addr;
143462587Sitojun		if (sa->sa_family != AF_INET6)
143553541Sshin			return EINVAL;
143662587Sitojun		if (sa->sa_len != sizeof(struct sockaddr_in6))
143753541Sshin			return EINVAL;
143853541Sshin		/* XXX need improvement */
143962587Sitojun		sa = (struct sockaddr *)&iflr->dstaddr;
144062587Sitojun		if (sa->sa_family && sa->sa_family != AF_INET6)
144153541Sshin			return EINVAL;
144262587Sitojun		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
144353541Sshin			return EINVAL;
144453541Sshin		break;
144595023Ssuz	default: /* shouldn't happen */
144662587Sitojun#if 0
144762587Sitojun		panic("invalid cmd to in6_lifaddr_ioctl");
144895023Ssuz		/* NOTREACHED */
144962587Sitojun#else
145053541Sshin		return EOPNOTSUPP;
145162587Sitojun#endif
145253541Sshin	}
145353541Sshin	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
145453541Sshin		return EINVAL;
145553541Sshin
145653541Sshin	switch (cmd) {
145753541Sshin	case SIOCALIFADDR:
145853541Sshin	    {
145953541Sshin		struct in6_aliasreq ifra;
146053541Sshin		struct in6_addr *hostid = NULL;
146153541Sshin		int prefixlen;
146253541Sshin
146353541Sshin		if ((iflr->flags & IFLR_PREFIX) != 0) {
146453541Sshin			struct sockaddr_in6 *sin6;
146553541Sshin
146653541Sshin			/*
146753541Sshin			 * hostid is to fill in the hostid part of the
146853541Sshin			 * address.  hostid points to the first link-local
146953541Sshin			 * address attached to the interface.
147053541Sshin			 */
147162587Sitojun			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
147253541Sshin			if (!ifa)
147353541Sshin				return EADDRNOTAVAIL;
147453541Sshin			hostid = IFA_IN6(ifa);
147553541Sshin
1476171260Sdelphij			/* prefixlen must be <= 64. */
147753541Sshin			if (64 < iflr->prefixlen)
147853541Sshin				return EINVAL;
147953541Sshin			prefixlen = iflr->prefixlen;
148053541Sshin
148153541Sshin			/* hostid part must be zero. */
148253541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1483126552Sume			if (sin6->sin6_addr.s6_addr32[2] != 0 ||
1484126552Sume			    sin6->sin6_addr.s6_addr32[3] != 0) {
148553541Sshin				return EINVAL;
148653541Sshin			}
148753541Sshin		} else
148853541Sshin			prefixlen = iflr->prefixlen;
148953541Sshin
149053541Sshin		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
149153541Sshin		bzero(&ifra, sizeof(ifra));
1492120891Sume		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
149353541Sshin
149462587Sitojun		bcopy(&iflr->addr, &ifra.ifra_addr,
1495120891Sume		    ((struct sockaddr *)&iflr->addr)->sa_len);
149653541Sshin		if (hostid) {
149753541Sshin			/* fill in hostid part */
149853541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1499120891Sume			    hostid->s6_addr32[2];
150053541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1501120891Sume			    hostid->s6_addr32[3];
150253541Sshin		}
150353541Sshin
1504120891Sume		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
150553541Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1506120891Sume			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
150753541Sshin			if (hostid) {
150853541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1509120891Sume				    hostid->s6_addr32[2];
151053541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1511120891Sume				    hostid->s6_addr32[3];
151253541Sshin			}
151353541Sshin		}
151453541Sshin
151553541Sshin		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1516121168Sume		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
151753541Sshin
151853541Sshin		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
151983366Sjulian		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
152053541Sshin	    }
152153541Sshin	case SIOCGLIFADDR:
152253541Sshin	case SIOCDLIFADDR:
152353541Sshin	    {
152453541Sshin		struct in6_ifaddr *ia;
152553541Sshin		struct in6_addr mask, candidate, match;
152653541Sshin		struct sockaddr_in6 *sin6;
152753541Sshin		int cmp;
152853541Sshin
152953541Sshin		bzero(&mask, sizeof(mask));
153053541Sshin		if (iflr->flags & IFLR_PREFIX) {
153153541Sshin			/* lookup a prefix rather than address. */
1532121168Sume			in6_prefixlen2mask(&mask, iflr->prefixlen);
153353541Sshin
153453541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
153553541Sshin			bcopy(&sin6->sin6_addr, &match, sizeof(match));
153653541Sshin			match.s6_addr32[0] &= mask.s6_addr32[0];
153753541Sshin			match.s6_addr32[1] &= mask.s6_addr32[1];
153853541Sshin			match.s6_addr32[2] &= mask.s6_addr32[2];
153953541Sshin			match.s6_addr32[3] &= mask.s6_addr32[3];
154053541Sshin
154153541Sshin			/* if you set extra bits, that's wrong */
154253541Sshin			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
154353541Sshin				return EINVAL;
154453541Sshin
154553541Sshin			cmp = 1;
154653541Sshin		} else {
154753541Sshin			if (cmd == SIOCGLIFADDR) {
154853541Sshin				/* on getting an address, take the 1st match */
154995023Ssuz				cmp = 0;	/* XXX */
155053541Sshin			} else {
155153541Sshin				/* on deleting an address, do exact match */
1552121168Sume				in6_prefixlen2mask(&mask, 128);
155353541Sshin				sin6 = (struct sockaddr_in6 *)&iflr->addr;
155453541Sshin				bcopy(&sin6->sin6_addr, &match, sizeof(match));
155553541Sshin
155653541Sshin				cmp = 1;
155753541Sshin			}
155853541Sshin		}
155953541Sshin
1560120891Sume		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
156153541Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
156253541Sshin				continue;
156353541Sshin			if (!cmp)
156453541Sshin				break;
156578064Sume
156678064Sume			/*
156778064Sume			 * XXX: this is adhoc, but is necessary to allow
156878064Sume			 * a user to specify fe80::/64 (not /10) for a
156978064Sume			 * link-local address.
157078064Sume			 */
1571148385Sume			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1572148385Sume			in6_clearscope(&candidate);
157353541Sshin			candidate.s6_addr32[0] &= mask.s6_addr32[0];
157453541Sshin			candidate.s6_addr32[1] &= mask.s6_addr32[1];
157553541Sshin			candidate.s6_addr32[2] &= mask.s6_addr32[2];
157653541Sshin			candidate.s6_addr32[3] &= mask.s6_addr32[3];
157753541Sshin			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
157853541Sshin				break;
157953541Sshin		}
158053541Sshin		if (!ifa)
158153541Sshin			return EADDRNOTAVAIL;
158253541Sshin		ia = ifa2ia6(ifa);
158353541Sshin
158453541Sshin		if (cmd == SIOCGLIFADDR) {
1585148385Sume			int error;
158678064Sume
158753541Sshin			/* fill in the if_laddrreq structure */
158853541Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1589148385Sume			error = sa6_recoverscope(
1590148385Sume			    (struct sockaddr_in6 *)&iflr->addr);
1591148385Sume			if (error != 0)
1592148385Sume				return (error);
1593148385Sume
159453541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
159553541Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1596120891Sume				    ia->ia_dstaddr.sin6_len);
1597148385Sume				error = sa6_recoverscope(
1598148385Sume				    (struct sockaddr_in6 *)&iflr->dstaddr);
1599148385Sume				if (error != 0)
1600148385Sume					return (error);
160153541Sshin			} else
160253541Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
160353541Sshin
160453541Sshin			iflr->prefixlen =
1605120891Sume			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
160653541Sshin
160795023Ssuz			iflr->flags = ia->ia6_flags;	/* XXX */
160853541Sshin
160953541Sshin			return 0;
161053541Sshin		} else {
161153541Sshin			struct in6_aliasreq ifra;
161253541Sshin
161353541Sshin			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
161453541Sshin			bzero(&ifra, sizeof(ifra));
161553541Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
1616120891Sume			    sizeof(ifra.ifra_name));
161753541Sshin
161853541Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
1619120891Sume			    ia->ia_addr.sin6_len);
162053541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
162153541Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1622120891Sume				    ia->ia_dstaddr.sin6_len);
162362587Sitojun			} else {
162462587Sitojun				bzero(&ifra.ifra_dstaddr,
162562587Sitojun				    sizeof(ifra.ifra_dstaddr));
162653541Sshin			}
162753541Sshin			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1628120891Sume			    ia->ia_prefixmask.sin6_len);
162953541Sshin
163053541Sshin			ifra.ifra_flags = ia->ia6_flags;
163153541Sshin			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1632120891Sume			    ifp, td);
163353541Sshin		}
163453541Sshin	    }
163553541Sshin	}
163653541Sshin
163795023Ssuz	return EOPNOTSUPP;	/* just for safety */
163853541Sshin}
163953541Sshin
164053541Sshin/*
164153541Sshin * Initialize an interface's intetnet6 address
164253541Sshin * and routing table entry.
164353541Sshin */
164478064Sumestatic int
1645171259Sdelphijin6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
1646171259Sdelphij    struct sockaddr_in6 *sin6, int newhost)
164753541Sshin{
164878064Sume	int	error = 0, plen, ifacount = 0;
164953541Sshin	int	s = splimp();
165078064Sume	struct ifaddr *ifa;
165153541Sshin
165253541Sshin	/*
165353541Sshin	 * Give the interface a chance to initialize
165453541Sshin	 * if this is its first address,
165553541Sshin	 * and to validate the address if necessary.
165653541Sshin	 */
1657120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
165878064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
165978064Sume			continue;
166078064Sume		ifacount++;
166178064Sume	}
166278064Sume
166378064Sume	ia->ia_addr = *sin6;
166478064Sume
1665146883Siedowse	if (ifacount <= 1 && ifp->if_ioctl) {
1666146883Siedowse		IFF_LOCKGIANT(ifp);
1667146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
1668146883Siedowse		IFF_UNLOCKGIANT(ifp);
1669146883Siedowse		if (error) {
1670146883Siedowse			splx(s);
1671146883Siedowse			return (error);
1672146883Siedowse		}
167353541Sshin	}
167478064Sume	splx(s);
167553541Sshin
167678064Sume	ia->ia_ifa.ifa_metric = ifp->if_metric;
167753541Sshin
167878064Sume	/* we could do in(6)_socktrim here, but just omit it at this moment. */
167978064Sume
1680162540Ssuz	if (newhost) {
1681162540Ssuz		/*
1682162540Ssuz		 * set the rtrequest function to create llinfo.  It also
1683162540Ssuz		 * adjust outgoing interface of the route for the local
1684162540Ssuz		 * address when called via in6_ifaddloop() below.
1685162540Ssuz		 */
1686159390Sgnn		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
1687159390Sgnn	}
1688159390Sgnn
168953541Sshin	/*
169078064Sume	 * Special case:
1691124337Sume	 * If a new destination address is specified for a point-to-point
169278064Sume	 * interface, install a route to the destination as an interface
1693159390Sgnn	 * direct route.  In addition, if the link is expected to have neighbor
1694159390Sgnn	 * cache entries, specify RTF_LLINFO so that a cache entry for the
1695159390Sgnn	 * destination address will be created.
1696159390Sgnn	 * created
1697124337Sume	 * XXX: the logic below rejects assigning multiple addresses on a p2p
1698159390Sgnn	 * interface that share the same destination.
169953541Sshin	 */
170078064Sume	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1701124337Sume	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
1702124337Sume	    ia->ia_dstaddr.sin6_family == AF_INET6) {
1703159390Sgnn		int rtflags = RTF_UP | RTF_HOST;
1704159390Sgnn		struct rtentry *rt = NULL, **rtp = NULL;
1705159390Sgnn
1706159390Sgnn		if (nd6_need_cache(ifp) != 0) {
1707159390Sgnn			rtflags |= RTF_LLINFO;
1708159390Sgnn			rtp = &rt;
1709159390Sgnn		}
1710159390Sgnn
1711159390Sgnn		error = rtrequest(RTM_ADD, (struct sockaddr *)&ia->ia_dstaddr,
1712159390Sgnn		    (struct sockaddr *)&ia->ia_addr,
1713159390Sgnn		    (struct sockaddr *)&ia->ia_prefixmask,
1714159390Sgnn		    ia->ia_flags | rtflags, rtp);
1715159390Sgnn		if (error != 0)
1716120856Sume			return (error);
1717159390Sgnn		if (rt != NULL) {
1718159390Sgnn			struct llinfo_nd6 *ln;
1719159390Sgnn
1720159390Sgnn			RT_LOCK(rt);
1721159390Sgnn			ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1722159390Sgnn			if (ln != NULL) {
1723159390Sgnn				/*
1724159390Sgnn				 * Set the state to STALE because we don't
1725159390Sgnn				 * have to perform address resolution on this
1726159390Sgnn				 * link.
1727159390Sgnn				 */
1728159390Sgnn				ln->ln_state = ND6_LLINFO_STALE;
1729159390Sgnn			}
1730159390Sgnn			RT_REMREF(rt);
1731159390Sgnn			RT_UNLOCK(rt);
1732159390Sgnn		}
173378064Sume		ia->ia_flags |= IFA_ROUTE;
173453541Sshin	}
173578064Sume	if (plen < 128) {
173678064Sume		/*
173778064Sume		 * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
173878064Sume		 */
173978064Sume		ia->ia_ifa.ifa_flags |= RTF_CLONING;
174078064Sume	}
174153541Sshin
174295023Ssuz	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
1743159390Sgnn	if (newhost)
174478064Sume		in6_ifaddloop(&(ia->ia_ifa));
174553541Sshin
1746120856Sume	return (error);
174753541Sshin}
174853541Sshin
1749142215Sglebiusstruct in6_multi_mship *
1750171259Sdelphijin6_joingroup(struct ifnet *ifp, struct in6_addr *addr,
1751171259Sdelphij    int *errorp, int delay)
1752142215Sglebius{
1753142215Sglebius	struct in6_multi_mship *imm;
1754142215Sglebius
1755149849Sobrien	imm = malloc(sizeof(*imm), M_IP6MADDR, M_NOWAIT);
1756142215Sglebius	if (!imm) {
1757142215Sglebius		*errorp = ENOBUFS;
1758142215Sglebius		return NULL;
1759142215Sglebius	}
1760151539Ssuz	imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp, delay);
1761142215Sglebius	if (!imm->i6mm_maddr) {
1762142215Sglebius		/* *errorp is alrady set */
1763149849Sobrien		free(imm, M_IP6MADDR);
1764142215Sglebius		return NULL;
1765142215Sglebius	}
1766142215Sglebius	return imm;
1767142215Sglebius}
1768142215Sglebius
1769142215Sglebiusint
1770171259Sdelphijin6_leavegroup(struct in6_multi_mship *imm)
1771142215Sglebius{
1772142215Sglebius
1773142215Sglebius	if (imm->i6mm_maddr)
1774142215Sglebius		in6_delmulti(imm->i6mm_maddr);
1775149849Sobrien	free(imm,  M_IP6MADDR);
1776142215Sglebius	return 0;
1777142215Sglebius}
1778142215Sglebius
177953541Sshin/*
178053541Sshin * Find an IPv6 interface link-local address specific to an interface.
178153541Sshin */
178253541Sshinstruct in6_ifaddr *
1783171259Sdelphijin6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
178453541Sshin{
178578064Sume	struct ifaddr *ifa;
178653541Sshin
1787120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
178853541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
178953541Sshin			continue;
179062587Sitojun		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
179162587Sitojun			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
179262587Sitojun			     ignoreflags) != 0)
179362587Sitojun				continue;
179453541Sshin			break;
179562587Sitojun		}
179653541Sshin	}
179753541Sshin
1798120856Sume	return ((struct in6_ifaddr *)ifa);
179953541Sshin}
180053541Sshin
180153541Sshin
180253541Sshin/*
180353541Sshin * find the internet address corresponding to a given interface and address.
180453541Sshin */
180553541Sshinstruct in6_ifaddr *
1806171259Sdelphijin6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
180753541Sshin{
180878064Sume	struct ifaddr *ifa;
180953541Sshin
1810120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
181153541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
181253541Sshin			continue;
181353541Sshin		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
181453541Sshin			break;
181553541Sshin	}
181653541Sshin
1817120856Sume	return ((struct in6_ifaddr *)ifa);
181853541Sshin}
181953541Sshin
182053541Sshin/*
1821165118Sbz * Convert IP6 address to printable (loggable) representation. Caller
1822165118Sbz * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long.
182353541Sshin */
182453541Sshinstatic char digits[] = "0123456789abcdef";
182553541Sshinchar *
1826165118Sbzip6_sprintf(char *ip6buf, const struct in6_addr *addr)
182753541Sshin{
182878064Sume	int i;
182978064Sume	char *cp;
1830126552Sume	const u_int16_t *a = (const u_int16_t *)addr;
1831126552Sume	const u_int8_t *d;
1832165287Sbz	int dcolon = 0, zero = 0;
183353541Sshin
1834165118Sbz	cp = ip6buf;
183553541Sshin
183653541Sshin	for (i = 0; i < 8; i++) {
183753541Sshin		if (dcolon == 1) {
183853541Sshin			if (*a == 0) {
183953541Sshin				if (i == 7)
184053541Sshin					*cp++ = ':';
184153541Sshin				a++;
184253541Sshin				continue;
184353541Sshin			} else
184453541Sshin				dcolon = 2;
184553541Sshin		}
184653541Sshin		if (*a == 0) {
184753541Sshin			if (dcolon == 0 && *(a + 1) == 0) {
184853541Sshin				if (i == 0)
184953541Sshin					*cp++ = ':';
185053541Sshin				*cp++ = ':';
185153541Sshin				dcolon = 1;
185253541Sshin			} else {
185353541Sshin				*cp++ = '0';
185453541Sshin				*cp++ = ':';
185553541Sshin			}
185653541Sshin			a++;
185753541Sshin			continue;
185853541Sshin		}
185991346Salfred		d = (const u_char *)a;
1860165287Sbz		/* Try to eliminate leading zeros in printout like in :0001. */
1861165287Sbz		zero = 1;
1862165287Sbz		*cp = digits[*d >> 4];
1863165287Sbz		if (*cp != '0') {
1864165287Sbz			zero = 0;
1865165287Sbz			cp++;
1866165287Sbz		}
1867165287Sbz		*cp = digits[*d++ & 0xf];
1868165287Sbz		if (zero == 0 || (*cp != '0')) {
1869165287Sbz			zero = 0;
1870165287Sbz			cp++;
1871165287Sbz		}
1872165287Sbz		*cp = digits[*d >> 4];
1873165287Sbz		if (zero == 0 || (*cp != '0')) {
1874165287Sbz			zero = 0;
1875165287Sbz			cp++;
1876165287Sbz		}
187753541Sshin		*cp++ = digits[*d & 0xf];
187853541Sshin		*cp++ = ':';
187953541Sshin		a++;
188053541Sshin	}
1881165118Sbz	*--cp = '\0';
1882165118Sbz	return (ip6buf);
188353541Sshin}
188453541Sshin
188553541Sshinint
1886171259Sdelphijin6_localaddr(struct in6_addr *in6)
188753541Sshin{
188853541Sshin	struct in6_ifaddr *ia;
188953541Sshin
189053541Sshin	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
189153541Sshin		return 1;
189253541Sshin
1893120891Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
189453541Sshin		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1895120891Sume		    &ia->ia_prefixmask.sin6_addr)) {
189653541Sshin			return 1;
1897120891Sume		}
1898120891Sume	}
189953541Sshin
190053541Sshin	return (0);
190153541Sshin}
190253541Sshin
190378064Sumeint
1904171259Sdelphijin6_is_addr_deprecated(struct sockaddr_in6 *sa6)
190578064Sume{
190678064Sume	struct in6_ifaddr *ia;
190778064Sume
190878064Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
190978064Sume		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
191078064Sume				       &sa6->sin6_addr) &&
191178064Sume		    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
1912120856Sume			return (1); /* true */
191378064Sume
191478064Sume		/* XXX: do we still have to go thru the rest of the list? */
191578064Sume	}
191678064Sume
1917120856Sume	return (0);		/* false */
191878064Sume}
191978064Sume
192053541Sshin/*
192153541Sshin * return length of part which dst and src are equal
192253541Sshin * hard coding...
192353541Sshin */
192453541Sshinint
1925171259Sdelphijin6_matchlen(struct in6_addr *src, struct in6_addr *dst)
192653541Sshin{
192753541Sshin	int match = 0;
192853541Sshin	u_char *s = (u_char *)src, *d = (u_char *)dst;
192953541Sshin	u_char *lim = s + 16, r;
193053541Sshin
193153541Sshin	while (s < lim)
193253541Sshin		if ((r = (*d++ ^ *s++)) != 0) {
193353541Sshin			while (r < 128) {
193453541Sshin				match++;
193553541Sshin				r <<= 1;
193653541Sshin			}
193753541Sshin			break;
193853541Sshin		} else
193953541Sshin			match += 8;
194053541Sshin	return match;
194153541Sshin}
194253541Sshin
194362587Sitojun/* XXX: to be scope conscious */
194453541Sshinint
1945171259Sdelphijin6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len)
194653541Sshin{
194753541Sshin	int bytelen, bitlen;
194853541Sshin
194953541Sshin	/* sanity check */
195053541Sshin	if (0 > len || len > 128) {
195153541Sshin		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
195253541Sshin		    len);
1953120856Sume		return (0);
195453541Sshin	}
195553541Sshin
195653541Sshin	bytelen = len / 8;
195753541Sshin	bitlen = len % 8;
195853541Sshin
195953541Sshin	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
1960120856Sume		return (0);
1961126184Scperciva	if (bitlen != 0 &&
1962126184Scperciva	    p1->s6_addr[bytelen] >> (8 - bitlen) !=
196353541Sshin	    p2->s6_addr[bytelen] >> (8 - bitlen))
1964120856Sume		return (0);
196553541Sshin
1966120856Sume	return (1);
196753541Sshin}
196853541Sshin
196953541Sshinvoid
1970171259Sdelphijin6_prefixlen2mask(struct in6_addr *maskp, int len)
197153541Sshin{
197253541Sshin	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
197353541Sshin	int bytelen, bitlen, i;
197453541Sshin
197553541Sshin	/* sanity check */
197653541Sshin	if (0 > len || len > 128) {
197753541Sshin		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
197853541Sshin		    len);
197953541Sshin		return;
198053541Sshin	}
198153541Sshin
198253541Sshin	bzero(maskp, sizeof(*maskp));
198353541Sshin	bytelen = len / 8;
198453541Sshin	bitlen = len % 8;
198553541Sshin	for (i = 0; i < bytelen; i++)
198653541Sshin		maskp->s6_addr[i] = 0xff;
198753541Sshin	if (bitlen)
198853541Sshin		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
198953541Sshin}
199053541Sshin
199153541Sshin/*
199253541Sshin * return the best address out of the same scope. if no address was
199353541Sshin * found, return the first valid address from designated IF.
199453541Sshin */
199553541Sshinstruct in6_ifaddr *
1996171259Sdelphijin6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
199753541Sshin{
199853541Sshin	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
199953541Sshin	struct ifaddr *ifa;
200053541Sshin	struct in6_ifaddr *besta = 0;
200195023Ssuz	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
200253541Sshin
200353541Sshin	dep[0] = dep[1] = NULL;
200453541Sshin
200553541Sshin	/*
200653541Sshin	 * We first look for addresses in the same scope.
200753541Sshin	 * If there is one, return it.
200853541Sshin	 * If two or more, return one which matches the dst longest.
200953541Sshin	 * If none, return one of global addresses assigned other ifs.
201053541Sshin	 */
2011120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
201253541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
201353541Sshin			continue;
201453541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
201553541Sshin			continue; /* XXX: is there any case to allow anycast? */
201653541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
201753541Sshin			continue; /* don't use this interface */
201853541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
201953541Sshin			continue;
202053541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
202153541Sshin			if (ip6_use_deprecated)
202253541Sshin				dep[0] = (struct in6_ifaddr *)ifa;
202353541Sshin			continue;
202453541Sshin		}
202553541Sshin
202653541Sshin		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
202753541Sshin			/*
202853541Sshin			 * call in6_matchlen() as few as possible
202953541Sshin			 */
203053541Sshin			if (besta) {
203153541Sshin				if (blen == -1)
203253541Sshin					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
203353541Sshin				tlen = in6_matchlen(IFA_IN6(ifa), dst);
203453541Sshin				if (tlen > blen) {
203553541Sshin					blen = tlen;
203653541Sshin					besta = (struct in6_ifaddr *)ifa;
203753541Sshin				}
203853541Sshin			} else
203953541Sshin				besta = (struct in6_ifaddr *)ifa;
204053541Sshin		}
204153541Sshin	}
204253541Sshin	if (besta)
2043120856Sume		return (besta);
204453541Sshin
2045120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
204653541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
204753541Sshin			continue;
204853541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
204953541Sshin			continue; /* XXX: is there any case to allow anycast? */
205053541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
205153541Sshin			continue; /* don't use this interface */
205253541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
205353541Sshin			continue;
205453541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
205553541Sshin			if (ip6_use_deprecated)
205653541Sshin				dep[1] = (struct in6_ifaddr *)ifa;
205753541Sshin			continue;
205853541Sshin		}
205953541Sshin
206053541Sshin		return (struct in6_ifaddr *)ifa;
206153541Sshin	}
206253541Sshin
206353541Sshin	/* use the last-resort values, that are, deprecated addresses */
206453541Sshin	if (dep[0])
206553541Sshin		return dep[0];
206653541Sshin	if (dep[1])
206753541Sshin		return dep[1];
206853541Sshin
206953541Sshin	return NULL;
207053541Sshin}
207153541Sshin
207253541Sshin/*
207353541Sshin * perform DAD when interface becomes IFF_UP.
207453541Sshin */
207553541Sshinvoid
2076171259Sdelphijin6_if_up(struct ifnet *ifp)
207753541Sshin{
207853541Sshin	struct ifaddr *ifa;
207953541Sshin	struct in6_ifaddr *ia;
208053541Sshin
2081120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
208253541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
208353541Sshin			continue;
208453541Sshin		ia = (struct in6_ifaddr *)ifa;
2085151539Ssuz		if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
2086151539Ssuz			/*
2087151539Ssuz			 * The TENTATIVE flag was likely set by hand
2088151539Ssuz			 * beforehand, implicitly indicating the need for DAD.
2089151539Ssuz			 * We may be able to skip the random delay in this
2090151539Ssuz			 * case, but we impose delays just in case.
2091151539Ssuz			 */
2092151539Ssuz			nd6_dad_start(ifa,
2093151539Ssuz			    arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
2094151539Ssuz		}
209553541Sshin	}
2096151539Ssuz
2097151539Ssuz	/*
2098151539Ssuz	 * special cases, like 6to4, are handled in in6_ifattach
2099151539Ssuz	 */
2100151539Ssuz	in6_ifattach(ifp, NULL);
210153541Sshin}
210253541Sshin
210378064Sumeint
2104171259Sdelphijin6if_do_dad(struct ifnet *ifp)
210578064Sume{
210678064Sume	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
2107120856Sume		return (0);
210878064Sume
210978064Sume	switch (ifp->if_type) {
211078064Sume#ifdef IFT_DUMMY
211178064Sume	case IFT_DUMMY:
211278064Sume#endif
211378064Sume	case IFT_FAITH:
211478064Sume		/*
211578064Sume		 * These interfaces do not have the IFF_LOOPBACK flag,
211678064Sume		 * but loop packets back.  We do not have to do DAD on such
211778064Sume		 * interfaces.  We should even omit it, because loop-backed
211878064Sume		 * NS would confuse the DAD procedure.
211978064Sume		 */
2120120856Sume		return (0);
212178064Sume	default:
212278064Sume		/*
212378064Sume		 * Our DAD routine requires the interface up and running.
212478064Sume		 * However, some interfaces can be up before the RUNNING
212578064Sume		 * status.  Additionaly, users may try to assign addresses
212678064Sume		 * before the interface becomes up (or running).
212778064Sume		 * We simply skip DAD in such a case as a work around.
212878064Sume		 * XXX: we should rather mark "tentative" on such addresses,
212978064Sume		 * and do DAD after the interface becomes ready.
213078064Sume		 */
2131148887Srwatson		if (!((ifp->if_flags & IFF_UP) &&
2132148887Srwatson		    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
2133120856Sume			return (0);
213478064Sume
2135120856Sume		return (1);
213678064Sume	}
213778064Sume}
213878064Sume
213953541Sshin/*
214053541Sshin * Calculate max IPv6 MTU through all the interfaces and store it
214153541Sshin * to in6_maxmtu.
214253541Sshin */
214353541Sshinvoid
2144171259Sdelphijin6_setmaxmtu(void)
214553541Sshin{
214653541Sshin	unsigned long maxmtu = 0;
214753541Sshin	struct ifnet *ifp;
214853541Sshin
2149108172Shsu	IFNET_RLOCK();
2150120891Sume	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
2151121283Sume		/* this function can be called during ifnet initialization */
2152121283Sume		if (!ifp->if_afdata[AF_INET6])
2153121283Sume			continue;
215453541Sshin		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2155121283Sume		    IN6_LINKMTU(ifp) > maxmtu)
2156121283Sume			maxmtu = IN6_LINKMTU(ifp);
215753541Sshin	}
2158108172Shsu	IFNET_RUNLOCK();
2159120891Sume	if (maxmtu)	     /* update only when maxmtu is positive */
216053541Sshin		in6_maxmtu = maxmtu;
216153541Sshin}
216253541Sshin
2163151539Ssuz/*
2164151539Ssuz * Provide the length of interface identifiers to be used for the link attached
2165151539Ssuz * to the given interface.  The length should be defined in "IPv6 over
2166151539Ssuz * xxx-link" document.  Note that address architecture might also define
2167151539Ssuz * the length for a particular set of address prefixes, regardless of the
2168151539Ssuz * link type.  As clarified in rfc2462bis, those two definitions should be
2169151539Ssuz * consistent, and those really are as of August 2004.
2170151539Ssuz */
2171151539Ssuzint
2172171259Sdelphijin6_if2idlen(struct ifnet *ifp)
2173151539Ssuz{
2174151539Ssuz	switch (ifp->if_type) {
2175151539Ssuz	case IFT_ETHER:		/* RFC2464 */
2176151539Ssuz#ifdef IFT_PROPVIRTUAL
2177151539Ssuz	case IFT_PROPVIRTUAL:	/* XXX: no RFC. treat it as ether */
2178151539Ssuz#endif
2179151539Ssuz#ifdef IFT_L2VLAN
2180151539Ssuz	case IFT_L2VLAN:	/* ditto */
2181151539Ssuz#endif
2182151539Ssuz#ifdef IFT_IEEE80211
2183151539Ssuz	case IFT_IEEE80211:	/* ditto */
2184151539Ssuz#endif
2185151539Ssuz#ifdef IFT_MIP
2186151539Ssuz	case IFT_MIP:	/* ditto */
2187151539Ssuz#endif
2188151539Ssuz		return (64);
2189151539Ssuz	case IFT_FDDI:		/* RFC2467 */
2190151539Ssuz		return (64);
2191151539Ssuz	case IFT_ISO88025:	/* RFC2470 (IPv6 over Token Ring) */
2192151539Ssuz		return (64);
2193151539Ssuz	case IFT_PPP:		/* RFC2472 */
2194151539Ssuz		return (64);
2195151539Ssuz	case IFT_ARCNET:	/* RFC2497 */
2196151539Ssuz		return (64);
2197151539Ssuz	case IFT_FRELAY:	/* RFC2590 */
2198151539Ssuz		return (64);
2199151539Ssuz	case IFT_IEEE1394:	/* RFC3146 */
2200151539Ssuz		return (64);
2201151539Ssuz	case IFT_GIF:
2202151539Ssuz		return (64);	/* draft-ietf-v6ops-mech-v2-07 */
2203151539Ssuz	case IFT_LOOP:
2204151539Ssuz		return (64);	/* XXX: is this really correct? */
2205151539Ssuz	default:
2206151539Ssuz		/*
2207151539Ssuz		 * Unknown link type:
2208151539Ssuz		 * It might be controversial to use the today's common constant
2209151539Ssuz		 * of 64 for these cases unconditionally.  For full compliance,
2210151539Ssuz		 * we should return an error in this case.  On the other hand,
2211151539Ssuz		 * if we simply miss the standard for the link type or a new
2212151539Ssuz		 * standard is defined for a new link type, the IFID length
2213151539Ssuz		 * is very likely to be the common constant.  As a compromise,
2214151539Ssuz		 * we always use the constant, but make an explicit notice
2215151539Ssuz		 * indicating the "unknown" case.
2216151539Ssuz		 */
2217151539Ssuz		printf("in6_if2idlen: unknown link type (%d)\n", ifp->if_type);
2218151539Ssuz		return (64);
2219151539Ssuz	}
2220151539Ssuz}
2221151539Ssuz
2222121161Sumevoid *
2223171259Sdelphijin6_domifattach(struct ifnet *ifp)
2224121161Sume{
2225121161Sume	struct in6_ifextra *ext;
2226121161Sume
2227121161Sume	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
2228121161Sume	bzero(ext, sizeof(*ext));
2229121161Sume
2230121161Sume	ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
2231121161Sume	    M_IFADDR, M_WAITOK);
2232121161Sume	bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
2233121161Sume
2234121161Sume	ext->icmp6_ifstat =
2235121161Sume	    (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
2236121161Sume	    M_IFADDR, M_WAITOK);
2237121161Sume	bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
2238121161Sume
2239121161Sume	ext->nd_ifinfo = nd6_ifattach(ifp);
2240121161Sume	ext->scope6_id = scope6_ifattach(ifp);
2241121161Sume	return ext;
2242121161Sume}
2243121161Sume
2244121161Sumevoid
2245171259Sdelphijin6_domifdetach(struct ifnet *ifp, void *aux)
2246121161Sume{
2247121161Sume	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
2248121161Sume
2249121161Sume	scope6_ifdetach(ext->scope6_id);
2250121161Sume	nd6_ifdetach(ext->nd_ifinfo);
2251121161Sume	free(ext->in6_ifstat, M_IFADDR);
2252121161Sume	free(ext->icmp6_ifstat, M_IFADDR);
2253121161Sume	free(ext, M_IFADDR);
2254121161Sume}
2255121161Sume
225653541Sshin/*
225795023Ssuz * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
225853541Sshin * v4 mapped addr or v4 compat addr
225953541Sshin */
226053541Sshinvoid
226153541Sshinin6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
226253541Sshin{
2263171259Sdelphij
226453541Sshin	bzero(sin, sizeof(*sin));
226553541Sshin	sin->sin_len = sizeof(struct sockaddr_in);
226653541Sshin	sin->sin_family = AF_INET;
226753541Sshin	sin->sin_port = sin6->sin6_port;
2268120891Sume	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
226953541Sshin}
227053541Sshin
227153541Sshin/* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
227253541Sshinvoid
227353541Sshinin6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
227453541Sshin{
227553541Sshin	bzero(sin6, sizeof(*sin6));
227653541Sshin	sin6->sin6_len = sizeof(struct sockaddr_in6);
227753541Sshin	sin6->sin6_family = AF_INET6;
227853541Sshin	sin6->sin6_port = sin->sin_port;
227953541Sshin	sin6->sin6_addr.s6_addr32[0] = 0;
228053541Sshin	sin6->sin6_addr.s6_addr32[1] = 0;
228153541Sshin	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
228253541Sshin	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
228353541Sshin}
228453541Sshin
228553541Sshin/* Convert sockaddr_in6 into sockaddr_in. */
228653541Sshinvoid
228753541Sshinin6_sin6_2_sin_in_sock(struct sockaddr *nam)
228853541Sshin{
228953541Sshin	struct sockaddr_in *sin_p;
229053541Sshin	struct sockaddr_in6 sin6;
229153541Sshin
229253541Sshin	/*
229353541Sshin	 * Save original sockaddr_in6 addr and convert it
229453541Sshin	 * to sockaddr_in.
229553541Sshin	 */
229653541Sshin	sin6 = *(struct sockaddr_in6 *)nam;
229753541Sshin	sin_p = (struct sockaddr_in *)nam;
229853541Sshin	in6_sin6_2_sin(sin_p, &sin6);
229953541Sshin}
230053541Sshin
230153541Sshin/* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
230253541Sshinvoid
230353541Sshinin6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
230453541Sshin{
230553541Sshin	struct sockaddr_in *sin_p;
230653541Sshin	struct sockaddr_in6 *sin6_p;
230753541Sshin
230853541Sshin	MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
2309111119Simp	       M_WAITOK);
231053541Sshin	sin_p = (struct sockaddr_in *)*nam;
231153541Sshin	in6_sin_2_v4mapsin6(sin_p, sin6_p);
231253541Sshin	FREE(*nam, M_SONAME);
231353541Sshin	*nam = (struct sockaddr *)sin6_p;
231453541Sshin}
2315