xref: /dflybsd-src/sys/netinet6/in6_src.c (revision 21fcee4d6e84a10a35d21e920106590570511048)
1 /*	$FreeBSD: src/sys/netinet6/in6_src.c,v 1.1.2.3 2002/02/26 18:02:06 ume Exp $	*/
2 /*	$DragonFly: src/sys/netinet6/in6_src.c,v 1.13 2006/12/29 18:02:56 victor Exp $	*/
3 /*	$KAME: in6_src.c,v 1.37 2001/03/29 05:34:31 itojun Exp $	*/
4 
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1982, 1986, 1991, 1993
36  *	The Regents of the University of California.  All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. All advertising materials mentioning features or use of this software
47  *    must display the following acknowledgement:
48  *	This product includes software developed by the University of
49  *	California, Berkeley and its contributors.
50  * 4. Neither the name of the University nor the names of its contributors
51  *    may be used to endorse or promote products derived from this software
52  *    without specific prior written permission.
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64  * SUCH DAMAGE.
65  *
66  *	@(#)in_pcb.c	8.2 (Berkeley) 1/4/94
67  */
68 
69 #include "opt_inet.h"
70 #include "opt_inet6.h"
71 
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/jail.h>
75 #include <sys/malloc.h>
76 #include <sys/mbuf.h>
77 #include <sys/protosw.h>
78 #include <sys/socket.h>
79 #include <sys/socketvar.h>
80 #include <sys/sockio.h>
81 #include <sys/sysctl.h>
82 #include <sys/errno.h>
83 #include <sys/time.h>
84 #include <sys/proc.h>
85 
86 #include <net/if.h>
87 #include <net/route.h>
88 
89 #include <netinet/in.h>
90 #include <netinet/in_var.h>
91 #include <netinet/in_systm.h>
92 #include <netinet/ip.h>
93 #include <netinet/in_pcb.h>
94 #include <netinet6/in6_var.h>
95 #include <netinet/ip6.h>
96 #include <netinet6/in6_pcb.h>
97 #include <netinet6/ip6_var.h>
98 #include <netinet6/nd6.h>
99 #ifdef ENABLE_DEFAULT_SCOPE
100 #include <netinet6/scope6_var.h>
101 #endif
102 
103 #include <net/net_osdep.h>
104 
105 #include "use_loop.h"
106 
107 #define ADDR_LABEL_NOTAPP (-1)
108 struct in6_addrpolicy defaultaddrpolicy;
109 
110 static void	init_policy_queue(void);
111 static int	add_addrsel_policyent(struct in6_addrpolicy *);
112 static int	delete_addrsel_policyent(struct in6_addrpolicy *);
113 static int	walk_addrsel_policy(int (*)(struct in6_addrpolicy *, void *),
114 				    void *);
115 static int	dump_addrsel_policyent(struct in6_addrpolicy *, void *);
116 
117 
118 /*
119  * Return an IPv6 address, which is the most appropriate for a given
120  * destination and user specified options.
121  * If necessary, this function lookups the routing table and returns
122  * an entry to the caller for later use.
123  */
124 struct in6_addr *
125 in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
126 	      struct ip6_moptions *mopts, struct route_in6 *ro,
127 	      struct in6_addr *laddr, int *errorp, struct thread *td)
128 {
129 	struct sockaddr_in6 jsin6;
130 	struct ucred *cred = NULL;
131 	struct in6_addr *dst;
132 	struct in6_ifaddr *ia6 = 0;
133 	struct in6_pktinfo *pi = NULL;
134 	int jailed = 0;
135 
136 	if (td && td->td_proc && td->td_proc->p_ucred)
137 		cred = td->td_proc->p_ucred;
138 	if (cred && cred->cr_prison)
139 		jailed = 1;
140 	jsin6.sin6_family = AF_INET6;
141 	dst = &dstsock->sin6_addr;
142 	*errorp = 0;
143 
144 	/*
145 	 * If the source address is explicitly specified by the caller,
146 	 * use it.
147 	 */
148 	if (opts && (pi = opts->ip6po_pktinfo) &&
149 	    !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
150 		jsin6.sin6_addr = pi->ipi6_addr;
151 		if (jailed && !jailed_ip(cred->cr_prison,
152 		    (struct sockaddr *)&jsin6)) {
153 			return(0);
154 		} else {
155 			return (&pi->ipi6_addr);
156 		}
157 	}
158 
159 	/*
160 	 * If the source address is not specified but the socket(if any)
161 	 * is already bound, use the bound address.
162 	 */
163 	if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) {
164 		jsin6.sin6_addr = *laddr;
165 		if (jailed && !jailed_ip(cred->cr_prison,
166 		    (struct sockaddr *)&jsin6)) {
167 			return(0);
168 		} else {
169 			return (laddr);
170 		}
171 	}
172 
173 	/*
174 	 * If the caller doesn't specify the source address but
175 	 * the outgoing interface, use an address associated with
176 	 * the interface.
177 	 */
178 	if (pi && pi->ipi6_ifindex) {
179 		/* XXX boundary check is assumed to be already done. */
180 		ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
181 				       dst);
182 
183 		if (ia6 && jailed) {
184 			jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
185 			if (!jailed_ip(cred->cr_prison,
186 				(struct sockaddr *)&jsin6))
187 				ia6 = 0;
188 		}
189 
190 		if (ia6 == 0) {
191 			*errorp = EADDRNOTAVAIL;
192 			return (0);
193 		}
194 		return (&satosin6(&ia6->ia_addr)->sin6_addr);
195 	}
196 
197 	/*
198 	 * If the destination address is a link-local unicast address or
199 	 * a multicast address, and if the outgoing interface is specified
200 	 * by the sin6_scope_id filed, use an address associated with the
201 	 * interface.
202 	 * XXX: We're now trying to define more specific semantics of
203 	 *      sin6_scope_id field, so this part will be rewritten in
204 	 *      the near future.
205 	 */
206 	if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
207 	    dstsock->sin6_scope_id) {
208 		/*
209 		 * I'm not sure if boundary check for scope_id is done
210 		 * somewhere...
211 		 */
212 		if (dstsock->sin6_scope_id < 0 ||
213 		    if_index < dstsock->sin6_scope_id) {
214 			*errorp = ENXIO; /* XXX: better error? */
215 			return (0);
216 		}
217 		ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
218 				       dst);
219 
220 		if (ia6 && jailed) {
221 			jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
222 			if (!jailed_ip(cred->cr_prison,
223 				(struct sockaddr *)&jsin6))
224 				ia6 = 0;
225 		}
226 
227 		if (ia6 == 0) {
228 			*errorp = EADDRNOTAVAIL;
229 			return (0);
230 		}
231 		return (&satosin6(&ia6->ia_addr)->sin6_addr);
232 	}
233 
234 	/*
235 	 * If the destination address is a multicast address and
236 	 * the outgoing interface for the address is specified
237 	 * by the caller, use an address associated with the interface.
238 	 * There is a sanity check here; if the destination has node-local
239 	 * scope, the outgoing interfacde should be a loopback address.
240 	 * Even if the outgoing interface is not specified, we also
241 	 * choose a loopback interface as the outgoing interface.
242 	 */
243 	if (!jailed && IN6_IS_ADDR_MULTICAST(dst)) {
244 		struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
245 
246 		if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
247 			ifp = &loif[0];
248 		}
249 
250 		if (ifp) {
251 			ia6 = in6_ifawithscope(ifp, dst);
252 			if (ia6 == 0) {
253 				*errorp = EADDRNOTAVAIL;
254 				return (0);
255 			}
256 			return (&satosin6(&ia6->ia_addr)->sin6_addr);
257 		}
258 	}
259 
260 	/*
261 	 * If the next hop address for the packet is specified
262 	 * by caller, use an address associated with the route
263 	 * to the next hop.
264 	 */
265 	{
266 		struct sockaddr_in6 *sin6_next;
267 		struct rtentry *rt;
268 
269 		if (opts && opts->ip6po_nexthop) {
270 			sin6_next = satosin6(opts->ip6po_nexthop);
271 			rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
272 			if (rt) {
273 				ia6 = in6_ifawithscope(rt->rt_ifp, dst);
274 				if (ia6 == 0)
275 					ia6 = ifatoia6(rt->rt_ifa);
276 			}
277 			if (ia6 && jailed) {
278 				jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
279 				if (!jailed_ip(cred->cr_prison,
280 					(struct sockaddr *)&jsin6))
281 					ia6 = 0;
282 			}
283 
284 			if (ia6 == 0) {
285 				*errorp = EADDRNOTAVAIL;
286 				return (0);
287 			}
288 			return (&satosin6(&ia6->ia_addr)->sin6_addr);
289 		}
290 	}
291 
292 	/*
293 	 * If route is known or can be allocated now,
294 	 * our src addr is taken from the i/f, else punt.
295 	 */
296 	if (ro) {
297 		if (ro->ro_rt &&
298 		    (!(ro->ro_rt->rt_flags & RTF_UP) ||
299 		     satosin6(&ro->ro_dst)->sin6_family != AF_INET6 ||
300 		     !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr,
301 					 dst))) {
302 			RTFREE(ro->ro_rt);
303 			ro->ro_rt = NULL;
304 		}
305 		if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL) {
306 			struct sockaddr_in6 *sa6;
307 
308 			/* No route yet, so try to acquire one */
309 			bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
310 			sa6 = &ro->ro_dst;
311 			sa6->sin6_family = AF_INET6;
312 			sa6->sin6_len = sizeof(struct sockaddr_in6);
313 			sa6->sin6_addr = *dst;
314 			sa6->sin6_scope_id = dstsock->sin6_scope_id;
315 			if (!jailed && IN6_IS_ADDR_MULTICAST(dst)) {
316 				ro->ro_rt =
317 				  rtpurelookup((struct sockaddr *)&ro->ro_dst);
318 			} else {
319 				rtalloc((struct route *)ro);
320 			}
321 		}
322 
323 		/*
324 		 * in_pcbconnect() checks out IFF_LOOPBACK to skip using
325 		 * the address. But we don't know why it does so.
326 		 * It is necessary to ensure the scope even for lo0
327 		 * so doesn't check out IFF_LOOPBACK.
328 		 */
329 
330 		if (ro->ro_rt) {
331 			ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
332 			if (ia6 && jailed) {
333 				jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
334 				if (!jailed_ip(cred->cr_prison,
335 					(struct sockaddr *)&jsin6))
336 					ia6 = 0;
337 			}
338 
339 			if (ia6 == 0) /* xxx scope error ?*/
340 				ia6 = ifatoia6(ro->ro_rt->rt_ifa);
341 
342 			if (ia6 && jailed) {
343 				jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
344 				if (!jailed_ip(cred->cr_prison,
345 					(struct sockaddr *)&jsin6))
346 					ia6 = 0;
347 			}
348 		}
349 #if 0
350 		/*
351 		 * xxx The followings are necessary? (kazu)
352 		 * I don't think so.
353 		 * It's for SO_DONTROUTE option in IPv4.(jinmei)
354 		 */
355 		if (ia6 == 0) {
356 			struct sockaddr_in6 sin6 = {sizeof(sin6), AF_INET6, 0};
357 
358 			sin6->sin6_addr = *dst;
359 
360 			ia6 = ifatoia6(ifa_ifwithdstaddr(sin6tosa(&sin6)));
361 			if (ia6 == 0)
362 				ia6 = ifatoia6(ifa_ifwithnet(sin6tosa(&sin6)));
363 			if (ia6 == 0)
364 				return (0);
365 			return (&satosin6(&ia6->ia_addr)->sin6_addr);
366 		}
367 #endif /* 0 */
368 		if (ia6 == 0) {
369 			*errorp = EHOSTUNREACH;	/* no route */
370 			return (0);
371 		}
372 		return (&satosin6(&ia6->ia_addr)->sin6_addr);
373 	}
374 
375 	*errorp = EADDRNOTAVAIL;
376 	return (0);
377 }
378 
379 /*
380  * Default hop limit selection. The precedence is as follows:
381  * 1. Hoplimit value specified via ioctl.
382  * 2. (If the outgoing interface is detected) the current
383  *     hop limit of the interface specified by router advertisement.
384  * 3. The system default hoplimit.
385 */
386 int
387 in6_selecthlim(struct in6pcb *in6p, struct ifnet *ifp)
388 {
389 	if (in6p && in6p->in6p_hops >= 0)
390 		return (in6p->in6p_hops);
391 	else if (ifp)
392 		return (ND_IFINFO(ifp)->chlim);
393 	else
394 		return (ip6_defhlim);
395 }
396 
397 /*
398  * XXX: this is borrowed from in6_pcbbind(). If possible, we should
399  * share this function by all *bsd*...
400  */
401 int
402 in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct thread *td)
403 {
404 	struct socket *so = inp->inp_socket;
405 	u_int16_t lport = 0, first, last, *lastport;
406 	int count, error = 0, wild = 0;
407 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
408 	struct ucred *cred = NULL;
409 
410 	/* XXX: this is redundant when called from in6_pcbbind */
411 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
412 		wild = INPLOOKUP_WILDCARD;
413 	if (td->td_proc && td->td_proc->p_ucred)
414 		cred = td->td_proc->p_ucred;
415 
416 	inp->inp_flags |= INP_ANONPORT;
417 
418 	if (inp->inp_flags & INP_HIGHPORT) {
419 		first = ipport_hifirstauto;	/* sysctl */
420 		last  = ipport_hilastauto;
421 		lastport = &pcbinfo->lasthi;
422 	} else if (inp->inp_flags & INP_LOWPORT) {
423 		if ((error = suser(td)) != 0)
424 			return error;
425 		first = ipport_lowfirstauto;	/* 1023 */
426 		last  = ipport_lowlastauto;	/* 600 */
427 		lastport = &pcbinfo->lastlow;
428 	} else {
429 		first = ipport_firstauto;	/* sysctl */
430 		last  = ipport_lastauto;
431 		lastport = &pcbinfo->lastport;
432 	}
433 	/*
434 	 * Simple check to ensure all ports are not used up causing
435 	 * a deadlock here.
436 	 *
437 	 * We split the two cases (up and down) so that the direction
438 	 * is not being tested on each round of the loop.
439 	 */
440 	if (first > last) {
441 		/*
442 		 * counting down
443 		 */
444 		count = first - last;
445 
446 		do {
447 			if (count-- < 0) {	/* completely used? */
448 				/*
449 				 * Undo any address bind that may have
450 				 * occurred above.
451 				 */
452 				inp->in6p_laddr = kin6addr_any;
453 				return (EAGAIN);
454 			}
455 			--*lastport;
456 			if (*lastport > first || *lastport < last)
457 				*lastport = first;
458 			lport = htons(*lastport);
459 		} while (in6_pcblookup_local(pcbinfo, &inp->in6p_laddr,
460 			 lport, wild, cred));
461 	} else {
462 		/*
463 		 * counting up
464 		 */
465 		count = last - first;
466 
467 		do {
468 			if (count-- < 0) {	/* completely used? */
469 				/*
470 				 * Undo any address bind that may have
471 				 * occurred above.
472 				 */
473 				inp->in6p_laddr = kin6addr_any;
474 				return (EAGAIN);
475 			}
476 			++*lastport;
477 			if (*lastport < first || *lastport > last)
478 				*lastport = first;
479 			lport = htons(*lastport);
480 		} while (in6_pcblookup_local(pcbinfo, &inp->in6p_laddr,
481 			 lport, wild, cred));
482 	}
483 
484 	inp->inp_lport = lport;
485 	if (in_pcbinsporthash(inp) != 0) {
486 		inp->in6p_laddr = kin6addr_any;
487 		inp->inp_lport = 0;
488 		return (EAGAIN);
489 	}
490 
491 	return (0);
492 }
493 
494 /*
495  * generate kernel-internal form (scopeid embedded into s6_addr16[1]).
496  * If the address scope of is link-local, embed the interface index in the
497  * address.  The routine determines our precedence
498  * between advanced API scope/interface specification and basic API
499  * specification.
500  *
501  * this function should be nuked in the future, when we get rid of
502  * embedded scopeid thing.
503  *
504  * XXX actually, it is over-specification to return ifp against sin6_scope_id.
505  * there can be multiple interfaces that belong to a particular scope zone
506  * (in specification, we have 1:N mapping between a scope zone and interfaces).
507  * we may want to change the function to return something other than ifp.
508  */
509 int
510 in6_embedscope(struct in6_addr *in6,
511 	       const struct sockaddr_in6 *sin6,
512 #ifdef HAVE_NRL_INPCB
513 	       struct inpcb *in6p,
514 #define in6p_outputopts inp_outputopts6
515 #define in6p_moptions   inp_moptions6
516 #else
517 	       struct in6pcb *in6p,
518 #endif
519 	       struct ifnet **ifpp)
520 {
521 	struct ifnet *ifp = NULL;
522 	u_int32_t scopeid;
523 
524 	*in6 = sin6->sin6_addr;
525 	scopeid = sin6->sin6_scope_id;
526 	if (ifpp)
527 		*ifpp = NULL;
528 
529 	/*
530 	 * don't try to read sin6->sin6_addr beyond here, since the caller may
531 	 * ask us to overwrite existing sockaddr_in6
532 	 */
533 
534 #ifdef ENABLE_DEFAULT_SCOPE
535 	if (scopeid == 0)
536 		scopeid = scope6_addr2default(in6);
537 #endif
538 
539 	if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
540 		struct in6_pktinfo *pi;
541 
542 		/*
543 		 * KAME assumption: link id == interface id
544 		 */
545 
546 		if (in6p && in6p->in6p_outputopts &&
547 		    (pi = in6p->in6p_outputopts->ip6po_pktinfo) &&
548 		    pi->ipi6_ifindex) {
549 			ifp = ifindex2ifnet[pi->ipi6_ifindex];
550 			in6->s6_addr16[1] = htons(pi->ipi6_ifindex);
551 		} else if (in6p && IN6_IS_ADDR_MULTICAST(in6) &&
552 			   in6p->in6p_moptions &&
553 			   in6p->in6p_moptions->im6o_multicast_ifp) {
554 			ifp = in6p->in6p_moptions->im6o_multicast_ifp;
555 			in6->s6_addr16[1] = htons(ifp->if_index);
556 		} else if (scopeid) {
557 			/* boundary check */
558 			if (scopeid < 0 || if_index < scopeid)
559 				return ENXIO;  /* XXX EINVAL? */
560 			ifp = ifindex2ifnet[scopeid];
561 			/*XXX assignment to 16bit from 32bit variable */
562 			in6->s6_addr16[1] = htons(scopeid & 0xffff);
563 		}
564 
565 		if (ifpp)
566 			*ifpp = ifp;
567 	}
568 
569 	return 0;
570 }
571 #ifdef HAVE_NRL_INPCB
572 #undef in6p_outputopts
573 #undef in6p_moptions
574 #endif
575 
576 /*
577  * generate standard sockaddr_in6 from embedded form.
578  * touches sin6_addr and sin6_scope_id only.
579  *
580  * this function should be nuked in the future, when we get rid of
581  * embedded scopeid thing.
582  */
583 int
584 in6_recoverscope(struct sockaddr_in6 *sin6, const struct in6_addr *in6,
585 		 struct ifnet *ifp)
586 {
587 	u_int32_t scopeid;
588 
589 	sin6->sin6_addr = *in6;
590 
591 	/*
592 	 * don't try to read *in6 beyond here, since the caller may
593 	 * ask us to overwrite existing sockaddr_in6
594 	 */
595 
596 	sin6->sin6_scope_id = 0;
597 	if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
598 		/*
599 		 * KAME assumption: link id == interface id
600 		 */
601 		scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]);
602 		if (scopeid) {
603 			/* sanity check */
604 			if (scopeid < 0 || if_index < scopeid)
605 				return ENXIO;
606 			if (ifp && ifp->if_index != scopeid)
607 				return ENXIO;
608 			sin6->sin6_addr.s6_addr16[1] = 0;
609 			sin6->sin6_scope_id = scopeid;
610 		}
611 	}
612 
613 	return 0;
614 }
615 
616 /*
617  * just clear the embedded scope identifer.
618  * XXX: currently used for bsdi4 only as a supplement function.
619  */
620 void
621 in6_clearscope(struct in6_addr *addr)
622 {
623 	if (IN6_IS_SCOPE_LINKLOCAL(addr))
624 		addr->s6_addr16[1] = 0;
625 }
626 
627 void
628 addrsel_policy_init(void)
629 {
630 
631 	init_policy_queue();
632 
633 	/* initialize the "last resort" policy */
634 	bzero(&defaultaddrpolicy, sizeof(defaultaddrpolicy));
635 	defaultaddrpolicy.label = ADDR_LABEL_NOTAPP;
636 }
637 
638 /*
639  * Subroutines to manage the address selection policy table via sysctl.
640  */
641 struct walkarg {
642 	struct sysctl_req *w_req;
643 };
644 
645 static int in6_src_sysctl(SYSCTL_HANDLER_ARGS);
646 SYSCTL_DECL(_net_inet6_ip6);
647 SYSCTL_NODE(_net_inet6_ip6, IPV6CTL_ADDRCTLPOLICY, addrctlpolicy,
648 	CTLFLAG_RD, in6_src_sysctl, "");
649 
650 static int
651 in6_src_sysctl(SYSCTL_HANDLER_ARGS)
652 {
653 	struct walkarg w;
654 
655 	if (req->newptr)
656 		return EPERM;
657 
658 	bzero(&w, sizeof(w));
659 	w.w_req = req;
660 
661 	return (walk_addrsel_policy(dump_addrsel_policyent, &w));
662 }
663 
664 int
665 in6_src_ioctl(u_long cmd, caddr_t data)
666 {
667 	int i;
668 	struct in6_addrpolicy ent0;
669 
670 	if (cmd != SIOCAADDRCTL_POLICY && cmd != SIOCDADDRCTL_POLICY)
671 		return (EOPNOTSUPP); /* check for safety */
672 
673 	ent0 = *(struct in6_addrpolicy *)data;
674 
675 	if (ent0.label == ADDR_LABEL_NOTAPP)
676 		return (EINVAL);
677 	/* check if the prefix mask is consecutive. */
678 	if (in6_mask2len(&ent0.addrmask.sin6_addr, NULL) < 0)
679 		return (EINVAL);
680 	/* clear trailing garbages (if any) of the prefix address. */
681 	for (i = 0; i < 4; i++) {
682 		ent0.addr.sin6_addr.s6_addr32[i] &=
683 			ent0.addrmask.sin6_addr.s6_addr32[i];
684 	}
685 	ent0.use = 0;
686 
687 	switch (cmd) {
688 	case SIOCAADDRCTL_POLICY:
689 		return (add_addrsel_policyent(&ent0));
690 	case SIOCDADDRCTL_POLICY:
691 		return (delete_addrsel_policyent(&ent0));
692 	}
693 
694 	return (0);		/* XXX: compromise compilers */
695 }
696 
697 /*
698  * The followings are implementation of the policy table using a
699  * simple tail queue.
700  * XXX such details should be hidden.
701  * XXX implementation using binary tree should be more efficient.
702  */
703 struct addrsel_policyent {
704 	TAILQ_ENTRY(addrsel_policyent) ape_entry;
705 	struct in6_addrpolicy ape_policy;
706 };
707 
708 TAILQ_HEAD(addrsel_policyhead, addrsel_policyent);
709 
710 struct addrsel_policyhead addrsel_policytab;
711 
712 static void
713 init_policy_queue(void)
714 {
715 	TAILQ_INIT(&addrsel_policytab);
716 }
717 
718 static int
719 add_addrsel_policyent(struct in6_addrpolicy *newpolicy)
720 {
721 	struct addrsel_policyent *new, *pol;
722 
723 	/* duplication check */
724 	for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
725 	     pol = TAILQ_NEXT(pol, ape_entry)) {
726 		if (SA6_ARE_ADDR_EQUAL(&newpolicy->addr,
727 				       &pol->ape_policy.addr) &&
728 		    SA6_ARE_ADDR_EQUAL(&newpolicy->addrmask,
729 				       &pol->ape_policy.addrmask)) {
730 			return (EEXIST);	/* or override it? */
731 		}
732 	}
733 
734 	new = kmalloc(sizeof(*new), M_IFADDR, M_WAITOK | M_ZERO);
735 
736 	/* XXX: should validate entry */
737 	new->ape_policy = *newpolicy;
738 
739 	TAILQ_INSERT_TAIL(&addrsel_policytab, new, ape_entry);
740 
741 	return (0);
742 }
743 
744 static int
745 delete_addrsel_policyent(struct in6_addrpolicy *key)
746 {
747 	struct addrsel_policyent *pol;
748 
749 	/* search for the entry in the table */
750 	for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
751 	     pol = TAILQ_NEXT(pol, ape_entry)) {
752 		if (SA6_ARE_ADDR_EQUAL(&key->addr, &pol->ape_policy.addr) &&
753 		    SA6_ARE_ADDR_EQUAL(&key->addrmask,
754 				       &pol->ape_policy.addrmask)) {
755 			break;
756 		}
757 	}
758 	if (pol == NULL)
759 		return (ESRCH);
760 
761 	TAILQ_REMOVE(&addrsel_policytab, pol, ape_entry);
762 	kfree(pol, M_IFADDR);
763 
764 	return (0);
765 }
766 
767 static int
768 walk_addrsel_policy(int(*callback)(struct in6_addrpolicy *, void *), void *w)
769 {
770 	struct addrsel_policyent *pol;
771 	int error = 0;
772 
773 	for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
774 	     pol = TAILQ_NEXT(pol, ape_entry)) {
775 		if ((error = (*callback)(&pol->ape_policy, w)) != 0)
776 			return (error);
777 	}
778 
779 	return (error);
780 }
781 
782 static int
783 dump_addrsel_policyent(struct in6_addrpolicy *pol, void *arg)
784 {
785 	int error = 0;
786 	struct walkarg *w = arg;
787 
788 	error = SYSCTL_OUT(w->w_req, pol, sizeof(*pol));
789 
790 	return (error);
791 }
792