in6.c revision 121742
1238106Sdes/*	$FreeBSD: head/sys/netinet6/in6.c 121742 2003-10-30 15:29:17Z ume $	*/
2238106Sdes/*	$KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $	*/
3238106Sdes
4238106Sdes/*
5238106Sdes * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6238106Sdes * All rights reserved.
7238106Sdes *
8238106Sdes * Redistribution and use in source and binary forms, with or without
9238106Sdes * modification, are permitted provided that the following conditions
10238106Sdes * are met:
11238106Sdes * 1. Redistributions of source code must retain the above copyright
12238106Sdes *    notice, this list of conditions and the following disclaimer.
13238106Sdes * 2. Redistributions in binary form must reproduce the above copyright
14238106Sdes *    notice, this list of conditions and the following disclaimer in the
15238106Sdes *    documentation and/or other materials provided with the distribution.
16238106Sdes * 3. Neither the name of the project nor the names of its contributors
17238106Sdes *    may be used to endorse or promote products derived from this software
18238106Sdes *    without specific prior written permission.
19238106Sdes *
20238106Sdes * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21238106Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22238106Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23238106Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24269257Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25269257Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26269257Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27269257Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28269257Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29269257Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30269257Sdes * SUCH DAMAGE.
31269257Sdes */
32269257Sdes
33269257Sdes/*
34238106Sdes * Copyright (c) 1982, 1986, 1991, 1993
35238106Sdes *	The Regents of the University of California.  All rights reserved.
36238106Sdes *
37238106Sdes * Redistribution and use in source and binary forms, with or without
38238106Sdes * modification, are permitted provided that the following conditions
39238106Sdes * are met:
40238106Sdes * 1. Redistributions of source code must retain the above copyright
41285206Sdes *    notice, this list of conditions and the following disclaimer.
42285206Sdes * 2. Redistributions in binary form must reproduce the above copyright
43238106Sdes *    notice, this list of conditions and the following disclaimer in the
44238106Sdes *    documentation and/or other materials provided with the distribution.
45238106Sdes * 3. All advertising materials mentioning features or use of this software
46238106Sdes *    must display the following acknowledgement:
47238106Sdes *	This product includes software developed by the University of
48238106Sdes *	California, Berkeley and its contributors.
49285206Sdes * 4. Neither the name of the University nor the names of its contributors
50285206Sdes *    may be used to endorse or promote products derived from this software
51285206Sdes *    without specific prior written permission.
52285206Sdes *
53238106Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54238106Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55238106Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56238106Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57238106Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58238106Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59238106Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60238106Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61238106Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62238106Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63238106Sdes * SUCH DAMAGE.
64238106Sdes *
65238106Sdes *	@(#)in.c	8.2 (Berkeley) 11/15/93
66238106Sdes */
67238106Sdes
68238106Sdes#include "opt_inet.h"
69238106Sdes#include "opt_inet6.h"
70238106Sdes
71238106Sdes#include <sys/param.h>
72238106Sdes#include <sys/errno.h>
73238106Sdes#include <sys/malloc.h>
74238106Sdes#include <sys/socket.h>
75238106Sdes#include <sys/socketvar.h>
76238106Sdes#include <sys/sockio.h>
77238106Sdes#include <sys/systm.h>
78238106Sdes#include <sys/proc.h>
79238106Sdes#include <sys/time.h>
80238106Sdes#include <sys/kernel.h>
81269257Sdes#include <sys/syslog.h>
82269257Sdes
83269257Sdes#include <net/if.h>
84269257Sdes#include <net/if_types.h>
85238106Sdes#include <net/route.h>
86238106Sdes#include <net/if_dl.h>
87238106Sdes
88238106Sdes#include <netinet/in.h>
89285206Sdes#include <netinet/in_var.h>
90285206Sdes#include <netinet/if_ether.h>
91285206Sdes#include <netinet/in_systm.h>
92238106Sdes#include <netinet/ip.h>
93238106Sdes#include <netinet/in_pcb.h>
94238106Sdes
95238106Sdes#include <netinet/ip6.h>
96238106Sdes#include <netinet6/ip6_var.h>
97238106Sdes#include <netinet6/nd6.h>
98238106Sdes#include <netinet6/mld6_var.h>
99238106Sdes#include <netinet6/ip6_mroute.h>
100238106Sdes#include <netinet6/in6_ifattach.h>
101238106Sdes#include <netinet6/scope6_var.h>
102238106Sdes#include <netinet6/in6_pcb.h>
103238106Sdes
104238106Sdes#include <net/net_osdep.h>
105238106Sdes
106238106SdesMALLOC_DEFINE(M_IPMADDR, "in6_multi", "internet multicast address");
107238106Sdes
108238106Sdes/*
109238106Sdes * Definitions of some costant IP6 addresses.
110238106Sdes */
111238106Sdesconst struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
112238106Sdesconst struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
113238106Sdesconst struct in6_addr in6addr_nodelocal_allnodes =
114238106Sdes	IN6ADDR_NODELOCAL_ALLNODES_INIT;
115238106Sdesconst struct in6_addr in6addr_linklocal_allnodes =
116238106Sdes	IN6ADDR_LINKLOCAL_ALLNODES_INIT;
117238106Sdesconst struct in6_addr in6addr_linklocal_allrouters =
118238106Sdes	IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
119238106Sdes
120238106Sdesconst struct in6_addr in6mask0 = IN6MASK0;
121238106Sdesconst struct in6_addr in6mask32 = IN6MASK32;
122238106Sdesconst struct in6_addr in6mask64 = IN6MASK64;
123238106Sdesconst struct in6_addr in6mask96 = IN6MASK96;
124238106Sdesconst struct in6_addr in6mask128 = IN6MASK128;
125238106Sdes
126238106Sdesconst struct sockaddr_in6 sa6_any = {sizeof(sa6_any), AF_INET6,
127238106Sdes				     0, 0, IN6ADDR_ANY_INIT, 0};
128238106Sdes
129238106Sdesstatic int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
130238106Sdes	struct ifnet *, struct thread *));
131238106Sdesstatic int in6_ifinit __P((struct ifnet *, struct in6_ifaddr *,
132238106Sdes	struct sockaddr_in6 *, int));
133238106Sdesstatic void in6_unlink_ifa __P((struct in6_ifaddr *, struct ifnet *));
134238106Sdes
135238106Sdesstruct in6_multihead in6_multihead;	/* XXX BSS initialization */
136238106Sdesint	(*faithprefix_p)(struct in6_addr *);
137238106Sdes
138238106Sdes/*
139238106Sdes * Subroutine for in6_ifaddloop() and in6_ifremloop().
140238106Sdes * This routine does actual work.
141285206Sdes */
142285206Sdesstatic void
143285206Sdesin6_ifloop_request(int cmd, struct ifaddr *ifa)
144285206Sdes{
145285206Sdes	struct sockaddr_in6 all1_sa;
146285206Sdes	struct rtentry *nrt = NULL;
147285206Sdes	int e;
148285206Sdes
149285206Sdes	bzero(&all1_sa, sizeof(all1_sa));
150285206Sdes	all1_sa.sin6_family = AF_INET6;
151285206Sdes	all1_sa.sin6_len = sizeof(struct sockaddr_in6);
152285206Sdes	all1_sa.sin6_addr = in6mask128;
153285206Sdes
154285206Sdes	/*
155285206Sdes	 * We specify the address itself as the gateway, and set the
156285206Sdes	 * RTF_LLINFO flag, so that the corresponding host route would have
157285206Sdes	 * the flag, and thus applications that assume traditional behavior
158285206Sdes	 * would be happy.  Note that we assume the caller of the function
159285206Sdes	 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
160285206Sdes	 * which changes the outgoing interface to the loopback interface.
161285206Sdes	 */
162285206Sdes	e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
163285206Sdes	    (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
164285206Sdes	if (e != 0) {
165285206Sdes		/* XXX need more descriptive message */
166285206Sdes		log(LOG_ERR, "in6_ifloop_request: "
167285206Sdes		    "%s operation failed for %s (errno=%d)\n",
168285206Sdes		    cmd == RTM_ADD ? "ADD" : "DELETE",
169285206Sdes		    ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
170285206Sdes		    e);
171285206Sdes	}
172285206Sdes
173285206Sdes	if (nrt) {
174285206Sdes		RT_LOCK(nrt);
175285206Sdes		/*
176238106Sdes		 * Make sure rt_ifa be equal to IFA, the second argument of
177238106Sdes		 * the function.  We need this because when we refer to
178238106Sdes		 * rt_ifa->ia6_flags in ip6_input, we assume that the rt_ifa
179238106Sdes		 * points to the address instead of the loopback address.
180238106Sdes		 */
181238106Sdes		if (cmd == RTM_ADD && ifa != nrt->rt_ifa) {
182238106Sdes			IFAFREE(nrt->rt_ifa);
183238106Sdes			IFAREF(ifa);
184238106Sdes			nrt->rt_ifa = ifa;
185238106Sdes		}
186238106Sdes
187238106Sdes		/*
188238106Sdes		 * Report the addition/removal of the address to the routing
189238106Sdes		 * socket.
190238106Sdes		 *
191238106Sdes		 * XXX: since we called rtinit for a p2p interface with a
192238106Sdes		 *      destination, we end up reporting twice in such a case.
193238106Sdes		 *      Should we rather omit the second report?
194238106Sdes		 */
195238106Sdes		rt_newaddrmsg(cmd, ifa, e, nrt);
196238106Sdes		if (cmd == RTM_DELETE) {
197238106Sdes			rtfree(nrt);
198238106Sdes		} else {
199285206Sdes			/* the cmd must be RTM_ADD here */
200238106Sdes			nrt->rt_refcnt--;
201238106Sdes			RT_UNLOCK(nrt);
202238106Sdes		}
203238106Sdes	}
204238106Sdes}
205285206Sdes
206285206Sdes/*
207285206Sdes * Add ownaddr as loopback rtentry.  We previously add the route only if
208285206Sdes * necessary (ex. on a p2p link).  However, since we now manage addresses
209285206Sdes * separately from prefixes, we should always add the route.  We can't
210285206Sdes * rely on the cloning mechanism from the corresponding interface route
211285206Sdes * any more.
212285206Sdes */
213285206Sdesstatic void
214285206Sdesin6_ifaddloop(struct ifaddr *ifa)
215285206Sdes{
216285206Sdes	struct rtentry *rt;
217285206Sdes	int need_loop;
218285206Sdes
219285206Sdes	/* If there is no loopback entry, allocate one. */
220285206Sdes	rt = rtalloc1(ifa->ifa_addr, 0, 0);
221285206Sdes	need_loop = (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
222285206Sdes	    (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0);
223285206Sdes	if (rt)
224285206Sdes		rtfree(rt);
225285206Sdes	if (need_loop)
226285206Sdes		in6_ifloop_request(RTM_ADD, ifa);
227285206Sdes}
228238106Sdes
229238106Sdes/*
230238106Sdes * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
231238106Sdes * if it exists.
232238106Sdes */
233238106Sdesstatic void
234238106Sdesin6_ifremloop(struct ifaddr *ifa)
235238106Sdes{
236238106Sdes	struct in6_ifaddr *ia;
237238106Sdes	struct rtentry *rt;
238238106Sdes	int ia_count = 0;
239238106Sdes
240238106Sdes	/*
241238106Sdes	 * Some of BSD variants do not remove cloned routes
242238106Sdes	 * from an interface direct route, when removing the direct route
243238106Sdes	 * (see comments in net/net_osdep.h).  Even for variants that do remove
244238106Sdes	 * cloned routes, they could fail to remove the cloned routes when
245238106Sdes	 * we handle multple addresses that share a common prefix.
246238106Sdes	 * So, we should remove the route corresponding to the deleted address
247238106Sdes	 * regardless of the result of in6_is_ifloop_auto().
248238106Sdes	 */
249238106Sdes
250238106Sdes	/*
251238106Sdes	 * Delete the entry only if exact one ifa exists.  More than one ifa
252238106Sdes	 * can exist if we assign a same single address to multiple
253238106Sdes	 * (probably p2p) interfaces.
254238106Sdes	 * XXX: we should avoid such a configuration in IPv6...
255238106Sdes	 */
256238106Sdes	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
257238106Sdes		if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
258238106Sdes			ia_count++;
259238106Sdes			if (ia_count > 1)
260238106Sdes				break;
261238106Sdes		}
262238106Sdes	}
263238106Sdes
264238106Sdes	if (ia_count == 1) {
265238106Sdes		/*
266238106Sdes		 * Before deleting, check if a corresponding loopbacked host
267238106Sdes		 * route surely exists.  With this check, we can avoid to
268238106Sdes		 * delete an interface direct route whose destination is same
269238106Sdes		 * as the address being removed.  This can happen when removing
270238106Sdes		 * a subnet-router anycast address on an interface attahced
271238106Sdes		 * to a shared medium.
272238106Sdes		 */
273238106Sdes		rt = rtalloc1(ifa->ifa_addr, 0, 0);
274238106Sdes		if (rt != NULL) {
275238106Sdes			if ((rt->rt_flags & RTF_HOST) != 0 &&
276238106Sdes			    (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
277238106Sdes				rtfree(rt);
278238106Sdes				in6_ifloop_request(RTM_DELETE, ifa);
279238106Sdes			} else
280238106Sdes				RT_UNLOCK(rt);
281238106Sdes		}
282238106Sdes	}
283238106Sdes}
284238106Sdes
285238106Sdesint
286238106Sdesin6_mask2len(mask, lim0)
287238106Sdes	struct in6_addr *mask;
288238106Sdes	u_char *lim0;
289238106Sdes{
290238106Sdes	int x = 0, y;
291238106Sdes	u_char *lim = lim0, *p;
292238106Sdes
293238106Sdes	/* ignore the scope_id part */
294238106Sdes	if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
295238106Sdes		lim = (u_char *)mask + sizeof(*mask);
296238106Sdes	for (p = (u_char *)mask; p < lim; x++, p++) {
297238106Sdes		if (*p != 0xff)
298238106Sdes			break;
299238106Sdes	}
300238106Sdes	y = 0;
301238106Sdes	if (p < lim) {
302238106Sdes		for (y = 0; y < 8; y++) {
303238106Sdes			if ((*p & (0x80 >> y)) == 0)
304285206Sdes				break;
305238106Sdes		}
306238106Sdes	}
307238106Sdes
308285206Sdes	/*
309285206Sdes	 * when the limit pointer is given, do a stricter check on the
310238106Sdes	 * remaining bits.
311238106Sdes	 */
312238106Sdes	if (p < lim) {
313238106Sdes		if (y != 0 && (*p & (0x00ff >> y)) != 0)
314238106Sdes			return (-1);
315238106Sdes		for (p = p + 1; p < lim; p++)
316238106Sdes			if (*p != 0)
317238106Sdes				return (-1);
318238106Sdes	}
319238106Sdes
320285206Sdes	return x * 8 + y;
321285206Sdes}
322285206Sdes
323285206Sdes#define ifa2ia6(ifa)	((struct in6_ifaddr *)(ifa))
324285206Sdes#define ia62ifa(ia6)	(&((ia6)->ia_ifa))
325285206Sdes
326285206Sdesint
327285206Sdesin6_control(so, cmd, data, ifp, td)
328285206Sdes	struct	socket *so;
329285206Sdes	u_long cmd;
330285206Sdes	caddr_t	data;
331285206Sdes	struct ifnet *ifp;
332285206Sdes	struct thread *td;
333285206Sdes{
334285206Sdes	struct	in6_ifreq *ifr = (struct in6_ifreq *)data;
335285206Sdes	struct	in6_ifaddr *ia = NULL;
336285206Sdes	struct	in6_aliasreq *ifra = (struct in6_aliasreq *)data;
337285206Sdes	int privileged;
338285206Sdes
339285206Sdes	privileged = 0;
340285206Sdes	if (td == NULL || !suser(td))
341285206Sdes		privileged++;
342285206Sdes
343238106Sdes	switch (cmd) {
344285206Sdes	case SIOCGETSGCNT_IN6:
345285206Sdes	case SIOCGETMIFCNT_IN6:
346285206Sdes		return (mrt6_ioctl(cmd, data));
347285206Sdes	}
348238106Sdes
349285206Sdes	switch(cmd) {
350285206Sdes	case SIOCAADDRCTL_POLICY:
351238106Sdes	case SIOCDADDRCTL_POLICY:
352285206Sdes		if (!privileged)
353238106Sdes			return (EPERM);
354285206Sdes		return (in6_src_ioctl(cmd, data));
355238106Sdes	}
356238106Sdes
357285206Sdes	if (ifp == NULL)
358285206Sdes		return (EOPNOTSUPP);
359285206Sdes
360285206Sdes	switch (cmd) {
361285206Sdes	case SIOCSNDFLUSH_IN6:
362285206Sdes	case SIOCSPFXFLUSH_IN6:
363238106Sdes	case SIOCSRTRFLUSH_IN6:
364238106Sdes	case SIOCSDEFIFACE_IN6:
365238106Sdes	case SIOCSIFINFO_FLAGS:
366238106Sdes		if (!privileged)
367238106Sdes			return (EPERM);
368238106Sdes		/* FALLTHROUGH */
369238106Sdes	case OSIOCGIFINFO_IN6:
370238106Sdes	case SIOCGIFINFO_IN6:
371238106Sdes	case SIOCGDRLST_IN6:
372238106Sdes	case SIOCGPRLST_IN6:
373238106Sdes	case SIOCGNBRINFO_IN6:
374238106Sdes	case SIOCGDEFIFACE_IN6:
375238106Sdes		return (nd6_ioctl(cmd, data, ifp));
376238106Sdes	}
377238106Sdes
378238106Sdes	switch (cmd) {
379238106Sdes	case SIOCSIFPREFIX_IN6:
380238106Sdes	case SIOCDIFPREFIX_IN6:
381238106Sdes	case SIOCAIFPREFIX_IN6:
382238106Sdes	case SIOCCIFPREFIX_IN6:
383238106Sdes	case SIOCSGIFPREFIX_IN6:
384238106Sdes	case SIOCGIFPREFIX_IN6:
385238106Sdes		log(LOG_NOTICE,
386238106Sdes		    "prefix ioctls are now invalidated. "
387238106Sdes		    "please use ifconfig.\n");
388238106Sdes		return (EOPNOTSUPP);
389238106Sdes	}
390238106Sdes
391238106Sdes	switch (cmd) {
392238106Sdes	case SIOCSSCOPE6:
393238106Sdes		if (!privileged)
394238106Sdes			return (EPERM);
395238106Sdes		return (scope6_set(ifp,
396238106Sdes		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
397238106Sdes	case SIOCGSCOPE6:
398238106Sdes		return (scope6_get(ifp,
399238106Sdes		    (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
400238106Sdes	case SIOCGSCOPE6DEF:
401285206Sdes		return (scope6_get_default((struct scope6_id *)
402238106Sdes		    ifr->ifr_ifru.ifru_scope_id));
403238106Sdes	}
404238106Sdes
405238106Sdes	switch (cmd) {
406238106Sdes	case SIOCALIFADDR:
407238106Sdes	case SIOCDLIFADDR:
408238106Sdes		if (!privileged)
409285206Sdes			return (EPERM);
410238106Sdes		/* FALLTHROUGH */
411238106Sdes	case SIOCGLIFADDR:
412238106Sdes		return in6_lifaddr_ioctl(so, cmd, data, ifp, td);
413238106Sdes	}
414285206Sdes
415238106Sdes	/*
416238106Sdes	 * Find address for this interface, if it exists.
417238106Sdes	 */
418238106Sdes	if (ifra->ifra_addr.sin6_family == AF_INET6) { /* XXX */
419238106Sdes		struct sockaddr_in6 *sa6 =
420238106Sdes			(struct sockaddr_in6 *)&ifra->ifra_addr;
421238106Sdes
422238106Sdes		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
423238106Sdes			if (sa6->sin6_addr.s6_addr16[1] == 0) {
424238106Sdes				/* link ID is not embedded by the user */
425238106Sdes				sa6->sin6_addr.s6_addr16[1] =
426238106Sdes				    htons(ifp->if_index);
427238106Sdes			} else if (sa6->sin6_addr.s6_addr16[1] !=
428238106Sdes			    htons(ifp->if_index)) {
429238106Sdes				return (EINVAL);	/* link ID contradicts */
430238106Sdes			}
431238106Sdes			if (sa6->sin6_scope_id) {
432238106Sdes				if (sa6->sin6_scope_id !=
433238106Sdes				    (u_int32_t)ifp->if_index)
434238106Sdes					return (EINVAL);
435238106Sdes				sa6->sin6_scope_id = 0; /* XXX: good way? */
436238106Sdes			}
437238106Sdes		}
438238106Sdes		ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
439238106Sdes	}
440238106Sdes
441238106Sdes	switch (cmd) {
442238106Sdes	case SIOCSIFADDR_IN6:
443238106Sdes	case SIOCSIFDSTADDR_IN6:
444238106Sdes	case SIOCSIFNETMASK_IN6:
445238106Sdes		/*
446238106Sdes		 * Since IPv6 allows a node to assign multiple addresses
447238106Sdes		 * on a single interface, SIOCSIFxxx ioctls are not suitable
448238106Sdes		 * and should be unused.
449238106Sdes		 */
450238106Sdes		/* we decided to obsolete this command (20000704) */
451238106Sdes		return (EINVAL);
452238106Sdes
453238106Sdes	case SIOCDIFADDR_IN6:
454238106Sdes		/*
455238106Sdes		 * for IPv4, we look for existing in_ifaddr here to allow
456238106Sdes		 * "ifconfig if0 delete" to remove first IPv4 address on the
457238106Sdes		 * interface.  For IPv6, as the spec allow multiple interface
458238106Sdes		 * address from the day one, we consider "remove the first one"
459238106Sdes		 * semantics to be not preferable.
460238106Sdes		 */
461238106Sdes		if (ia == NULL)
462238106Sdes			return (EADDRNOTAVAIL);
463238106Sdes		/* FALLTHROUGH */
464238106Sdes	case SIOCAIFADDR_IN6:
465238106Sdes		/*
466238106Sdes		 * We always require users to specify a valid IPv6 address for
467238106Sdes		 * the corresponding operation.
468238106Sdes		 */
469238106Sdes		if (ifra->ifra_addr.sin6_family != AF_INET6 ||
470238106Sdes		    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
471238106Sdes			return (EAFNOSUPPORT);
472238106Sdes		if (!privileged)
473238106Sdes			return (EPERM);
474238106Sdes
475238106Sdes		break;
476238106Sdes
477238106Sdes	case SIOCGIFADDR_IN6:
478238106Sdes		/* This interface is basically deprecated. use SIOCGIFCONF. */
479238106Sdes		/* FALLTHROUGH */
480238106Sdes	case SIOCGIFAFLAG_IN6:
481238106Sdes	case SIOCGIFNETMASK_IN6:
482238106Sdes	case SIOCGIFDSTADDR_IN6:
483238106Sdes	case SIOCGIFALIFETIME_IN6:
484238106Sdes		/* must think again about its semantics */
485238106Sdes		if (ia == NULL)
486238106Sdes			return (EADDRNOTAVAIL);
487238106Sdes		break;
488238106Sdes	case SIOCSIFALIFETIME_IN6:
489238106Sdes	    {
490238106Sdes		struct in6_addrlifetime *lt;
491238106Sdes
492238106Sdes		if (!privileged)
493238106Sdes			return (EPERM);
494238106Sdes		if (ia == NULL)
495238106Sdes			return (EADDRNOTAVAIL);
496238106Sdes		/* sanity for overflow - beware unsigned */
497238106Sdes		lt = &ifr->ifr_ifru.ifru_lifetime;
498238106Sdes		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
499238106Sdes		 && lt->ia6t_vltime + time_second < time_second) {
500238106Sdes			return EINVAL;
501238106Sdes		}
502238106Sdes		if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
503238106Sdes		 && lt->ia6t_pltime + time_second < time_second) {
504238106Sdes			return EINVAL;
505238106Sdes		}
506238106Sdes		break;
507238106Sdes	    }
508238106Sdes	}
509238106Sdes
510238106Sdes	switch (cmd) {
511238106Sdes
512238106Sdes	case SIOCGIFADDR_IN6:
513238106Sdes		ifr->ifr_addr = ia->ia_addr;
514238106Sdes		break;
515238106Sdes
516238106Sdes	case SIOCGIFDSTADDR_IN6:
517238106Sdes		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
518238106Sdes			return (EINVAL);
519238106Sdes		/*
520238106Sdes		 * XXX: should we check if ifa_dstaddr is NULL and return
521238106Sdes		 * an error?
522238106Sdes		 */
523238106Sdes		ifr->ifr_dstaddr = ia->ia_dstaddr;
524238106Sdes		break;
525238106Sdes
526238106Sdes	case SIOCGIFNETMASK_IN6:
527238106Sdes		ifr->ifr_addr = ia->ia_prefixmask;
528238106Sdes		break;
529238106Sdes
530238106Sdes	case SIOCGIFAFLAG_IN6:
531238106Sdes		ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
532238106Sdes		break;
533238106Sdes
534238106Sdes	case SIOCGIFSTAT_IN6:
535238106Sdes		if (ifp == NULL)
536238106Sdes			return EINVAL;
537238106Sdes		bzero(&ifr->ifr_ifru.ifru_stat,
538238106Sdes		    sizeof(ifr->ifr_ifru.ifru_stat));
539238106Sdes		ifr->ifr_ifru.ifru_stat =
540238106Sdes		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
541238106Sdes		break;
542238106Sdes
543238106Sdes	case SIOCGIFSTAT_ICMP6:
544238106Sdes		if (ifp == NULL)
545238106Sdes			return EINVAL;
546238106Sdes		bzero(&ifr->ifr_ifru.ifru_stat,
547238106Sdes		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
548238106Sdes		ifr->ifr_ifru.ifru_icmp6stat =
549238106Sdes		    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
550238106Sdes		break;
551238106Sdes
552238106Sdes	case SIOCGIFALIFETIME_IN6:
553238106Sdes		ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
554238106Sdes		break;
555238106Sdes
556238106Sdes	case SIOCSIFALIFETIME_IN6:
557238106Sdes		ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
558238106Sdes		/* for sanity */
559238106Sdes		if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
560238106Sdes			ia->ia6_lifetime.ia6t_expire =
561238106Sdes				time_second + ia->ia6_lifetime.ia6t_vltime;
562238106Sdes		} else
563238106Sdes			ia->ia6_lifetime.ia6t_expire = 0;
564238106Sdes		if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
565238106Sdes			ia->ia6_lifetime.ia6t_preferred =
566238106Sdes				time_second + ia->ia6_lifetime.ia6t_pltime;
567238106Sdes		} else
568238106Sdes			ia->ia6_lifetime.ia6t_preferred = 0;
569238106Sdes		break;
570238106Sdes
571238106Sdes	case SIOCAIFADDR_IN6:
572238106Sdes	{
573238106Sdes		int i, error = 0;
574238106Sdes		struct nd_prefix pr0, *pr;
575238106Sdes
576238106Sdes		/*
577238106Sdes		 * first, make or update the interface address structure,
578238106Sdes		 * and link it to the list.
579238106Sdes		 */
580238106Sdes		if ((error = in6_update_ifa(ifp, ifra, ia)) != 0)
581238106Sdes			return (error);
582238106Sdes
583238106Sdes		/*
584238106Sdes		 * then, make the prefix on-link on the interface.
585238106Sdes		 * XXX: we'd rather create the prefix before the address, but
586238106Sdes		 * we need at least one address to install the corresponding
587238106Sdes		 * interface route, so we configure the address first.
588238106Sdes		 */
589238106Sdes
590238106Sdes		/*
591238106Sdes		 * convert mask to prefix length (prefixmask has already
592238106Sdes		 * been validated in in6_update_ifa().
593238106Sdes		 */
594238106Sdes		bzero(&pr0, sizeof(pr0));
595238106Sdes		pr0.ndpr_ifp = ifp;
596238106Sdes		pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
597238106Sdes		    NULL);
598238106Sdes		if (pr0.ndpr_plen == 128) {
599238106Sdes			break;	/* we don't need to install a host route. */
600238106Sdes		}
601238106Sdes		pr0.ndpr_prefix = ifra->ifra_addr;
602238106Sdes		pr0.ndpr_mask = ifra->ifra_prefixmask.sin6_addr;
603238106Sdes		/* apply the mask for safety. */
604238106Sdes		for (i = 0; i < 4; i++) {
605238106Sdes			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
606238106Sdes			    ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
607238106Sdes		}
608238106Sdes		/*
609238106Sdes		 * XXX: since we don't have an API to set prefix (not address)
610238106Sdes		 * lifetimes, we just use the same lifetimes as addresses.
611238106Sdes		 * The (temporarily) installed lifetimes can be overridden by
612238106Sdes		 * later advertised RAs (when accept_rtadv is non 0), which is
613238106Sdes		 * an intended behavior.
614238106Sdes		 */
615238106Sdes		pr0.ndpr_raf_onlink = 1; /* should be configurable? */
616238106Sdes		pr0.ndpr_raf_auto =
617238106Sdes		    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
618238106Sdes		pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
619238106Sdes		pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
620238106Sdes
621238106Sdes		/* add the prefix if not yet. */
622238106Sdes		if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
623238106Sdes			/*
624238106Sdes			 * nd6_prelist_add will install the corresponding
625238106Sdes			 * interface route.
626238106Sdes			 */
627238106Sdes			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
628238106Sdes				return (error);
629238106Sdes			if (pr == NULL) {
630238106Sdes				log(LOG_ERR, "nd6_prelist_add succeeded but "
631238106Sdes				    "no prefix\n");
632238106Sdes				return (EINVAL); /* XXX panic here? */
633238106Sdes			}
634238106Sdes		}
635238106Sdes		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
636238106Sdes		    == NULL) {
637238106Sdes		    	/* XXX: this should not happen! */
638238106Sdes			log(LOG_ERR, "in6_control: addition succeeded, but"
639238106Sdes			    " no ifaddr\n");
640238106Sdes		} else {
641238106Sdes			if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
642238106Sdes			    ia->ia6_ndpr == NULL) { /* new autoconfed addr */
643238106Sdes				ia->ia6_ndpr = pr;
644238106Sdes				pr->ndpr_refcnt++;
645238106Sdes
646238106Sdes				/*
647238106Sdes				 * If this is the first autoconf address from
648238106Sdes				 * the prefix, create a temporary address
649238106Sdes				 * as well (when specified).
650285206Sdes				 */
651238106Sdes				if (ip6_use_tempaddr &&
652238106Sdes				    pr->ndpr_refcnt == 1) {
653238106Sdes					int e;
654238106Sdes					if ((e = in6_tmpifadd(ia, 1)) != 0) {
655238106Sdes						log(LOG_NOTICE, "in6_control: "
656238106Sdes						    "failed to create a "
657238106Sdes						    "temporary address, "
658238106Sdes						    "errno=%d\n",
659238106Sdes						    e);
660238106Sdes					}
661238106Sdes				}
662238106Sdes			}
663238106Sdes
664238106Sdes			/*
665238106Sdes			 * this might affect the status of autoconfigured
666238106Sdes			 * addresses, that is, this address might make
667238106Sdes			 * other addresses detached.
668238106Sdes			 */
669238106Sdes			pfxlist_onlink_check();
670238106Sdes		}
671238106Sdes		break;
672238106Sdes	}
673238106Sdes
674238106Sdes	case SIOCDIFADDR_IN6:
675238106Sdes	{
676238106Sdes		int i = 0;
677238106Sdes		struct nd_prefix pr0, *pr;
678238106Sdes
679238106Sdes		/*
680238106Sdes		 * If the address being deleted is the only one that owns
681238106Sdes		 * the corresponding prefix, expire the prefix as well.
682238106Sdes		 * XXX: theoretically, we don't have to worry about such
683238106Sdes		 * relationship, since we separate the address management
684238106Sdes		 * and the prefix management.  We do this, however, to provide
685238106Sdes		 * as much backward compatibility as possible in terms of
686238106Sdes		 * the ioctl operation.
687238106Sdes		 */
688238106Sdes		bzero(&pr0, sizeof(pr0));
689238106Sdes		pr0.ndpr_ifp = ifp;
690238106Sdes		pr0.ndpr_plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr,
691238106Sdes					     NULL);
692238106Sdes		if (pr0.ndpr_plen == 128)
693238106Sdes			goto purgeaddr;
694238106Sdes		pr0.ndpr_prefix = ia->ia_addr;
695238106Sdes		pr0.ndpr_mask = ia->ia_prefixmask.sin6_addr;
696238106Sdes		for (i = 0; i < 4; i++) {
697285206Sdes			pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
698285206Sdes				ia->ia_prefixmask.sin6_addr.s6_addr32[i];
699285206Sdes		}
700285206Sdes		/*
701238106Sdes		 * The logic of the following condition is a bit complicated.
702285206Sdes		 * We expire the prefix when
703285206Sdes		 * 1. the address obeys autoconfiguration and it is the
704285206Sdes		 *    only owner of the associated prefix, or
705285206Sdes		 * 2. the address does not obey autoconf and there is no
706285206Sdes		 *    other owner of the prefix.
707285206Sdes		 */
708238106Sdes		if ((pr = nd6_prefix_lookup(&pr0)) != NULL &&
709238106Sdes		    (((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
710238106Sdes		      pr->ndpr_refcnt == 1) ||
711238106Sdes		     ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0 &&
712238106Sdes		      pr->ndpr_refcnt == 0))) {
713285206Sdes			pr->ndpr_expire = 1; /* XXX: just for expiration */
714285206Sdes		}
715285206Sdes
716285206Sdes	  purgeaddr:
717285206Sdes		in6_purgeaddr(&ia->ia_ifa);
718285206Sdes		break;
719285206Sdes	}
720285206Sdes
721285206Sdes	default:
722285206Sdes		if (ifp == NULL || ifp->if_ioctl == 0)
723238106Sdes			return (EOPNOTSUPP);
724269257Sdes		return ((*ifp->if_ioctl)(ifp, cmd, data));
725269257Sdes	}
726238106Sdes
727238106Sdes	return (0);
728238106Sdes}
729238106Sdes
730238106Sdes/*
731238106Sdes * Update parameters of an IPv6 interface address.
732238106Sdes * If necessary, a new entry is created and linked into address chains.
733238106Sdes * This function is separated from in6_control().
734238106Sdes * XXX: should this be performed under splnet()?
735238106Sdes */
736238106Sdesint
737238106Sdesin6_update_ifa(ifp, ifra, ia)
738238106Sdes	struct ifnet *ifp;
739238106Sdes	struct in6_aliasreq *ifra;
740238106Sdes	struct in6_ifaddr *ia;
741238106Sdes{
742238106Sdes	int error = 0, hostIsNew = 0, plen = -1;
743255579Sdes	struct in6_ifaddr *oia;
744238106Sdes	struct sockaddr_in6 dst6;
745238106Sdes	struct in6_addrlifetime *lt;
746238106Sdes
747238106Sdes	/* Validate parameters */
748238106Sdes	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
749238106Sdes		return (EINVAL);
750238106Sdes
751238106Sdes	/*
752285206Sdes	 * The destination address for a p2p link must have a family
753238106Sdes	 * of AF_UNSPEC or AF_INET6.
754238106Sdes	 */
755238106Sdes	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
756238106Sdes	    ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
757238106Sdes	    ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
758238106Sdes		return (EAFNOSUPPORT);
759238106Sdes	/*
760238106Sdes	 * validate ifra_prefixmask.  don't check sin6_family, netmask
761238106Sdes	 * does not carry fields other than sin6_len.
762238106Sdes	 */
763238106Sdes	if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
764238106Sdes		return (EINVAL);
765238106Sdes	/*
766238106Sdes	 * Because the IPv6 address architecture is classless, we require
767238106Sdes	 * users to specify a (non 0) prefix length (mask) for a new address.
768238106Sdes	 * We also require the prefix (when specified) mask is valid, and thus
769238106Sdes	 * reject a non-consecutive mask.
770238106Sdes	 */
771238106Sdes	if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
772238106Sdes		return (EINVAL);
773238106Sdes	if (ifra->ifra_prefixmask.sin6_len != 0) {
774238106Sdes		plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
775238106Sdes		    (u_char *)&ifra->ifra_prefixmask +
776238106Sdes		    ifra->ifra_prefixmask.sin6_len);
777238106Sdes		if (plen <= 0)
778238106Sdes			return (EINVAL);
779238106Sdes	} else {
780238106Sdes		/*
781238106Sdes		 * In this case, ia must not be NULL.  We just use its prefix
782238106Sdes		 * length.
783238106Sdes		 */
784238106Sdes		plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
785238106Sdes	}
786238106Sdes	/*
787238106Sdes	 * If the destination address on a p2p interface is specified,
788238106Sdes	 * and the address is a scoped one, validate/set the scope
789238106Sdes	 * zone identifier.
790238106Sdes	 */
791238106Sdes	dst6 = ifra->ifra_dstaddr;
792238106Sdes	if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
793238106Sdes	    (dst6.sin6_family == AF_INET6)) {
794238106Sdes		int scopeid;
795238106Sdes
796238106Sdes		if ((error = in6_recoverscope(&dst6,
797238106Sdes		    &ifra->ifra_dstaddr.sin6_addr, ifp)) != 0)
798238106Sdes			return (error);
799238106Sdes		if (in6_addr2zoneid(ifp, &dst6.sin6_addr, &scopeid))
800238106Sdes			return (EINVAL);
801238106Sdes		if (dst6.sin6_scope_id == 0) /* user omit to specify the ID. */
802238106Sdes			dst6.sin6_scope_id = scopeid;
803238106Sdes		else if (dst6.sin6_scope_id != scopeid)
804238106Sdes			return (EINVAL); /* scope ID mismatch. */
805238106Sdes		if ((error = in6_embedscope(&dst6.sin6_addr, &dst6, NULL, NULL))
806238106Sdes		    != 0)
807238106Sdes			return (error);
808269257Sdes		dst6.sin6_scope_id = 0; /* XXX */
809269257Sdes	}
810269257Sdes	/*
811269257Sdes	 * The destination address can be specified only for a p2p or a
812269257Sdes	 * loopback interface.  If specified, the corresponding prefix length
813269257Sdes	 * must be 128.
814238106Sdes	 */
815238106Sdes	if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
816238106Sdes		if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
817238106Sdes			/* XXX: noisy message */
818238106Sdes			log(LOG_INFO, "in6_update_ifa: a destination can be "
819238106Sdes			    "specified for a p2p or a loopback IF only\n");
820238106Sdes			return (EINVAL);
821238106Sdes		}
822238106Sdes		if (plen != 128) {
823238106Sdes			/*
824238106Sdes			 * The following message seems noisy, but we dare to
825238106Sdes			 * add it for diagnosis.
826238106Sdes			 */
827238106Sdes			log(LOG_INFO, "in6_update_ifa: prefixlen must be 128 "
828238106Sdes			    "when dstaddr is specified\n");
829238106Sdes			return (EINVAL);
830238106Sdes		}
831285206Sdes	}
832238106Sdes	/* lifetime consistency check */
833238106Sdes	lt = &ifra->ifra_lifetime;
834238106Sdes	if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
835238106Sdes	    && lt->ia6t_vltime + time_second < time_second) {
836285206Sdes		return EINVAL;
837238106Sdes	}
838238106Sdes	if (lt->ia6t_vltime == 0) {
839238106Sdes		/*
840238106Sdes		 * the following log might be noisy, but this is a typical
841238106Sdes		 * configuration mistake or a tool's bug.
842238106Sdes		 */
843238106Sdes		log(LOG_INFO,
844238106Sdes		    "in6_update_ifa: valid lifetime is 0 for %s\n",
845238106Sdes		    ip6_sprintf(&ifra->ifra_addr.sin6_addr));
846238106Sdes	}
847238106Sdes	if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
848238106Sdes	    && lt->ia6t_pltime + time_second < time_second) {
849238106Sdes		return EINVAL;
850238106Sdes	}
851269257Sdes
852269257Sdes	/*
853238106Sdes	 * If this is a new address, allocate a new ifaddr and link it
854238106Sdes	 * into chains.
855238106Sdes	 */
856238106Sdes	if (ia == NULL) {
857269257Sdes		hostIsNew = 1;
858238106Sdes		/*
859238106Sdes		 * When in6_update_ifa() is called in a process of a received
860238106Sdes		 * RA, it is called under an interrupt context.  So, we should
861238106Sdes		 * call malloc with M_NOWAIT.
862238106Sdes		 */
863238106Sdes		ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
864238106Sdes		    M_NOWAIT);
865238106Sdes		if (ia == NULL)
866238106Sdes			return (ENOBUFS);
867238106Sdes		bzero((caddr_t)ia, sizeof(*ia));
868238106Sdes		/* Initialize the address and masks */
869238106Sdes		IFA_LOCK_INIT(&ia->ia_ifa);
870238106Sdes		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
871238106Sdes		ia->ia_addr.sin6_family = AF_INET6;
872238106Sdes		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
873285206Sdes		if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
874285206Sdes			/*
875238106Sdes			 * XXX: some functions expect that ifa_dstaddr is not
876238106Sdes			 * NULL for p2p interfaces.
877285206Sdes			 */
878285206Sdes			ia->ia_ifa.ifa_dstaddr =
879238106Sdes			    (struct sockaddr *)&ia->ia_dstaddr;
880238106Sdes		} else {
881238106Sdes			ia->ia_ifa.ifa_dstaddr = NULL;
882238106Sdes		}
883238106Sdes		ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
884269257Sdes
885238106Sdes		ia->ia_ifp = ifp;
886238106Sdes		if ((oia = in6_ifaddr) != NULL) {
887238106Sdes			for ( ; oia->ia_next; oia = oia->ia_next)
888238106Sdes				continue;
889238106Sdes			oia->ia_next = ia;
890285206Sdes		} else
891285206Sdes			in6_ifaddr = ia;
892238106Sdes
893238106Sdes		ia->ia_ifa.ifa_refcnt = 1;
894285206Sdes		TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
895285206Sdes	}
896238106Sdes
897238106Sdes	/* set prefix mask */
898238106Sdes	if (ifra->ifra_prefixmask.sin6_len) {
899238106Sdes		/*
900238106Sdes		 * We prohibit changing the prefix length of an existing
901269257Sdes		 * address, because
902238106Sdes		 * + such an operation should be rare in IPv6, and
903238106Sdes		 * + the operation would confuse prefix management.
904238106Sdes		 */
905238106Sdes		if (ia->ia_prefixmask.sin6_len &&
906238106Sdes		    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
907285206Sdes			log(LOG_INFO, "in6_update_ifa: the prefix length of an"
908285206Sdes			    " existing (%s) address should not be changed\n",
909238106Sdes			    ip6_sprintf(&ia->ia_addr.sin6_addr));
910238106Sdes			error = EINVAL;
911285206Sdes			goto unlink;
912285206Sdes		}
913285206Sdes		ia->ia_prefixmask = ifra->ifra_prefixmask;
914285206Sdes	}
915285206Sdes
916285206Sdes	/*
917238106Sdes	 * If a new destination address is specified, scrub the old one and
918285206Sdes	 * install the new destination.  Note that the interface must be
919285206Sdes	 * p2p or loopback (see the check above.)
920285206Sdes	 */
921285206Sdes	if (dst6.sin6_family == AF_INET6 &&
922285206Sdes	    !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
923285206Sdes		int e;
924285206Sdes
925285206Sdes		if ((ia->ia_flags & IFA_ROUTE) != 0 &&
926285206Sdes		    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
927285206Sdes			log(LOG_ERR, "in6_update_ifa: failed to remove "
928285206Sdes			    "a route to the old destination: %s\n",
929285206Sdes			    ip6_sprintf(&ia->ia_addr.sin6_addr));
930285206Sdes			/* proceed anyway... */
931285206Sdes		} else
932285206Sdes			ia->ia_flags &= ~IFA_ROUTE;
933285206Sdes		ia->ia_dstaddr = dst6;
934285206Sdes	}
935285206Sdes
936285206Sdes	/* reset the interface and routing table appropriately. */
937285206Sdes	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
938238106Sdes		goto unlink;
939238106Sdes
940238106Sdes	/*
941285206Sdes	 * Beyond this point, we should call in6_purgeaddr upon an error,
942285206Sdes	 * not just go to unlink.
943238106Sdes	 */
944269257Sdes
945238106Sdes	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
946238106Sdes		struct sockaddr_in6 mltaddr, mltmask;
947238106Sdes		struct in6_multi *in6m;
948238106Sdes
949238106Sdes		if (hostIsNew) {
950285206Sdes			/* join solicited multicast addr for new host id */
951285206Sdes			struct in6_addr llsol;
952238106Sdes
953238106Sdes			bzero(&llsol, sizeof(struct in6_addr));
954285206Sdes			llsol.s6_addr16[0] = htons(0xff02);
955285206Sdes			llsol.s6_addr16[1] = htons(ifp->if_index);
956238106Sdes			llsol.s6_addr32[1] = 0;
957238106Sdes			llsol.s6_addr32[2] = htonl(1);
958285206Sdes			llsol.s6_addr32[3] =
959285206Sdes				ifra->ifra_addr.sin6_addr.s6_addr32[3];
960285206Sdes			llsol.s6_addr8[12] = 0xff;
961285206Sdes			(void)in6_addmulti(&llsol, ifp, &error);
962285206Sdes			if (error != 0) {
963285206Sdes				log(LOG_WARNING,
964238106Sdes				    "in6_update_ifa: addmulti failed for "
965285206Sdes				    "%s on %s (errno=%d)\n",
966285206Sdes				    ip6_sprintf(&llsol), if_name(ifp),
967285206Sdes				    error);
968285206Sdes				in6_purgeaddr((struct ifaddr *)ia);
969285206Sdes				return (error);
970285206Sdes			}
971285206Sdes		}
972285206Sdes
973285206Sdes		bzero(&mltmask, sizeof(mltmask));
974285206Sdes		mltmask.sin6_len = sizeof(struct sockaddr_in6);
975285206Sdes		mltmask.sin6_family = AF_INET6;
976285206Sdes		mltmask.sin6_addr = in6mask32;
977285206Sdes
978238106Sdes		/*
979238106Sdes		 * join link-local all-nodes address
980238106Sdes		 */
981238106Sdes		bzero(&mltaddr, sizeof(mltaddr));
982238106Sdes		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
983238106Sdes		mltaddr.sin6_family = AF_INET6;
984238106Sdes		mltaddr.sin6_addr = in6addr_linklocal_allnodes;
985238106Sdes		mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
986238106Sdes
987238106Sdes		IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
988238106Sdes		if (in6m == NULL) {
989238106Sdes			rtrequest(RTM_ADD,
990238106Sdes				  (struct sockaddr *)&mltaddr,
991238106Sdes				  (struct sockaddr *)&ia->ia_addr,
992238106Sdes				  (struct sockaddr *)&mltmask,
993238106Sdes				  RTF_UP|RTF_CLONING,  /* xxx */
994238106Sdes				  (struct rtentry **)0);
995238106Sdes			(void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
996238106Sdes			if (error != 0) {
997238106Sdes				log(LOG_WARNING,
998238106Sdes				    "in6_update_ifa: addmulti failed for "
999238106Sdes				    "%s on %s (errno=%d)\n",
1000238106Sdes				    ip6_sprintf(&mltaddr.sin6_addr),
1001238106Sdes				    if_name(ifp), error);
1002238106Sdes			}
1003238106Sdes		}
1004238106Sdes
1005238106Sdes		/*
1006238106Sdes		 * join node information group address
1007238106Sdes		 */
1008238106Sdes#define hostnamelen	strlen(hostname)
1009238106Sdes		if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr)
1010238106Sdes		    == 0) {
1011238106Sdes			IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
1012238106Sdes			if (in6m == NULL && ia != NULL) {
1013238106Sdes				(void)in6_addmulti(&mltaddr.sin6_addr,
1014238106Sdes				    ifp, &error);
1015238106Sdes				if (error != 0) {
1016238106Sdes					log(LOG_WARNING, "in6_update_ifa: "
1017238106Sdes					    "addmulti failed for "
1018238106Sdes					    "%s on %s (errno=%d)\n",
1019269257Sdes					    ip6_sprintf(&mltaddr.sin6_addr),
1020269257Sdes					    if_name(ifp), error);
1021269257Sdes				}
1022238106Sdes			}
1023238106Sdes		}
1024238106Sdes#undef hostnamelen
1025269257Sdes
1026269257Sdes		/*
1027269257Sdes		 * join node-local all-nodes address, on loopback.
1028269257Sdes		 * XXX: since "node-local" is obsoleted by interface-local,
1029269257Sdes		 *      we have to join the group on every interface with
1030238106Sdes		 *      some interface-boundary restriction.
1031238106Sdes		 */
1032269257Sdes		if (ifp->if_flags & IFF_LOOPBACK) {
1033238106Sdes			struct in6_ifaddr *ia_loop;
1034238106Sdes
1035238106Sdes			struct in6_addr loop6 = in6addr_loopback;
1036238106Sdes			ia_loop = in6ifa_ifpwithaddr(ifp, &loop6);
1037238106Sdes
1038238106Sdes			mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
1039238106Sdes
1040238106Sdes			IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
1041238106Sdes			if (in6m == NULL && ia_loop != NULL) {
1042238106Sdes				rtrequest(RTM_ADD,
1043238106Sdes					  (struct sockaddr *)&mltaddr,
1044238106Sdes					  (struct sockaddr *)&ia_loop->ia_addr,
1045238106Sdes					  (struct sockaddr *)&mltmask,
1046238106Sdes					  RTF_UP,
1047238106Sdes					  (struct rtentry **)0);
1048238106Sdes				(void)in6_addmulti(&mltaddr.sin6_addr, ifp,
1049238106Sdes						   &error);
1050238106Sdes				if (error != 0) {
1051238106Sdes					log(LOG_WARNING, "in6_update_ifa: "
1052238106Sdes					    "addmulti failed for %s on %s "
1053238106Sdes					    "(errno=%d)\n",
1054238106Sdes					    ip6_sprintf(&mltaddr.sin6_addr),
1055238106Sdes					    if_name(ifp), error);
1056238106Sdes				}
1057238106Sdes			}
1058238106Sdes		}
1059238106Sdes	}
1060238106Sdes
1061238106Sdes	ia->ia6_flags = ifra->ifra_flags;
1062238106Sdes	ia->ia6_flags &= ~IN6_IFF_DUPLICATED;	/*safety*/
1063238106Sdes	ia->ia6_flags &= ~IN6_IFF_NODAD;	/* Mobile IPv6 */
1064238106Sdes
1065238106Sdes	ia->ia6_lifetime = ifra->ifra_lifetime;
1066238106Sdes	/* for sanity */
1067238106Sdes	if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
1068238106Sdes		ia->ia6_lifetime.ia6t_expire =
1069238106Sdes			time_second + ia->ia6_lifetime.ia6t_vltime;
1070238106Sdes	} else
1071238106Sdes		ia->ia6_lifetime.ia6t_expire = 0;
1072238106Sdes	if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
1073238106Sdes		ia->ia6_lifetime.ia6t_preferred =
1074238106Sdes			time_second + ia->ia6_lifetime.ia6t_pltime;
1075238106Sdes	} else
1076238106Sdes		ia->ia6_lifetime.ia6t_preferred = 0;
1077238106Sdes
1078238106Sdes	/*
1079238106Sdes	 * Perform DAD, if needed.
1080238106Sdes	 * XXX It may be of use, if we can administratively
1081238106Sdes	 * disable DAD.
1082238106Sdes	 */
1083238106Sdes	if (in6if_do_dad(ifp) && (ifra->ifra_flags & IN6_IFF_NODAD) == 0) {
1084238106Sdes		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1085269257Sdes		nd6_dad_start((struct ifaddr *)ia, NULL);
1086238106Sdes	}
1087238106Sdes
1088238106Sdes	return (error);
1089238106Sdes
1090238106Sdes  unlink:
1091238106Sdes	/*
1092238106Sdes	 * XXX: if a change of an existing address failed, keep the entry
1093269257Sdes	 * anyway.
1094238106Sdes	 */
1095238106Sdes	if (hostIsNew)
1096238106Sdes		in6_unlink_ifa(ia, ifp);
1097238106Sdes	return (error);
1098238106Sdes}
1099269257Sdes
1100238106Sdesvoid
1101238106Sdesin6_purgeaddr(ifa)
1102238106Sdes	struct ifaddr *ifa;
1103269257Sdes{
1104238106Sdes	struct ifnet *ifp = ifa->ifa_ifp;
1105238106Sdes	struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
1106238106Sdes
1107238106Sdes	/* stop DAD processing */
1108238106Sdes	nd6_dad_stop(ifa);
1109238106Sdes
1110238106Sdes	/*
1111238106Sdes	 * delete route to the destination of the address being purged.
1112238106Sdes	 * The interface must be p2p or loopback in this case.
1113238106Sdes	 */
1114238106Sdes	if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
1115238106Sdes		int e;
1116238106Sdes
1117269257Sdes		if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
1118238106Sdes		    != 0) {
1119238106Sdes			log(LOG_ERR, "in6_purgeaddr: failed to remove "
1120238106Sdes			    "a route to the p2p destination: %s on %s, "
1121238106Sdes			    "errno=%d\n",
1122238106Sdes			    ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp),
1123269257Sdes			    e);
1124238106Sdes			/* proceed anyway... */
1125238106Sdes		} else
1126238106Sdes			ia->ia_flags &= ~IFA_ROUTE;
1127238106Sdes	}
1128238106Sdes
1129238106Sdes	/* Remove ownaddr's loopback rtentry, if it exists. */
1130238106Sdes	in6_ifremloop(&(ia->ia_ifa));
1131238106Sdes
1132269257Sdes	if (ifp->if_flags & IFF_MULTICAST) {
1133238106Sdes		/*
1134238106Sdes		 * delete solicited multicast addr for deleting host id
1135238106Sdes		 */
1136238106Sdes		struct in6_multi *in6m;
1137238106Sdes		struct in6_addr llsol;
1138238106Sdes		bzero(&llsol, sizeof(struct in6_addr));
1139238106Sdes		llsol.s6_addr16[0] = htons(0xff02);
1140238106Sdes		llsol.s6_addr16[1] = htons(ifp->if_index);
1141238106Sdes		llsol.s6_addr32[1] = 0;
1142238106Sdes		llsol.s6_addr32[2] = htonl(1);
1143238106Sdes		llsol.s6_addr32[3] =
1144238106Sdes			ia->ia_addr.sin6_addr.s6_addr32[3];
1145238106Sdes		llsol.s6_addr8[12] = 0xff;
1146238106Sdes
1147238106Sdes		IN6_LOOKUP_MULTI(llsol, ifp, in6m);
1148238106Sdes		if (in6m)
1149238106Sdes			in6_delmulti(in6m);
1150238106Sdes	}
1151238106Sdes
1152238106Sdes	in6_unlink_ifa(ia, ifp);
1153238106Sdes}
1154238106Sdes
1155238106Sdesstatic void
1156238106Sdesin6_unlink_ifa(ia, ifp)
1157238106Sdes	struct in6_ifaddr *ia;
1158238106Sdes	struct ifnet *ifp;
1159238106Sdes{
1160238106Sdes	int plen, iilen;
1161238106Sdes	struct in6_ifaddr *oia;
1162238106Sdes	int	s = splnet();
1163238106Sdes
1164238106Sdes	TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
1165238106Sdes
1166238106Sdes	oia = ia;
1167238106Sdes	if (oia == (ia = in6_ifaddr))
1168238106Sdes		in6_ifaddr = ia->ia_next;
1169238106Sdes	else {
1170238106Sdes		while (ia->ia_next && (ia->ia_next != oia))
1171238106Sdes			ia = ia->ia_next;
1172238106Sdes		if (ia->ia_next)
1173238106Sdes			ia->ia_next = oia->ia_next;
1174238106Sdes		else {
1175238106Sdes			/* search failed */
1176238106Sdes			printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
1177238106Sdes		}
1178238106Sdes	}
1179238106Sdes
1180238106Sdes	if (oia->ia6_ifpr) {	/* check for safety */
1181238106Sdes		plen = in6_mask2len(&oia->ia_prefixmask.sin6_addr, NULL);
1182285206Sdes		iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) - plen;
1183238106Sdes		in6_prefix_remove_ifid(iilen, oia);
1184285206Sdes	}
1185285206Sdes
1186285206Sdes	/*
1187285206Sdes	 * When an autoconfigured address is being removed, release the
1188285206Sdes	 * reference to the base prefix.  Also, since the release might
1189238106Sdes	 * affect the status of other (detached) addresses, call
1190238106Sdes	 * pfxlist_onlink_check().
1191238106Sdes	 */
1192238106Sdes	if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
1193238106Sdes		if (oia->ia6_ndpr == NULL) {
1194238106Sdes			log(LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "
1195238106Sdes			    "%p has no prefix\n", oia);
1196238106Sdes		} else {
1197238106Sdes			oia->ia6_ndpr->ndpr_refcnt--;
1198238106Sdes			oia->ia6_flags &= ~IN6_IFF_AUTOCONF;
1199238106Sdes			oia->ia6_ndpr = NULL;
1200238106Sdes		}
1201238106Sdes
1202238106Sdes		pfxlist_onlink_check();
1203238106Sdes	}
1204269257Sdes
1205238106Sdes	/*
1206238106Sdes	 * release another refcnt for the link from in6_ifaddr.
1207238106Sdes	 * Note that we should decrement the refcnt at least once for all *BSD.
1208238106Sdes	 */
1209238106Sdes	IFAFREE(&oia->ia_ifa);
1210238106Sdes
1211238106Sdes	splx(s);
1212238106Sdes}
1213238106Sdes
1214238106Sdesvoid
1215238106Sdesin6_purgeif(ifp)
1216238106Sdes	struct ifnet *ifp;
1217238106Sdes{
1218238106Sdes	struct ifaddr *ifa, *nifa;
1219238106Sdes
1220238106Sdes	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
1221238106Sdes		nifa = TAILQ_NEXT(ifa, ifa_list);
1222238106Sdes		if (ifa->ifa_addr->sa_family != AF_INET6)
1223238106Sdes			continue;
1224238106Sdes		in6_purgeaddr(ifa);
1225238106Sdes	}
1226238106Sdes
1227238106Sdes	in6_ifdetach(ifp);
1228238106Sdes}
1229238106Sdes
1230238106Sdes/*
1231238106Sdes * SIOC[GAD]LIFADDR.
1232269257Sdes *	SIOCGLIFADDR: get first address. (?)
1233238106Sdes *	SIOCGLIFADDR with IFLR_PREFIX:
1234269257Sdes *		get first address that matches the specified prefix.
1235238106Sdes *	SIOCALIFADDR: add the specified address.
1236238106Sdes *	SIOCALIFADDR with IFLR_PREFIX:
1237238106Sdes *		add the specified prefix, filling hostid part from
1238238106Sdes *		the first link-local address.  prefixlen must be <= 64.
1239238106Sdes *	SIOCDLIFADDR: delete the specified address.
1240238106Sdes *	SIOCDLIFADDR with IFLR_PREFIX:
1241238106Sdes *		delete the first address that matches the specified prefix.
1242238106Sdes * return values:
1243238106Sdes *	EINVAL on invalid parameters
1244238106Sdes *	EADDRNOTAVAIL on prefix match failed/specified address not found
1245238106Sdes *	other values may be returned from in6_ioctl()
1246238106Sdes *
1247238106Sdes * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
1248238106Sdes * this is to accomodate address naming scheme other than RFC2374,
1249238106Sdes * in the future.
1250238106Sdes * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
1251238106Sdes * address encoding scheme. (see figure on page 8)
1252238106Sdes */
1253238106Sdesstatic int
1254238106Sdesin6_lifaddr_ioctl(so, cmd, data, ifp, td)
1255238106Sdes	struct socket *so;
1256238106Sdes	u_long cmd;
1257238106Sdes	caddr_t	data;
1258238106Sdes	struct ifnet *ifp;
1259238106Sdes	struct thread *td;
1260238106Sdes{
1261238106Sdes	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
1262238106Sdes	struct ifaddr *ifa;
1263238106Sdes	struct sockaddr *sa;
1264238106Sdes
1265238106Sdes	/* sanity checks */
1266238106Sdes	if (!data || !ifp) {
1267238106Sdes		panic("invalid argument to in6_lifaddr_ioctl");
1268238106Sdes		/* NOTREACHED */
1269238106Sdes	}
1270238106Sdes
1271238106Sdes	switch (cmd) {
1272238106Sdes	case SIOCGLIFADDR:
1273238106Sdes		/* address must be specified on GET with IFLR_PREFIX */
1274238106Sdes		if ((iflr->flags & IFLR_PREFIX) == 0)
1275238106Sdes			break;
1276238106Sdes		/* FALLTHROUGH */
1277238106Sdes	case SIOCALIFADDR:
1278238106Sdes	case SIOCDLIFADDR:
1279238106Sdes		/* address must be specified on ADD and DELETE */
1280238106Sdes		sa = (struct sockaddr *)&iflr->addr;
1281238106Sdes		if (sa->sa_family != AF_INET6)
1282238106Sdes			return EINVAL;
1283238106Sdes		if (sa->sa_len != sizeof(struct sockaddr_in6))
1284238106Sdes			return EINVAL;
1285238106Sdes		/* XXX need improvement */
1286238106Sdes		sa = (struct sockaddr *)&iflr->dstaddr;
1287238106Sdes		if (sa->sa_family && sa->sa_family != AF_INET6)
1288238106Sdes			return EINVAL;
1289238106Sdes		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
1290238106Sdes			return EINVAL;
1291238106Sdes		break;
1292238106Sdes	default: /* shouldn't happen */
1293238106Sdes#if 0
1294238106Sdes		panic("invalid cmd to in6_lifaddr_ioctl");
1295238106Sdes		/* NOTREACHED */
1296238106Sdes#else
1297238106Sdes		return EOPNOTSUPP;
1298238106Sdes#endif
1299238106Sdes	}
1300238106Sdes	if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
1301238106Sdes		return EINVAL;
1302238106Sdes
1303238106Sdes	switch (cmd) {
1304238106Sdes	case SIOCALIFADDR:
1305238106Sdes	    {
1306238106Sdes		struct in6_aliasreq ifra;
1307238106Sdes		struct in6_addr *hostid = NULL;
1308238106Sdes		int prefixlen;
1309238106Sdes
1310238106Sdes		if ((iflr->flags & IFLR_PREFIX) != 0) {
1311238106Sdes			struct sockaddr_in6 *sin6;
1312238106Sdes
1313238106Sdes			/*
1314238106Sdes			 * hostid is to fill in the hostid part of the
1315238106Sdes			 * address.  hostid points to the first link-local
1316238106Sdes			 * address attached to the interface.
1317238106Sdes			 */
1318238106Sdes			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
1319238106Sdes			if (!ifa)
1320238106Sdes				return EADDRNOTAVAIL;
1321238106Sdes			hostid = IFA_IN6(ifa);
1322238106Sdes
1323238106Sdes		 	/* prefixlen must be <= 64. */
1324238106Sdes			if (64 < iflr->prefixlen)
1325238106Sdes				return EINVAL;
1326238106Sdes			prefixlen = iflr->prefixlen;
1327238106Sdes
1328238106Sdes			/* hostid part must be zero. */
1329238106Sdes			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1330238106Sdes			if (sin6->sin6_addr.s6_addr32[2] != 0
1331238106Sdes			 || sin6->sin6_addr.s6_addr32[3] != 0) {
1332238106Sdes				return EINVAL;
1333238106Sdes			}
1334238106Sdes		} else
1335238106Sdes			prefixlen = iflr->prefixlen;
1336238106Sdes
1337238106Sdes		/* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1338238106Sdes		bzero(&ifra, sizeof(ifra));
1339238106Sdes		bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
1340238106Sdes
1341238106Sdes		bcopy(&iflr->addr, &ifra.ifra_addr,
1342238106Sdes		    ((struct sockaddr *)&iflr->addr)->sa_len);
1343238106Sdes		if (hostid) {
1344238106Sdes			/* fill in hostid part */
1345238106Sdes			ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1346238106Sdes			    hostid->s6_addr32[2];
1347238106Sdes			ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1348238106Sdes			    hostid->s6_addr32[3];
1349238106Sdes		}
1350238106Sdes
1351238106Sdes		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
1352238106Sdes			bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1353238106Sdes			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
1354238106Sdes			if (hostid) {
1355238106Sdes				ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1356238106Sdes				    hostid->s6_addr32[2];
1357238106Sdes				ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1358238106Sdes				    hostid->s6_addr32[3];
1359238106Sdes			}
1360238106Sdes		}
1361238106Sdes
1362238106Sdes		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1363238106Sdes		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
1364238106Sdes
1365238106Sdes		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
1366238106Sdes		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, td);
1367238106Sdes	    }
1368238106Sdes	case SIOCGLIFADDR:
1369238106Sdes	case SIOCDLIFADDR:
1370238106Sdes	    {
1371238106Sdes		struct in6_ifaddr *ia;
1372238106Sdes		struct in6_addr mask, candidate, match;
1373238106Sdes		struct sockaddr_in6 *sin6;
1374238106Sdes		int cmp;
1375238106Sdes
1376238106Sdes		bzero(&mask, sizeof(mask));
1377238106Sdes		if (iflr->flags & IFLR_PREFIX) {
1378238106Sdes			/* lookup a prefix rather than address. */
1379238106Sdes			in6_prefixlen2mask(&mask, iflr->prefixlen);
1380238106Sdes
1381238106Sdes			sin6 = (struct sockaddr_in6 *)&iflr->addr;
1382238106Sdes			bcopy(&sin6->sin6_addr, &match, sizeof(match));
1383238106Sdes			match.s6_addr32[0] &= mask.s6_addr32[0];
1384238106Sdes			match.s6_addr32[1] &= mask.s6_addr32[1];
1385238106Sdes			match.s6_addr32[2] &= mask.s6_addr32[2];
1386238106Sdes			match.s6_addr32[3] &= mask.s6_addr32[3];
1387238106Sdes
1388238106Sdes			/* if you set extra bits, that's wrong */
1389238106Sdes			if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
1390238106Sdes				return EINVAL;
1391238106Sdes
1392238106Sdes			cmp = 1;
1393238106Sdes		} else {
1394238106Sdes			if (cmd == SIOCGLIFADDR) {
1395285206Sdes				/* on getting an address, take the 1st match */
1396285206Sdes				cmp = 0;	/* XXX */
1397285206Sdes			} else {
1398238106Sdes				/* on deleting an address, do exact match */
1399238106Sdes				in6_prefixlen2mask(&mask, 128);
1400249141Sdes				sin6 = (struct sockaddr_in6 *)&iflr->addr;
1401249141Sdes				bcopy(&sin6->sin6_addr, &match, sizeof(match));
1402249141Sdes
1403249141Sdes				cmp = 1;
1404249141Sdes			}
1405249141Sdes		}
1406249141Sdes
1407249141Sdes		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1408249141Sdes			if (ifa->ifa_addr->sa_family != AF_INET6)
1409249141Sdes				continue;
1410249141Sdes			if (!cmp)
1411249141Sdes				break;
1412249141Sdes
1413249141Sdes			bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1414249141Sdes			/*
1415249141Sdes			 * XXX: this is adhoc, but is necessary to allow
1416249141Sdes			 * a user to specify fe80::/64 (not /10) for a
1417249141Sdes			 * link-local address.
1418249141Sdes			 */
1419249141Sdes			if (IN6_IS_ADDR_LINKLOCAL(&candidate))
1420249141Sdes				candidate.s6_addr16[1] = 0;
1421249141Sdes			candidate.s6_addr32[0] &= mask.s6_addr32[0];
1422249141Sdes			candidate.s6_addr32[1] &= mask.s6_addr32[1];
1423249141Sdes			candidate.s6_addr32[2] &= mask.s6_addr32[2];
1424249141Sdes			candidate.s6_addr32[3] &= mask.s6_addr32[3];
1425249141Sdes			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
1426249141Sdes				break;
1427249141Sdes		}
1428249141Sdes		if (!ifa)
1429249141Sdes			return EADDRNOTAVAIL;
1430249141Sdes		ia = ifa2ia6(ifa);
1431249141Sdes
1432249141Sdes		if (cmd == SIOCGLIFADDR) {
1433249141Sdes			struct sockaddr_in6 *s6;
1434249141Sdes
1435249141Sdes			/* fill in the if_laddrreq structure */
1436249141Sdes			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1437249141Sdes			s6 = (struct sockaddr_in6 *)&iflr->addr;
1438249141Sdes			if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {
1439285206Sdes				s6->sin6_addr.s6_addr16[1] = 0;
1440249141Sdes				if (in6_addr2zoneid(ifp, &s6->sin6_addr,
1441249141Sdes				    &s6->sin6_scope_id))
1442249141Sdes					return (EINVAL);/* XXX */
1443249141Sdes			}
1444249141Sdes			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1445249141Sdes				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1446249141Sdes				    ia->ia_dstaddr.sin6_len);
1447249141Sdes				s6 = (struct sockaddr_in6 *)&iflr->dstaddr;
1448249141Sdes				if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {
1449249141Sdes					s6->sin6_addr.s6_addr16[1] = 0;
1450249141Sdes					if (in6_addr2zoneid(ifp,
1451249141Sdes					    &s6->sin6_addr, &s6->sin6_scope_id))
1452249141Sdes						return (EINVAL); /* EINVAL */
1453249141Sdes				}
1454249141Sdes			} else
1455249141Sdes				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
1456249141Sdes
1457249141Sdes			iflr->prefixlen =
1458249141Sdes			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
1459249141Sdes
1460249141Sdes			iflr->flags = ia->ia6_flags;	/* XXX */
1461249141Sdes
1462249141Sdes			return 0;
1463285206Sdes		} else {
1464285206Sdes			struct in6_aliasreq ifra;
1465285206Sdes
1466249141Sdes			/* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1467249141Sdes			bzero(&ifra, sizeof(ifra));
1468285206Sdes			bcopy(iflr->iflr_name, ifra.ifra_name,
1469285206Sdes			    sizeof(ifra.ifra_name));
1470285206Sdes
1471285206Sdes			bcopy(&ia->ia_addr, &ifra.ifra_addr,
1472285206Sdes			    ia->ia_addr.sin6_len);
1473285206Sdes			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1474285206Sdes				bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1475285206Sdes				    ia->ia_dstaddr.sin6_len);
1476285206Sdes			} else {
1477285206Sdes				bzero(&ifra.ifra_dstaddr,
1478285206Sdes				    sizeof(ifra.ifra_dstaddr));
1479285206Sdes			}
1480285206Sdes			bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1481285206Sdes			    ia->ia_prefixmask.sin6_len);
1482285206Sdes
1483285206Sdes			ifra.ifra_flags = ia->ia6_flags;
1484285206Sdes			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1485285206Sdes			    ifp, td);
1486285206Sdes		}
1487285206Sdes	    }
1488285206Sdes	}
1489285206Sdes
1490285206Sdes	return EOPNOTSUPP;	/* just for safety */
1491285206Sdes}
1492285206Sdes
1493285206Sdes/*
1494285206Sdes * Initialize an interface's intetnet6 address
1495285206Sdes * and routing table entry.
1496285206Sdes */
1497285206Sdesstatic int
1498285206Sdesin6_ifinit(ifp, ia, sin6, newhost)
1499285206Sdes	struct ifnet *ifp;
1500285206Sdes	struct in6_ifaddr *ia;
1501285206Sdes	struct sockaddr_in6 *sin6;
1502285206Sdes	int newhost;
1503285206Sdes{
1504285206Sdes	int	error = 0, plen, ifacount = 0;
1505285206Sdes	int	s = splimp();
1506285206Sdes	struct ifaddr *ifa;
1507285206Sdes
1508285206Sdes	/*
1509285206Sdes	 * Give the interface a chance to initialize
1510285206Sdes	 * if this is its first address,
1511285206Sdes	 * and to validate the address if necessary.
1512285206Sdes	 */
1513285206Sdes	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1514285206Sdes		if (ifa->ifa_addr == NULL)
1515285206Sdes			continue;	/* just for safety */
1516285206Sdes		if (ifa->ifa_addr->sa_family != AF_INET6)
1517285206Sdes			continue;
1518285206Sdes		ifacount++;
1519285206Sdes	}
1520285206Sdes
1521285206Sdes	ia->ia_addr = *sin6;
1522285206Sdes
1523285206Sdes	if (ifacount <= 1 && ifp->if_ioctl &&
1524285206Sdes	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
1525285206Sdes		splx(s);
1526285206Sdes		return (error);
1527285206Sdes	}
1528285206Sdes	splx(s);
1529285206Sdes
1530285206Sdes	ia->ia_ifa.ifa_metric = ifp->if_metric;
1531285206Sdes
1532285206Sdes	/* we could do in(6)_socktrim here, but just omit it at this moment. */
1533285206Sdes
1534285206Sdes	/*
1535285206Sdes	 * Special case:
1536285206Sdes	 * If the destination address is specified for a point-to-point
1537285206Sdes	 * interface, install a route to the destination as an interface
1538285206Sdes	 * direct route.
1539285206Sdes	 */
1540285206Sdes	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
1541285206Sdes	if (plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) {
1542285206Sdes		if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
1543285206Sdes				    RTF_UP | RTF_HOST)) != 0)
1544238106Sdes			return (error);
1545238106Sdes		ia->ia_flags |= IFA_ROUTE;
1546238106Sdes	}
1547238106Sdes	if (plen < 128) {
1548238106Sdes		/*
1549238106Sdes		 * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
1550238106Sdes		 */
1551238106Sdes		ia->ia_ifa.ifa_flags |= RTF_CLONING;
1552238106Sdes	}
1553238106Sdes
1554238106Sdes	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
1555238106Sdes	if (newhost) {
1556238106Sdes		/* set the rtrequest function to create llinfo */
1557238106Sdes		ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
1558238106Sdes		in6_ifaddloop(&(ia->ia_ifa));
1559238106Sdes	}
1560238106Sdes
1561238106Sdes	return (error);
1562238106Sdes}
1563238106Sdes
1564238106Sdes/*
1565238106Sdes * Add an address to the list of IP6 multicast addresses for a
1566238106Sdes * given interface.
1567238106Sdes */
1568238106Sdesstruct	in6_multi *
1569238106Sdesin6_addmulti(maddr6, ifp, errorp)
1570255579Sdes	struct in6_addr *maddr6;
1571238106Sdes	struct ifnet *ifp;
1572238106Sdes	int *errorp;
1573238106Sdes{
1574238106Sdes	struct	in6_multi *in6m;
1575238106Sdes	struct sockaddr_in6 sin6;
1576238106Sdes	struct ifmultiaddr *ifma;
1577238106Sdes	int	s = splnet();
1578269257Sdes
1579238106Sdes	*errorp = 0;
1580285206Sdes
1581238106Sdes	/*
1582238106Sdes	 * Call generic routine to add membership or increment
1583238106Sdes	 * refcount.  It wants addresses in the form of a sockaddr,
1584238106Sdes	 * so we build one here (being careful to zero the unused bytes).
1585238106Sdes	 */
1586238106Sdes	bzero(&sin6, sizeof sin6);
1587238106Sdes	sin6.sin6_family = AF_INET6;
1588238106Sdes	sin6.sin6_len = sizeof sin6;
1589238106Sdes	sin6.sin6_addr = *maddr6;
1590238106Sdes	*errorp = if_addmulti(ifp, (struct sockaddr *)&sin6, &ifma);
1591238106Sdes	if (*errorp) {
1592238106Sdes		splx(s);
1593238106Sdes		return 0;
1594238106Sdes	}
1595238106Sdes
1596238106Sdes	/*
1597238106Sdes	 * If ifma->ifma_protospec is null, then if_addmulti() created
1598238106Sdes	 * a new record.  Otherwise, we are done.
1599238106Sdes	 */
1600238106Sdes	if (ifma->ifma_protospec != 0)
1601238106Sdes		return ifma->ifma_protospec;
1602238106Sdes
1603238106Sdes	/* XXX - if_addmulti uses M_WAITOK.  Can this really be called
1604238106Sdes	   at interrupt time?  If so, need to fix if_addmulti. XXX */
1605238106Sdes	in6m = (struct in6_multi *)malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
1606238106Sdes	if (in6m == NULL) {
1607238106Sdes		splx(s);
1608238106Sdes		return (NULL);
1609238106Sdes	}
1610238106Sdes
1611238106Sdes	bzero(in6m, sizeof *in6m);
1612238106Sdes	in6m->in6m_addr = *maddr6;
1613238106Sdes	in6m->in6m_ifp = ifp;
1614238106Sdes	in6m->in6m_ifma = ifma;
1615238106Sdes	ifma->ifma_protospec = in6m;
1616238106Sdes	LIST_INSERT_HEAD(&in6_multihead, in6m, in6m_entry);
1617238106Sdes
1618238106Sdes	/*
1619238106Sdes	 * Let MLD6 know that we have joined a new IPv6 multicast
1620238106Sdes	 * group.
1621238106Sdes	 */
1622238106Sdes	mld6_start_listening(in6m);
1623238106Sdes	splx(s);
1624238106Sdes	return (in6m);
1625238106Sdes}
1626238106Sdes
1627238106Sdes/*
1628238106Sdes * Delete a multicast address record.
1629238106Sdes */
1630238106Sdesvoid
1631238106Sdesin6_delmulti(in6m)
1632238106Sdes	struct in6_multi *in6m;
1633238106Sdes{
1634238106Sdes	struct ifmultiaddr *ifma = in6m->in6m_ifma;
1635238106Sdes	int	s = splnet();
1636238106Sdes
1637238106Sdes	if (ifma->ifma_refcount == 1) {
1638238106Sdes		/*
1639238106Sdes		 * No remaining claims to this record; let MLD6 know
1640238106Sdes		 * that we are leaving the multicast group.
1641238106Sdes		 */
1642238106Sdes		mld6_stop_listening(in6m);
1643238106Sdes		ifma->ifma_protospec = 0;
1644238106Sdes		LIST_REMOVE(in6m, in6m_entry);
1645238106Sdes		free(in6m, M_IPMADDR);
1646238106Sdes	}
1647238106Sdes	/* XXX - should be separate API for when we have an ifma? */
1648238106Sdes	if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
1649238106Sdes	splx(s);
1650238106Sdes}
1651249141Sdes
1652238106Sdes/*
1653238106Sdes * Find an IPv6 interface link-local address specific to an interface.
1654238106Sdes */
1655238106Sdesstruct in6_ifaddr *
1656238106Sdesin6ifa_ifpforlinklocal(ifp, ignoreflags)
1657238106Sdes	struct ifnet *ifp;
1658238106Sdes	int ignoreflags;
1659238106Sdes{
1660238106Sdes	struct ifaddr *ifa;
1661238106Sdes
1662238106Sdes	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1663238106Sdes		if (ifa->ifa_addr == NULL)
1664238106Sdes			continue;	/* just for safety */
1665238106Sdes		if (ifa->ifa_addr->sa_family != AF_INET6)
1666238106Sdes			continue;
1667238106Sdes		if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
1668238106Sdes			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
1669238106Sdes			     ignoreflags) != 0)
1670238106Sdes				continue;
1671238106Sdes			break;
1672238106Sdes		}
1673238106Sdes	}
1674238106Sdes
1675238106Sdes	return ((struct in6_ifaddr *)ifa);
1676238106Sdes}
1677238106Sdes
1678238106Sdes
1679238106Sdes/*
1680238106Sdes * find the internet address corresponding to a given interface and address.
1681238106Sdes */
1682238106Sdesstruct in6_ifaddr *
1683238106Sdesin6ifa_ifpwithaddr(ifp, addr)
1684238106Sdes	struct ifnet *ifp;
1685238106Sdes	struct in6_addr *addr;
1686238106Sdes{
1687238106Sdes	struct ifaddr *ifa;
1688238106Sdes
1689238106Sdes	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1690238106Sdes		if (ifa->ifa_addr == NULL)
1691238106Sdes			continue;	/* just for safety */
1692238106Sdes		if (ifa->ifa_addr->sa_family != AF_INET6)
1693238106Sdes			continue;
1694238106Sdes		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
1695238106Sdes			break;
1696238106Sdes	}
1697238106Sdes
1698238106Sdes	return ((struct in6_ifaddr *)ifa);
1699238106Sdes}
1700238106Sdes
1701238106Sdes/*
1702238106Sdes * Convert IP6 address to printable (loggable) representation.
1703238106Sdes */
1704238106Sdesstatic char digits[] = "0123456789abcdef";
1705238106Sdesstatic int ip6round = 0;
1706238106Sdeschar *
1707238106Sdesip6_sprintf(addr)
1708238106Sdes	const struct in6_addr *addr;
1709238106Sdes{
1710238106Sdes	static char ip6buf[8][48];
1711238106Sdes	int i;
1712238106Sdes	char *cp;
1713238106Sdes	const u_short *a = (const u_short *)addr;
1714238106Sdes	const u_char *d;
1715238106Sdes	int dcolon = 0;
1716238106Sdes
1717238106Sdes	ip6round = (ip6round + 1) & 7;
1718238106Sdes	cp = ip6buf[ip6round];
1719238106Sdes
1720238106Sdes	for (i = 0; i < 8; i++) {
1721238106Sdes		if (dcolon == 1) {
1722238106Sdes			if (*a == 0) {
1723238106Sdes				if (i == 7)
1724238106Sdes					*cp++ = ':';
1725238106Sdes				a++;
1726238106Sdes				continue;
1727238106Sdes			} else
1728238106Sdes				dcolon = 2;
1729238106Sdes		}
1730238106Sdes		if (*a == 0) {
1731238106Sdes			if (dcolon == 0 && *(a + 1) == 0) {
1732238106Sdes				if (i == 0)
1733238106Sdes					*cp++ = ':';
1734238106Sdes				*cp++ = ':';
1735238106Sdes				dcolon = 1;
1736238106Sdes			} else {
1737238106Sdes				*cp++ = '0';
1738238106Sdes				*cp++ = ':';
1739238106Sdes			}
1740238106Sdes			a++;
1741238106Sdes			continue;
1742238106Sdes		}
1743238106Sdes		d = (const u_char *)a;
1744238106Sdes		*cp++ = digits[*d >> 4];
1745238106Sdes		*cp++ = digits[*d++ & 0xf];
1746238106Sdes		*cp++ = digits[*d >> 4];
1747238106Sdes		*cp++ = digits[*d & 0xf];
1748238106Sdes		*cp++ = ':';
1749238106Sdes		a++;
1750238106Sdes	}
1751238106Sdes	*--cp = 0;
1752238106Sdes	return (ip6buf[ip6round]);
1753238106Sdes}
1754238106Sdes
1755238106Sdesint
1756238106Sdesin6_localaddr(in6)
1757238106Sdes	struct in6_addr *in6;
1758238106Sdes{
1759238106Sdes	struct in6_ifaddr *ia;
1760238106Sdes
1761269257Sdes	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
1762238106Sdes		return 1;
1763238106Sdes
1764238106Sdes	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
1765238106Sdes		if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
1766238106Sdes		    &ia->ia_prefixmask.sin6_addr)) {
1767238106Sdes			return 1;
1768238106Sdes		}
1769238106Sdes	}
1770238106Sdes
1771238106Sdes	return (0);
1772238106Sdes}
1773238106Sdes
1774238106Sdesint
1775238106Sdesin6_is_addr_deprecated(sa6)
1776238106Sdes	struct sockaddr_in6 *sa6;
1777238106Sdes{
1778238106Sdes	struct in6_ifaddr *ia;
1779238106Sdes
1780238106Sdes	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
1781238106Sdes		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
1782238106Sdes				       &sa6->sin6_addr) &&
1783238106Sdes		    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
1784238106Sdes			return (1); /* true */
1785238106Sdes
1786238106Sdes		/* XXX: do we still have to go thru the rest of the list? */
1787238106Sdes	}
1788269257Sdes
1789238106Sdes	return (0);		/* false */
1790238106Sdes}
1791238106Sdes
1792238106Sdes/*
1793238106Sdes * return length of part which dst and src are equal
1794238106Sdes * hard coding...
1795238106Sdes */
1796238106Sdesint
1797238106Sdesin6_matchlen(src, dst)
1798238106Sdesstruct in6_addr *src, *dst;
1799238106Sdes{
1800238106Sdes	int match = 0;
1801238106Sdes	u_char *s = (u_char *)src, *d = (u_char *)dst;
1802238106Sdes	u_char *lim = s + 16, r;
1803238106Sdes
1804238106Sdes	while (s < lim)
1805238106Sdes		if ((r = (*d++ ^ *s++)) != 0) {
1806269257Sdes			while (r < 128) {
1807238106Sdes				match++;
1808238106Sdes				r <<= 1;
1809238106Sdes			}
1810238106Sdes			break;
1811238106Sdes		} else
1812238106Sdes			match += 8;
1813238106Sdes	return match;
1814238106Sdes}
1815238106Sdes
1816269257Sdes/* XXX: to be scope conscious */
1817269257Sdesint
1818269257Sdesin6_are_prefix_equal(p1, p2, len)
1819238106Sdes	struct in6_addr *p1, *p2;
1820238106Sdes	int len;
1821238106Sdes{
1822238106Sdes	int bytelen, bitlen;
1823238106Sdes
1824238106Sdes	/* sanity check */
1825238106Sdes	if (0 > len || len > 128) {
1826238106Sdes		log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
1827269257Sdes		    len);
1828269257Sdes		return (0);
1829269257Sdes	}
1830238106Sdes
1831238106Sdes	bytelen = len / 8;
1832238106Sdes	bitlen = len % 8;
1833238106Sdes
1834238106Sdes	if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
1835238106Sdes		return (0);
1836238106Sdes	if (p1->s6_addr[bytelen] >> (8 - bitlen) !=
1837238106Sdes	    p2->s6_addr[bytelen] >> (8 - bitlen))
1838238106Sdes		return (0);
1839238106Sdes
1840238106Sdes	return (1);
1841238106Sdes}
1842238106Sdes
1843238106Sdesvoid
1844238106Sdesin6_prefixlen2mask(maskp, len)
1845238106Sdes	struct in6_addr *maskp;
1846269257Sdes	int len;
1847238106Sdes{
1848238106Sdes	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
1849238106Sdes	int bytelen, bitlen, i;
1850238106Sdes
1851238106Sdes	/* sanity check */
1852238106Sdes	if (0 > len || len > 128) {
1853238106Sdes		log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
1854238106Sdes		    len);
1855269257Sdes		return;
1856269257Sdes	}
1857269257Sdes
1858269257Sdes	bzero(maskp, sizeof(*maskp));
1859269257Sdes	bytelen = len / 8;
1860269257Sdes	bitlen = len % 8;
1861269257Sdes	for (i = 0; i < bytelen; i++)
1862269257Sdes		maskp->s6_addr[i] = 0xff;
1863269257Sdes	if (bitlen)
1864269257Sdes		maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
1865269257Sdes}
1866269257Sdes
1867269257Sdes/*
1868269257Sdes * return the best address out of the same scope
1869269257Sdes */
1870269257Sdesstruct in6_ifaddr *
1871269257Sdesin6_ifawithscope(oifp, dst)
1872269257Sdes	struct ifnet *oifp;
1873269257Sdes	struct in6_addr *dst;
1874269257Sdes{
1875269257Sdes	int dst_scope =	in6_addrscope(dst), src_scope, best_scope = 0;
1876269257Sdes	int blen = -1;
1877269257Sdes	struct ifaddr *ifa;
1878269257Sdes	struct ifnet *ifp;
1879269257Sdes	struct in6_ifaddr *ifa_best = NULL;
1880269257Sdes	u_int32_t dstzone, odstzone;
1881269257Sdes
1882269257Sdes	if (oifp == NULL) {
1883269257Sdes		return (NULL);
1884269257Sdes	}
1885269257Sdes
1886269257Sdes	if (in6_addr2zoneid(oifp, dst, &odstzone))
1887269257Sdes		return (NULL);
1888269257Sdes
1889269257Sdes	/*
1890269257Sdes	 * We search for all addresses on all interfaces from the beginning.
1891269257Sdes	 * Comparing an interface with the outgoing interface will be done
1892238106Sdes	 * only at the final stage of tiebreaking.
1893238106Sdes	 */
1894238106Sdes	IFNET_RLOCK();
1895238106Sdes	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
1896238106Sdes	{
1897238106Sdes		/*
1898238106Sdes		 * We can never take an address that breaks the scope zone
1899238106Sdes		 * of the destination.
1900238106Sdes		 */
1901238106Sdes		if (in6_addr2zoneid(ifp, dst, &dstzone) || dstzone != odstzone)
1902238106Sdes			continue;
1903238106Sdes
1904238106Sdes		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1905238106Sdes		{
1906238106Sdes			int tlen = -1, dscopecmp, bscopecmp, matchcmp;
1907238106Sdes
1908238106Sdes			if (ifa->ifa_addr->sa_family != AF_INET6)
1909238106Sdes				continue;
1910238106Sdes
1911238106Sdes			src_scope = in6_addrscope(IFA_IN6(ifa));
1912238106Sdes
1913269257Sdes			/*
1914238106Sdes			 * Don't use an address before completing DAD
1915285206Sdes			 * nor a duplicated address.
1916285206Sdes			 */
1917285206Sdes			if (((struct in6_ifaddr *)ifa)->ia6_flags &
1918285206Sdes			    IN6_IFF_NOTREADY)
1919238106Sdes				continue;
1920238106Sdes
1921238106Sdes			/* XXX: is there any case to allow anycasts? */
1922238106Sdes			if (((struct in6_ifaddr *)ifa)->ia6_flags &
1923238106Sdes			    IN6_IFF_ANYCAST)
1924238106Sdes				continue;
1925238106Sdes
1926238106Sdes			if (((struct in6_ifaddr *)ifa)->ia6_flags &
1927238106Sdes			    IN6_IFF_DETACHED)
1928238106Sdes				continue;
1929238106Sdes
1930238106Sdes			/*
1931238106Sdes			 * If this is the first address we find,
1932238106Sdes			 * keep it anyway.
1933238106Sdes			 */
1934238106Sdes			if (ifa_best == NULL)
1935238106Sdes				goto replace;
1936269257Sdes
1937269257Sdes			/*
1938238106Sdes			 * ifa_best is never NULL beyond this line except
1939238106Sdes			 * within the block labeled "replace".
1940238106Sdes			 */
1941238106Sdes
1942238106Sdes			/*
1943238106Sdes			 * If ifa_best has a smaller scope than dst and
1944238106Sdes			 * the current address has a larger one than
1945238106Sdes			 * (or equal to) dst, always replace ifa_best.
1946238106Sdes			 * Also, if the current address has a smaller scope
1947238106Sdes			 * than dst, ignore it unless ifa_best also has a
1948238106Sdes			 * smaller scope.
1949238106Sdes			 * Consequently, after the two if-clause below,
1950238106Sdes			 * the followings must be satisfied:
1951238106Sdes			 * (scope(src) < scope(dst) &&
1952238106Sdes			 *  scope(best) < scope(dst))
1953238106Sdes			 *  OR
1954238106Sdes			 * (scope(best) >= scope(dst) &&
1955238106Sdes			 *  scope(src) >= scope(dst))
1956238106Sdes			 */
1957238106Sdes			if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0 &&
1958238106Sdes			    IN6_ARE_SCOPE_CMP(src_scope, dst_scope) >= 0)
1959238106Sdes				goto replace; /* (A) */
1960238106Sdes			if (IN6_ARE_SCOPE_CMP(src_scope, dst_scope) < 0 &&
1961238106Sdes			    IN6_ARE_SCOPE_CMP(best_scope, dst_scope) >= 0)
1962238106Sdes				continue; /* (B) */
1963238106Sdes
1964238106Sdes			/*
1965238106Sdes			 * A deprecated address SHOULD NOT be used in new
1966238106Sdes			 * communications if an alternate (non-deprecated)
1967238106Sdes			 * address is available and has sufficient scope.
1968238106Sdes			 * RFC 2462, Section 5.5.4.
1969238106Sdes			 */
1970238106Sdes			if (((struct in6_ifaddr *)ifa)->ia6_flags &
1971238106Sdes			    IN6_IFF_DEPRECATED) {
1972238106Sdes				/*
1973238106Sdes				 * Ignore any deprecated addresses if
1974238106Sdes				 * specified by configuration.
1975238106Sdes				 */
1976238106Sdes				if (!ip6_use_deprecated)
1977238106Sdes					continue;
1978238106Sdes
1979238106Sdes				/*
1980238106Sdes				 * If we have already found a non-deprecated
1981238106Sdes				 * candidate, just ignore deprecated addresses.
1982269257Sdes				 */
1983269257Sdes				if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED)
1984238106Sdes				    == 0)
1985269257Sdes					continue;
1986269257Sdes			}
1987238106Sdes
1988238106Sdes			/*
1989238106Sdes			 * A non-deprecated address is always preferred
1990238106Sdes			 * to a deprecated one regardless of scopes and
1991238106Sdes			 * address matching (Note invariants ensured by the
1992238106Sdes			 * conditions (A) and (B) above.)
1993238106Sdes			 */
1994238106Sdes			if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) &&
1995238106Sdes			    (((struct in6_ifaddr *)ifa)->ia6_flags &
1996238106Sdes			     IN6_IFF_DEPRECATED) == 0)
1997238106Sdes				goto replace;
1998238106Sdes
1999238106Sdes			/*
2000238106Sdes			 * When we use temporary addresses described in
2001238106Sdes			 * RFC 3041, we prefer temporary addresses to
2002238106Sdes			 * public autoconf addresses.  Again, note the
2003238106Sdes			 * invariants from (A) and (B).  Also note that we
2004238106Sdes			 * don't have any preference between static addresses
2005238106Sdes			 * and autoconf addresses (despite of whether or not
2006238106Sdes			 * the latter is temporary or public.)
2007238106Sdes			 */
2008238106Sdes			if (ip6_use_tempaddr) {
2009238106Sdes				struct in6_ifaddr *ifat;
2010238106Sdes
2011238106Sdes				ifat = (struct in6_ifaddr *)ifa;
2012238106Sdes				if ((ifa_best->ia6_flags &
2013238106Sdes				     (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
2014238106Sdes				     == IN6_IFF_AUTOCONF &&
2015269257Sdes				    (ifat->ia6_flags &
2016269257Sdes				     (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
2017238106Sdes				     == (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY)) {
2018238106Sdes					goto replace;
2019238106Sdes				}
2020238106Sdes				if ((ifa_best->ia6_flags &
2021269257Sdes				     (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
2022269257Sdes				    == (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY) &&
2023238106Sdes				    (ifat->ia6_flags &
2024238106Sdes				     (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY))
2025238106Sdes				     == IN6_IFF_AUTOCONF) {
2026238106Sdes					continue;
2027238106Sdes				}
2028238106Sdes			}
2029238106Sdes
2030238106Sdes			/*
2031238106Sdes			 * At this point, we have two cases:
2032238106Sdes			 * 1. we are looking at a non-deprecated address,
2033238106Sdes			 *    and ifa_best is also non-deprecated.
2034238106Sdes			 * 2. we are looking at a deprecated address,
2035238106Sdes			 *    and ifa_best is also deprecated.
2036238106Sdes			 * Also, we do not have to consider a case where
2037238106Sdes			 * the scope of if_best is larger(smaller) than dst and
2038238106Sdes			 * the scope of the current address is smaller(larger)
2039238106Sdes			 * than dst. Such a case has already been covered.
2040269257Sdes			 * Tiebreaking is done according to the following
2041285206Sdes			 * items:
2042285206Sdes			 * - the scope comparison between the address and
2043285206Sdes			 *   dst (dscopecmp)
2044238106Sdes			 * - the scope comparison between the address and
2045238106Sdes			 *   ifa_best (bscopecmp)
2046238106Sdes			 * - if the address match dst longer than ifa_best
2047238106Sdes			 *   (matchcmp)
2048238106Sdes			 * - if the address is on the outgoing I/F (outI/F)
2049238106Sdes			 *
2050238106Sdes			 * Roughly speaking, the selection policy is
2051238106Sdes			 * - the most important item is scope. The same scope
2052238106Sdes			 *   is best. Then search for a larger scope.
2053238106Sdes			 *   Smaller scopes are the last resort.
2054238106Sdes			 * - A deprecated address is chosen only when we have
2055285206Sdes			 *   no address that has an enough scope, but is
2056285206Sdes			 *   prefered to any addresses of smaller scopes
2057238106Sdes			 *   (this must be already done above.)
2058238106Sdes			 * - addresses on the outgoing I/F are preferred to
2059238106Sdes			 *   ones on other interfaces if none of above
2060238106Sdes			 *   tiebreaks.  In the table below, the column "bI"
2061238106Sdes			 *   means if the best_ifa is on the outgoing
2062238106Sdes			 *   interface, and the column "sI" means if the ifa
2063285206Sdes			 *   is on the outgoing interface.
2064285206Sdes			 * - If there is no other reasons to choose one,
2065285206Sdes			 *   longest address match against dst is considered.
2066285206Sdes			 *
2067238106Sdes			 * The precise decision table is as follows:
2068238106Sdes			 * dscopecmp bscopecmp    match  bI oI | replace?
2069238106Sdes			 *       N/A     equal      N/A   Y  N |   No (1)
2070285206Sdes			 *       N/A     equal      N/A   N  Y |  Yes (2)
2071238106Sdes			 *       N/A     equal   larger    N/A |  Yes (3)
2072238106Sdes			 *       N/A     equal  !larger    N/A |   No (4)
2073285206Sdes			 *    larger    larger      N/A    N/A |   No (5)
2074238106Sdes			 *    larger   smaller      N/A    N/A |  Yes (6)
2075238106Sdes			 *   smaller    larger      N/A    N/A |  Yes (7)
2076238106Sdes			 *   smaller   smaller      N/A    N/A |   No (8)
2077238106Sdes			 *     equal   smaller      N/A    N/A |  Yes (9)
2078238106Sdes			 *     equal    larger       (already done at A above)
2079285206Sdes			 */
2080285206Sdes			dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
2081238106Sdes			bscopecmp = IN6_ARE_SCOPE_CMP(src_scope, best_scope);
2082285206Sdes
2083238106Sdes			if (bscopecmp == 0) {
2084238106Sdes				struct ifnet *bifp = ifa_best->ia_ifp;
2085238106Sdes
2086238106Sdes				if (bifp == oifp && ifp != oifp) /* (1) */
2087238106Sdes					continue;
2088238106Sdes				if (bifp != oifp && ifp == oifp) /* (2) */
2089238106Sdes					goto replace;
2090238106Sdes
2091238106Sdes				/*
2092238106Sdes				 * Both bifp and ifp are on the outgoing
2093285206Sdes				 * interface, or both two are on a different
2094238106Sdes				 * interface from the outgoing I/F.
2095238106Sdes				 * now we need address matching against dst
2096238106Sdes				 * for tiebreaking.
2097238106Sdes				 */
2098238106Sdes				tlen = in6_matchlen(IFA_IN6(ifa), dst);
2099238106Sdes				matchcmp = tlen - blen;
2100238106Sdes				if (matchcmp > 0) /* (3) */
2101238106Sdes					goto replace;
2102238106Sdes				continue; /* (4) */
2103238106Sdes			}
2104238106Sdes			if (dscopecmp > 0) {
2105238106Sdes				if (bscopecmp > 0) /* (5) */
2106238106Sdes					continue;
2107238106Sdes				goto replace; /* (6) */
2108238106Sdes			}
2109238106Sdes			if (dscopecmp < 0) {
2110238106Sdes				if (bscopecmp > 0) /* (7) */
2111238106Sdes					goto replace;
2112238106Sdes				continue; /* (8) */
2113238106Sdes			}
2114238106Sdes
2115238106Sdes			/* now dscopecmp must be 0 */
2116238106Sdes			if (bscopecmp < 0)
2117238106Sdes				goto replace; /* (9) */
2118238106Sdes
2119238106Sdes		  replace:
2120238106Sdes			ifa_best = (struct in6_ifaddr *)ifa;
2121238106Sdes			blen = tlen >= 0 ? tlen :
2122238106Sdes				in6_matchlen(IFA_IN6(ifa), dst);
2123238106Sdes			best_scope = in6_addrscope(&ifa_best->ia_addr.sin6_addr);
2124238106Sdes		}
2125238106Sdes	}
2126238106Sdes	IFNET_RUNLOCK();
2127238106Sdes
2128238106Sdes	/* count statistics for future improvements */
2129238106Sdes	if (ifa_best == NULL)
2130238106Sdes		ip6stat.ip6s_sources_none++;
2131238106Sdes	else {
2132238106Sdes		if (oifp == ifa_best->ia_ifp)
2133238106Sdes			ip6stat.ip6s_sources_sameif[best_scope]++;
2134238106Sdes		else
2135238106Sdes			ip6stat.ip6s_sources_otherif[best_scope]++;
2136238106Sdes
2137238106Sdes		if (best_scope == dst_scope)
2138238106Sdes			ip6stat.ip6s_sources_samescope[best_scope]++;
2139238106Sdes		else
2140238106Sdes			ip6stat.ip6s_sources_otherscope[best_scope]++;
2141238106Sdes
2142238106Sdes		if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) != 0)
2143238106Sdes			ip6stat.ip6s_sources_deprecated[best_scope]++;
2144238106Sdes	}
2145238106Sdes
2146285206Sdes	return (ifa_best);
2147285206Sdes}
2148238106Sdes
2149238106Sdes/*
2150285206Sdes * return the best address out of the same scope. if no address was
2151285206Sdes * found, return the first valid address from designated IF.
2152285206Sdes */
2153285206Sdesstruct in6_ifaddr *
2154285206Sdesin6_ifawithifp(ifp, dst)
2155285206Sdes	struct ifnet *ifp;
2156285206Sdes	struct in6_addr *dst;
2157285206Sdes{
2158285206Sdes	int dst_scope =	in6_addrscope(dst), blen = -1, tlen;
2159285206Sdes	struct ifaddr *ifa;
2160285206Sdes	struct in6_ifaddr *besta = 0;
2161285206Sdes	struct in6_ifaddr *dep[2];	/* last-resort: deprecated */
2162285206Sdes
2163238106Sdes	dep[0] = dep[1] = NULL;
2164238106Sdes
2165238106Sdes	/*
2166238106Sdes	 * We first look for addresses in the same scope.
2167238106Sdes	 * If there is one, return it.
2168238106Sdes	 * If two or more, return one which matches the dst longest.
2169238106Sdes	 * If none, return one of global addresses assigned other ifs.
2170238106Sdes	 */
2171238106Sdes	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2172285206Sdes		if (ifa->ifa_addr->sa_family != AF_INET6)
2173285206Sdes			continue;
2174285206Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
2175238106Sdes			continue; /* XXX: is there any case to allow anycast? */
2176285206Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
2177285206Sdes			continue; /* don't use this interface */
2178285206Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
2179285206Sdes			continue;
2180285206Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2181285206Sdes			if (ip6_use_deprecated)
2182285206Sdes				dep[0] = (struct in6_ifaddr *)ifa;
2183285206Sdes			continue;
2184285206Sdes		}
2185285206Sdes
2186285206Sdes		if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
2187285206Sdes			/*
2188285206Sdes			 * call in6_matchlen() as few as possible
2189285206Sdes			 */
2190238106Sdes			if (besta) {
2191238106Sdes				if (blen == -1)
2192238106Sdes					blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
2193238106Sdes				tlen = in6_matchlen(IFA_IN6(ifa), dst);
2194238106Sdes				if (tlen > blen) {
2195238106Sdes					blen = tlen;
2196238106Sdes					besta = (struct in6_ifaddr *)ifa;
2197238106Sdes				}
2198238106Sdes			} else
2199238106Sdes				besta = (struct in6_ifaddr *)ifa;
2200238106Sdes		}
2201238106Sdes	}
2202269257Sdes	if (besta)
2203238106Sdes		return (besta);
2204238106Sdes
2205238106Sdes	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2206285206Sdes		if (ifa->ifa_addr->sa_family != AF_INET6)
2207285206Sdes			continue;
2208285206Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
2209285206Sdes			continue; /* XXX: is there any case to allow anycast? */
2210285206Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
2211285206Sdes			continue; /* don't use this interface */
2212285206Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
2213238106Sdes			continue;
2214238106Sdes		if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2215269257Sdes			if (ip6_use_deprecated)
2216238106Sdes				dep[1] = (struct in6_ifaddr *)ifa;
2217238106Sdes			continue;
2218238106Sdes		}
2219238106Sdes
2220238106Sdes		return (struct in6_ifaddr *)ifa;
2221238106Sdes	}
2222238106Sdes
2223238106Sdes	/* use the last-resort values, that are, deprecated addresses */
2224238106Sdes	if (dep[0])
2225238106Sdes		return dep[0];
2226269257Sdes	if (dep[1])
2227269257Sdes		return dep[1];
2228269257Sdes
2229238106Sdes	return NULL;
2230238106Sdes}
2231238106Sdes
2232238106Sdes/*
2233269257Sdes * perform DAD when interface becomes IFF_UP.
2234269257Sdes */
2235269257Sdesvoid
2236269257Sdesin6_if_up(ifp)
2237269257Sdes	struct ifnet *ifp;
2238269257Sdes{
2239269257Sdes	struct ifaddr *ifa;
2240269257Sdes	struct in6_ifaddr *ia;
2241269257Sdes	int dad_delay;		/* delay ticks before DAD output */
2242269257Sdes
2243269257Sdes	/*
2244269257Sdes	 * special cases, like 6to4, are handled in in6_ifattach
2245238106Sdes	 */
2246238106Sdes	in6_ifattach(ifp, NULL);
2247238106Sdes
2248238106Sdes	dad_delay = 0;
2249269257Sdes	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2250238106Sdes		if (ifa->ifa_addr->sa_family != AF_INET6)
2251238106Sdes			continue;
2252238106Sdes		ia = (struct in6_ifaddr *)ifa;
2253238106Sdes		if (ia->ia6_flags & IN6_IFF_TENTATIVE)
2254238106Sdes			nd6_dad_start(ifa, &dad_delay);
2255238106Sdes	}
2256238106Sdes}
2257238106Sdes
2258238106Sdesint
2259238106Sdesin6if_do_dad(ifp)
2260238106Sdes	struct ifnet *ifp;
2261238106Sdes{
2262238106Sdes	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
2263238106Sdes		return (0);
2264238106Sdes
2265238106Sdes	switch (ifp->if_type) {
2266238106Sdes#ifdef IFT_DUMMY
2267238106Sdes	case IFT_DUMMY:
2268238106Sdes#endif
2269238106Sdes	case IFT_FAITH:
2270238106Sdes		/*
2271238106Sdes		 * These interfaces do not have the IFF_LOOPBACK flag,
2272238106Sdes		 * but loop packets back.  We do not have to do DAD on such
2273238106Sdes		 * interfaces.  We should even omit it, because loop-backed
2274238106Sdes		 * NS would confuse the DAD procedure.
2275238106Sdes		 */
2276238106Sdes		return (0);
2277238106Sdes	default:
2278238106Sdes		/*
2279238106Sdes		 * Our DAD routine requires the interface up and running.
2280238106Sdes		 * However, some interfaces can be up before the RUNNING
2281238106Sdes		 * status.  Additionaly, users may try to assign addresses
2282238106Sdes		 * before the interface becomes up (or running).
2283238106Sdes		 * We simply skip DAD in such a case as a work around.
2284238106Sdes		 * XXX: we should rather mark "tentative" on such addresses,
2285238106Sdes		 * and do DAD after the interface becomes ready.
2286238106Sdes		 */
2287238106Sdes		if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) !=
2288238106Sdes		    (IFF_UP|IFF_RUNNING))
2289238106Sdes			return (0);
2290238106Sdes
2291238106Sdes		return (1);
2292238106Sdes	}
2293238106Sdes}
2294238106Sdes
2295238106Sdes/*
2296238106Sdes * Calculate max IPv6 MTU through all the interfaces and store it
2297238106Sdes * to in6_maxmtu.
2298238106Sdes */
2299238106Sdesvoid
2300238106Sdesin6_setmaxmtu()
2301238106Sdes{
2302238106Sdes	unsigned long maxmtu = 0;
2303238106Sdes	struct ifnet *ifp;
2304238106Sdes
2305238106Sdes	IFNET_RLOCK();
2306238106Sdes	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
2307238106Sdes		/* this function can be called during ifnet initialization */
2308238106Sdes		if (!ifp->if_afdata[AF_INET6])
2309238106Sdes			continue;
2310238106Sdes		if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2311238106Sdes		    IN6_LINKMTU(ifp) > maxmtu)
2312238106Sdes			maxmtu = IN6_LINKMTU(ifp);
2313238106Sdes	}
2314238106Sdes	IFNET_RUNLOCK();
2315238106Sdes	if (maxmtu)	     /* update only when maxmtu is positive */
2316238106Sdes		in6_maxmtu = maxmtu;
2317238106Sdes}
2318238106Sdes
2319238106Sdesvoid *
2320238106Sdesin6_domifattach(ifp)
2321238106Sdes	struct ifnet *ifp;
2322238106Sdes{
2323238106Sdes	struct in6_ifextra *ext;
2324238106Sdes
2325238106Sdes	ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
2326238106Sdes	bzero(ext, sizeof(*ext));
2327238106Sdes
2328238106Sdes	ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
2329238106Sdes	    M_IFADDR, M_WAITOK);
2330238106Sdes	bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
2331238106Sdes
2332238106Sdes	ext->icmp6_ifstat =
2333238106Sdes	    (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
2334238106Sdes	    M_IFADDR, M_WAITOK);
2335238106Sdes	bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
2336238106Sdes
2337238106Sdes	ext->nd_ifinfo = nd6_ifattach(ifp);
2338269257Sdes	ext->scope6_id = scope6_ifattach(ifp);
2339269257Sdes	return ext;
2340269257Sdes}
2341269257Sdes
2342269257Sdesvoid
2343269257Sdesin6_domifdetach(ifp, aux)
2344269257Sdes	struct ifnet *ifp;
2345269257Sdes	void *aux;
2346269257Sdes{
2347269257Sdes	struct in6_ifextra *ext = (struct in6_ifextra *)aux;
2348238106Sdes
2349238106Sdes	scope6_ifdetach(ext->scope6_id);
2350238106Sdes	nd6_ifdetach(ext->nd_ifinfo);
2351238106Sdes	free(ext->in6_ifstat, M_IFADDR);
2352238106Sdes	free(ext->icmp6_ifstat, M_IFADDR);
2353238106Sdes	free(ext, M_IFADDR);
2354238106Sdes}
2355238106Sdes
2356238106Sdes/*
2357238106Sdes * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
2358238106Sdes * v4 mapped addr or v4 compat addr
2359238106Sdes */
2360238106Sdesvoid
2361238106Sdesin6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
2362238106Sdes{
2363238106Sdes	bzero(sin, sizeof(*sin));
2364238106Sdes	sin->sin_len = sizeof(struct sockaddr_in);
2365238106Sdes	sin->sin_family = AF_INET;
2366238106Sdes	sin->sin_port = sin6->sin6_port;
2367238106Sdes	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
2368238106Sdes}
2369238106Sdes
2370238106Sdes/* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
2371238106Sdesvoid
2372238106Sdesin6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
2373238106Sdes{
2374238106Sdes	bzero(sin6, sizeof(*sin6));
2375238106Sdes	sin6->sin6_len = sizeof(struct sockaddr_in6);
2376238106Sdes	sin6->sin6_family = AF_INET6;
2377238106Sdes	sin6->sin6_port = sin->sin_port;
2378238106Sdes	sin6->sin6_addr.s6_addr32[0] = 0;
2379238106Sdes	sin6->sin6_addr.s6_addr32[1] = 0;
2380238106Sdes	sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
2381238106Sdes	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
2382238106Sdes}
2383238106Sdes
2384238106Sdes/* Convert sockaddr_in6 into sockaddr_in. */
2385238106Sdesvoid
2386238106Sdesin6_sin6_2_sin_in_sock(struct sockaddr *nam)
2387238106Sdes{
2388238106Sdes	struct sockaddr_in *sin_p;
2389238106Sdes	struct sockaddr_in6 sin6;
2390238106Sdes
2391238106Sdes	/*
2392238106Sdes	 * Save original sockaddr_in6 addr and convert it
2393238106Sdes	 * to sockaddr_in.
2394238106Sdes	 */
2395238106Sdes	sin6 = *(struct sockaddr_in6 *)nam;
2396238106Sdes	sin_p = (struct sockaddr_in *)nam;
2397238106Sdes	in6_sin6_2_sin(sin_p, &sin6);
2398238106Sdes}
2399238106Sdes
2400238106Sdes/* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
2401238106Sdesvoid
2402238106Sdesin6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
2403238106Sdes{
2404249141Sdes	struct sockaddr_in *sin_p;
2405249141Sdes	struct sockaddr_in6 *sin6_p;
2406285206Sdes
2407285206Sdes	MALLOC(sin6_p, struct sockaddr_in6 *, sizeof *sin6_p, M_SONAME,
2408238106Sdes	       M_WAITOK);
2409238106Sdes	sin_p = (struct sockaddr_in *)*nam;
2410238106Sdes	in6_sin_2_v4mapsin6(sin_p, sin6_p);
2411238106Sdes	FREE(*nam, M_SONAME);
2412238106Sdes	*nam = (struct sockaddr *)sin6_p;
2413238106Sdes}
2414238106Sdes