xref: /freebsd/sys/netinet6/in6_src.c (revision 33841545909f4a4ee94aa148b3a9cbcdc1abb02a)
1686cdd19SJun-ichiro itojun Hagino /*	$FreeBSD$	*/
233841545SHajimu UMEMOTO /*	$KAME: in6_src.c,v 1.37 2001/03/29 05:34:31 itojun Exp $	*/
3686cdd19SJun-ichiro itojun Hagino 
4686cdd19SJun-ichiro itojun Hagino /*
5686cdd19SJun-ichiro itojun Hagino  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6686cdd19SJun-ichiro itojun Hagino  * All rights reserved.
7686cdd19SJun-ichiro itojun Hagino  *
8686cdd19SJun-ichiro itojun Hagino  * Redistribution and use in source and binary forms, with or without
9686cdd19SJun-ichiro itojun Hagino  * modification, are permitted provided that the following conditions
10686cdd19SJun-ichiro itojun Hagino  * are met:
11686cdd19SJun-ichiro itojun Hagino  * 1. Redistributions of source code must retain the above copyright
12686cdd19SJun-ichiro itojun Hagino  *    notice, this list of conditions and the following disclaimer.
13686cdd19SJun-ichiro itojun Hagino  * 2. Redistributions in binary form must reproduce the above copyright
14686cdd19SJun-ichiro itojun Hagino  *    notice, this list of conditions and the following disclaimer in the
15686cdd19SJun-ichiro itojun Hagino  *    documentation and/or other materials provided with the distribution.
16686cdd19SJun-ichiro itojun Hagino  * 3. Neither the name of the project nor the names of its contributors
17686cdd19SJun-ichiro itojun Hagino  *    may be used to endorse or promote products derived from this software
18686cdd19SJun-ichiro itojun Hagino  *    without specific prior written permission.
19686cdd19SJun-ichiro itojun Hagino  *
20686cdd19SJun-ichiro itojun Hagino  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21686cdd19SJun-ichiro itojun Hagino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22686cdd19SJun-ichiro itojun Hagino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23686cdd19SJun-ichiro itojun Hagino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24686cdd19SJun-ichiro itojun Hagino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25686cdd19SJun-ichiro itojun Hagino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26686cdd19SJun-ichiro itojun Hagino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27686cdd19SJun-ichiro itojun Hagino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28686cdd19SJun-ichiro itojun Hagino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29686cdd19SJun-ichiro itojun Hagino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30686cdd19SJun-ichiro itojun Hagino  * SUCH DAMAGE.
31686cdd19SJun-ichiro itojun Hagino  */
32686cdd19SJun-ichiro itojun Hagino 
33686cdd19SJun-ichiro itojun Hagino /*
34686cdd19SJun-ichiro itojun Hagino  * Copyright (c) 1982, 1986, 1991, 1993
35686cdd19SJun-ichiro itojun Hagino  *	The Regents of the University of California.  All rights reserved.
36686cdd19SJun-ichiro itojun Hagino  *
37686cdd19SJun-ichiro itojun Hagino  * Redistribution and use in source and binary forms, with or without
38686cdd19SJun-ichiro itojun Hagino  * modification, are permitted provided that the following conditions
39686cdd19SJun-ichiro itojun Hagino  * are met:
40686cdd19SJun-ichiro itojun Hagino  * 1. Redistributions of source code must retain the above copyright
41686cdd19SJun-ichiro itojun Hagino  *    notice, this list of conditions and the following disclaimer.
42686cdd19SJun-ichiro itojun Hagino  * 2. Redistributions in binary form must reproduce the above copyright
43686cdd19SJun-ichiro itojun Hagino  *    notice, this list of conditions and the following disclaimer in the
44686cdd19SJun-ichiro itojun Hagino  *    documentation and/or other materials provided with the distribution.
45686cdd19SJun-ichiro itojun Hagino  * 3. All advertising materials mentioning features or use of this software
46686cdd19SJun-ichiro itojun Hagino  *    must display the following acknowledgement:
47686cdd19SJun-ichiro itojun Hagino  *	This product includes software developed by the University of
48686cdd19SJun-ichiro itojun Hagino  *	California, Berkeley and its contributors.
49686cdd19SJun-ichiro itojun Hagino  * 4. Neither the name of the University nor the names of its contributors
50686cdd19SJun-ichiro itojun Hagino  *    may be used to endorse or promote products derived from this software
51686cdd19SJun-ichiro itojun Hagino  *    without specific prior written permission.
52686cdd19SJun-ichiro itojun Hagino  *
53686cdd19SJun-ichiro itojun Hagino  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54686cdd19SJun-ichiro itojun Hagino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55686cdd19SJun-ichiro itojun Hagino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56686cdd19SJun-ichiro itojun Hagino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57686cdd19SJun-ichiro itojun Hagino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58686cdd19SJun-ichiro itojun Hagino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59686cdd19SJun-ichiro itojun Hagino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60686cdd19SJun-ichiro itojun Hagino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61686cdd19SJun-ichiro itojun Hagino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62686cdd19SJun-ichiro itojun Hagino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63686cdd19SJun-ichiro itojun Hagino  * SUCH DAMAGE.
64686cdd19SJun-ichiro itojun Hagino  *
65686cdd19SJun-ichiro itojun Hagino  *	@(#)in_pcb.c	8.2 (Berkeley) 1/4/94
66686cdd19SJun-ichiro itojun Hagino  */
67686cdd19SJun-ichiro itojun Hagino 
68686cdd19SJun-ichiro itojun Hagino #include "opt_inet.h"
69686cdd19SJun-ichiro itojun Hagino #include "opt_inet6.h"
70686cdd19SJun-ichiro itojun Hagino 
71686cdd19SJun-ichiro itojun Hagino #include <sys/param.h>
72686cdd19SJun-ichiro itojun Hagino #include <sys/systm.h>
7333841545SHajimu UMEMOTO #include <sys/malloc.h>
74686cdd19SJun-ichiro itojun Hagino #include <sys/mbuf.h>
75686cdd19SJun-ichiro itojun Hagino #include <sys/protosw.h>
76686cdd19SJun-ichiro itojun Hagino #include <sys/socket.h>
77686cdd19SJun-ichiro itojun Hagino #include <sys/socketvar.h>
78686cdd19SJun-ichiro itojun Hagino #include <sys/errno.h>
79686cdd19SJun-ichiro itojun Hagino #include <sys/time.h>
80686cdd19SJun-ichiro itojun Hagino 
81686cdd19SJun-ichiro itojun Hagino #include <net/if.h>
82686cdd19SJun-ichiro itojun Hagino #include <net/route.h>
83686cdd19SJun-ichiro itojun Hagino 
84686cdd19SJun-ichiro itojun Hagino #include <netinet/in.h>
85686cdd19SJun-ichiro itojun Hagino #include <netinet/in_var.h>
86686cdd19SJun-ichiro itojun Hagino #include <netinet/in_systm.h>
87686cdd19SJun-ichiro itojun Hagino #include <netinet/ip.h>
88686cdd19SJun-ichiro itojun Hagino #include <netinet/in_pcb.h>
89686cdd19SJun-ichiro itojun Hagino #include <netinet6/in6_var.h>
90686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h>
91686cdd19SJun-ichiro itojun Hagino #include <netinet6/in6_pcb.h>
92686cdd19SJun-ichiro itojun Hagino #include <netinet6/ip6_var.h>
93686cdd19SJun-ichiro itojun Hagino #include <netinet6/nd6.h>
94686cdd19SJun-ichiro itojun Hagino #ifdef ENABLE_DEFAULT_SCOPE
95686cdd19SJun-ichiro itojun Hagino #include <netinet6/scope6_var.h>
96686cdd19SJun-ichiro itojun Hagino #endif
97686cdd19SJun-ichiro itojun Hagino 
98686cdd19SJun-ichiro itojun Hagino #include <net/net_osdep.h>
99686cdd19SJun-ichiro itojun Hagino 
100686cdd19SJun-ichiro itojun Hagino /*
10133841545SHajimu UMEMOTO  * Return an IPv6 address, which is the most appropriate for a given
102686cdd19SJun-ichiro itojun Hagino  * destination and user specified options.
10333841545SHajimu UMEMOTO  * If necessary, this function lookups the routing table and returns
104686cdd19SJun-ichiro itojun Hagino  * an entry to the caller for later use.
105686cdd19SJun-ichiro itojun Hagino  */
106686cdd19SJun-ichiro itojun Hagino struct in6_addr *
107686cdd19SJun-ichiro itojun Hagino in6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)
108686cdd19SJun-ichiro itojun Hagino 	struct sockaddr_in6 *dstsock;
109686cdd19SJun-ichiro itojun Hagino 	struct ip6_pktopts *opts;
110686cdd19SJun-ichiro itojun Hagino 	struct ip6_moptions *mopts;
111686cdd19SJun-ichiro itojun Hagino 	struct route_in6 *ro;
112686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *laddr;
113686cdd19SJun-ichiro itojun Hagino 	int *errorp;
114686cdd19SJun-ichiro itojun Hagino {
115686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *dst;
116686cdd19SJun-ichiro itojun Hagino 	struct in6_ifaddr *ia6 = 0;
117686cdd19SJun-ichiro itojun Hagino 	struct in6_pktinfo *pi = NULL;
118686cdd19SJun-ichiro itojun Hagino 
119686cdd19SJun-ichiro itojun Hagino 	dst = &dstsock->sin6_addr;
120686cdd19SJun-ichiro itojun Hagino 	*errorp = 0;
121686cdd19SJun-ichiro itojun Hagino 
122686cdd19SJun-ichiro itojun Hagino 	/*
123686cdd19SJun-ichiro itojun Hagino 	 * If the source address is explicitly specified by the caller,
124686cdd19SJun-ichiro itojun Hagino 	 * use it.
125686cdd19SJun-ichiro itojun Hagino 	 */
126686cdd19SJun-ichiro itojun Hagino 	if (opts && (pi = opts->ip6po_pktinfo) &&
127686cdd19SJun-ichiro itojun Hagino 	    !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr))
128686cdd19SJun-ichiro itojun Hagino 		return(&pi->ipi6_addr);
129686cdd19SJun-ichiro itojun Hagino 
130686cdd19SJun-ichiro itojun Hagino 	/*
131686cdd19SJun-ichiro itojun Hagino 	 * If the source address is not specified but the socket(if any)
132686cdd19SJun-ichiro itojun Hagino 	 * is already bound, use the bound address.
133686cdd19SJun-ichiro itojun Hagino 	 */
134686cdd19SJun-ichiro itojun Hagino 	if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
135686cdd19SJun-ichiro itojun Hagino 		return(laddr);
136686cdd19SJun-ichiro itojun Hagino 
137686cdd19SJun-ichiro itojun Hagino 	/*
138686cdd19SJun-ichiro itojun Hagino 	 * If the caller doesn't specify the source address but
139686cdd19SJun-ichiro itojun Hagino 	 * the outgoing interface, use an address associated with
140686cdd19SJun-ichiro itojun Hagino 	 * the interface.
141686cdd19SJun-ichiro itojun Hagino 	 */
142686cdd19SJun-ichiro itojun Hagino 	if (pi && pi->ipi6_ifindex) {
143686cdd19SJun-ichiro itojun Hagino 		/* XXX boundary check is assumed to be already done. */
144686cdd19SJun-ichiro itojun Hagino 		ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
145686cdd19SJun-ichiro itojun Hagino 				       dst);
146686cdd19SJun-ichiro itojun Hagino 		if (ia6 == 0) {
147686cdd19SJun-ichiro itojun Hagino 			*errorp = EADDRNOTAVAIL;
148686cdd19SJun-ichiro itojun Hagino 			return(0);
149686cdd19SJun-ichiro itojun Hagino 		}
150686cdd19SJun-ichiro itojun Hagino 		return(&satosin6(&ia6->ia_addr)->sin6_addr);
151686cdd19SJun-ichiro itojun Hagino 	}
152686cdd19SJun-ichiro itojun Hagino 
153686cdd19SJun-ichiro itojun Hagino 	/*
154686cdd19SJun-ichiro itojun Hagino 	 * If the destination address is a link-local unicast address or
155686cdd19SJun-ichiro itojun Hagino 	 * a multicast address, and if the outgoing interface is specified
156686cdd19SJun-ichiro itojun Hagino 	 * by the sin6_scope_id filed, use an address associated with the
157686cdd19SJun-ichiro itojun Hagino 	 * interface.
158686cdd19SJun-ichiro itojun Hagino 	 * XXX: We're now trying to define more specific semantics of
159686cdd19SJun-ichiro itojun Hagino 	 *      sin6_scope_id field, so this part will be rewritten in
160686cdd19SJun-ichiro itojun Hagino 	 *      the near future.
161686cdd19SJun-ichiro itojun Hagino 	 */
162686cdd19SJun-ichiro itojun Hagino 	if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
163686cdd19SJun-ichiro itojun Hagino 	    dstsock->sin6_scope_id) {
164686cdd19SJun-ichiro itojun Hagino 		/*
165686cdd19SJun-ichiro itojun Hagino 		 * I'm not sure if boundary check for scope_id is done
166686cdd19SJun-ichiro itojun Hagino 		 * somewhere...
167686cdd19SJun-ichiro itojun Hagino 		 */
168686cdd19SJun-ichiro itojun Hagino 		if (dstsock->sin6_scope_id < 0 ||
169686cdd19SJun-ichiro itojun Hagino 		    if_index < dstsock->sin6_scope_id) {
170686cdd19SJun-ichiro itojun Hagino 			*errorp = ENXIO; /* XXX: better error? */
171686cdd19SJun-ichiro itojun Hagino 			return(0);
172686cdd19SJun-ichiro itojun Hagino 		}
173686cdd19SJun-ichiro itojun Hagino 		ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
174686cdd19SJun-ichiro itojun Hagino 				       dst);
175686cdd19SJun-ichiro itojun Hagino 		if (ia6 == 0) {
176686cdd19SJun-ichiro itojun Hagino 			*errorp = EADDRNOTAVAIL;
177686cdd19SJun-ichiro itojun Hagino 			return(0);
178686cdd19SJun-ichiro itojun Hagino 		}
179686cdd19SJun-ichiro itojun Hagino 		return(&satosin6(&ia6->ia_addr)->sin6_addr);
180686cdd19SJun-ichiro itojun Hagino 	}
181686cdd19SJun-ichiro itojun Hagino 
182686cdd19SJun-ichiro itojun Hagino 	/*
183686cdd19SJun-ichiro itojun Hagino 	 * If the destination address is a multicast address and
184686cdd19SJun-ichiro itojun Hagino 	 * the outgoing interface for the address is specified
185686cdd19SJun-ichiro itojun Hagino 	 * by the caller, use an address associated with the interface.
186686cdd19SJun-ichiro itojun Hagino 	 * There is a sanity check here; if the destination has node-local
187686cdd19SJun-ichiro itojun Hagino 	 * scope, the outgoing interfacde should be a loopback address.
188686cdd19SJun-ichiro itojun Hagino 	 * Even if the outgoing interface is not specified, we also
189686cdd19SJun-ichiro itojun Hagino 	 * choose a loopback interface as the outgoing interface.
190686cdd19SJun-ichiro itojun Hagino 	 */
191686cdd19SJun-ichiro itojun Hagino 	if (IN6_IS_ADDR_MULTICAST(dst)) {
192686cdd19SJun-ichiro itojun Hagino 		struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
193686cdd19SJun-ichiro itojun Hagino 
194686cdd19SJun-ichiro itojun Hagino 		if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
195686cdd19SJun-ichiro itojun Hagino 			ifp = &loif[0];
196686cdd19SJun-ichiro itojun Hagino 		}
197686cdd19SJun-ichiro itojun Hagino 
198686cdd19SJun-ichiro itojun Hagino 		if (ifp) {
199686cdd19SJun-ichiro itojun Hagino 			ia6 = in6_ifawithscope(ifp, dst);
200686cdd19SJun-ichiro itojun Hagino 			if (ia6 == 0) {
201686cdd19SJun-ichiro itojun Hagino 				*errorp = EADDRNOTAVAIL;
202686cdd19SJun-ichiro itojun Hagino 				return(0);
203686cdd19SJun-ichiro itojun Hagino 			}
204686cdd19SJun-ichiro itojun Hagino 			return(&satosin6(&ia6->ia_addr)->sin6_addr);
205686cdd19SJun-ichiro itojun Hagino 		}
206686cdd19SJun-ichiro itojun Hagino 	}
207686cdd19SJun-ichiro itojun Hagino 
208686cdd19SJun-ichiro itojun Hagino 	/*
209686cdd19SJun-ichiro itojun Hagino 	 * If the next hop address for the packet is specified
210686cdd19SJun-ichiro itojun Hagino 	 * by caller, use an address associated with the route
211686cdd19SJun-ichiro itojun Hagino 	 * to the next hop.
212686cdd19SJun-ichiro itojun Hagino 	 */
213686cdd19SJun-ichiro itojun Hagino 	{
214686cdd19SJun-ichiro itojun Hagino 		struct sockaddr_in6 *sin6_next;
215686cdd19SJun-ichiro itojun Hagino 		struct rtentry *rt;
216686cdd19SJun-ichiro itojun Hagino 
217686cdd19SJun-ichiro itojun Hagino 		if (opts && opts->ip6po_nexthop) {
218686cdd19SJun-ichiro itojun Hagino 			sin6_next = satosin6(opts->ip6po_nexthop);
219686cdd19SJun-ichiro itojun Hagino 			rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
220686cdd19SJun-ichiro itojun Hagino 			if (rt) {
221686cdd19SJun-ichiro itojun Hagino 				ia6 = in6_ifawithscope(rt->rt_ifp, dst);
222686cdd19SJun-ichiro itojun Hagino 				if (ia6 == 0)
223686cdd19SJun-ichiro itojun Hagino 					ia6 = ifatoia6(rt->rt_ifa);
224686cdd19SJun-ichiro itojun Hagino 			}
225686cdd19SJun-ichiro itojun Hagino 			if (ia6 == 0) {
226686cdd19SJun-ichiro itojun Hagino 				*errorp = EADDRNOTAVAIL;
227686cdd19SJun-ichiro itojun Hagino 				return(0);
228686cdd19SJun-ichiro itojun Hagino 			}
229686cdd19SJun-ichiro itojun Hagino 			return(&satosin6(&ia6->ia_addr)->sin6_addr);
230686cdd19SJun-ichiro itojun Hagino 		}
231686cdd19SJun-ichiro itojun Hagino 	}
232686cdd19SJun-ichiro itojun Hagino 
233686cdd19SJun-ichiro itojun Hagino 	/*
234686cdd19SJun-ichiro itojun Hagino 	 * If route is known or can be allocated now,
235686cdd19SJun-ichiro itojun Hagino 	 * our src addr is taken from the i/f, else punt.
236686cdd19SJun-ichiro itojun Hagino 	 */
237686cdd19SJun-ichiro itojun Hagino 	if (ro) {
238686cdd19SJun-ichiro itojun Hagino 		if (ro->ro_rt &&
239686cdd19SJun-ichiro itojun Hagino 		    !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
240686cdd19SJun-ichiro itojun Hagino 			RTFREE(ro->ro_rt);
241686cdd19SJun-ichiro itojun Hagino 			ro->ro_rt = (struct rtentry *)0;
242686cdd19SJun-ichiro itojun Hagino 		}
243686cdd19SJun-ichiro itojun Hagino 		if (ro->ro_rt == (struct rtentry *)0 ||
244686cdd19SJun-ichiro itojun Hagino 		    ro->ro_rt->rt_ifp == (struct ifnet *)0) {
24533841545SHajimu UMEMOTO 			struct sockaddr_in6 *sa6;
24633841545SHajimu UMEMOTO 
247686cdd19SJun-ichiro itojun Hagino 			/* No route yet, so try to acquire one */
248686cdd19SJun-ichiro itojun Hagino 			bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
24933841545SHajimu UMEMOTO 			sa6 = (struct sockaddr_in6 *)&ro->ro_dst;
25033841545SHajimu UMEMOTO 			sa6->sin6_family = AF_INET6;
25133841545SHajimu UMEMOTO 			sa6->sin6_len = sizeof(struct sockaddr_in6);
25233841545SHajimu UMEMOTO 			sa6->sin6_addr = *dst;
25333841545SHajimu UMEMOTO 			sa6->sin6_scope_id = dstsock->sin6_scope_id;
254686cdd19SJun-ichiro itojun Hagino 			if (IN6_IS_ADDR_MULTICAST(dst)) {
255686cdd19SJun-ichiro itojun Hagino 				ro->ro_rt = rtalloc1(&((struct route *)ro)
256686cdd19SJun-ichiro itojun Hagino 						     ->ro_dst, 0, 0UL);
257686cdd19SJun-ichiro itojun Hagino 			} else {
258686cdd19SJun-ichiro itojun Hagino 				rtalloc((struct route *)ro);
259686cdd19SJun-ichiro itojun Hagino 			}
260686cdd19SJun-ichiro itojun Hagino 		}
261686cdd19SJun-ichiro itojun Hagino 
262686cdd19SJun-ichiro itojun Hagino 		/*
263686cdd19SJun-ichiro itojun Hagino 		 * in_pcbconnect() checks out IFF_LOOPBACK to skip using
264686cdd19SJun-ichiro itojun Hagino 		 * the address. But we don't know why it does so.
265686cdd19SJun-ichiro itojun Hagino 		 * It is necessary to ensure the scope even for lo0
266686cdd19SJun-ichiro itojun Hagino 		 * so doesn't check out IFF_LOOPBACK.
267686cdd19SJun-ichiro itojun Hagino 		 */
268686cdd19SJun-ichiro itojun Hagino 
269686cdd19SJun-ichiro itojun Hagino 		if (ro->ro_rt) {
270686cdd19SJun-ichiro itojun Hagino 			ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
271686cdd19SJun-ichiro itojun Hagino 			if (ia6 == 0) /* xxx scope error ?*/
272686cdd19SJun-ichiro itojun Hagino 				ia6 = ifatoia6(ro->ro_rt->rt_ifa);
273686cdd19SJun-ichiro itojun Hagino 		}
274686cdd19SJun-ichiro itojun Hagino #if 0
275686cdd19SJun-ichiro itojun Hagino 		/*
276686cdd19SJun-ichiro itojun Hagino 		 * xxx The followings are necessary? (kazu)
277686cdd19SJun-ichiro itojun Hagino 		 * I don't think so.
278686cdd19SJun-ichiro itojun Hagino 		 * It's for SO_DONTROUTE option in IPv4.(jinmei)
279686cdd19SJun-ichiro itojun Hagino 		 */
280686cdd19SJun-ichiro itojun Hagino 		if (ia6 == 0) {
281686cdd19SJun-ichiro itojun Hagino 			struct sockaddr_in6 sin6 = {sizeof(sin6), AF_INET6, 0};
282686cdd19SJun-ichiro itojun Hagino 
283686cdd19SJun-ichiro itojun Hagino 			sin6->sin6_addr = *dst;
284686cdd19SJun-ichiro itojun Hagino 
285686cdd19SJun-ichiro itojun Hagino 			ia6 = ifatoia6(ifa_ifwithdstaddr(sin6tosa(&sin6)));
286686cdd19SJun-ichiro itojun Hagino 			if (ia6 == 0)
287686cdd19SJun-ichiro itojun Hagino 				ia6 = ifatoia6(ifa_ifwithnet(sin6tosa(&sin6)));
288686cdd19SJun-ichiro itojun Hagino 			if (ia6 == 0)
289686cdd19SJun-ichiro itojun Hagino 				return(0);
290686cdd19SJun-ichiro itojun Hagino 			return(&satosin6(&ia6->ia_addr)->sin6_addr);
291686cdd19SJun-ichiro itojun Hagino 		}
292686cdd19SJun-ichiro itojun Hagino #endif /* 0 */
293686cdd19SJun-ichiro itojun Hagino 		if (ia6 == 0) {
294686cdd19SJun-ichiro itojun Hagino 			*errorp = EHOSTUNREACH;	/* no route */
295686cdd19SJun-ichiro itojun Hagino 			return(0);
296686cdd19SJun-ichiro itojun Hagino 		}
297686cdd19SJun-ichiro itojun Hagino 		return(&satosin6(&ia6->ia_addr)->sin6_addr);
298686cdd19SJun-ichiro itojun Hagino 	}
299686cdd19SJun-ichiro itojun Hagino 
300686cdd19SJun-ichiro itojun Hagino 	*errorp = EADDRNOTAVAIL;
301686cdd19SJun-ichiro itojun Hagino 	return(0);
302686cdd19SJun-ichiro itojun Hagino }
303686cdd19SJun-ichiro itojun Hagino 
304686cdd19SJun-ichiro itojun Hagino /*
305686cdd19SJun-ichiro itojun Hagino  * Default hop limit selection. The precedence is as follows:
306686cdd19SJun-ichiro itojun Hagino  * 1. Hoplimit value specified via ioctl.
307686cdd19SJun-ichiro itojun Hagino  * 2. (If the outgoing interface is detected) the current
308686cdd19SJun-ichiro itojun Hagino  *     hop limit of the interface specified by router advertisement.
309686cdd19SJun-ichiro itojun Hagino  * 3. The system default hoplimit.
310686cdd19SJun-ichiro itojun Hagino */
311686cdd19SJun-ichiro itojun Hagino int
312686cdd19SJun-ichiro itojun Hagino in6_selecthlim(in6p, ifp)
313686cdd19SJun-ichiro itojun Hagino 	struct in6pcb *in6p;
314686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp;
315686cdd19SJun-ichiro itojun Hagino {
316686cdd19SJun-ichiro itojun Hagino 	if (in6p && in6p->in6p_hops >= 0)
317686cdd19SJun-ichiro itojun Hagino 		return(in6p->in6p_hops);
318686cdd19SJun-ichiro itojun Hagino 	else if (ifp)
319686cdd19SJun-ichiro itojun Hagino 		return(nd_ifinfo[ifp->if_index].chlim);
320686cdd19SJun-ichiro itojun Hagino 	else
321686cdd19SJun-ichiro itojun Hagino 		return(ip6_defhlim);
322686cdd19SJun-ichiro itojun Hagino }
323686cdd19SJun-ichiro itojun Hagino 
324686cdd19SJun-ichiro itojun Hagino /*
325686cdd19SJun-ichiro itojun Hagino  * XXX: this is borrowed from in6_pcbbind(). If possible, we should
326686cdd19SJun-ichiro itojun Hagino  * share this function by all *bsd*...
327686cdd19SJun-ichiro itojun Hagino  */
328686cdd19SJun-ichiro itojun Hagino int
329686cdd19SJun-ichiro itojun Hagino in6_pcbsetport(laddr, inp, p)
330686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *laddr;
331686cdd19SJun-ichiro itojun Hagino 	struct inpcb *inp;
332686cdd19SJun-ichiro itojun Hagino 	struct proc *p;
333686cdd19SJun-ichiro itojun Hagino {
334686cdd19SJun-ichiro itojun Hagino 	struct socket *so = inp->inp_socket;
335686cdd19SJun-ichiro itojun Hagino 	u_int16_t lport = 0, first, last, *lastport;
336686cdd19SJun-ichiro itojun Hagino 	int count, error = 0, wild = 0;
337686cdd19SJun-ichiro itojun Hagino 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
338686cdd19SJun-ichiro itojun Hagino 
339686cdd19SJun-ichiro itojun Hagino 	/* XXX: this is redundant when called from in6_pcbbind */
340686cdd19SJun-ichiro itojun Hagino 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
341686cdd19SJun-ichiro itojun Hagino 		wild = INPLOOKUP_WILDCARD;
342686cdd19SJun-ichiro itojun Hagino 
343686cdd19SJun-ichiro itojun Hagino 	inp->inp_flags |= INP_ANONPORT;
344686cdd19SJun-ichiro itojun Hagino 
345686cdd19SJun-ichiro itojun Hagino 	if (inp->inp_flags & INP_HIGHPORT) {
346686cdd19SJun-ichiro itojun Hagino 		first = ipport_hifirstauto;	/* sysctl */
347686cdd19SJun-ichiro itojun Hagino 		last  = ipport_hilastauto;
348686cdd19SJun-ichiro itojun Hagino 		lastport = &pcbinfo->lasthi;
349686cdd19SJun-ichiro itojun Hagino 	} else if (inp->inp_flags & INP_LOWPORT) {
350686cdd19SJun-ichiro itojun Hagino 		if (p && (error = suser(p)))
351686cdd19SJun-ichiro itojun Hagino 			return error;
352686cdd19SJun-ichiro itojun Hagino 		first = ipport_lowfirstauto;	/* 1023 */
353686cdd19SJun-ichiro itojun Hagino 		last  = ipport_lowlastauto;	/* 600 */
354686cdd19SJun-ichiro itojun Hagino 		lastport = &pcbinfo->lastlow;
355686cdd19SJun-ichiro itojun Hagino 	} else {
356686cdd19SJun-ichiro itojun Hagino 		first = ipport_firstauto;	/* sysctl */
357686cdd19SJun-ichiro itojun Hagino 		last  = ipport_lastauto;
358686cdd19SJun-ichiro itojun Hagino 		lastport = &pcbinfo->lastport;
359686cdd19SJun-ichiro itojun Hagino 	}
360686cdd19SJun-ichiro itojun Hagino 	/*
361686cdd19SJun-ichiro itojun Hagino 	 * Simple check to ensure all ports are not used up causing
362686cdd19SJun-ichiro itojun Hagino 	 * a deadlock here.
363686cdd19SJun-ichiro itojun Hagino 	 *
364686cdd19SJun-ichiro itojun Hagino 	 * We split the two cases (up and down) so that the direction
365686cdd19SJun-ichiro itojun Hagino 	 * is not being tested on each round of the loop.
366686cdd19SJun-ichiro itojun Hagino 	 */
367686cdd19SJun-ichiro itojun Hagino 	if (first > last) {
368686cdd19SJun-ichiro itojun Hagino 		/*
369686cdd19SJun-ichiro itojun Hagino 		 * counting down
370686cdd19SJun-ichiro itojun Hagino 		 */
371686cdd19SJun-ichiro itojun Hagino 		count = first - last;
372686cdd19SJun-ichiro itojun Hagino 
373686cdd19SJun-ichiro itojun Hagino 		do {
374686cdd19SJun-ichiro itojun Hagino 			if (count-- < 0) {	/* completely used? */
375686cdd19SJun-ichiro itojun Hagino 				/*
376686cdd19SJun-ichiro itojun Hagino 				 * Undo any address bind that may have
377686cdd19SJun-ichiro itojun Hagino 				 * occurred above.
378686cdd19SJun-ichiro itojun Hagino 				 */
379686cdd19SJun-ichiro itojun Hagino 				inp->in6p_laddr = in6addr_any;
380686cdd19SJun-ichiro itojun Hagino 				return (EAGAIN);
381686cdd19SJun-ichiro itojun Hagino 			}
382686cdd19SJun-ichiro itojun Hagino 			--*lastport;
383686cdd19SJun-ichiro itojun Hagino 			if (*lastport > first || *lastport < last)
384686cdd19SJun-ichiro itojun Hagino 				*lastport = first;
385686cdd19SJun-ichiro itojun Hagino 			lport = htons(*lastport);
386686cdd19SJun-ichiro itojun Hagino 		} while (in6_pcblookup_local(pcbinfo,
387686cdd19SJun-ichiro itojun Hagino 					     &inp->in6p_laddr, lport, wild));
388686cdd19SJun-ichiro itojun Hagino 	} else {
389686cdd19SJun-ichiro itojun Hagino 		/*
390686cdd19SJun-ichiro itojun Hagino 			 * counting up
391686cdd19SJun-ichiro itojun Hagino 			 */
392686cdd19SJun-ichiro itojun Hagino 		count = last - first;
393686cdd19SJun-ichiro itojun Hagino 
394686cdd19SJun-ichiro itojun Hagino 		do {
395686cdd19SJun-ichiro itojun Hagino 			if (count-- < 0) {	/* completely used? */
396686cdd19SJun-ichiro itojun Hagino 				/*
397686cdd19SJun-ichiro itojun Hagino 				 * Undo any address bind that may have
398686cdd19SJun-ichiro itojun Hagino 				 * occurred above.
399686cdd19SJun-ichiro itojun Hagino 				 */
400686cdd19SJun-ichiro itojun Hagino 				inp->in6p_laddr = in6addr_any;
401686cdd19SJun-ichiro itojun Hagino 				return (EAGAIN);
402686cdd19SJun-ichiro itojun Hagino 			}
403686cdd19SJun-ichiro itojun Hagino 			++*lastport;
404686cdd19SJun-ichiro itojun Hagino 			if (*lastport < first || *lastport > last)
405686cdd19SJun-ichiro itojun Hagino 				*lastport = first;
406686cdd19SJun-ichiro itojun Hagino 			lport = htons(*lastport);
407686cdd19SJun-ichiro itojun Hagino 		} while (in6_pcblookup_local(pcbinfo,
408686cdd19SJun-ichiro itojun Hagino 					     &inp->in6p_laddr, lport, wild));
409686cdd19SJun-ichiro itojun Hagino 	}
410686cdd19SJun-ichiro itojun Hagino 
411686cdd19SJun-ichiro itojun Hagino 	inp->inp_lport = lport;
412686cdd19SJun-ichiro itojun Hagino 	if (in_pcbinshash(inp) != 0) {
413686cdd19SJun-ichiro itojun Hagino 		inp->in6p_laddr = in6addr_any;
414686cdd19SJun-ichiro itojun Hagino 		inp->inp_lport = 0;
415686cdd19SJun-ichiro itojun Hagino 		return (EAGAIN);
416686cdd19SJun-ichiro itojun Hagino 	}
417686cdd19SJun-ichiro itojun Hagino 
418686cdd19SJun-ichiro itojun Hagino 	return(0);
419686cdd19SJun-ichiro itojun Hagino }
420686cdd19SJun-ichiro itojun Hagino 
421686cdd19SJun-ichiro itojun Hagino /*
422686cdd19SJun-ichiro itojun Hagino  * generate kernel-internal form (scopeid embedded into s6_addr16[1]).
423686cdd19SJun-ichiro itojun Hagino  * If the address scope of is link-local, embed the interface index in the
424686cdd19SJun-ichiro itojun Hagino  * address.  The routine determines our precedence
425686cdd19SJun-ichiro itojun Hagino  * between advanced API scope/interface specification and basic API
426686cdd19SJun-ichiro itojun Hagino  * specification.
427686cdd19SJun-ichiro itojun Hagino  *
428686cdd19SJun-ichiro itojun Hagino  * this function should be nuked in the future, when we get rid of
429686cdd19SJun-ichiro itojun Hagino  * embedded scopeid thing.
430686cdd19SJun-ichiro itojun Hagino  *
431686cdd19SJun-ichiro itojun Hagino  * XXX actually, it is over-specification to return ifp against sin6_scope_id.
432686cdd19SJun-ichiro itojun Hagino  * there can be multiple interfaces that belong to a particular scope zone
433686cdd19SJun-ichiro itojun Hagino  * (in specification, we have 1:N mapping between a scope zone and interfaces).
434686cdd19SJun-ichiro itojun Hagino  * we may want to change the function to return something other than ifp.
435686cdd19SJun-ichiro itojun Hagino  */
436686cdd19SJun-ichiro itojun Hagino int
437686cdd19SJun-ichiro itojun Hagino in6_embedscope(in6, sin6, in6p, ifpp)
438686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *in6;
439686cdd19SJun-ichiro itojun Hagino 	const struct sockaddr_in6 *sin6;
440686cdd19SJun-ichiro itojun Hagino #ifdef HAVE_NRL_INPCB
441686cdd19SJun-ichiro itojun Hagino 	struct inpcb *in6p;
442686cdd19SJun-ichiro itojun Hagino #define in6p_outputopts	inp_outputopts6
443686cdd19SJun-ichiro itojun Hagino #define in6p_moptions	inp_moptions6
444686cdd19SJun-ichiro itojun Hagino #else
445686cdd19SJun-ichiro itojun Hagino 	struct in6pcb *in6p;
446686cdd19SJun-ichiro itojun Hagino #endif
447686cdd19SJun-ichiro itojun Hagino 	struct ifnet **ifpp;
448686cdd19SJun-ichiro itojun Hagino {
449686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp = NULL;
450686cdd19SJun-ichiro itojun Hagino 	u_int32_t scopeid;
451686cdd19SJun-ichiro itojun Hagino 
452686cdd19SJun-ichiro itojun Hagino 	*in6 = sin6->sin6_addr;
453686cdd19SJun-ichiro itojun Hagino 	scopeid = sin6->sin6_scope_id;
454686cdd19SJun-ichiro itojun Hagino 	if (ifpp)
455686cdd19SJun-ichiro itojun Hagino 		*ifpp = NULL;
456686cdd19SJun-ichiro itojun Hagino 
457686cdd19SJun-ichiro itojun Hagino 	/*
458686cdd19SJun-ichiro itojun Hagino 	 * don't try to read sin6->sin6_addr beyond here, since the caller may
459686cdd19SJun-ichiro itojun Hagino 	 * ask us to overwrite existing sockaddr_in6
460686cdd19SJun-ichiro itojun Hagino 	 */
461686cdd19SJun-ichiro itojun Hagino 
462686cdd19SJun-ichiro itojun Hagino #ifdef ENABLE_DEFAULT_SCOPE
463686cdd19SJun-ichiro itojun Hagino 	if (scopeid == 0)
464686cdd19SJun-ichiro itojun Hagino 		scopeid = scope6_addr2default(in6);
465686cdd19SJun-ichiro itojun Hagino #endif
466686cdd19SJun-ichiro itojun Hagino 
467686cdd19SJun-ichiro itojun Hagino 	if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
468686cdd19SJun-ichiro itojun Hagino 		struct in6_pktinfo *pi;
469686cdd19SJun-ichiro itojun Hagino 
470686cdd19SJun-ichiro itojun Hagino 		/*
471686cdd19SJun-ichiro itojun Hagino 		 * KAME assumption: link id == interface id
472686cdd19SJun-ichiro itojun Hagino 		 */
473686cdd19SJun-ichiro itojun Hagino 
474686cdd19SJun-ichiro itojun Hagino 		if (in6p && in6p->in6p_outputopts &&
475686cdd19SJun-ichiro itojun Hagino 		    (pi = in6p->in6p_outputopts->ip6po_pktinfo) &&
476686cdd19SJun-ichiro itojun Hagino 		    pi->ipi6_ifindex) {
477686cdd19SJun-ichiro itojun Hagino 			ifp = ifindex2ifnet[pi->ipi6_ifindex];
478686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr16[1] = htons(pi->ipi6_ifindex);
479686cdd19SJun-ichiro itojun Hagino 		} else if (in6p && IN6_IS_ADDR_MULTICAST(in6) &&
480686cdd19SJun-ichiro itojun Hagino 			   in6p->in6p_moptions &&
481686cdd19SJun-ichiro itojun Hagino 			   in6p->in6p_moptions->im6o_multicast_ifp) {
482686cdd19SJun-ichiro itojun Hagino 			ifp = in6p->in6p_moptions->im6o_multicast_ifp;
483686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr16[1] = htons(ifp->if_index);
484686cdd19SJun-ichiro itojun Hagino 		} else if (scopeid) {
485686cdd19SJun-ichiro itojun Hagino 			/* boundary check */
486686cdd19SJun-ichiro itojun Hagino 			if (scopeid < 0 || if_index < scopeid)
487686cdd19SJun-ichiro itojun Hagino 				return ENXIO;  /* XXX EINVAL? */
488686cdd19SJun-ichiro itojun Hagino 			ifp = ifindex2ifnet[scopeid];
489686cdd19SJun-ichiro itojun Hagino 			/*XXX assignment to 16bit from 32bit variable */
490686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr16[1] = htons(scopeid & 0xffff);
491686cdd19SJun-ichiro itojun Hagino 		}
492686cdd19SJun-ichiro itojun Hagino 
493686cdd19SJun-ichiro itojun Hagino 		if (ifpp)
494686cdd19SJun-ichiro itojun Hagino 			*ifpp = ifp;
495686cdd19SJun-ichiro itojun Hagino 	}
496686cdd19SJun-ichiro itojun Hagino 
497686cdd19SJun-ichiro itojun Hagino 	return 0;
498686cdd19SJun-ichiro itojun Hagino }
499686cdd19SJun-ichiro itojun Hagino #ifdef HAVE_NRL_INPCB
500686cdd19SJun-ichiro itojun Hagino #undef in6p_outputopts
501686cdd19SJun-ichiro itojun Hagino #undef in6p_moptions
502686cdd19SJun-ichiro itojun Hagino #endif
503686cdd19SJun-ichiro itojun Hagino 
504686cdd19SJun-ichiro itojun Hagino /*
505686cdd19SJun-ichiro itojun Hagino  * generate standard sockaddr_in6 from embedded form.
506686cdd19SJun-ichiro itojun Hagino  * touches sin6_addr and sin6_scope_id only.
507686cdd19SJun-ichiro itojun Hagino  *
508686cdd19SJun-ichiro itojun Hagino  * this function should be nuked in the future, when we get rid of
509686cdd19SJun-ichiro itojun Hagino  * embedded scopeid thing.
510686cdd19SJun-ichiro itojun Hagino  */
511686cdd19SJun-ichiro itojun Hagino int
512686cdd19SJun-ichiro itojun Hagino in6_recoverscope(sin6, in6, ifp)
513686cdd19SJun-ichiro itojun Hagino 	struct sockaddr_in6 *sin6;
514686cdd19SJun-ichiro itojun Hagino 	const struct in6_addr *in6;
515686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp;
516686cdd19SJun-ichiro itojun Hagino {
517686cdd19SJun-ichiro itojun Hagino 	u_int32_t scopeid;
518686cdd19SJun-ichiro itojun Hagino 
519686cdd19SJun-ichiro itojun Hagino 	sin6->sin6_addr = *in6;
520686cdd19SJun-ichiro itojun Hagino 
521686cdd19SJun-ichiro itojun Hagino 	/*
522686cdd19SJun-ichiro itojun Hagino 	 * don't try to read *in6 beyond here, since the caller may
523686cdd19SJun-ichiro itojun Hagino 	 * ask us to overwrite existing sockaddr_in6
524686cdd19SJun-ichiro itojun Hagino 	 */
525686cdd19SJun-ichiro itojun Hagino 
526686cdd19SJun-ichiro itojun Hagino 	sin6->sin6_scope_id = 0;
527686cdd19SJun-ichiro itojun Hagino 	if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
528686cdd19SJun-ichiro itojun Hagino 		/*
529686cdd19SJun-ichiro itojun Hagino 		 * KAME assumption: link id == interface id
530686cdd19SJun-ichiro itojun Hagino 		 */
531686cdd19SJun-ichiro itojun Hagino 		scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]);
532686cdd19SJun-ichiro itojun Hagino 		if (scopeid) {
533686cdd19SJun-ichiro itojun Hagino 			/* sanity check */
534686cdd19SJun-ichiro itojun Hagino 			if (scopeid < 0 || if_index < scopeid)
535686cdd19SJun-ichiro itojun Hagino 				return ENXIO;
536686cdd19SJun-ichiro itojun Hagino 			if (ifp && ifp->if_index != scopeid)
537686cdd19SJun-ichiro itojun Hagino 				return ENXIO;
538686cdd19SJun-ichiro itojun Hagino 			sin6->sin6_addr.s6_addr16[1] = 0;
539686cdd19SJun-ichiro itojun Hagino 			sin6->sin6_scope_id = scopeid;
540686cdd19SJun-ichiro itojun Hagino 		}
541686cdd19SJun-ichiro itojun Hagino 	}
542686cdd19SJun-ichiro itojun Hagino 
543686cdd19SJun-ichiro itojun Hagino 	return 0;
544686cdd19SJun-ichiro itojun Hagino }
54533841545SHajimu UMEMOTO 
54633841545SHajimu UMEMOTO /*
54733841545SHajimu UMEMOTO  * just clear the embedded scope identifer.
54833841545SHajimu UMEMOTO  * XXX: currently used for bsdi4 only as a supplement function.
54933841545SHajimu UMEMOTO  */
55033841545SHajimu UMEMOTO void
55133841545SHajimu UMEMOTO in6_clearscope(addr)
55233841545SHajimu UMEMOTO 	struct in6_addr *addr;
55333841545SHajimu UMEMOTO {
55433841545SHajimu UMEMOTO 	if (IN6_IS_SCOPE_LINKLOCAL(addr))
55533841545SHajimu UMEMOTO 		addr->s6_addr16[1] = 0;
55633841545SHajimu UMEMOTO }
557