in6.c revision 155454
162587Sitojun/*	$FreeBSD: head/sys/netinet6/in6.c 155454 2006-02-08 07:16:46Z gnn $	*/
295023Ssuz/*	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $	*/
362587Sitojun
4139826Simp/*-
553541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
653541Sshin * All rights reserved.
753541Sshin *
853541Sshin * Redistribution and use in source and binary forms, with or without
953541Sshin * modification, are permitted provided that the following conditions
1053541Sshin * are met:
1153541Sshin * 1. Redistributions of source code must retain the above copyright
1253541Sshin *    notice, this list of conditions and the following disclaimer.
1353541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1453541Sshin *    notice, this list of conditions and the following disclaimer in the
1553541Sshin *    documentation and/or other materials provided with the distribution.
1653541Sshin * 3. Neither the name of the project nor the names of its contributors
1753541Sshin *    may be used to endorse or promote products derived from this software
1853541Sshin *    without specific prior written permission.
1953541Sshin *
2053541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2153541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2253541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2353541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2453541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2553541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2653541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2753541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2853541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2953541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3053541Sshin * SUCH DAMAGE.
3153541Sshin */
3253541Sshin
33139826Simp/*-
3453541Sshin * Copyright (c) 1982, 1986, 1991, 1993
3553541Sshin *	The Regents of the University of California.  All rights reserved.
3653541Sshin *
3753541Sshin * Redistribution and use in source and binary forms, with or without
3853541Sshin * modification, are permitted provided that the following conditions
3953541Sshin * are met:
4053541Sshin * 1. Redistributions of source code must retain the above copyright
4153541Sshin *    notice, this list of conditions and the following disclaimer.
4253541Sshin * 2. Redistributions in binary form must reproduce the above copyright
4353541Sshin *    notice, this list of conditions and the following disclaimer in the
4453541Sshin *    documentation and/or other materials provided with the distribution.
4553541Sshin * 4. Neither the name of the University nor the names of its contributors
4653541Sshin *    may be used to endorse or promote products derived from this software
4753541Sshin *    without specific prior written permission.
4853541Sshin *
4953541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5053541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5153541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5253541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5353541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5453541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5553541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5653541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5753541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5853541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5953541Sshin * SUCH DAMAGE.
6053541Sshin *
6153541Sshin *	@(#)in.c	8.2 (Berkeley) 11/15/93
6253541Sshin */
6353541Sshin
6462587Sitojun#include "opt_inet.h"
6562587Sitojun#include "opt_inet6.h"
6662587Sitojun
6753541Sshin#include <sys/param.h>
6853541Sshin#include <sys/errno.h>
6953541Sshin#include <sys/malloc.h>
7053541Sshin#include <sys/socket.h>
7153541Sshin#include <sys/socketvar.h>
7253541Sshin#include <sys/sockio.h>
7353541Sshin#include <sys/systm.h>
7453541Sshin#include <sys/proc.h>
7553541Sshin#include <sys/time.h>
7653541Sshin#include <sys/kernel.h>
7753541Sshin#include <sys/syslog.h>
7853541Sshin
7953541Sshin#include <net/if.h>
8053541Sshin#include <net/if_types.h>
8153541Sshin#include <net/route.h>
8253541Sshin#include <net/if_dl.h>
8353541Sshin
8453541Sshin#include <netinet/in.h>
8553541Sshin#include <netinet/in_var.h>
8653541Sshin#include <netinet/if_ether.h>
8778064Sume#include <netinet/in_systm.h>
8878064Sume#include <netinet/ip.h>
8978064Sume#include <netinet/in_pcb.h>
9053541Sshin
9162587Sitojun#include <netinet/ip6.h>
9253541Sshin#include <netinet6/ip6_var.h>
9395023Ssuz#include <netinet6/nd6.h>
9453541Sshin#include <netinet6/mld6_var.h>
9562587Sitojun#include <netinet6/ip6_mroute.h>
9653541Sshin#include <netinet6/in6_ifattach.h>
9762587Sitojun#include <netinet6/scope6_var.h>
9878064Sume#include <netinet6/in6_pcb.h>
9962587Sitojun
10053541Sshin#include <net/net_osdep.h>
10153541Sshin
102149849SobrienMALLOC_DEFINE(M_IP6MADDR, "in6_multi", "internet multicast address");
10353541Sshin
10453541Sshin/*
10553541Sshin * Definitions of some costant IP6 addresses.
10653541Sshin */
10762587Sitojunconst struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
10862587Sitojunconst struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
10962587Sitojunconst struct in6_addr in6addr_nodelocal_allnodes =
11053541Sshin	IN6ADDR_NODELOCAL_ALLNODES_INIT;
11162587Sitojunconst struct in6_addr in6addr_linklocal_allnodes =
11253541Sshin	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
11362587Sitojunconst struct in6_addr in6addr_linklocal_allrouters =
11453541Sshin	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
11553541Sshin
11662587Sitojunconst struct in6_addr in6mask0 = IN6MASK0;
11762587Sitojunconst struct in6_addr in6mask32 = IN6MASK32;
11862587Sitojunconst struct in6_addr in6mask64 = IN6MASK64;
11962587Sitojunconst struct in6_addr in6mask96 = IN6MASK96;
12062587Sitojunconst struct in6_addr in6mask128 = IN6MASK128;
12153541Sshin
122126552Sumeconst struct sockaddr_in6 sa6_any =
123126552Sume	{ sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 };
12478064Sume
12562587Sitojunstatic int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
12683366Sjulian	struct ifnet *, struct thread *));
12778064Sumestatic int in6_ifinit __P((struct ifnet *, struct in6_ifaddr *,
128120891Sume	struct sockaddr_in6 *, int));
12978064Sumestatic void in6_unlink_ifa __P((struct in6_ifaddr *, struct ifnet *));
13053541Sshin
13162587Sitojunstruct in6_multihead in6_multihead;	/* XXX BSS initialization */
13283934Sbrooksint	(*faithprefix_p)(struct in6_addr *);
13383934Sbrooks
13453541Sshin/*
13553541Sshin * Subroutine for in6_ifaddloop() and in6_ifremloop().
13653541Sshin * This routine does actual work.
13753541Sshin */
13853541Sshinstatic void
13953541Sshinin6_ifloop_request(int cmd, struct ifaddr *ifa)
14053541Sshin{
14153541Sshin	struct sockaddr_in6 all1_sa;
14278064Sume	struct rtentry *nrt = NULL;
14378064Sume	int e;
144120891Sume
14553541Sshin	bzero(&all1_sa, sizeof(all1_sa));
14678064Sume	all1_sa.sin6_family = AF_INET6;
14778064Sume	all1_sa.sin6_len = sizeof(struct sockaddr_in6);
14853541Sshin	all1_sa.sin6_addr = in6mask128;
14978064Sume
15062587Sitojun	/*
15178064Sume	 * We specify the address itself as the gateway, and set the
15278064Sume	 * RTF_LLINFO flag, so that the corresponding host route would have
15378064Sume	 * the flag, and thus applications that assume traditional behavior
15478064Sume	 * would be happy.  Note that we assume the caller of the function
15578064Sume	 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
15678064Sume	 * which changes the outgoing interface to the loopback interface.
15762587Sitojun	 */
15878064Sume	e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
159120891Sume	    (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
16078064Sume	if (e != 0) {
161120891Sume		/* XXX need more descriptive message */
16278064Sume		log(LOG_ERR, "in6_ifloop_request: "
16378064Sume		    "%s operation failed for %s (errno=%d)\n",
16478064Sume		    cmd == RTM_ADD ? "ADD" : "DELETE",
16578064Sume		    ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
16678064Sume		    e);
16778064Sume	}
16853541Sshin
169151465Ssuz	/*
170151465Ssuz	 * Report the addition/removal of the address to the routing socket.
171151465Ssuz	 * XXX: since we called rtinit for a p2p interface with a destination,
172151465Ssuz	 *      we end up reporting twice in such a case.  Should we rather
173151465Ssuz	 *      omit the second report?
174151465Ssuz	 */
175120727Ssam	if (nrt) {
176120727Ssam		RT_LOCK(nrt);
177120727Ssam		/*
178120727Ssam		 * Make sure rt_ifa be equal to IFA, the second argument of
179120727Ssam		 * the function.  We need this because when we refer to
180120727Ssam		 * rt_ifa->ia6_flags in ip6_input, we assume that the rt_ifa
181120727Ssam		 * points to the address instead of the loopback address.
182120727Ssam		 */
183120727Ssam		if (cmd == RTM_ADD && ifa != nrt->rt_ifa) {
184120727Ssam			IFAFREE(nrt->rt_ifa);
185120727Ssam			IFAREF(ifa);
186120727Ssam			nrt->rt_ifa = ifa;
187120727Ssam		}
18878064Sume
18978064Sume		rt_newaddrmsg(cmd, ifa, e, nrt);
19078064Sume		if (cmd == RTM_DELETE) {
191120727Ssam			rtfree(nrt);
19278064Sume		} else {
19378064Sume			/* the cmd must be RTM_ADD here */
194122334Ssam			RT_REMREF(nrt);
195120727Ssam			RT_UNLOCK(nrt);
19678064Sume		}
19778064Sume	}
19853541Sshin}
19953541Sshin
20053541Sshin/*
20178064Sume * Add ownaddr as loopback rtentry.  We previously add the route only if
20278064Sume * necessary (ex. on a p2p link).  However, since we now manage addresses
20378064Sume * separately from prefixes, we should always add the route.  We can't
20478064Sume * rely on the cloning mechanism from the corresponding interface route
20578064Sume * any more.
20653541Sshin */
207142215Sglebiusvoid
20853541Sshinin6_ifaddloop(struct ifaddr *ifa)
20953541Sshin{
21078064Sume	struct rtentry *rt;
211121716Ssam	int need_loop;
21253541Sshin
21378064Sume	/* If there is no loopback entry, allocate one. */
21478064Sume	rt = rtalloc1(ifa->ifa_addr, 0, 0);
215121716Ssam	need_loop = (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
216121716Ssam	    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0);
21778064Sume	if (rt)
218120727Ssam		rtfree(rt);
219121716Ssam	if (need_loop)
220121716Ssam		in6_ifloop_request(RTM_ADD, ifa);
22153541Sshin}
22253541Sshin
22353541Sshin/*
22453541Sshin * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
22553541Sshin * if it exists.
22653541Sshin */
227142215Sglebiusvoid
22853541Sshinin6_ifremloop(struct ifaddr *ifa)
22953541Sshin{
23062587Sitojun	struct in6_ifaddr *ia;
23178064Sume	struct rtentry *rt;
23262587Sitojun	int ia_count = 0;
23353541Sshin
23462587Sitojun	/*
23578064Sume	 * Some of BSD variants do not remove cloned routes
23662587Sitojun	 * from an interface direct route, when removing the direct route
23778064Sume	 * (see comments in net/net_osdep.h).  Even for variants that do remove
23878064Sume	 * cloned routes, they could fail to remove the cloned routes when
23978064Sume	 * we handle multple addresses that share a common prefix.
240151465Ssuz	 * So, we should remove the route corresponding to the deleted address.
24162587Sitojun	 */
24278064Sume
24378064Sume	/*
24495023Ssuz	 * Delete the entry only if exact one ifa exists.  More than one ifa
24578064Sume	 * can exist if we assign a same single address to multiple
24678064Sume	 * (probably p2p) interfaces.
24778064Sume	 * XXX: we should avoid such a configuration in IPv6...
24878064Sume	 */
24978064Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
25078064Sume		if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
25178064Sume			ia_count++;
25278064Sume			if (ia_count > 1)
25378064Sume				break;
25453541Sshin		}
25578064Sume	}
25678064Sume
25778064Sume	if (ia_count == 1) {
25878064Sume		/*
25978064Sume		 * Before deleting, check if a corresponding loopbacked host
26095023Ssuz		 * route surely exists.  With this check, we can avoid to
26178064Sume		 * delete an interface direct route whose destination is same
262120891Sume		 * as the address being removed.  This can happen when removing
26378064Sume		 * a subnet-router anycast address on an interface attahced
26478064Sume		 * to a shared medium.
26578064Sume		 */
26678064Sume		rt = rtalloc1(ifa->ifa_addr, 0, 0);
267120727Ssam		if (rt != NULL) {
268120727Ssam			if ((rt->rt_flags & RTF_HOST) != 0 &&
269120727Ssam			    (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
270120727Ssam				rtfree(rt);
271120727Ssam				in6_ifloop_request(RTM_DELETE, ifa);
272120727Ssam			} else
273120727Ssam				RT_UNLOCK(rt);
27478064Sume		}
27553541Sshin	}
27653541Sshin}
27753541Sshin
27853541Sshinint
27978064Sumein6_mask2len(mask, lim0)
28053541Sshin	struct in6_addr *mask;
28178064Sume	u_char *lim0;
28253541Sshin{
28378064Sume	int x = 0, y;
28478064Sume	u_char *lim = lim0, *p;
28553541Sshin
286120891Sume	/* ignore the scope_id part */
287120891Sume	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
28878064Sume		lim = (u_char *)mask + sizeof(*mask);
28978064Sume	for (p = (u_char *)mask; p < lim; x++, p++) {
29078064Sume		if (*p != 0xff)
29153541Sshin			break;
29253541Sshin	}
29353541Sshin	y = 0;
29478064Sume	if (p < lim) {
29553541Sshin		for (y = 0; y < 8; y++) {
29678064Sume			if ((*p & (0x80 >> y)) == 0)
29753541Sshin				break;
29853541Sshin		}
29953541Sshin	}
30078064Sume
30178064Sume	/*
30278064Sume	 * when the limit pointer is given, do a stricter check on the
30378064Sume	 * remaining bits.
30478064Sume	 */
30578064Sume	if (p < lim) {
30678064Sume		if (y != 0 && (*p & (0x00ff >> y)) != 0)
307120856Sume			return (-1);
30878064Sume		for (p = p + 1; p < lim; p++)
30978064Sume			if (*p != 0)
310120856Sume				return (-1);
31178064Sume	}
312120891Sume
31353541Sshin	return x * 8 + y;
31453541Sshin}
31553541Sshin
31653541Sshin#define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
31762587Sitojun#define ia62ifa(ia6)	(&((ia6)->ia_ifa))
31853541Sshin
31953541Sshinint
32083366Sjulianin6_control(so, cmd, data, ifp, td)
32153541Sshin	struct	socket *so;
32253541Sshin	u_long cmd;
32353541Sshin	caddr_t	data;
32453541Sshin	struct ifnet *ifp;
32583366Sjulian	struct thread *td;
32653541Sshin{
32753541Sshin	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
32878064Sume	struct	in6_ifaddr *ia = NULL;
32953541Sshin	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
330148385Sume	int error, privileged;
331151539Ssuz	struct sockaddr_in6 *sa6;
33253541Sshin
33353541Sshin	privileged = 0;
33493593Sjhb	if (td == NULL || !suser(td))
33553541Sshin		privileged++;
33653541Sshin
33762587Sitojun	switch (cmd) {
33862587Sitojun	case SIOCGETSGCNT_IN6:
33962587Sitojun	case SIOCGETMIFCNT_IN6:
34062587Sitojun		return (mrt6_ioctl(cmd, data));
34162587Sitojun	}
34253541Sshin
343121742Sume	switch(cmd) {
344121742Sume	case SIOCAADDRCTL_POLICY:
345121742Sume	case SIOCDADDRCTL_POLICY:
346121742Sume		if (!privileged)
347121742Sume			return (EPERM);
348121742Sume		return (in6_src_ioctl(cmd, data));
349121742Sume	}
350121742Sume
35162587Sitojun	if (ifp == NULL)
352120856Sume		return (EOPNOTSUPP);
35353541Sshin
35453541Sshin	switch (cmd) {
35553541Sshin	case SIOCSNDFLUSH_IN6:
35653541Sshin	case SIOCSPFXFLUSH_IN6:
35753541Sshin	case SIOCSRTRFLUSH_IN6:
35862587Sitojun	case SIOCSDEFIFACE_IN6:
35962587Sitojun	case SIOCSIFINFO_FLAGS:
36053541Sshin		if (!privileged)
361120856Sume			return (EPERM);
362120891Sume		/* FALLTHROUGH */
36378064Sume	case OSIOCGIFINFO_IN6:
36453541Sshin	case SIOCGIFINFO_IN6:
365151468Ssuz	case SIOCSIFINFO_IN6:
36653541Sshin	case SIOCGDRLST_IN6:
36753541Sshin	case SIOCGPRLST_IN6:
36853541Sshin	case SIOCGNBRINFO_IN6:
36962587Sitojun	case SIOCGDEFIFACE_IN6:
370120856Sume		return (nd6_ioctl(cmd, data, ifp));
37153541Sshin	}
37253541Sshin
37353541Sshin	switch (cmd) {
37453541Sshin	case SIOCSIFPREFIX_IN6:
37553541Sshin	case SIOCDIFPREFIX_IN6:
37653541Sshin	case SIOCAIFPREFIX_IN6:
37753541Sshin	case SIOCCIFPREFIX_IN6:
37853541Sshin	case SIOCSGIFPREFIX_IN6:
37953541Sshin	case SIOCGIFPREFIX_IN6:
38078064Sume		log(LOG_NOTICE,
38178064Sume		    "prefix ioctls are now invalidated. "
38278064Sume		    "please use ifconfig.\n");
383120856Sume		return (EOPNOTSUPP);
38453541Sshin	}
38553541Sshin
38695023Ssuz	switch (cmd) {
38762587Sitojun	case SIOCSSCOPE6:
38862587Sitojun		if (!privileged)
389120856Sume			return (EPERM);
390121161Sume		return (scope6_set(ifp,
391121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
39262587Sitojun	case SIOCGSCOPE6:
393121161Sume		return (scope6_get(ifp,
394121161Sume		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
39562587Sitojun	case SIOCGSCOPE6DEF:
396121161Sume		return (scope6_get_default((struct scope6_id *)
397121161Sume		    ifr->ifr_ifru.ifru_scope_id));
39862587Sitojun	}
39962587Sitojun
40053541Sshin	switch (cmd) {
40153541Sshin	case SIOCALIFADDR:
40253541Sshin	case SIOCDLIFADDR:
40353541Sshin		if (!privileged)
404120856Sume			return (EPERM);
405120891Sume		/* FALLTHROUGH */
40653541Sshin	case SIOCGLIFADDR:
40783366Sjulian		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
40853541Sshin	}
40953541Sshin
41053541Sshin	/*
41153541Sshin	 * Find address for this interface, if it exists.
412151539Ssuz	 *
413151539Ssuz	 * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
414151539Ssuz	 * only, and used the first interface address as the target of other
415151539Ssuz	 * operations (without checking ifra_addr).  This was because netinet
416151539Ssuz	 * code/API assumed at most 1 interface address per interface.
417151539Ssuz	 * Since IPv6 allows a node to assign multiple addresses
418151539Ssuz	 * on a single interface, we almost always look and check the
419151539Ssuz	 * presence of ifra_addr, and reject invalid ones here.
420151539Ssuz	 * It also decreases duplicated code among SIOC*_IN6 operations.
42153541Sshin	 */
422151539Ssuz	switch (cmd) {
423151539Ssuz	case SIOCAIFADDR_IN6:
424151539Ssuz	case SIOCSIFPHYADDR_IN6:
425151539Ssuz		sa6 = &ifra->ifra_addr;
426151539Ssuz		break;
427151539Ssuz	case SIOCSIFADDR_IN6:
428151539Ssuz	case SIOCGIFADDR_IN6:
429151539Ssuz	case SIOCSIFDSTADDR_IN6:
430151539Ssuz	case SIOCSIFNETMASK_IN6:
431151539Ssuz	case SIOCGIFDSTADDR_IN6:
432151539Ssuz	case SIOCGIFNETMASK_IN6:
433151539Ssuz	case SIOCDIFADDR_IN6:
434151539Ssuz	case SIOCGIFPSRCADDR_IN6:
435151539Ssuz	case SIOCGIFPDSTADDR_IN6:
436151539Ssuz	case SIOCGIFAFLAG_IN6:
437151539Ssuz	case SIOCSNDFLUSH_IN6:
438151539Ssuz	case SIOCSPFXFLUSH_IN6:
439151539Ssuz	case SIOCSRTRFLUSH_IN6:
440151539Ssuz	case SIOCGIFALIFETIME_IN6:
441151539Ssuz	case SIOCSIFALIFETIME_IN6:
442151539Ssuz	case SIOCGIFSTAT_IN6:
443151539Ssuz	case SIOCGIFSTAT_ICMP6:
444151539Ssuz		sa6 = &ifr->ifr_addr;
445151539Ssuz		break;
446151539Ssuz	default:
447151539Ssuz		sa6 = NULL;
448151539Ssuz		break;
449151539Ssuz	}
450151539Ssuz	if (sa6 && sa6->sin6_family == AF_INET6) {
451148385Sume		int error = 0;
45253541Sshin
453151539Ssuz		if (sa6->sin6_scope_id != 0)
454151539Ssuz			error = sa6_embedscope(sa6, 0);
455148385Sume		else
456151539Ssuz			error = in6_setscope(&sa6->sin6_addr, ifp, NULL);
457148385Sume		if (error != 0)
458148385Sume			return (error);
459151539Ssuz		ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
460151539Ssuz	} else
461151539Ssuz		ia = NULL;
46253541Sshin
46353541Sshin	switch (cmd) {
46478064Sume	case SIOCSIFADDR_IN6:
46578064Sume	case SIOCSIFDSTADDR_IN6:
46678064Sume	case SIOCSIFNETMASK_IN6:
46778064Sume		/*
46878064Sume		 * Since IPv6 allows a node to assign multiple addresses
469151465Ssuz		 * on a single interface, SIOCSIFxxx ioctls are deprecated.
47078064Sume		 */
47178064Sume		/* we decided to obsolete this command (20000704) */
472120856Sume		return (EINVAL);
47353541Sshin
47453541Sshin	case SIOCDIFADDR_IN6:
47562587Sitojun		/*
47678064Sume		 * for IPv4, we look for existing in_ifaddr here to allow
477151465Ssuz		 * "ifconfig if0 delete" to remove the first IPv4 address on
478151465Ssuz		 * the interface.  For IPv6, as the spec allows multiple
479151465Ssuz		 * interface address from the day one, we consider "remove the
480151465Ssuz		 * first one" semantics to be not preferable.
48162587Sitojun		 */
48262587Sitojun		if (ia == NULL)
483120856Sume			return (EADDRNOTAVAIL);
48453541Sshin		/* FALLTHROUGH */
48553541Sshin	case SIOCAIFADDR_IN6:
48662587Sitojun		/*
48778064Sume		 * We always require users to specify a valid IPv6 address for
48878064Sume		 * the corresponding operation.
48962587Sitojun		 */
49078064Sume		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
49178064Sume		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
492120856Sume			return (EAFNOSUPPORT);
49353541Sshin		if (!privileged)
494120856Sume			return (EPERM);
49553541Sshin
49653541Sshin		break;
49753541Sshin
49853541Sshin	case SIOCGIFADDR_IN6:
49953541Sshin		/* This interface is basically deprecated. use SIOCGIFCONF. */
500120891Sume		/* FALLTHROUGH */
50153541Sshin	case SIOCGIFAFLAG_IN6:
50253541Sshin	case SIOCGIFNETMASK_IN6:
50353541Sshin	case SIOCGIFDSTADDR_IN6:
50453541Sshin	case SIOCGIFALIFETIME_IN6:
50553541Sshin		/* must think again about its semantics */
50662587Sitojun		if (ia == NULL)
507120856Sume			return (EADDRNOTAVAIL);
50853541Sshin		break;
50953541Sshin	case SIOCSIFALIFETIME_IN6:
51053541Sshin	    {
51153541Sshin		struct in6_addrlifetime *lt;
51253541Sshin
51353541Sshin		if (!privileged)
514120856Sume			return (EPERM);
51562587Sitojun		if (ia == NULL)
516120856Sume			return (EADDRNOTAVAIL);
51753541Sshin		/* sanity for overflow - beware unsigned */
51853541Sshin		lt = &ifr->ifr_ifru.ifru_lifetime;
519126552Sume		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
520126552Sume		    lt->ia6t_vltime + time_second < time_second) {
52153541Sshin			return EINVAL;
52253541Sshin		}
523126552Sume		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME &&
524126552Sume		    lt->ia6t_pltime + time_second < time_second) {
52553541Sshin			return EINVAL;
52653541Sshin		}
52753541Sshin		break;
52853541Sshin	    }
52953541Sshin	}
53053541Sshin
53153541Sshin	switch (cmd) {
53253541Sshin
53353541Sshin	case SIOCGIFADDR_IN6:
53453541Sshin		ifr->ifr_addr = ia->ia_addr;
535148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
536148385Sume			return (error);
53753541Sshin		break;
53853541Sshin
53953541Sshin	case SIOCGIFDSTADDR_IN6:
54053541Sshin		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
541120856Sume			return (EINVAL);
54262587Sitojun		/*
54362587Sitojun		 * XXX: should we check if ifa_dstaddr is NULL and return
54462587Sitojun		 * an error?
54562587Sitojun		 */
54653541Sshin		ifr->ifr_dstaddr = ia->ia_dstaddr;
547148385Sume		if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
548148385Sume			return (error);
54953541Sshin		break;
55053541Sshin
55153541Sshin	case SIOCGIFNETMASK_IN6:
55253541Sshin		ifr->ifr_addr = ia->ia_prefixmask;
55353541Sshin		break;
55453541Sshin
55553541Sshin	case SIOCGIFAFLAG_IN6:
55653541Sshin		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
55753541Sshin		break;
55853541Sshin
55953541Sshin	case SIOCGIFSTAT_IN6:
560121167Sume		if (ifp == NULL)
561121167Sume			return EINVAL;
562121161Sume		bzero(&ifr->ifr_ifru.ifru_stat,
563121161Sume		    sizeof(ifr->ifr_ifru.ifru_stat));
564121161Sume		ifr->ifr_ifru.ifru_stat =
565121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
56653541Sshin		break;
56753541Sshin
56853541Sshin	case SIOCGIFSTAT_ICMP6:
56953541Sshin		if (ifp == NULL)
57053541Sshin			return EINVAL;
571155454Sgnn		bzero(&ifr->ifr_ifru.ifru_icmp6stat,
572121161Sume		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
573121161Sume		ifr->ifr_ifru.ifru_icmp6stat =
574121161Sume		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
57553541Sshin		break;
57653541Sshin
57753541Sshin	case SIOCGIFALIFETIME_IN6:
57853541Sshin		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
579151539Ssuz		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
580151539Ssuz			time_t maxexpire;
581151539Ssuz			struct in6_addrlifetime *retlt =
582151539Ssuz			    &ifr->ifr_ifru.ifru_lifetime;
583151539Ssuz
584151539Ssuz			/*
585151539Ssuz			 * XXX: adjust expiration time assuming time_t is
586151539Ssuz			 * signed.
587151539Ssuz			 */
588151539Ssuz			maxexpire = (-1) &
589151546Ssuz			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
590151539Ssuz			if (ia->ia6_lifetime.ia6t_vltime <
591151539Ssuz			    maxexpire - ia->ia6_updatetime) {
592151539Ssuz				retlt->ia6t_expire = ia->ia6_updatetime +
593151539Ssuz				    ia->ia6_lifetime.ia6t_vltime;
594151539Ssuz			} else
595151539Ssuz				retlt->ia6t_expire = maxexpire;
596151539Ssuz		}
597151539Ssuz		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
598151539Ssuz			time_t maxexpire;
599151539Ssuz			struct in6_addrlifetime *retlt =
600151539Ssuz			    &ifr->ifr_ifru.ifru_lifetime;
601151539Ssuz
602151539Ssuz			/*
603151539Ssuz			 * XXX: adjust expiration time assuming time_t is
604151539Ssuz			 * signed.
605151539Ssuz			 */
606151539Ssuz			maxexpire = (-1) &
607151546Ssuz			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
608151539Ssuz			if (ia->ia6_lifetime.ia6t_pltime <
609151539Ssuz			    maxexpire - ia->ia6_updatetime) {
610151539Ssuz				retlt->ia6t_preferred = ia->ia6_updatetime +
611151539Ssuz				    ia->ia6_lifetime.ia6t_pltime;
612151539Ssuz			} else
613151539Ssuz				retlt->ia6t_preferred = maxexpire;
614151539Ssuz		}
61553541Sshin		break;
61653541Sshin
61753541Sshin	case SIOCSIFALIFETIME_IN6:
61853541Sshin		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
61953541Sshin		/* for sanity */
62053541Sshin		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
62153541Sshin			ia->ia6_lifetime.ia6t_expire =
62253541Sshin				time_second + ia->ia6_lifetime.ia6t_vltime;
62353541Sshin		} else
62453541Sshin			ia->ia6_lifetime.ia6t_expire = 0;
62553541Sshin		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
62653541Sshin			ia->ia6_lifetime.ia6t_preferred =
62753541Sshin				time_second + ia->ia6_lifetime.ia6t_pltime;
62853541Sshin		} else
62953541Sshin			ia->ia6_lifetime.ia6t_preferred = 0;
63053541Sshin		break;
63153541Sshin
63278064Sume	case SIOCAIFADDR_IN6:
63378064Sume	{
63478064Sume		int i, error = 0;
635151539Ssuz		struct nd_prefixctl pr0;
636151539Ssuz		struct nd_prefix *pr;
63778064Sume
63862587Sitojun		/*
63978064Sume		 * first, make or update the interface address structure,
64078064Sume		 * and link it to the list.
64162587Sitojun		 */
642151539Ssuz		if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
643120856Sume			return (error);
644151915Ssuz		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
645151915Ssuz		    == NULL) {
646151915Ssuz		    	/*
647151915Ssuz			 * this can happen when the user specify the 0 valid
648151915Ssuz			 * lifetime.
649151915Ssuz			 */
650151915Ssuz			break;
651151915Ssuz		}
65253541Sshin
65378064Sume		/*
65478064Sume		 * then, make the prefix on-link on the interface.
65578064Sume		 * XXX: we'd rather create the prefix before the address, but
65678064Sume		 * we need at least one address to install the corresponding
65778064Sume		 * interface route, so we configure the address first.
65878064Sume		 */
65978064Sume
66078064Sume		/*
66178064Sume		 * convert mask to prefix length (prefixmask has already
66278064Sume		 * been validated in in6_update_ifa().
66378064Sume		 */
66478064Sume		bzero(&pr0, sizeof(pr0));
66578064Sume		pr0.ndpr_ifp = ifp;
66678064Sume		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
667120891Sume		    NULL);
668120891Sume		if (pr0.ndpr_plen == 128) {
66978064Sume			break;	/* we don't need to install a host route. */
670120891Sume		}
67178064Sume		pr0.ndpr_prefix = ifra->ifra_addr;
67278064Sume		/* apply the mask for safety. */
67378064Sume		for (i = 0; i < 4; i++) {
67478064Sume			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
675120891Sume			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
67678064Sume		}
67778064Sume		/*
67895023Ssuz		 * XXX: since we don't have an API to set prefix (not address)
67995023Ssuz		 * lifetimes, we just use the same lifetimes as addresses.
68095023Ssuz		 * The (temporarily) installed lifetimes can be overridden by
68195023Ssuz		 * later advertised RAs (when accept_rtadv is non 0), which is
68295023Ssuz		 * an intended behavior.
68378064Sume		 */
68478064Sume		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
68578064Sume		pr0.ndpr_raf_auto =
686120891Sume		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
68778064Sume		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
68878064Sume		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
68978064Sume
690120891Sume		/* add the prefix if not yet. */
69178064Sume		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
69278064Sume			/*
69378064Sume			 * nd6_prelist_add will install the corresponding
69478064Sume			 * interface route.
69578064Sume			 */
69678064Sume			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
697120856Sume				return (error);
69878064Sume			if (pr == NULL) {
699120891Sume				log(LOG_ERR, "nd6_prelist_add succeeded but "
70078064Sume				    "no prefix\n");
701120856Sume				return (EINVAL); /* XXX panic here? */
70278064Sume			}
70378064Sume		}
70478064Sume
705151915Ssuz		/* relate the address to the prefix */
706151915Ssuz		if (ia->ia6_ndpr == NULL) {
707151915Ssuz			ia->ia6_ndpr = pr;
708151915Ssuz			pr->ndpr_refcnt++;
70978064Sume
71078064Sume			/*
711151915Ssuz			 * If this is the first autoconf address from the
712151915Ssuz			 * prefix, create a temporary address as well
713151915Ssuz			 * (when required).
71478064Sume			 */
715151915Ssuz			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) &&
716151915Ssuz			    ip6_use_tempaddr && pr->ndpr_refcnt == 1) {
717151915Ssuz				int e;
718151915Ssuz				if ((e = in6_tmpifadd(ia, 1, 0)) != 0) {
719151915Ssuz					log(LOG_NOTICE, "in6_control: failed "
720151915Ssuz					    "to create a temporary address, "
721151915Ssuz					    "errno=%d\n", e);
722151915Ssuz				}
723151915Ssuz			}
72462587Sitojun		}
725151915Ssuz
726151915Ssuz		/*
727151915Ssuz		 * this might affect the status of autoconfigured addresses,
728151915Ssuz		 * that is, this address might make other addresses detached.
729151915Ssuz		 */
730151915Ssuz		pfxlist_onlink_check();
731126264Smlaier		if (error == 0 && ia)
732126264Smlaier			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
73378064Sume		break;
73478064Sume	}
73562587Sitojun
73678064Sume	case SIOCDIFADDR_IN6:
73778064Sume	{
738151539Ssuz		struct nd_prefix *pr;
73978064Sume
74078064Sume		/*
74178064Sume		 * If the address being deleted is the only one that owns
74278064Sume		 * the corresponding prefix, expire the prefix as well.
743120891Sume		 * XXX: theoretically, we don't have to worry about such
74478064Sume		 * relationship, since we separate the address management
74578064Sume		 * and the prefix management.  We do this, however, to provide
74678064Sume		 * as much backward compatibility as possible in terms of
74778064Sume		 * the ioctl operation.
748151915Ssuz		 * Note that in6_purgeaddr() will decrement ndpr_refcnt.
74978064Sume		 */
750151915Ssuz		pr = ia->ia6_ndpr;
75178064Sume		in6_purgeaddr(&ia->ia_ifa);
752151915Ssuz		if (pr && pr->ndpr_refcnt == 0)
753151915Ssuz			prelist_remove(pr);
754126264Smlaier		EVENTHANDLER_INVOKE(ifaddr_event, ifp);
75553541Sshin		break;
75678064Sume	}
75753541Sshin
75878064Sume	default:
75978064Sume		if (ifp == NULL || ifp->if_ioctl == 0)
760120856Sume			return (EOPNOTSUPP);
761120856Sume		return ((*ifp->if_ioctl)(ifp, cmd, data));
76278064Sume	}
76353541Sshin
764120856Sume	return (0);
76578064Sume}
76653541Sshin
76778064Sume/*
76878064Sume * Update parameters of an IPv6 interface address.
76978064Sume * If necessary, a new entry is created and linked into address chains.
77078064Sume * This function is separated from in6_control().
77178064Sume * XXX: should this be performed under splnet()?
77278064Sume */
77378064Sumeint
774151539Ssuzin6_update_ifa(ifp, ifra, ia, flags)
77578064Sume	struct ifnet *ifp;
77678064Sume	struct in6_aliasreq *ifra;
77778064Sume	struct in6_ifaddr *ia;
778151539Ssuz	int flags;
77978064Sume{
78078064Sume	int error = 0, hostIsNew = 0, plen = -1;
78178064Sume	struct in6_ifaddr *oia;
78278064Sume	struct sockaddr_in6 dst6;
78378064Sume	struct in6_addrlifetime *lt;
784151539Ssuz	struct in6_multi_mship *imm;
785151539Ssuz	struct in6_multi *in6m_sol;
786148385Sume	struct rtentry *rt;
787151539Ssuz	int delay;
78878064Sume
78978064Sume	/* Validate parameters */
79078064Sume	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
791120856Sume		return (EINVAL);
79278064Sume
79378064Sume	/*
79478064Sume	 * The destination address for a p2p link must have a family
79578064Sume	 * of AF_UNSPEC or AF_INET6.
79678064Sume	 */
79778064Sume	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
79878064Sume	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
79978064Sume	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
800120856Sume		return (EAFNOSUPPORT);
80178064Sume	/*
80278064Sume	 * validate ifra_prefixmask.  don't check sin6_family, netmask
80378064Sume	 * does not carry fields other than sin6_len.
80478064Sume	 */
80578064Sume	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
806120856Sume		return (EINVAL);
80778064Sume	/*
80878064Sume	 * Because the IPv6 address architecture is classless, we require
80978064Sume	 * users to specify a (non 0) prefix length (mask) for a new address.
81078064Sume	 * We also require the prefix (when specified) mask is valid, and thus
81178064Sume	 * reject a non-consecutive mask.
81278064Sume	 */
81378064Sume	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
814120856Sume		return (EINVAL);
81578064Sume	if (ifra->ifra_prefixmask.sin6_len != 0) {
81678064Sume		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
817120891Sume		    (u_char *)&ifra->ifra_prefixmask +
818120891Sume		    ifra->ifra_prefixmask.sin6_len);
81978064Sume		if (plen <= 0)
820120856Sume			return (EINVAL);
821120891Sume	} else {
82262587Sitojun		/*
82395023Ssuz		 * In this case, ia must not be NULL.  We just use its prefix
82478064Sume		 * length.
82562587Sitojun		 */
82678064Sume		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
82778064Sume	}
82878064Sume	/*
82978064Sume	 * If the destination address on a p2p interface is specified,
83078064Sume	 * and the address is a scoped one, validate/set the scope
83178064Sume	 * zone identifier.
83278064Sume	 */
83378064Sume	dst6 = ifra->ifra_dstaddr;
834120891Sume	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
83578064Sume	    (dst6.sin6_family == AF_INET6)) {
836148385Sume		struct in6_addr in6_tmp;
837126552Sume		u_int32_t zoneid;
83878064Sume
839148385Sume		in6_tmp = dst6.sin6_addr;
840148385Sume		if (in6_setscope(&in6_tmp, ifp, &zoneid))
841148385Sume			return (EINVAL); /* XXX: should be impossible */
842148385Sume
843148385Sume		if (dst6.sin6_scope_id != 0) {
844148385Sume			if (dst6.sin6_scope_id != zoneid)
845148385Sume				return (EINVAL);
846148385Sume		} else		/* user omit to specify the ID. */
847126552Sume			dst6.sin6_scope_id = zoneid;
848148385Sume
849148385Sume		/* convert into the internal form */
850148385Sume		if (sa6_embedscope(&dst6, 0))
851148385Sume			return (EINVAL); /* XXX: should be impossible */
85278064Sume	}
85378064Sume	/*
85478064Sume	 * The destination address can be specified only for a p2p or a
85578064Sume	 * loopback interface.  If specified, the corresponding prefix length
85678064Sume	 * must be 128.
85778064Sume	 */
85878064Sume	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
85978064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
860126552Sume			/* XXX: noisy message */
861122059Sume			nd6log((LOG_INFO, "in6_update_ifa: a destination can "
862122059Sume			    "be specified for a p2p or a loopback IF only\n"));
863120856Sume			return (EINVAL);
86478064Sume		}
86578064Sume		if (plen != 128) {
866122059Sume			nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
867122059Sume			    "be 128 when dstaddr is specified\n"));
868120856Sume			return (EINVAL);
86978064Sume		}
87078064Sume	}
87178064Sume	/* lifetime consistency check */
87278064Sume	lt = &ifra->ifra_lifetime;
873151539Ssuz	if (lt->ia6t_pltime > lt->ia6t_vltime)
874151539Ssuz		return (EINVAL);
87578064Sume	if (lt->ia6t_vltime == 0) {
87662587Sitojun		/*
87778064Sume		 * the following log might be noisy, but this is a typical
87878064Sume		 * configuration mistake or a tool's bug.
87962587Sitojun		 */
880122059Sume		nd6log((LOG_INFO,
88178064Sume		    "in6_update_ifa: valid lifetime is 0 for %s\n",
882122059Sume		    ip6_sprintf(&ifra->ifra_addr.sin6_addr)));
883151539Ssuz
884151539Ssuz		if (ia == NULL)
885151539Ssuz			return (0); /* there's nothing to do */
88678064Sume	}
88762587Sitojun
88878064Sume	/*
88978064Sume	 * If this is a new address, allocate a new ifaddr and link it
89078064Sume	 * into chains.
89178064Sume	 */
89278064Sume	if (ia == NULL) {
89378064Sume		hostIsNew = 1;
89479763Sume		/*
89579763Sume		 * When in6_update_ifa() is called in a process of a received
896120891Sume		 * RA, it is called under an interrupt context.  So, we should
897120891Sume		 * call malloc with M_NOWAIT.
89879763Sume		 */
899120891Sume		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
900120891Sume		    M_NOWAIT);
90178064Sume		if (ia == NULL)
90278064Sume			return (ENOBUFS);
90378064Sume		bzero((caddr_t)ia, sizeof(*ia));
904151539Ssuz		/* Initialize the address and masks, and put time stamp */
905108033Shsu		IFA_LOCK_INIT(&ia->ia_ifa);
90678064Sume		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
90778064Sume		ia->ia_addr.sin6_family = AF_INET6;
90878064Sume		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
909151539Ssuz		ia->ia6_createtime = time_second;
91078064Sume		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
91178064Sume			/*
91278064Sume			 * XXX: some functions expect that ifa_dstaddr is not
91378064Sume			 * NULL for p2p interfaces.
91478064Sume			 */
915120891Sume			ia->ia_ifa.ifa_dstaddr =
916120891Sume			    (struct sockaddr *)&ia->ia_dstaddr;
91778064Sume		} else {
91878064Sume			ia->ia_ifa.ifa_dstaddr = NULL;
91953541Sshin		}
920108033Shsu		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
92178064Sume
92278064Sume		ia->ia_ifp = ifp;
92378064Sume		if ((oia = in6_ifaddr) != NULL) {
92478064Sume			for ( ; oia->ia_next; oia = oia->ia_next)
92578064Sume				continue;
92678064Sume			oia->ia_next = ia;
92778064Sume		} else
92878064Sume			in6_ifaddr = ia;
92978064Sume
930108033Shsu		ia->ia_ifa.ifa_refcnt = 1;
931108033Shsu		TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
93278064Sume	}
93378064Sume
934151539Ssuz	/* update timestamp */
935151539Ssuz	ia->ia6_updatetime = time_second;
936151539Ssuz
93778064Sume	/* set prefix mask */
93878064Sume	if (ifra->ifra_prefixmask.sin6_len) {
93978064Sume		/*
94078064Sume		 * We prohibit changing the prefix length of an existing
94178064Sume		 * address, because
94278064Sume		 * + such an operation should be rare in IPv6, and
94378064Sume		 * + the operation would confuse prefix management.
94478064Sume		 */
94578064Sume		if (ia->ia_prefixmask.sin6_len &&
94678064Sume		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
947122059Sume			nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
94878064Sume			    " existing (%s) address should not be changed\n",
949122059Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr)));
95078064Sume			error = EINVAL;
95178064Sume			goto unlink;
95253541Sshin		}
95378064Sume		ia->ia_prefixmask = ifra->ifra_prefixmask;
95478064Sume	}
95578064Sume
95678064Sume	/*
95778064Sume	 * If a new destination address is specified, scrub the old one and
95878064Sume	 * install the new destination.  Note that the interface must be
959120891Sume	 * p2p or loopback (see the check above.)
96078064Sume	 */
96178064Sume	if (dst6.sin6_family == AF_INET6 &&
962120891Sume	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
96378064Sume		int e;
96478064Sume
96578064Sume		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
966120891Sume		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
967122059Sume			nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
96878064Sume			    "a route to the old destination: %s\n",
969122059Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr)));
97078064Sume			/* proceed anyway... */
971120891Sume		} else
97278064Sume			ia->ia_flags &= ~IFA_ROUTE;
97378064Sume		ia->ia_dstaddr = dst6;
97478064Sume	}
97553541Sshin
976148385Sume	/*
977148385Sume	 * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
978148385Sume	 * to see if the address is deprecated or invalidated, but initialize
979148385Sume	 * these members for applications.
980148385Sume	 */
981148385Sume	ia->ia6_lifetime = ifra->ifra_lifetime;
982148385Sume	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
983148385Sume		ia->ia6_lifetime.ia6t_expire =
984148385Sume		    time_second + ia->ia6_lifetime.ia6t_vltime;
985148385Sume	} else
986148385Sume		ia->ia6_lifetime.ia6t_expire = 0;
987148385Sume	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
988148385Sume		ia->ia6_lifetime.ia6t_preferred =
989148385Sume		    time_second + ia->ia6_lifetime.ia6t_pltime;
990148385Sume	} else
991148385Sume		ia->ia6_lifetime.ia6t_preferred = 0;
992148385Sume
99378064Sume	/* reset the interface and routing table appropriately. */
99478064Sume	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
99578064Sume		goto unlink;
99678064Sume
99778064Sume	/*
998148385Sume	 * configure address flags.
999148385Sume	 */
1000148385Sume	ia->ia6_flags = ifra->ifra_flags;
1001148385Sume	/*
1002148385Sume	 * backward compatibility - if IN6_IFF_DEPRECATED is set from the
1003148385Sume	 * userland, make it deprecated.
1004148385Sume	 */
1005148385Sume	if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
1006148385Sume		ia->ia6_lifetime.ia6t_pltime = 0;
1007148385Sume		ia->ia6_lifetime.ia6t_preferred = time_second;
1008148385Sume	}
1009148385Sume	/*
1010151539Ssuz	 * Make the address tentative before joining multicast addresses,
1011151539Ssuz	 * so that corresponding MLD responses would not have a tentative
1012151539Ssuz	 * source address.
1013148385Sume	 */
1014151539Ssuz	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/* safety */
1015151539Ssuz	if (hostIsNew && in6if_do_dad(ifp))
1016148385Sume		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1017148385Sume
1018148385Sume	/*
1019148385Sume	 * We are done if we have simply modified an existing address.
1020148385Sume	 */
1021148385Sume	if (!hostIsNew)
1022148385Sume		return (error);
1023148385Sume
1024148385Sume	/*
102578064Sume	 * Beyond this point, we should call in6_purgeaddr upon an error,
1026120891Sume	 * not just go to unlink.
102778064Sume	 */
102878064Sume
1029151465Ssuz	/* Join necessary multicast groups */
1030151539Ssuz	in6m_sol = NULL;
103178064Sume	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
103278064Sume		struct sockaddr_in6 mltaddr, mltmask;
1033148385Sume		struct in6_addr llsol;
103478064Sume
1035148385Sume		/* join solicited multicast addr for new host id */
1036148385Sume		bzero(&llsol, sizeof(struct in6_addr));
1037151465Ssuz		llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
1038148385Sume		llsol.s6_addr32[1] = 0;
1039148385Sume		llsol.s6_addr32[2] = htonl(1);
1040148385Sume		llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
1041148385Sume		llsol.s6_addr8[12] = 0xff;
1042148385Sume		if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
1043148385Sume			/* XXX: should not happen */
1044148385Sume			log(LOG_ERR, "in6_update_ifa: "
1045148385Sume			    "in6_setscope failed\n");
1046148385Sume			goto cleanup;
104753541Sshin		}
1048151539Ssuz		delay = 0;
1049151539Ssuz		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1050151539Ssuz			/*
1051151539Ssuz			 * We need a random delay for DAD on the address
1052151539Ssuz			 * being configured.  It also means delaying
1053151539Ssuz			 * transmission of the corresponding MLD report to
1054151539Ssuz			 * avoid report collision.
1055151539Ssuz			 * [draft-ietf-ipv6-rfc2462bis-02.txt]
1056151539Ssuz			 */
1057151539Ssuz			delay = arc4random() %
1058151539Ssuz			    (MAX_RTR_SOLICITATION_DELAY * hz);
1059151539Ssuz		}
1060151539Ssuz		imm = in6_joingroup(ifp, &llsol, &error, delay);
1061148385Sume		if (error != 0) {
1062148385Sume			nd6log((LOG_WARNING,
1063148385Sume			    "in6_update_ifa: addmulti failed for "
1064148385Sume			    "%s on %s (errno=%d)\n",
1065148385Sume			    ip6_sprintf(&llsol), if_name(ifp),
1066148385Sume			    error));
1067151539Ssuz			in6_purgeaddr((struct ifaddr *)ia);
1068151539Ssuz			return (error);
1069148385Sume		}
1070151539Ssuz		in6m_sol = imm->i6mm_maddr;
107153541Sshin
107278064Sume		bzero(&mltmask, sizeof(mltmask));
107378064Sume		mltmask.sin6_len = sizeof(struct sockaddr_in6);
107478064Sume		mltmask.sin6_family = AF_INET6;
107578064Sume		mltmask.sin6_addr = in6mask32;
1076151465Ssuz#define	MLTMASK_LEN  4	/* mltmask's masklen (=32bit=4octet) */
107753541Sshin
107853541Sshin		/*
107978064Sume		 * join link-local all-nodes address
108071207Sitojun		 */
108178064Sume		bzero(&mltaddr, sizeof(mltaddr));
108278064Sume		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
108378064Sume		mltaddr.sin6_family = AF_INET6;
108478064Sume		mltaddr.sin6_addr = in6addr_linklocal_allnodes;
1085148385Sume		if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) !=
1086148385Sume		    0)
1087148385Sume			goto cleanup; /* XXX: should not fail */
108871207Sitojun
1089148385Sume		/*
1090148385Sume		 * XXX: do we really need this automatic routes?
1091148385Sume		 * We should probably reconsider this stuff.  Most applications
1092148385Sume		 * actually do not need the routes, since they usually specify
1093148385Sume		 * the outgoing interface.
1094148385Sume		 */
1095148385Sume		rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
1096148385Sume		if (rt) {
1097148385Sume			if (memcmp(&mltaddr.sin6_addr,
1098148385Sume			    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1099151465Ssuz			    MLTMASK_LEN)) {
1100148385Sume				RTFREE_LOCKED(rt);
1101148385Sume				rt = NULL;
1102148385Sume			}
1103148385Sume		}
1104148385Sume		if (!rt) {
1105148385Sume			/* XXX: we need RTF_CLONING to fake nd6_rtrequest */
1106148385Sume			error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
1107148385Sume			    (struct sockaddr *)&ia->ia_addr,
1108148385Sume			    (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
1109148385Sume			    (struct rtentry **)0);
1110148385Sume			if (error)
1111148385Sume				goto cleanup;
1112148385Sume		} else
1113148385Sume			RTFREE_LOCKED(rt);
1114148385Sume
1115151539Ssuz		/*
1116151539Ssuz		 * XXX: do we really need this automatic routes?
1117151539Ssuz		 * We should probably reconsider this stuff.  Most applications
1118151539Ssuz		 * actually do not need the routes, since they usually specify
1119151539Ssuz		 * the outgoing interface.
1120151539Ssuz		 */
1121151539Ssuz		rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
1122151539Ssuz		if (rt) {
1123151539Ssuz			/* XXX: only works in !SCOPEDROUTING case. */
1124151539Ssuz			if (memcmp(&mltaddr.sin6_addr,
1125151539Ssuz			    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1126151539Ssuz			    MLTMASK_LEN)) {
1127151539Ssuz				RTFREE_LOCKED(rt);
1128151539Ssuz				rt = NULL;
112978064Sume			}
113078064Sume		}
1131151539Ssuz		if (!rt) {
1132151539Ssuz			error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
1133151539Ssuz			    (struct sockaddr *)&ia->ia_addr,
1134151539Ssuz			    (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
1135151539Ssuz			    (struct rtentry **)0);
1136151539Ssuz			if (error)
1137151539Ssuz				goto cleanup;
1138151539Ssuz		} else {
1139151539Ssuz			RTFREE_LOCKED(rt);
1140151539Ssuz		}
114178064Sume
1142151539Ssuz		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
1143151539Ssuz		if (!imm) {
1144151539Ssuz			nd6log((LOG_WARNING,
1145151539Ssuz			    "in6_update_ifa: addmulti failed for "
1146151539Ssuz			    "%s on %s (errno=%d)\n",
1147151539Ssuz			    ip6_sprintf(&mltaddr.sin6_addr),
1148151539Ssuz			    if_name(ifp), error));
1149151539Ssuz			goto cleanup;
1150151539Ssuz		}
1151151539Ssuz
115271207Sitojun		/*
115378064Sume		 * join node information group address
115453541Sshin		 */
115578064Sume#define hostnamelen	strlen(hostname)
1156151539Ssuz		delay = 0;
1157151539Ssuz		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1158151539Ssuz			/*
1159151539Ssuz			 * The spec doesn't say anything about delay for this
1160151539Ssuz			 * group, but the same logic should apply.
1161151539Ssuz			 */
1162151539Ssuz			delay = arc4random() %
1163151539Ssuz			    (MAX_RTR_SOLICITATION_DELAY * hz);
1164151539Ssuz		}
116578064Sume		if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr)
116678064Sume		    == 0) {
1167151539Ssuz			imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error,
1168151539Ssuz			    delay); /* XXX jinmei */
1169151539Ssuz			if (!imm) {
1170151539Ssuz				nd6log((LOG_WARNING, "in6_update_ifa: "
1171151539Ssuz				    "addmulti failed for %s on %s "
1172151539Ssuz				    "(errno=%d)\n",
1173151539Ssuz				    ip6_sprintf(&mltaddr.sin6_addr),
1174151539Ssuz				    if_name(ifp), error));
1175151539Ssuz				/* XXX not very fatal, go on... */
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		/* XXX: again, do we really need the route? */
1209151539Ssuz		rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0UL);
1210151539Ssuz		if (rt) {
1211151539Ssuz			if (memcmp(&mltaddr.sin6_addr,
1212151539Ssuz			    &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1213151539Ssuz			    MLTMASK_LEN)) {
1214151539Ssuz				RTFREE_LOCKED(rt);
1215151539Ssuz				rt = NULL;
121678064Sume			}
121753541Sshin		}
1218151539Ssuz		if (!rt) {
1219151539Ssuz			error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
1220151539Ssuz			    (struct sockaddr *)&ia->ia_addr,
1221151539Ssuz			    (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
1222151539Ssuz			    (struct rtentry **)0);
1223151539Ssuz			if (error)
1224151539Ssuz				goto cleanup;
1225151539Ssuz		} else {
1226151539Ssuz			RTFREE_LOCKED(rt);
1227151539Ssuz		}
1228151539Ssuz
1229151539Ssuz		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
1230151539Ssuz		if (!imm) {
1231151539Ssuz			nd6log((LOG_WARNING, "in6_update_ifa: "
1232151539Ssuz			    "addmulti failed for %s on %s "
1233151539Ssuz			    "(errno=%d)\n",
1234151539Ssuz			    ip6_sprintf(&mltaddr.sin6_addr),
1235151539Ssuz			    if_name(ifp), error));
1236151539Ssuz			goto cleanup;
1237151539Ssuz		}
1238151465Ssuz#undef	MLTMASK_LEN
123978064Sume	}
124053541Sshin
1241151539Ssuz	/*
1242151539Ssuz	 * Perform DAD, if needed.
1243151539Ssuz	 * XXX It may be of use, if we can administratively
1244151539Ssuz	 * disable DAD.
1245151539Ssuz	 */
1246151539Ssuz	if (hostIsNew && in6if_do_dad(ifp) &&
1247151539Ssuz	    ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
1248151539Ssuz	    (ia->ia6_flags & IN6_IFF_TENTATIVE))
1249151539Ssuz	{
1250151539Ssuz		int mindelay, maxdelay;
1251151539Ssuz
1252151539Ssuz		delay = 0;
1253151539Ssuz		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
1254151539Ssuz			/*
1255151539Ssuz			 * We need to impose a delay before sending an NS
1256151539Ssuz			 * for DAD.  Check if we also needed a delay for the
1257151539Ssuz			 * corresponding MLD message.  If we did, the delay
1258151539Ssuz			 * should be larger than the MLD delay (this could be
1259151539Ssuz			 * relaxed a bit, but this simple logic is at least
1260151539Ssuz			 * safe).
1261151539Ssuz			 */
1262151539Ssuz			mindelay = 0;
1263151539Ssuz			if (in6m_sol != NULL &&
1264151539Ssuz			    in6m_sol->in6m_state == MLD_REPORTPENDING) {
1265151539Ssuz				mindelay = in6m_sol->in6m_timer;
1266151539Ssuz			}
1267151539Ssuz			maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
1268151539Ssuz			if (maxdelay - mindelay == 0)
1269151539Ssuz				delay = 0;
1270151539Ssuz			else {
1271151539Ssuz				delay =
1272151539Ssuz				    (arc4random() % (maxdelay - mindelay)) +
1273151539Ssuz				    mindelay;
1274151539Ssuz			}
1275151539Ssuz		}
1276151539Ssuz		nd6_dad_start((struct ifaddr *)ia, delay);
1277151539Ssuz	}
1278151539Ssuz
1279120856Sume	return (error);
128078064Sume
128178064Sume  unlink:
128278064Sume	/*
128378064Sume	 * XXX: if a change of an existing address failed, keep the entry
128478064Sume	 * anyway.
128578064Sume	 */
128678064Sume	if (hostIsNew)
128778064Sume		in6_unlink_ifa(ia, ifp);
1288120856Sume	return (error);
1289148385Sume
1290148385Sume  cleanup:
1291148385Sume	in6_purgeaddr(&ia->ia_ifa);
1292148385Sume	return error;
129353541Sshin}
129453541Sshin
129562587Sitojunvoid
129678064Sumein6_purgeaddr(ifa)
129762587Sitojun	struct ifaddr *ifa;
129862587Sitojun{
129978064Sume	struct ifnet *ifp = ifa->ifa_ifp;
130078064Sume	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
130162587Sitojun
130278064Sume	/* stop DAD processing */
130378064Sume	nd6_dad_stop(ifa);
130462587Sitojun
130578064Sume	/*
130678064Sume	 * delete route to the destination of the address being purged.
130778064Sume	 * The interface must be p2p or loopback in this case.
130878064Sume	 */
130978064Sume	if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
131078064Sume		int e;
131178064Sume
131278064Sume		if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
131378064Sume		    != 0) {
131478064Sume			log(LOG_ERR, "in6_purgeaddr: failed to remove "
131578064Sume			    "a route to the p2p destination: %s on %s, "
131678064Sume			    "errno=%d\n",
131778064Sume			    ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp),
131878064Sume			    e);
131978064Sume			/* proceed anyway... */
1320120891Sume		} else
132178064Sume			ia->ia_flags &= ~IFA_ROUTE;
132278064Sume	}
132378064Sume
132478064Sume	/* Remove ownaddr's loopback rtentry, if it exists. */
132578064Sume	in6_ifremloop(&(ia->ia_ifa));
132678064Sume
132762587Sitojun	if (ifp->if_flags & IFF_MULTICAST) {
132862587Sitojun		/*
132962587Sitojun		 * delete solicited multicast addr for deleting host id
133062587Sitojun		 */
133162587Sitojun		struct in6_multi *in6m;
133262587Sitojun		struct in6_addr llsol;
133362587Sitojun		bzero(&llsol, sizeof(struct in6_addr));
1334151465Ssuz		llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
133562587Sitojun		llsol.s6_addr32[1] = 0;
133662587Sitojun		llsol.s6_addr32[2] = htonl(1);
133762587Sitojun		llsol.s6_addr32[3] =
133862587Sitojun			ia->ia_addr.sin6_addr.s6_addr32[3];
133962587Sitojun		llsol.s6_addr8[12] = 0xff;
1340148385Sume		(void)in6_setscope(&llsol, ifp, NULL); /* XXX proceed anyway */
134162587Sitojun
134262587Sitojun		IN6_LOOKUP_MULTI(llsol, ifp, in6m);
134362587Sitojun		if (in6m)
134462587Sitojun			in6_delmulti(in6m);
134562587Sitojun	}
134662587Sitojun
134778064Sume	in6_unlink_ifa(ia, ifp);
134878064Sume}
134978064Sume
135078064Sumestatic void
135178064Sumein6_unlink_ifa(ia, ifp)
135278064Sume	struct in6_ifaddr *ia;
135378064Sume	struct ifnet *ifp;
135478064Sume{
135578064Sume	struct in6_ifaddr *oia;
135678064Sume	int	s = splnet();
135778064Sume
135862587Sitojun	TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
135962587Sitojun
136062587Sitojun	oia = ia;
136162587Sitojun	if (oia == (ia = in6_ifaddr))
136262587Sitojun		in6_ifaddr = ia->ia_next;
136362587Sitojun	else {
136462587Sitojun		while (ia->ia_next && (ia->ia_next != oia))
136562587Sitojun			ia = ia->ia_next;
136662587Sitojun		if (ia->ia_next)
136762587Sitojun			ia->ia_next = oia->ia_next;
136878064Sume		else {
136978064Sume			/* search failed */
137078064Sume			printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
137178064Sume		}
137262587Sitojun	}
137362587Sitojun
137462587Sitojun	/*
1375151915Ssuz	 * Release the reference to the base prefix.  There should be a
1376151915Ssuz	 * positive reference.
137762587Sitojun	 */
1378151915Ssuz	if (oia->ia6_ndpr == NULL) {
1379151915Ssuz		nd6log((LOG_NOTICE,
1380151915Ssuz		    "in6_unlink_ifa: autoconf'ed address "
1381151915Ssuz		    "%p has no prefix\n", oia));
1382151915Ssuz	} else {
1383151915Ssuz		oia->ia6_ndpr->ndpr_refcnt--;
1384151915Ssuz		oia->ia6_ndpr = NULL;
1385151915Ssuz	}
138662587Sitojun
1387151915Ssuz	/*
1388151915Ssuz	 * Also, if the address being removed is autoconf'ed, call
1389151915Ssuz	 * pfxlist_onlink_check() since the release might affect the status of
1390151915Ssuz	 * other (detached) addresses.
1391151915Ssuz	 */
1392151915Ssuz	if ((oia->ia6_flags & IN6_IFF_AUTOCONF)) {
139378064Sume		pfxlist_onlink_check();
139462587Sitojun	}
139578064Sume
139678064Sume	/*
139778064Sume	 * release another refcnt for the link from in6_ifaddr.
139878064Sume	 * Note that we should decrement the refcnt at least once for all *BSD.
139978064Sume	 */
140062587Sitojun	IFAFREE(&oia->ia_ifa);
140178064Sume
140278064Sume	splx(s);
140362587Sitojun}
140462587Sitojun
140578064Sumevoid
140678064Sumein6_purgeif(ifp)
140778064Sume	struct ifnet *ifp;
140878064Sume{
140978064Sume	struct ifaddr *ifa, *nifa;
141078064Sume
1411120891Sume	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
141278064Sume		nifa = TAILQ_NEXT(ifa, ifa_list);
141378064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
141478064Sume			continue;
141578064Sume		in6_purgeaddr(ifa);
141678064Sume	}
141778064Sume
141878064Sume	in6_ifdetach(ifp);
141978064Sume}
142078064Sume
142153541Sshin/*
142253541Sshin * SIOC[GAD]LIFADDR.
142362744Sgrog *	SIOCGLIFADDR: get first address. (?)
142453541Sshin *	SIOCGLIFADDR with IFLR_PREFIX:
142553541Sshin *		get first address that matches the specified prefix.
142653541Sshin *	SIOCALIFADDR: add the specified address.
142753541Sshin *	SIOCALIFADDR with IFLR_PREFIX:
142853541Sshin *		add the specified prefix, filling hostid part from
142953541Sshin *		the first link-local address.  prefixlen must be <= 64.
143053541Sshin *	SIOCDLIFADDR: delete the specified address.
143153541Sshin *	SIOCDLIFADDR with IFLR_PREFIX:
143253541Sshin *		delete the first address that matches the specified prefix.
143353541Sshin * return values:
143453541Sshin *	EINVAL on invalid parameters
143553541Sshin *	EADDRNOTAVAIL on prefix match failed/specified address not found
143653541Sshin *	other values may be returned from in6_ioctl()
143753541Sshin *
143853541Sshin * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
143953541Sshin * this is to accomodate address naming scheme other than RFC2374,
144053541Sshin * in the future.
144153541Sshin * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
144253541Sshin * address encoding scheme. (see figure on page 8)
144353541Sshin */
144453541Sshinstatic int
144583366Sjulianin6_lifaddr_ioctl(so, cmd, data, ifp, td)
144653541Sshin	struct socket *so;
144753541Sshin	u_long cmd;
144853541Sshin	caddr_t	data;
144953541Sshin	struct ifnet *ifp;
145083366Sjulian	struct thread *td;
145153541Sshin{
145253541Sshin	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
145353541Sshin	struct ifaddr *ifa;
145462587Sitojun	struct sockaddr *sa;
145553541Sshin
145653541Sshin	/* sanity checks */
145753541Sshin	if (!data || !ifp) {
145853541Sshin		panic("invalid argument to in6_lifaddr_ioctl");
1459120891Sume		/* NOTREACHED */
146053541Sshin	}
146153541Sshin
146253541Sshin	switch (cmd) {
146353541Sshin	case SIOCGLIFADDR:
146453541Sshin		/* address must be specified on GET with IFLR_PREFIX */
146553541Sshin		if ((iflr->flags & IFLR_PREFIX) == 0)
146653541Sshin			break;
146795023Ssuz		/* FALLTHROUGH */
146853541Sshin	case SIOCALIFADDR:
146953541Sshin	case SIOCDLIFADDR:
147053541Sshin		/* address must be specified on ADD and DELETE */
147162587Sitojun		sa = (struct sockaddr *)&iflr->addr;
147262587Sitojun		if (sa->sa_family != AF_INET6)
147353541Sshin			return EINVAL;
147462587Sitojun		if (sa->sa_len != sizeof(struct sockaddr_in6))
147553541Sshin			return EINVAL;
147653541Sshin		/* XXX need improvement */
147762587Sitojun		sa = (struct sockaddr *)&iflr->dstaddr;
147862587Sitojun		if (sa->sa_family && sa->sa_family != AF_INET6)
147953541Sshin			return EINVAL;
148062587Sitojun		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
148153541Sshin			return EINVAL;
148253541Sshin		break;
148395023Ssuz	default: /* shouldn't happen */
148462587Sitojun#if 0
148562587Sitojun		panic("invalid cmd to in6_lifaddr_ioctl");
148695023Ssuz		/* NOTREACHED */
148762587Sitojun#else
148853541Sshin		return EOPNOTSUPP;
148962587Sitojun#endif
149053541Sshin	}
149153541Sshin	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
149253541Sshin		return EINVAL;
149353541Sshin
149453541Sshin	switch (cmd) {
149553541Sshin	case SIOCALIFADDR:
149653541Sshin	    {
149753541Sshin		struct in6_aliasreq ifra;
149853541Sshin		struct in6_addr *hostid = NULL;
149953541Sshin		int prefixlen;
150053541Sshin
150153541Sshin		if ((iflr->flags & IFLR_PREFIX) != 0) {
150253541Sshin			struct sockaddr_in6 *sin6;
150353541Sshin
150453541Sshin			/*
150553541Sshin			 * hostid is to fill in the hostid part of the
150653541Sshin			 * address.  hostid points to the first link-local
150753541Sshin			 * address attached to the interface.
150853541Sshin			 */
150962587Sitojun			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
151053541Sshin			if (!ifa)
151153541Sshin				return EADDRNOTAVAIL;
151253541Sshin			hostid = IFA_IN6(ifa);
151353541Sshin
151453541Sshin		 	/* prefixlen must be <= 64. */
151553541Sshin			if (64 < iflr->prefixlen)
151653541Sshin				return EINVAL;
151753541Sshin			prefixlen = iflr->prefixlen;
151853541Sshin
151953541Sshin			/* hostid part must be zero. */
152053541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1521126552Sume			if (sin6->sin6_addr.s6_addr32[2] != 0 ||
1522126552Sume			    sin6->sin6_addr.s6_addr32[3] != 0) {
152353541Sshin				return EINVAL;
152453541Sshin			}
152553541Sshin		} else
152653541Sshin			prefixlen = iflr->prefixlen;
152753541Sshin
152853541Sshin		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
152953541Sshin		bzero(&ifra, sizeof(ifra));
1530120891Sume		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
153153541Sshin
153262587Sitojun		bcopy(&iflr->addr, &ifra.ifra_addr,
1533120891Sume		    ((struct sockaddr *)&iflr->addr)->sa_len);
153453541Sshin		if (hostid) {
153553541Sshin			/* fill in hostid part */
153653541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1537120891Sume			    hostid->s6_addr32[2];
153853541Sshin			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1539120891Sume			    hostid->s6_addr32[3];
154053541Sshin		}
154153541Sshin
1542120891Sume		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
154353541Sshin			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1544120891Sume			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
154553541Sshin			if (hostid) {
154653541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1547120891Sume				    hostid->s6_addr32[2];
154853541Sshin				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1549120891Sume				    hostid->s6_addr32[3];
155053541Sshin			}
155153541Sshin		}
155253541Sshin
155353541Sshin		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1554121168Sume		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
155553541Sshin
155653541Sshin		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
155783366Sjulian		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
155853541Sshin	    }
155953541Sshin	case SIOCGLIFADDR:
156053541Sshin	case SIOCDLIFADDR:
156153541Sshin	    {
156253541Sshin		struct in6_ifaddr *ia;
156353541Sshin		struct in6_addr mask, candidate, match;
156453541Sshin		struct sockaddr_in6 *sin6;
156553541Sshin		int cmp;
156653541Sshin
156753541Sshin		bzero(&mask, sizeof(mask));
156853541Sshin		if (iflr->flags & IFLR_PREFIX) {
156953541Sshin			/* lookup a prefix rather than address. */
1570121168Sume			in6_prefixlen2mask(&mask, iflr->prefixlen);
157153541Sshin
157253541Sshin			sin6 = (struct sockaddr_in6 *)&iflr->addr;
157353541Sshin			bcopy(&sin6->sin6_addr, &match, sizeof(match));
157453541Sshin			match.s6_addr32[0] &= mask.s6_addr32[0];
157553541Sshin			match.s6_addr32[1] &= mask.s6_addr32[1];
157653541Sshin			match.s6_addr32[2] &= mask.s6_addr32[2];
157753541Sshin			match.s6_addr32[3] &= mask.s6_addr32[3];
157853541Sshin
157953541Sshin			/* if you set extra bits, that's wrong */
158053541Sshin			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
158153541Sshin				return EINVAL;
158253541Sshin
158353541Sshin			cmp = 1;
158453541Sshin		} else {
158553541Sshin			if (cmd == SIOCGLIFADDR) {
158653541Sshin				/* on getting an address, take the 1st match */
158795023Ssuz				cmp = 0;	/* XXX */
158853541Sshin			} else {
158953541Sshin				/* on deleting an address, do exact match */
1590121168Sume				in6_prefixlen2mask(&mask, 128);
159153541Sshin				sin6 = (struct sockaddr_in6 *)&iflr->addr;
159253541Sshin				bcopy(&sin6->sin6_addr, &match, sizeof(match));
159353541Sshin
159453541Sshin				cmp = 1;
159553541Sshin			}
159653541Sshin		}
159753541Sshin
1598120891Sume		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
159953541Sshin			if (ifa->ifa_addr->sa_family != AF_INET6)
160053541Sshin				continue;
160153541Sshin			if (!cmp)
160253541Sshin				break;
160378064Sume
160478064Sume			/*
160578064Sume			 * XXX: this is adhoc, but is necessary to allow
160678064Sume			 * a user to specify fe80::/64 (not /10) for a
160778064Sume			 * link-local address.
160878064Sume			 */
1609148385Sume			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1610148385Sume			in6_clearscope(&candidate);
161153541Sshin			candidate.s6_addr32[0] &= mask.s6_addr32[0];
161253541Sshin			candidate.s6_addr32[1] &= mask.s6_addr32[1];
161353541Sshin			candidate.s6_addr32[2] &= mask.s6_addr32[2];
161453541Sshin			candidate.s6_addr32[3] &= mask.s6_addr32[3];
161553541Sshin			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
161653541Sshin				break;
161753541Sshin		}
161853541Sshin		if (!ifa)
161953541Sshin			return EADDRNOTAVAIL;
162053541Sshin		ia = ifa2ia6(ifa);
162153541Sshin
162253541Sshin		if (cmd == SIOCGLIFADDR) {
1623148385Sume			int error;
162478064Sume
162553541Sshin			/* fill in the if_laddrreq structure */
162653541Sshin			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1627148385Sume			error = sa6_recoverscope(
1628148385Sume			    (struct sockaddr_in6 *)&iflr->addr);
1629148385Sume			if (error != 0)
1630148385Sume				return (error);
1631148385Sume
163253541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
163353541Sshin				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1634120891Sume				    ia->ia_dstaddr.sin6_len);
1635148385Sume				error = sa6_recoverscope(
1636148385Sume				    (struct sockaddr_in6 *)&iflr->dstaddr);
1637148385Sume				if (error != 0)
1638148385Sume					return (error);
163953541Sshin			} else
164053541Sshin				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
164153541Sshin
164253541Sshin			iflr->prefixlen =
1643120891Sume			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
164453541Sshin
164595023Ssuz			iflr->flags = ia->ia6_flags;	/* XXX */
164653541Sshin
164753541Sshin			return 0;
164853541Sshin		} else {
164953541Sshin			struct in6_aliasreq ifra;
165053541Sshin
165153541Sshin			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
165253541Sshin			bzero(&ifra, sizeof(ifra));
165353541Sshin			bcopy(iflr->iflr_name, ifra.ifra_name,
1654120891Sume			    sizeof(ifra.ifra_name));
165553541Sshin
165653541Sshin			bcopy(&ia->ia_addr, &ifra.ifra_addr,
1657120891Sume			    ia->ia_addr.sin6_len);
165853541Sshin			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
165953541Sshin				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1660120891Sume				    ia->ia_dstaddr.sin6_len);
166162587Sitojun			} else {
166262587Sitojun				bzero(&ifra.ifra_dstaddr,
166362587Sitojun				    sizeof(ifra.ifra_dstaddr));
166453541Sshin			}
166553541Sshin			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1666120891Sume			    ia->ia_prefixmask.sin6_len);
166753541Sshin
166853541Sshin			ifra.ifra_flags = ia->ia6_flags;
166953541Sshin			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1670120891Sume			    ifp, td);
167153541Sshin		}
167253541Sshin	    }
167353541Sshin	}
167453541Sshin
167595023Ssuz	return EOPNOTSUPP;	/* just for safety */
167653541Sshin}
167753541Sshin
167853541Sshin/*
167953541Sshin * Initialize an interface's intetnet6 address
168053541Sshin * and routing table entry.
168153541Sshin */
168278064Sumestatic int
168378064Sumein6_ifinit(ifp, ia, sin6, newhost)
168453541Sshin	struct ifnet *ifp;
168553541Sshin	struct in6_ifaddr *ia;
168653541Sshin	struct sockaddr_in6 *sin6;
168778064Sume	int newhost;
168853541Sshin{
168978064Sume	int	error = 0, plen, ifacount = 0;
169053541Sshin	int	s = splimp();
169178064Sume	struct ifaddr *ifa;
169253541Sshin
169353541Sshin	/*
169453541Sshin	 * Give the interface a chance to initialize
169553541Sshin	 * if this is its first address,
169653541Sshin	 * and to validate the address if necessary.
169753541Sshin	 */
1698120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
169978064Sume		if (ifa->ifa_addr == NULL)
170078064Sume			continue;	/* just for safety */
170178064Sume		if (ifa->ifa_addr->sa_family != AF_INET6)
170278064Sume			continue;
170378064Sume		ifacount++;
170478064Sume	}
170578064Sume
170678064Sume	ia->ia_addr = *sin6;
170778064Sume
1708146883Siedowse	if (ifacount <= 1 && ifp->if_ioctl) {
1709146883Siedowse		IFF_LOCKGIANT(ifp);
1710146883Siedowse		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
1711146883Siedowse		IFF_UNLOCKGIANT(ifp);
1712146883Siedowse		if (error) {
1713146883Siedowse			splx(s);
1714146883Siedowse			return (error);
1715146883Siedowse		}
171653541Sshin	}
171778064Sume	splx(s);
171853541Sshin
171978064Sume	ia->ia_ifa.ifa_metric = ifp->if_metric;
172053541Sshin
172178064Sume	/* we could do in(6)_socktrim here, but just omit it at this moment. */
172278064Sume
172353541Sshin	/*
172478064Sume	 * Special case:
1725124337Sume	 * If a new destination address is specified for a point-to-point
172678064Sume	 * interface, install a route to the destination as an interface
172778064Sume	 * direct route.
1728124337Sume	 * XXX: the logic below rejects assigning multiple addresses on a p2p
1729124337Sume	 * interface that share a same destination.
173053541Sshin	 */
173178064Sume	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1732124337Sume	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
1733124337Sume	    ia->ia_dstaddr.sin6_family == AF_INET6) {
173478064Sume		if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
173578064Sume				    RTF_UP | RTF_HOST)) != 0)
1736120856Sume			return (error);
173778064Sume		ia->ia_flags |= IFA_ROUTE;
173853541Sshin	}
173978064Sume	if (plen < 128) {
174078064Sume		/*
174178064Sume		 * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
174278064Sume		 */
174378064Sume		ia->ia_ifa.ifa_flags |= RTF_CLONING;
174478064Sume	}
174553541Sshin
174695023Ssuz	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
174778064Sume	if (newhost) {
174878064Sume		/* set the rtrequest function to create llinfo */
174978064Sume		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
175078064Sume		in6_ifaddloop(&(ia->ia_ifa));
175178064Sume	}
175253541Sshin
1753120856Sume	return (error);
175453541Sshin}
175553541Sshin
1756142215Sglebiusstruct in6_multi_mship *
1757151539Ssuzin6_joingroup(ifp, addr, errorp, delay)
1758142215Sglebius	struct ifnet *ifp;
1759142215Sglebius	struct in6_addr *addr;
1760142215Sglebius	int *errorp;
1761151539Ssuz	int delay;
1762142215Sglebius{
1763142215Sglebius	struct in6_multi_mship *imm;
1764142215Sglebius
1765149849Sobrien	imm = malloc(sizeof(*imm), M_IP6MADDR, M_NOWAIT);
1766142215Sglebius	if (!imm) {
1767142215Sglebius		*errorp = ENOBUFS;
1768142215Sglebius		return NULL;
1769142215Sglebius	}
1770151539Ssuz	imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp, delay);
1771142215Sglebius	if (!imm->i6mm_maddr) {
1772142215Sglebius		/* *errorp is alrady set */
1773149849Sobrien		free(imm, M_IP6MADDR);
1774142215Sglebius		return NULL;
1775142215Sglebius	}
1776142215Sglebius	return imm;
1777142215Sglebius}
1778142215Sglebius
1779142215Sglebiusint
1780142215Sglebiusin6_leavegroup(imm)
1781142215Sglebius	struct in6_multi_mship *imm;
1782142215Sglebius{
1783142215Sglebius
1784142215Sglebius	if (imm->i6mm_maddr)
1785142215Sglebius		in6_delmulti(imm->i6mm_maddr);
1786149849Sobrien	free(imm,  M_IP6MADDR);
1787142215Sglebius	return 0;
1788142215Sglebius}
1789142215Sglebius
179053541Sshin/*
179153541Sshin * Find an IPv6 interface link-local address specific to an interface.
179253541Sshin */
179353541Sshinstruct in6_ifaddr *
179462587Sitojunin6ifa_ifpforlinklocal(ifp, ignoreflags)
179553541Sshin	struct ifnet *ifp;
179662587Sitojun	int ignoreflags;
179753541Sshin{
179878064Sume	struct ifaddr *ifa;
179953541Sshin
1800120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
180153541Sshin		if (ifa->ifa_addr == NULL)
180253541Sshin			continue;	/* just for safety */
180353541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
180453541Sshin			continue;
180562587Sitojun		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
180662587Sitojun			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
180762587Sitojun			     ignoreflags) != 0)
180862587Sitojun				continue;
180953541Sshin			break;
181062587Sitojun		}
181153541Sshin	}
181253541Sshin
1813120856Sume	return ((struct in6_ifaddr *)ifa);
181453541Sshin}
181553541Sshin
181653541Sshin
181753541Sshin/*
181853541Sshin * find the internet address corresponding to a given interface and address.
181953541Sshin */
182053541Sshinstruct in6_ifaddr *
182153541Sshinin6ifa_ifpwithaddr(ifp, addr)
182253541Sshin	struct ifnet *ifp;
182353541Sshin	struct in6_addr *addr;
182453541Sshin{
182578064Sume	struct ifaddr *ifa;
182653541Sshin
1827120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
182853541Sshin		if (ifa->ifa_addr == NULL)
182953541Sshin			continue;	/* just for safety */
183053541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
183153541Sshin			continue;
183253541Sshin		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
183353541Sshin			break;
183453541Sshin	}
183553541Sshin
1836120856Sume	return ((struct in6_ifaddr *)ifa);
183753541Sshin}
183853541Sshin
183953541Sshin/*
184053541Sshin * Convert IP6 address to printable (loggable) representation.
184153541Sshin */
184253541Sshinstatic char digits[] = "0123456789abcdef";
184353541Sshinstatic int ip6round = 0;
184453541Sshinchar *
184553541Sshinip6_sprintf(addr)
184678064Sume	const struct in6_addr *addr;
184753541Sshin{
184853541Sshin	static char ip6buf[8][48];
184978064Sume	int i;
185078064Sume	char *cp;
1851126552Sume	const u_int16_t *a = (const u_int16_t *)addr;
1852126552Sume	const u_int8_t *d;
185353541Sshin	int dcolon = 0;
185453541Sshin
185553541Sshin	ip6round = (ip6round + 1) & 7;
185653541Sshin	cp = ip6buf[ip6round];
185753541Sshin
185853541Sshin	for (i = 0; i < 8; i++) {
185953541Sshin		if (dcolon == 1) {
186053541Sshin			if (*a == 0) {
186153541Sshin				if (i == 7)
186253541Sshin					*cp++ = ':';
186353541Sshin				a++;
186453541Sshin				continue;
186553541Sshin			} else
186653541Sshin				dcolon = 2;
186753541Sshin		}
186853541Sshin		if (*a == 0) {
186953541Sshin			if (dcolon == 0 && *(a + 1) == 0) {
187053541Sshin				if (i == 0)
187153541Sshin					*cp++ = ':';
187253541Sshin				*cp++ = ':';
187353541Sshin				dcolon = 1;
187453541Sshin			} else {
187553541Sshin				*cp++ = '0';
187653541Sshin				*cp++ = ':';
187753541Sshin			}
187853541Sshin			a++;
187953541Sshin			continue;
188053541Sshin		}
188191346Salfred		d = (const u_char *)a;
188253541Sshin		*cp++ = digits[*d >> 4];
188353541Sshin		*cp++ = digits[*d++ & 0xf];
188453541Sshin		*cp++ = digits[*d >> 4];
188553541Sshin		*cp++ = digits[*d & 0xf];
188653541Sshin		*cp++ = ':';
188753541Sshin		a++;
188853541Sshin	}
188953541Sshin	*--cp = 0;
1890120856Sume	return (ip6buf[ip6round]);
189153541Sshin}
189253541Sshin
189353541Sshinint
189453541Sshinin6_localaddr(in6)
189553541Sshin	struct in6_addr *in6;
189653541Sshin{
189753541Sshin	struct in6_ifaddr *ia;
189853541Sshin
189953541Sshin	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
190053541Sshin		return 1;
190153541Sshin
1902120891Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
190353541Sshin		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1904120891Sume		    &ia->ia_prefixmask.sin6_addr)) {
190553541Sshin			return 1;
1906120891Sume		}
1907120891Sume	}
190853541Sshin
190953541Sshin	return (0);
191053541Sshin}
191153541Sshin
191278064Sumeint
191378064Sumein6_is_addr_deprecated(sa6)
191478064Sume	struct sockaddr_in6 *sa6;
191578064Sume{
191678064Sume	struct in6_ifaddr *ia;
191778064Sume
191878064Sume	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
191978064Sume		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
192078064Sume				       &sa6->sin6_addr) &&
192178064Sume		    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
1922120856Sume			return (1); /* true */
192378064Sume
192478064Sume		/* XXX: do we still have to go thru the rest of the list? */
192578064Sume	}
192678064Sume
1927120856Sume	return (0);		/* false */
192878064Sume}
192978064Sume
193053541Sshin/*
193153541Sshin * return length of part which dst and src are equal
193253541Sshin * hard coding...
193353541Sshin */
193453541Sshinint
193553541Sshinin6_matchlen(src, dst)
193653541Sshinstruct in6_addr *src, *dst;
193753541Sshin{
193853541Sshin	int match = 0;
193953541Sshin	u_char *s = (u_char *)src, *d = (u_char *)dst;
194053541Sshin	u_char *lim = s + 16, r;
194153541Sshin
194253541Sshin	while (s < lim)
194353541Sshin		if ((r = (*d++ ^ *s++)) != 0) {
194453541Sshin			while (r < 128) {
194553541Sshin				match++;
194653541Sshin				r <<= 1;
194753541Sshin			}
194853541Sshin			break;
194953541Sshin		} else
195053541Sshin			match += 8;
195153541Sshin	return match;
195253541Sshin}
195353541Sshin
195462587Sitojun/* XXX: to be scope conscious */
195553541Sshinint
195653541Sshinin6_are_prefix_equal(p1, p2, len)
195753541Sshin	struct in6_addr *p1, *p2;
195853541Sshin	int len;
195953541Sshin{
196053541Sshin	int bytelen, bitlen;
196153541Sshin
196253541Sshin	/* sanity check */
196353541Sshin	if (0 > len || len > 128) {
196453541Sshin		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
196553541Sshin		    len);
1966120856Sume		return (0);
196753541Sshin	}
196853541Sshin
196953541Sshin	bytelen = len / 8;
197053541Sshin	bitlen = len % 8;
197153541Sshin
197253541Sshin	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
1973120856Sume		return (0);
1974126184Scperciva	if (bitlen != 0 &&
1975126184Scperciva	    p1->s6_addr[bytelen] >> (8 - bitlen) !=
197653541Sshin	    p2->s6_addr[bytelen] >> (8 - bitlen))
1977120856Sume		return (0);
197853541Sshin
1979120856Sume	return (1);
198053541Sshin}
198153541Sshin
198253541Sshinvoid
198353541Sshinin6_prefixlen2mask(maskp, len)
198453541Sshin	struct in6_addr *maskp;
198553541Sshin	int len;
198653541Sshin{
198753541Sshin	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
198853541Sshin	int bytelen, bitlen, i;
198953541Sshin
199053541Sshin	/* sanity check */
199153541Sshin	if (0 > len || len > 128) {
199253541Sshin		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
199353541Sshin		    len);
199453541Sshin		return;
199553541Sshin	}
199653541Sshin
199753541Sshin	bzero(maskp, sizeof(*maskp));
199853541Sshin	bytelen = len / 8;
199953541Sshin	bitlen = len % 8;
200053541Sshin	for (i = 0; i < bytelen; i++)
200153541Sshin		maskp->s6_addr[i] = 0xff;
200253541Sshin	if (bitlen)
200353541Sshin		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
200453541Sshin}
200553541Sshin
200653541Sshin/*
200753541Sshin * return the best address out of the same scope. if no address was
200853541Sshin * found, return the first valid address from designated IF.
200953541Sshin */
201053541Sshinstruct in6_ifaddr *
201153541Sshinin6_ifawithifp(ifp, dst)
201278064Sume	struct ifnet *ifp;
201378064Sume	struct in6_addr *dst;
201453541Sshin{
201553541Sshin	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
201653541Sshin	struct ifaddr *ifa;
201753541Sshin	struct in6_ifaddr *besta = 0;
201895023Ssuz	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
201953541Sshin
202053541Sshin	dep[0] = dep[1] = NULL;
202153541Sshin
202253541Sshin	/*
202353541Sshin	 * We first look for addresses in the same scope.
202453541Sshin	 * If there is one, return it.
202553541Sshin	 * If two or more, return one which matches the dst longest.
202653541Sshin	 * If none, return one of global addresses assigned other ifs.
202753541Sshin	 */
2028120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
202953541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
203053541Sshin			continue;
203153541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
203253541Sshin			continue; /* XXX: is there any case to allow anycast? */
203353541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
203453541Sshin			continue; /* don't use this interface */
203553541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
203653541Sshin			continue;
203753541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
203853541Sshin			if (ip6_use_deprecated)
203953541Sshin				dep[0] = (struct in6_ifaddr *)ifa;
204053541Sshin			continue;
204153541Sshin		}
204253541Sshin
204353541Sshin		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
204453541Sshin			/*
204553541Sshin			 * call in6_matchlen() as few as possible
204653541Sshin			 */
204753541Sshin			if (besta) {
204853541Sshin				if (blen == -1)
204953541Sshin					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
205053541Sshin				tlen = in6_matchlen(IFA_IN6(ifa), dst);
205153541Sshin				if (tlen > blen) {
205253541Sshin					blen = tlen;
205353541Sshin					besta = (struct in6_ifaddr *)ifa;
205453541Sshin				}
205553541Sshin			} else
205653541Sshin				besta = (struct in6_ifaddr *)ifa;
205753541Sshin		}
205853541Sshin	}
205953541Sshin	if (besta)
2060120856Sume		return (besta);
206153541Sshin
2062120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
206353541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
206453541Sshin			continue;
206553541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
206653541Sshin			continue; /* XXX: is there any case to allow anycast? */
206753541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
206853541Sshin			continue; /* don't use this interface */
206953541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
207053541Sshin			continue;
207153541Sshin		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
207253541Sshin			if (ip6_use_deprecated)
207353541Sshin				dep[1] = (struct in6_ifaddr *)ifa;
207453541Sshin			continue;
207553541Sshin		}
207653541Sshin
207753541Sshin		return (struct in6_ifaddr *)ifa;
207853541Sshin	}
207953541Sshin
208053541Sshin	/* use the last-resort values, that are, deprecated addresses */
208153541Sshin	if (dep[0])
208253541Sshin		return dep[0];
208353541Sshin	if (dep[1])
208453541Sshin		return dep[1];
208553541Sshin
208653541Sshin	return NULL;
208753541Sshin}
208853541Sshin
208953541Sshin/*
209053541Sshin * perform DAD when interface becomes IFF_UP.
209153541Sshin */
209253541Sshinvoid
209353541Sshinin6_if_up(ifp)
209453541Sshin	struct ifnet *ifp;
209553541Sshin{
209653541Sshin	struct ifaddr *ifa;
209753541Sshin	struct in6_ifaddr *ia;
209853541Sshin
2099120891Sume	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
210053541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6)
210153541Sshin			continue;
210253541Sshin		ia = (struct in6_ifaddr *)ifa;
2103151539Ssuz		if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
2104151539Ssuz			/*
2105151539Ssuz			 * The TENTATIVE flag was likely set by hand
2106151539Ssuz			 * beforehand, implicitly indicating the need for DAD.
2107151539Ssuz			 * We may be able to skip the random delay in this
2108151539Ssuz			 * case, but we impose delays just in case.
2109151539Ssuz			 */
2110151539Ssuz			nd6_dad_start(ifa,
2111151539Ssuz			    arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
2112151539Ssuz		}
211353541Sshin	}
2114151539Ssuz
2115151539Ssuz	/*
2116151539Ssuz	 * special cases, like 6to4, are handled in in6_ifattach
2117151539Ssuz	 */
2118151539Ssuz	in6_ifattach(ifp, NULL);
211953541Sshin}
212053541Sshin
212178064Sumeint
212278064Sumein6if_do_dad(ifp)
212378064Sume	struct ifnet *ifp;
212478064Sume{
212578064Sume	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
2126120856Sume		return (0);
212778064Sume
212878064Sume	switch (ifp->if_type) {
212978064Sume#ifdef IFT_DUMMY
213078064Sume	case IFT_DUMMY:
213178064Sume#endif
213278064Sume	case IFT_FAITH:
213378064Sume		/*
213478064Sume		 * These interfaces do not have the IFF_LOOPBACK flag,
213578064Sume		 * but loop packets back.  We do not have to do DAD on such
213678064Sume		 * interfaces.  We should even omit it, because loop-backed
213778064Sume		 * NS would confuse the DAD procedure.
213878064Sume		 */
2139120856Sume		return (0);
214078064Sume	default:
214178064Sume		/*
214278064Sume		 * Our DAD routine requires the interface up and running.
214378064Sume		 * However, some interfaces can be up before the RUNNING
214478064Sume		 * status.  Additionaly, users may try to assign addresses
214578064Sume		 * before the interface becomes up (or running).
214678064Sume		 * We simply skip DAD in such a case as a work around.
214778064Sume		 * XXX: we should rather mark "tentative" on such addresses,
214878064Sume		 * and do DAD after the interface becomes ready.
214978064Sume		 */
2150148887Srwatson		if (!((ifp->if_flags & IFF_UP) &&
2151148887Srwatson		    (ifp->if_drv_flags & IFF_DRV_RUNNING)))
2152120856Sume			return (0);
215378064Sume
2154120856Sume		return (1);
215578064Sume	}
215678064Sume}
215778064Sume
215853541Sshin/*
215953541Sshin * Calculate max IPv6 MTU through all the interfaces and store it
216053541Sshin * to in6_maxmtu.
216153541Sshin */
216253541Sshinvoid
216353541Sshinin6_setmaxmtu()
216453541Sshin{
216553541Sshin	unsigned long maxmtu = 0;
216653541Sshin	struct ifnet *ifp;
216753541Sshin
2168108172Shsu	IFNET_RLOCK();
2169120891Sume	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
2170121283Sume		/* this function can be called during ifnet initialization */
2171121283Sume		if (!ifp->if_afdata[AF_INET6])
2172121283Sume			continue;
217353541Sshin		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2174121283Sume		    IN6_LINKMTU(ifp) > maxmtu)
2175121283Sume			maxmtu = IN6_LINKMTU(ifp);
217653541Sshin	}
2177108172Shsu	IFNET_RUNLOCK();
2178120891Sume	if (maxmtu)	     /* update only when maxmtu is positive */
217953541Sshin		in6_maxmtu = maxmtu;
218053541Sshin}
218153541Sshin
2182151539Ssuz/*
2183151539Ssuz * Provide the length of interface identifiers to be used for the link attached
2184151539Ssuz * to the given interface.  The length should be defined in "IPv6 over
2185151539Ssuz * xxx-link" document.  Note that address architecture might also define
2186151539Ssuz * the length for a particular set of address prefixes, regardless of the
2187151539Ssuz * link type.  As clarified in rfc2462bis, those two definitions should be
2188151539Ssuz * consistent, and those really are as of August 2004.
2189151539Ssuz */
2190151539Ssuzint
2191151539Ssuzin6_if2idlen(ifp)
2192151539Ssuz	struct ifnet *ifp;
2193151539Ssuz{
2194151539Ssuz	switch (ifp->if_type) {
2195151539Ssuz	case IFT_ETHER:		/* RFC2464 */
2196151539Ssuz#ifdef IFT_PROPVIRTUAL
2197151539Ssuz	case IFT_PROPVIRTUAL:	/* XXX: no RFC. treat it as ether */
2198151539Ssuz#endif
2199151539Ssuz#ifdef IFT_L2VLAN
2200151539Ssuz	case IFT_L2VLAN:	/* ditto */
2201151539Ssuz#endif
2202151539Ssuz#ifdef IFT_IEEE80211
2203151539Ssuz	case IFT_IEEE80211:	/* ditto */
2204151539Ssuz#endif
2205151539Ssuz#ifdef IFT_MIP
2206151539Ssuz	case IFT_MIP:	/* ditto */
2207151539Ssuz#endif
2208151539Ssuz		return (64);
2209151539Ssuz	case IFT_FDDI:		/* RFC2467 */
2210151539Ssuz		return (64);
2211151539Ssuz	case IFT_ISO88025:	/* RFC2470 (IPv6 over Token Ring) */
2212151539Ssuz		return (64);
2213151539Ssuz	case IFT_PPP:		/* RFC2472 */
2214151539Ssuz		return (64);
2215151539Ssuz	case IFT_ARCNET:	/* RFC2497 */
2216151539Ssuz		return (64);
2217151539Ssuz	case IFT_FRELAY:	/* RFC2590 */
2218151539Ssuz		return (64);
2219151539Ssuz	case IFT_IEEE1394:	/* RFC3146 */
2220151539Ssuz		return (64);
2221151539Ssuz	case IFT_GIF:
2222151539Ssuz		return (64);	/* draft-ietf-v6ops-mech-v2-07 */
2223151539Ssuz	case IFT_LOOP:
2224151539Ssuz		return (64);	/* XXX: is this really correct? */
2225151539Ssuz	default:
2226151539Ssuz		/*
2227151539Ssuz		 * Unknown link type:
2228151539Ssuz		 * It might be controversial to use the today's common constant
2229151539Ssuz		 * of 64 for these cases unconditionally.  For full compliance,
2230151539Ssuz		 * we should return an error in this case.  On the other hand,
2231151539Ssuz		 * if we simply miss the standard for the link type or a new
2232151539Ssuz		 * standard is defined for a new link type, the IFID length
2233151539Ssuz		 * is very likely to be the common constant.  As a compromise,
2234151539Ssuz		 * we always use the constant, but make an explicit notice
2235151539Ssuz		 * indicating the "unknown" case.
2236151539Ssuz		 */
2237151539Ssuz		printf("in6_if2idlen: unknown link type (%d)\n", ifp->if_type);
2238151539Ssuz		return (64);
2239151539Ssuz	}
2240151539Ssuz}
2241151539Ssuz
2242121161Sumevoid *
2243121161Sumein6_domifattach(ifp)
2244121161Sume	struct ifnet *ifp;
2245121161Sume{
2246121161Sume	struct in6_ifextra *ext;
2247121161Sume
2248121161Sume	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
2249121161Sume	bzero(ext, sizeof(*ext));
2250121161Sume
2251121161Sume	ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
2252121161Sume	    M_IFADDR, M_WAITOK);
2253121161Sume	bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
2254121161Sume
2255121161Sume	ext->icmp6_ifstat =
2256121161Sume	    (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
2257121161Sume	    M_IFADDR, M_WAITOK);
2258121161Sume	bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
2259121161Sume
2260121161Sume	ext->nd_ifinfo = nd6_ifattach(ifp);
2261121161Sume	ext->scope6_id = scope6_ifattach(ifp);
2262121161Sume	return ext;
2263121161Sume}
2264121161Sume
2265121161Sumevoid
2266121161Sumein6_domifdetach(ifp, aux)
2267121161Sume	struct ifnet *ifp;
2268121161Sume	void *aux;
2269121161Sume{
2270121161Sume	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
2271121161Sume
2272121161Sume	scope6_ifdetach(ext->scope6_id);
2273121161Sume	nd6_ifdetach(ext->nd_ifinfo);
2274121161Sume	free(ext->in6_ifstat, M_IFADDR);
2275121161Sume	free(ext->icmp6_ifstat, M_IFADDR);
2276121161Sume	free(ext, M_IFADDR);
2277121161Sume}
2278121161Sume
227953541Sshin/*
228095023Ssuz * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
228153541Sshin * v4 mapped addr or v4 compat addr
228253541Sshin */
228353541Sshinvoid
228453541Sshinin6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
228553541Sshin{
228653541Sshin	bzero(sin, sizeof(*sin));
228753541Sshin	sin->sin_len = sizeof(struct sockaddr_in);
228853541Sshin	sin->sin_family = AF_INET;
228953541Sshin	sin->sin_port = sin6->sin6_port;
2290120891Sume	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
229153541Sshin}
229253541Sshin
229353541Sshin/* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
229453541Sshinvoid
229553541Sshinin6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
229653541Sshin{
229753541Sshin	bzero(sin6, sizeof(*sin6));
229853541Sshin	sin6->sin6_len = sizeof(struct sockaddr_in6);
229953541Sshin	sin6->sin6_family = AF_INET6;
230053541Sshin	sin6->sin6_port = sin->sin_port;
230153541Sshin	sin6->sin6_addr.s6_addr32[0] = 0;
230253541Sshin	sin6->sin6_addr.s6_addr32[1] = 0;
230353541Sshin	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
230453541Sshin	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
230553541Sshin}
230653541Sshin
230753541Sshin/* Convert sockaddr_in6 into sockaddr_in. */
230853541Sshinvoid
230953541Sshinin6_sin6_2_sin_in_sock(struct sockaddr *nam)
231053541Sshin{
231153541Sshin	struct sockaddr_in *sin_p;
231253541Sshin	struct sockaddr_in6 sin6;
231353541Sshin
231453541Sshin	/*
231553541Sshin	 * Save original sockaddr_in6 addr and convert it
231653541Sshin	 * to sockaddr_in.
231753541Sshin	 */
231853541Sshin	sin6 = *(struct sockaddr_in6 *)nam;
231953541Sshin	sin_p = (struct sockaddr_in *)nam;
232053541Sshin	in6_sin6_2_sin(sin_p, &sin6);
232153541Sshin}
232253541Sshin
232353541Sshin/* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
232453541Sshinvoid
232553541Sshinin6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
232653541Sshin{
232753541Sshin	struct sockaddr_in *sin_p;
232853541Sshin	struct sockaddr_in6 *sin6_p;
232953541Sshin
233053541Sshin	MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
2331111119Simp	       M_WAITOK);
233253541Sshin	sin_p = (struct sockaddr_in *)*nam;
233353541Sshin	in6_sin_2_v4mapsin6(sin_p, sin6_p);
233453541Sshin	FREE(*nam, M_SONAME);
233553541Sshin	*nam = (struct sockaddr *)sin6_p;
233653541Sshin}
2337