1139826Simp/*- 262587Sitojun * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 362587Sitojun * All rights reserved. 462587Sitojun * 562587Sitojun * Redistribution and use in source and binary forms, with or without 662587Sitojun * modification, are permitted provided that the following conditions 762587Sitojun * are met: 862587Sitojun * 1. Redistributions of source code must retain the above copyright 962587Sitojun * notice, this list of conditions and the following disclaimer. 1062587Sitojun * 2. Redistributions in binary form must reproduce the above copyright 1162587Sitojun * notice, this list of conditions and the following disclaimer in the 1262587Sitojun * documentation and/or other materials provided with the distribution. 1362587Sitojun * 3. Neither the name of the project nor the names of its contributors 1462587Sitojun * may be used to endorse or promote products derived from this software 1562587Sitojun * without specific prior written permission. 1662587Sitojun * 1762587Sitojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1862587Sitojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1962587Sitojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2062587Sitojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2162587Sitojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2262587Sitojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2362587Sitojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2462587Sitojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2562587Sitojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2662587Sitojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2762587Sitojun * SUCH DAMAGE. 28174510Sobrien * 29174510Sobrien * $KAME: in6_src.c,v 1.132 2003/08/26 04:42:27 keiichi Exp $ 3062587Sitojun */ 3162587Sitojun 32139826Simp/*- 3362587Sitojun * Copyright (c) 1982, 1986, 1991, 1993 3462587Sitojun * The Regents of the University of California. All rights reserved. 3562587Sitojun * 3662587Sitojun * Redistribution and use in source and binary forms, with or without 3762587Sitojun * modification, are permitted provided that the following conditions 3862587Sitojun * are met: 3962587Sitojun * 1. Redistributions of source code must retain the above copyright 4062587Sitojun * notice, this list of conditions and the following disclaimer. 4162587Sitojun * 2. Redistributions in binary form must reproduce the above copyright 4262587Sitojun * notice, this list of conditions and the following disclaimer in the 4362587Sitojun * documentation and/or other materials provided with the distribution. 4462587Sitojun * 4. Neither the name of the University nor the names of its contributors 4562587Sitojun * may be used to endorse or promote products derived from this software 4662587Sitojun * without specific prior written permission. 4762587Sitojun * 4862587Sitojun * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 4962587Sitojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5062587Sitojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5162587Sitojun * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5262587Sitojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5362587Sitojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5462587Sitojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5562587Sitojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5662587Sitojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5762587Sitojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5862587Sitojun * SUCH DAMAGE. 5962587Sitojun * 6062587Sitojun * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 6162587Sitojun */ 6262587Sitojun 63174510Sobrien#include <sys/cdefs.h> 64174510Sobrien__FBSDID("$FreeBSD$"); 65174510Sobrien 6662587Sitojun#include "opt_inet.h" 6762587Sitojun#include "opt_inet6.h" 68178167Sqingli#include "opt_mpath.h" 6962587Sitojun 7062587Sitojun#include <sys/param.h> 7162587Sitojun#include <sys/systm.h> 72168191Sjhb#include <sys/lock.h> 7378064Sume#include <sys/malloc.h> 7462587Sitojun#include <sys/mbuf.h> 75164033Srwatson#include <sys/priv.h> 7662587Sitojun#include <sys/protosw.h> 7762587Sitojun#include <sys/socket.h> 7862587Sitojun#include <sys/socketvar.h> 79121742Sume#include <sys/sockio.h> 80121742Sume#include <sys/sysctl.h> 8162587Sitojun#include <sys/errno.h> 8262587Sitojun#include <sys/time.h> 83185435Sbz#include <sys/jail.h> 84122058Sume#include <sys/kernel.h> 85149200Sume#include <sys/sx.h> 8662587Sitojun 8762587Sitojun#include <net/if.h> 88196864Sqingli#include <net/if_dl.h> 8962587Sitojun#include <net/route.h> 90186119Sqingli#include <net/if_llatbl.h> 91178167Sqingli#ifdef RADIX_MPATH 92178167Sqingli#include <net/radix_mpath.h> 93178167Sqingli#endif 9462587Sitojun 9562587Sitojun#include <netinet/in.h> 9662587Sitojun#include <netinet/in_var.h> 9762587Sitojun#include <netinet/in_systm.h> 9862587Sitojun#include <netinet/ip.h> 9962587Sitojun#include <netinet/in_pcb.h> 100184096Sbz#include <netinet/ip_var.h> 101184096Sbz#include <netinet/udp.h> 102184096Sbz#include <netinet/udp_var.h> 103185571Sbz 10462587Sitojun#include <netinet6/in6_var.h> 10562587Sitojun#include <netinet/ip6.h> 10662587Sitojun#include <netinet6/in6_pcb.h> 10762587Sitojun#include <netinet6/ip6_var.h> 108148385Sume#include <netinet6/scope6_var.h> 10962587Sitojun#include <netinet6/nd6.h> 11062587Sitojun 111121742Sumestatic struct mtx addrsel_lock; 112121742Sume#define ADDRSEL_LOCK_INIT() mtx_init(&addrsel_lock, "addrsel_lock", NULL, MTX_DEF) 113121742Sume#define ADDRSEL_LOCK() mtx_lock(&addrsel_lock) 114121742Sume#define ADDRSEL_UNLOCK() mtx_unlock(&addrsel_lock) 115121742Sume#define ADDRSEL_LOCK_ASSERT() mtx_assert(&addrsel_lock, MA_OWNED) 116121742Sume 117149200Sumestatic struct sx addrsel_sxlock; 118149200Sume#define ADDRSEL_SXLOCK_INIT() sx_init(&addrsel_sxlock, "addrsel_sxlock") 119149200Sume#define ADDRSEL_SLOCK() sx_slock(&addrsel_sxlock) 120149200Sume#define ADDRSEL_SUNLOCK() sx_sunlock(&addrsel_sxlock) 121149200Sume#define ADDRSEL_XLOCK() sx_xlock(&addrsel_sxlock) 122149200Sume#define ADDRSEL_XUNLOCK() sx_xunlock(&addrsel_sxlock) 123149200Sume 124121742Sume#define ADDR_LABEL_NOTAPP (-1) 125215701Sdimstatic VNET_DEFINE(struct in6_addrpolicy, defaultaddrpolicy); 126195727Srwatson#define V_defaultaddrpolicy VNET(defaultaddrpolicy) 127195699Srwatson 128207369SbzVNET_DEFINE(int, ip6_prefer_tempaddr) = 0; 129207369Sbz 130244524Sdelphijstatic int selectroute(struct sockaddr_in6 *, struct ip6_pktopts *, 131148385Sume struct ip6_moptions *, struct route_in6 *, struct ifnet **, 132244524Sdelphij struct rtentry **, int, u_int); 133244524Sdelphijstatic int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *, 134232292Sbz struct ip6_moptions *, struct route_in6 *ro, struct ifnet **, 135244524Sdelphij struct ifnet *, u_int); 136122077Sume 137175162Sobrienstatic struct in6_addrpolicy *lookup_addrsel_policy(struct sockaddr_in6 *); 138122077Sume 139175162Sobrienstatic void init_policy_queue(void); 140175162Sobrienstatic int add_addrsel_policyent(struct in6_addrpolicy *); 141175162Sobrienstatic int delete_addrsel_policyent(struct in6_addrpolicy *); 142244524Sdelphijstatic int walk_addrsel_policy(int (*)(struct in6_addrpolicy *, void *), 143244524Sdelphij void *); 144175162Sobrienstatic int dump_addrsel_policyent(struct in6_addrpolicy *, void *); 145175162Sobrienstatic struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *); 146121742Sume 14762587Sitojun/* 14878064Sume * Return an IPv6 address, which is the most appropriate for a given 14962587Sitojun * destination and user specified options. 15078064Sume * If necessary, this function lookups the routing table and returns 15162587Sitojun * an entry to the caller for later use. 15262587Sitojun */ 153122077Sume#define REPLACE(r) do {\ 154250044Sae IP6STAT_INC(ip6s_sources_rule[(r)]); \ 155250044Sae rule = (r); \ 156175512Sbz /* { \ 157175512Sbz char ip6buf[INET6_ADDRSTRLEN], ip6b[INET6_ADDRSTRLEN]; \ 158175512Sbz printf("in6_selectsrc: replace %s with %s by %d\n", ia_best ? ip6_sprintf(ip6buf, &ia_best->ia_addr.sin6_addr) : "none", ip6_sprintf(ip6b, &ia->ia_addr.sin6_addr), (r)); \ 159175512Sbz } */ \ 160122077Sume goto replace; \ 161122077Sume} while(0) 162122077Sume#define NEXT(r) do {\ 163175512Sbz /* { \ 164175512Sbz char ip6buf[INET6_ADDRSTRLEN], ip6b[INET6_ADDRSTRLEN]; \ 165175512Sbz printf("in6_selectsrc: keep %s against %s by %d\n", ia_best ? ip6_sprintf(ip6buf, &ia_best->ia_addr.sin6_addr) : "none", ip6_sprintf(ip6b, &ia->ia_addr.sin6_addr), (r)); \ 166175512Sbz } */ \ 167171260Sdelphij goto next; /* XXX: we can't use 'continue' here */ \ 168122077Sume} while(0) 169122077Sume#define BREAK(r) do { \ 170250044Sae IP6STAT_INC(ip6s_sources_rule[(r)]); \ 171250044Sae rule = (r); \ 172171260Sdelphij goto out; /* XXX: we can't use 'break' here */ \ 173122077Sume} while(0) 174122077Sume 175194777Sbzint 176171259Sdelphijin6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 177180371Sbz struct inpcb *inp, struct route_in6 *ro, struct ucred *cred, 178194777Sbz struct ifnet **ifpp, struct in6_addr *srcp) 17962587Sitojun{ 180207276Sbz struct in6_addr dst, tmp; 181232292Sbz struct ifnet *ifp = NULL, *oifp = NULL; 182122077Sume struct in6_ifaddr *ia = NULL, *ia_best = NULL; 18362587Sitojun struct in6_pktinfo *pi = NULL; 184122077Sume int dst_scope = -1, best_scope = -1, best_matchlen = -1; 185122077Sume struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL; 186122077Sume u_int32_t odstzone; 187122077Sume int prefer_tempaddr; 188250044Sae int error, rule; 189180371Sbz struct ip6_moptions *mopts; 19062587Sitojun 191194777Sbz KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__)); 192194777Sbz 193148385Sume dst = dstsock->sin6_addr; /* make a copy for local operation */ 194232292Sbz if (ifpp) { 195232292Sbz /* 196232292Sbz * Save a possibly passed in ifp for in6_selectsrc. Only 197232292Sbz * neighbor discovery code should use this feature, where 198232292Sbz * we may know the interface but not the FIB number holding 199232292Sbz * the connected subnet in case someone deleted it from the 200232292Sbz * default FIB and we need to check the interface. 201232292Sbz */ 202232292Sbz if (*ifpp != NULL) 203232292Sbz oifp = *ifpp; 204148385Sume *ifpp = NULL; 205232292Sbz } 20662587Sitojun 207180386Sbz if (inp != NULL) { 208180386Sbz INP_LOCK_ASSERT(inp); 209180371Sbz mopts = inp->in6p_moptions; 210180386Sbz } else { 211180371Sbz mopts = NULL; 212180386Sbz } 213180371Sbz 21462587Sitojun /* 21562587Sitojun * If the source address is explicitly specified by the caller, 216122077Sume * check if the requested source address is indeed a unicast address 217122077Sume * assigned to the node, and can be used as the packet's source 218122077Sume * address. If everything is okay, use the address as source. 21962587Sitojun */ 22062587Sitojun if (opts && (pi = opts->ip6po_pktinfo) && 221122077Sume !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) { 222122077Sume struct sockaddr_in6 srcsock; 223122077Sume struct in6_ifaddr *ia6; 22462587Sitojun 225122077Sume /* get the outgoing interface */ 226232292Sbz if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp, oifp, 227232292Sbz (inp != NULL) ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB)) 228232292Sbz != 0) 229194777Sbz return (error); 230125436Sume 231122077Sume /* 232122077Sume * determine the appropriate zone id of the source based on 233122077Sume * the zone of the destination and the outgoing interface. 234148385Sume * If the specified address is ambiguous wrt the scope zone, 235148385Sume * the interface must be specified; otherwise, ifa_ifwithaddr() 236148385Sume * will fail matching the address. 237122077Sume */ 238122077Sume bzero(&srcsock, sizeof(srcsock)); 239122077Sume srcsock.sin6_family = AF_INET6; 240122077Sume srcsock.sin6_len = sizeof(srcsock); 241122077Sume srcsock.sin6_addr = pi->ipi6_addr; 242122077Sume if (ifp) { 243194777Sbz error = in6_setscope(&srcsock.sin6_addr, ifp, NULL); 244194777Sbz if (error) 245194777Sbz return (error); 246122077Sume } 247194777Sbz if (cred != NULL && (error = prison_local_ip6(cred, 248188144Sjamie &srcsock.sin6_addr, (inp != NULL && 249188144Sjamie (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) 250194777Sbz return (error); 251148385Sume 252194760Srwatson ia6 = (struct in6_ifaddr *)ifa_ifwithaddr( 253194760Srwatson (struct sockaddr *)&srcsock); 254122077Sume if (ia6 == NULL || 255122077Sume (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) { 256194760Srwatson if (ia6 != NULL) 257194760Srwatson ifa_free(&ia6->ia_ifa); 258194777Sbz return (EADDRNOTAVAIL); 259122077Sume } 260122077Sume pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */ 261148385Sume if (ifpp) 262148385Sume *ifpp = ifp; 263194777Sbz bcopy(&ia6->ia_addr.sin6_addr, srcp, sizeof(*srcp)); 264194760Srwatson ifa_free(&ia6->ia_ifa); 265194777Sbz return (0); 266122077Sume } 267122077Sume 26862587Sitojun /* 269122077Sume * Otherwise, if the socket has already bound the source, just use it. 27062587Sitojun */ 271180371Sbz if (inp != NULL && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 272188144Sjamie if (cred != NULL && 273194777Sbz (error = prison_local_ip6(cred, &inp->in6p_laddr, 274188144Sjamie ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) 275194777Sbz return (error); 276194777Sbz bcopy(&inp->in6p_laddr, srcp, sizeof(*srcp)); 277194777Sbz return (0); 278180371Sbz } 27962587Sitojun 28062587Sitojun /* 281202468Sbz * Bypass source address selection and use the primary jail IP 282202468Sbz * if requested. 283202468Sbz */ 284202468Sbz if (cred != NULL && !prison_saddrsel_ip6(cred, srcp)) 285202468Sbz return (0); 286202468Sbz 287202468Sbz /* 288122077Sume * If the address is not specified, choose the best one based on 289122077Sume * the outgoing interface and the destination address. 29062587Sitojun */ 291122077Sume /* get the outgoing interface */ 292232292Sbz if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp, oifp, 293232292Sbz (inp != NULL) ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB)) != 0) 294194777Sbz return (error); 29562587Sitojun 296122077Sume#ifdef DIAGNOSTIC 297122077Sume if (ifp == NULL) /* this should not happen */ 298122077Sume panic("in6_selectsrc: NULL ifp"); 299122077Sume#endif 300194777Sbz error = in6_setscope(&dst, ifp, &odstzone); 301194777Sbz if (error) 302194777Sbz return (error); 303148385Sume 304250044Sae rule = 0; 305194971Srwatson IN6_IFADDR_RLOCK(); 306194907Srwatson TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { 307122077Sume int new_scope = -1, new_matchlen = -1; 308122077Sume struct in6_addrpolicy *new_policy = NULL; 309122077Sume u_int32_t srczone, osrczone, dstzone; 310148385Sume struct in6_addr src; 311122077Sume struct ifnet *ifp1 = ia->ia_ifp; 312122077Sume 313122077Sume /* 314122077Sume * We'll never take an address that breaks the scope zone 315122077Sume * of the destination. We also skip an address if its zone 316122077Sume * does not contain the outgoing interface. 317122077Sume * XXX: we should probably use sin6_scope_id here. 318122077Sume */ 319148385Sume if (in6_setscope(&dst, ifp1, &dstzone) || 320122077Sume odstzone != dstzone) { 321122077Sume continue; 32262587Sitojun } 323148385Sume src = ia->ia_addr.sin6_addr; 324148385Sume if (in6_setscope(&src, ifp, &osrczone) || 325148385Sume in6_setscope(&src, ifp1, &srczone) || 326122077Sume osrczone != srczone) { 327122077Sume continue; 328122077Sume } 32962587Sitojun 330122077Sume /* avoid unusable addresses */ 331122077Sume if ((ia->ia6_flags & 332122077Sume (IN6_IFF_NOTREADY | IN6_IFF_ANYCAST | IN6_IFF_DETACHED))) { 333122077Sume continue; 33462587Sitojun } 335181803Sbz if (!V_ip6_use_deprecated && IFA6_IS_DEPRECATED(ia)) 336122077Sume continue; 337122077Sume 338207276Sbz /* If jailed only take addresses of the jail into account. */ 339185435Sbz if (cred != NULL && 340207276Sbz prison_check_ip6(cred, &ia->ia_addr.sin6_addr) != 0) 341185435Sbz continue; 342185435Sbz 343122077Sume /* Rule 1: Prefer same address */ 344148385Sume if (IN6_ARE_ADDR_EQUAL(&dst, &ia->ia_addr.sin6_addr)) { 345122077Sume ia_best = ia; 346122077Sume BREAK(1); /* there should be no better candidate */ 347122077Sume } 348122077Sume 349122077Sume if (ia_best == NULL) 350122077Sume REPLACE(0); 351122077Sume 352122077Sume /* Rule 2: Prefer appropriate scope */ 353122077Sume if (dst_scope < 0) 354148385Sume dst_scope = in6_addrscope(&dst); 355122077Sume new_scope = in6_addrscope(&ia->ia_addr.sin6_addr); 356122077Sume if (IN6_ARE_SCOPE_CMP(best_scope, new_scope) < 0) { 357122077Sume if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0) 358122077Sume REPLACE(2); 359122077Sume NEXT(2); 360122077Sume } else if (IN6_ARE_SCOPE_CMP(new_scope, best_scope) < 0) { 361122077Sume if (IN6_ARE_SCOPE_CMP(new_scope, dst_scope) < 0) 362122077Sume NEXT(2); 363122077Sume REPLACE(2); 364122077Sume } 365122077Sume 366122077Sume /* 367122077Sume * Rule 3: Avoid deprecated addresses. Note that the case of 368122077Sume * !ip6_use_deprecated is already rejected above. 369122077Sume */ 370122077Sume if (!IFA6_IS_DEPRECATED(ia_best) && IFA6_IS_DEPRECATED(ia)) 371122077Sume NEXT(3); 372122077Sume if (IFA6_IS_DEPRECATED(ia_best) && !IFA6_IS_DEPRECATED(ia)) 373122077Sume REPLACE(3); 374122077Sume 375122077Sume /* Rule 4: Prefer home addresses */ 376122077Sume /* 377122077Sume * XXX: This is a TODO. We should probably merge the MIP6 378122077Sume * case above. 379122077Sume */ 380122077Sume 381122077Sume /* Rule 5: Prefer outgoing interface */ 382245555Sume if (!(ND_IFINFO(ifp)->flags & ND6_IFF_NO_PREFER_IFACE)) { 383245555Sume if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp) 384245555Sume NEXT(5); 385245555Sume if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp) 386245555Sume REPLACE(5); 387245555Sume } 388122077Sume 389122077Sume /* 390122077Sume * Rule 6: Prefer matching label 391122077Sume * Note that best_policy should be non-NULL here. 392122077Sume */ 393122077Sume if (dst_policy == NULL) 394122077Sume dst_policy = lookup_addrsel_policy(dstsock); 395122077Sume if (dst_policy->label != ADDR_LABEL_NOTAPP) { 396122077Sume new_policy = lookup_addrsel_policy(&ia->ia_addr); 397122077Sume if (dst_policy->label == best_policy->label && 398122077Sume dst_policy->label != new_policy->label) 399122077Sume NEXT(6); 400122077Sume if (dst_policy->label != best_policy->label && 401122077Sume dst_policy->label == new_policy->label) 402122077Sume REPLACE(6); 403122077Sume } 404122077Sume 405122077Sume /* 406122077Sume * Rule 7: Prefer public addresses. 407122077Sume * We allow users to reverse the logic by configuring 408122077Sume * a sysctl variable, so that privacy conscious users can 409122077Sume * always prefer temporary addresses. 410122077Sume */ 411122077Sume if (opts == NULL || 412122077Sume opts->ip6po_prefer_tempaddr == IP6PO_TEMPADDR_SYSTEM) { 413181803Sbz prefer_tempaddr = V_ip6_prefer_tempaddr; 414122077Sume } else if (opts->ip6po_prefer_tempaddr == 415122077Sume IP6PO_TEMPADDR_NOTPREFER) { 416122077Sume prefer_tempaddr = 0; 417122077Sume } else 418122077Sume prefer_tempaddr = 1; 419122077Sume if (!(ia_best->ia6_flags & IN6_IFF_TEMPORARY) && 420122077Sume (ia->ia6_flags & IN6_IFF_TEMPORARY)) { 421122077Sume if (prefer_tempaddr) 422122077Sume REPLACE(7); 423122077Sume else 424122077Sume NEXT(7); 425122077Sume } 426122077Sume if ((ia_best->ia6_flags & IN6_IFF_TEMPORARY) && 427122077Sume !(ia->ia6_flags & IN6_IFF_TEMPORARY)) { 428122077Sume if (prefer_tempaddr) 429122077Sume NEXT(7); 430122077Sume else 431122077Sume REPLACE(7); 432122077Sume } 433122077Sume 434122077Sume /* 435122077Sume * Rule 8: prefer addresses on alive interfaces. 436122077Sume * This is a KAME specific rule. 437122077Sume */ 438122077Sume if ((ia_best->ia_ifp->if_flags & IFF_UP) && 439122077Sume !(ia->ia_ifp->if_flags & IFF_UP)) 440122077Sume NEXT(8); 441122077Sume if (!(ia_best->ia_ifp->if_flags & IFF_UP) && 442122077Sume (ia->ia_ifp->if_flags & IFF_UP)) 443122077Sume REPLACE(8); 444122077Sume 445122077Sume /* 446122077Sume * Rule 14: Use longest matching prefix. 447122077Sume * Note: in the address selection draft, this rule is 448122077Sume * documented as "Rule 8". However, since it is also 449122077Sume * documented that this rule can be overridden, we assign 450122077Sume * a large number so that it is easy to assign smaller numbers 451122077Sume * to more preferred rules. 452122077Sume */ 453148385Sume new_matchlen = in6_matchlen(&ia->ia_addr.sin6_addr, &dst); 454122077Sume if (best_matchlen < new_matchlen) 455122077Sume REPLACE(14); 456122077Sume if (new_matchlen < best_matchlen) 457122077Sume NEXT(14); 458122077Sume 459122077Sume /* Rule 15 is reserved. */ 460122077Sume 461122077Sume /* 462122077Sume * Last resort: just keep the current candidate. 463122077Sume * Or, do we need more rules? 464122077Sume */ 465122077Sume continue; 466122077Sume 467122077Sume replace: 468122077Sume ia_best = ia; 469122077Sume best_scope = (new_scope >= 0 ? new_scope : 470122077Sume in6_addrscope(&ia_best->ia_addr.sin6_addr)); 471122077Sume best_policy = (new_policy ? new_policy : 472122077Sume lookup_addrsel_policy(&ia_best->ia_addr)); 473122077Sume best_matchlen = (new_matchlen >= 0 ? new_matchlen : 474122077Sume in6_matchlen(&ia_best->ia_addr.sin6_addr, 475148385Sume &dst)); 476122077Sume 477122077Sume next: 478122077Sume continue; 479122077Sume 480122077Sume out: 481122077Sume break; 48262587Sitojun } 48362587Sitojun 484194971Srwatson if ((ia = ia_best) == NULL) { 485194971Srwatson IN6_IFADDR_RUNLOCK(); 486250044Sae IP6STAT_INC(ip6s_sources_none); 487194777Sbz return (EADDRNOTAVAIL); 488194971Srwatson } 489122077Sume 490207276Sbz /* 491207276Sbz * At this point at least one of the addresses belonged to the jail 492207276Sbz * but it could still be, that we want to further restrict it, e.g. 493207276Sbz * theoratically IN6_IS_ADDR_LOOPBACK. 494207276Sbz * It must not be IN6_IS_ADDR_UNSPECIFIED anymore. 495207276Sbz * prison_local_ip6() will fix an IN6_IS_ADDR_LOOPBACK but should 496207276Sbz * let all others previously selected pass. 497207276Sbz * Use tmp to not change ::1 on lo0 to the primary jail address. 498207276Sbz */ 499207276Sbz tmp = ia->ia_addr.sin6_addr; 500207276Sbz if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL && 501207276Sbz (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { 502207276Sbz IN6_IFADDR_RUNLOCK(); 503250044Sae IP6STAT_INC(ip6s_sources_none); 504207276Sbz return (EADDRNOTAVAIL); 505207276Sbz } 506207276Sbz 507148385Sume if (ifpp) 508148385Sume *ifpp = ifp; 509148385Sume 510207276Sbz bcopy(&tmp, srcp, sizeof(*srcp)); 511250044Sae if (ia->ia_ifp == ifp) 512250044Sae IP6STAT_INC(ip6s_sources_sameif[best_scope]); 513250044Sae else 514250044Sae IP6STAT_INC(ip6s_sources_otherif[best_scope]); 515250044Sae if (dst_scope == best_scope) 516250044Sae IP6STAT_INC(ip6s_sources_samescope[best_scope]); 517250044Sae else 518250044Sae IP6STAT_INC(ip6s_sources_otherscope[best_scope]); 519250044Sae if (IFA6_IS_DEPRECATED(ia)) 520250044Sae IP6STAT_INC(ip6s_sources_deprecated[best_scope]); 521194971Srwatson IN6_IFADDR_RUNLOCK(); 522194777Sbz return (0); 523122077Sume} 524122077Sume 525171259Sdelphij/* 526171259Sdelphij * clone - meaningful only for bsdi and freebsd 527171259Sdelphij */ 528122077Sumestatic int 529171259Sdelphijselectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 530171259Sdelphij struct ip6_moptions *mopts, struct route_in6 *ro, 531232292Sbz struct ifnet **retifp, struct rtentry **retrt, int norouteok, u_int fibnum) 532122077Sume{ 533122077Sume int error = 0; 534122077Sume struct ifnet *ifp = NULL; 535122077Sume struct rtentry *rt = NULL; 536122077Sume struct sockaddr_in6 *sin6_next; 537122077Sume struct in6_pktinfo *pi = NULL; 538122077Sume struct in6_addr *dst = &dstsock->sin6_addr; 539165118Sbz#if 0 540165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 541122077Sume 542122077Sume if (dstsock->sin6_addr.s6_addr32[0] == 0 && 543122077Sume dstsock->sin6_addr.s6_addr32[1] == 0 && 544122077Sume !IN6_IS_ADDR_LOOPBACK(&dstsock->sin6_addr)) { 545122077Sume printf("in6_selectroute: strange destination %s\n", 546165118Sbz ip6_sprintf(ip6buf, &dstsock->sin6_addr)); 547122077Sume } else { 548122077Sume printf("in6_selectroute: destination = %s%%%d\n", 549165118Sbz ip6_sprintf(ip6buf, &dstsock->sin6_addr), 550122077Sume dstsock->sin6_scope_id); /* for debug */ 551122077Sume } 552122077Sume#endif 553122077Sume 554122077Sume /* If the caller specify the outgoing interface explicitly, use it. */ 555122077Sume if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) { 556122077Sume /* XXX boundary check is assumed to be already done. */ 557122077Sume ifp = ifnet_byindex(pi->ipi6_ifindex); 558122077Sume if (ifp != NULL && 559148385Sume (norouteok || retrt == NULL || 560148385Sume IN6_IS_ADDR_MULTICAST(dst))) { 561122077Sume /* 562148987Sume * we do not have to check or get the route for 563122077Sume * multicast. 564122077Sume */ 565122077Sume goto done; 566122077Sume } else 567122077Sume goto getroute; 568122077Sume } 569122077Sume 570122077Sume /* 571122077Sume * If the destination address is a multicast address and the outgoing 572122077Sume * interface for the address is specified by the caller, use it. 573122077Sume */ 574122077Sume if (IN6_IS_ADDR_MULTICAST(dst) && 575122077Sume mopts != NULL && (ifp = mopts->im6o_multicast_ifp) != NULL) { 576122077Sume goto done; /* we do not need a route for multicast. */ 577122077Sume } 578122077Sume 579122077Sume getroute: 580122077Sume /* 581122077Sume * If the next hop address for the packet is specified by the caller, 582122077Sume * use it as the gateway. 583122077Sume */ 584122077Sume if (opts && opts->ip6po_nexthop) { 585122077Sume struct route_in6 *ron; 586186119Sqingli struct llentry *la; 587186119Sqingli 588122077Sume sin6_next = satosin6(opts->ip6po_nexthop); 589186119Sqingli 590122077Sume /* at this moment, we only support AF_INET6 next hops */ 591122077Sume if (sin6_next->sin6_family != AF_INET6) { 592122077Sume error = EAFNOSUPPORT; /* or should we proceed? */ 593122077Sume goto done; 594122077Sume } 595122077Sume 596122077Sume /* 597122077Sume * If the next hop is an IPv6 address, then the node identified 598122077Sume * by that address must be a neighbor of the sending host. 599122077Sume */ 600122077Sume ron = &opts->ip6po_nextroute; 601186119Sqingli /* 602186119Sqingli * XXX what do we do here? 603186119Sqingli * PLZ to be fixing 604186119Sqingli */ 605186119Sqingli 606186119Sqingli 607186119Sqingli if (ron->ro_rt == NULL) { 608232292Sbz in6_rtalloc(ron, fibnum); /* multi path case? */ 609186119Sqingli if (ron->ro_rt == NULL) { 610186119Sqingli if (ron->ro_rt) { 611186119Sqingli RTFREE(ron->ro_rt); 612186119Sqingli ron->ro_rt = NULL; 613186119Sqingli } 614186119Sqingli error = EHOSTUNREACH; 615186119Sqingli goto done; 616186119Sqingli } 617186119Sqingli } 618186119Sqingli 619186119Sqingli rt = ron->ro_rt; 620186119Sqingli ifp = rt->rt_ifp; 621243382Sae IF_AFDATA_RLOCK(ifp); 622186119Sqingli la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6_next->sin6_addr); 623243382Sae IF_AFDATA_RUNLOCK(ifp); 624186158Skmacy if (la != NULL) 625186119Sqingli LLE_RUNLOCK(la); 626186119Sqingli else { 627186119Sqingli error = EHOSTUNREACH; 628186119Sqingli goto done; 629186119Sqingli } 630186119Sqingli#if 0 631122077Sume if ((ron->ro_rt && 632122077Sume (ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) != 633122077Sume (RTF_UP | RTF_LLINFO)) || 634151478Ssuz !IN6_ARE_ADDR_EQUAL(&satosin6(&ron->ro_dst)->sin6_addr, 635151478Ssuz &sin6_next->sin6_addr)) { 636122077Sume if (ron->ro_rt) { 637122077Sume RTFREE(ron->ro_rt); 638122077Sume ron->ro_rt = NULL; 63962587Sitojun } 640122077Sume *satosin6(&ron->ro_dst) = *sin6_next; 641122077Sume } 642122077Sume if (ron->ro_rt == NULL) { 643232292Sbz in6_rtalloc(ron, fibnum); /* multi path case? */ 644122077Sume if (ron->ro_rt == NULL || 645122077Sume !(ron->ro_rt->rt_flags & RTF_LLINFO)) { 646122077Sume if (ron->ro_rt) { 647122077Sume RTFREE(ron->ro_rt); 648122077Sume ron->ro_rt = NULL; 649122077Sume } 650122077Sume error = EHOSTUNREACH; 651122077Sume goto done; 65262587Sitojun } 65362587Sitojun } 654186119Sqingli#endif 655122077Sume 656122077Sume /* 657122077Sume * When cloning is required, try to allocate a route to the 658122077Sume * destination so that the caller can store path MTU 659122077Sume * information. 660122077Sume */ 661186119Sqingli goto done; 66262587Sitojun } 66362587Sitojun 66462587Sitojun /* 665122077Sume * Use a cached route if it exists and is valid, else try to allocate 666122077Sume * a new one. Note that we should check the address family of the 667122077Sume * cached destination, in case of sharing the cache with IPv4. 66862587Sitojun */ 66962587Sitojun if (ro) { 67062587Sitojun if (ro->ro_rt && 67189623Sume (!(ro->ro_rt->rt_flags & RTF_UP) || 672122077Sume ((struct sockaddr *)(&ro->ro_dst))->sa_family != AF_INET6 || 67389623Sume !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, 674125436Sume dst))) { 67562587Sitojun RTFREE(ro->ro_rt); 676122077Sume ro->ro_rt = (struct rtentry *)NULL; 67762587Sitojun } 678122077Sume if (ro->ro_rt == (struct rtentry *)NULL) { 67978064Sume struct sockaddr_in6 *sa6; 68078064Sume 68162587Sitojun /* No route yet, so try to acquire one */ 68262587Sitojun bzero(&ro->ro_dst, sizeof(struct sockaddr_in6)); 68378064Sume sa6 = (struct sockaddr_in6 *)&ro->ro_dst; 684122077Sume *sa6 = *dstsock; 685122122Sume sa6->sin6_scope_id = 0; 686122922Sandre 687178167Sqingli#ifdef RADIX_MPATH 688232292Sbz rtalloc_mpath_fib((struct route *)ro, 689232292Sbz ntohl(sa6->sin6_addr.s6_addr32[3]), fibnum); 690186119Sqingli#else 691232292Sbz ro->ro_rt = in6_rtalloc1((struct sockaddr *) 692232292Sbz &ro->ro_dst, 0, 0UL, fibnum); 693121445Ssam if (ro->ro_rt) 694121445Ssam RT_UNLOCK(ro->ro_rt); 695186119Sqingli#endif 69662587Sitojun } 697186119Sqingli 69862587Sitojun /* 699122077Sume * do not care about the result if we have the nexthop 700122077Sume * explicitly specified. 70162587Sitojun */ 702122077Sume if (opts && opts->ip6po_nexthop) 703122077Sume goto done; 70462587Sitojun 70562587Sitojun if (ro->ro_rt) { 706122077Sume ifp = ro->ro_rt->rt_ifp; 707122077Sume 708122077Sume if (ifp == NULL) { /* can this really happen? */ 709122077Sume RTFREE(ro->ro_rt); 710122077Sume ro->ro_rt = NULL; 711122077Sume } 71262587Sitojun } 713122077Sume if (ro->ro_rt == NULL) 714122077Sume error = EHOSTUNREACH; 715122077Sume rt = ro->ro_rt; 716122077Sume 717122077Sume /* 718122077Sume * Check if the outgoing interface conflicts with 719122077Sume * the interface specified by ipi6_ifindex (if specified). 720122077Sume * Note that loopback interface is always okay. 721122077Sume * (this may happen when we are sending a packet to one of 722122077Sume * our own addresses.) 723122077Sume */ 724146228Sgnn if (ifp && opts && opts->ip6po_pktinfo && 725125436Sume opts->ip6po_pktinfo->ipi6_ifindex) { 726122077Sume if (!(ifp->if_flags & IFF_LOOPBACK) && 727122077Sume ifp->if_index != 728122077Sume opts->ip6po_pktinfo->ipi6_ifindex) { 729122077Sume error = EHOSTUNREACH; 730122077Sume goto done; 731122077Sume } 73262587Sitojun } 73362587Sitojun } 73462587Sitojun 735122077Sume done: 736122077Sume if (ifp == NULL && rt == NULL) { 737122077Sume /* 738122077Sume * This can happen if the caller did not pass a cached route 739122077Sume * nor any other hints. We treat this case an error. 740122077Sume */ 741122077Sume error = EHOSTUNREACH; 742122077Sume } 743122077Sume if (error == EHOSTUNREACH) 744250044Sae IP6STAT_INC(ip6s_noroute); 745122077Sume 746196864Sqingli if (retifp != NULL) { 747122077Sume *retifp = ifp; 748196864Sqingli 749196864Sqingli /* 750196864Sqingli * Adjust the "outgoing" interface. If we're going to loop 751196864Sqingli * the packet back to ourselves, the ifp would be the loopback 752196864Sqingli * interface. However, we'd rather know the interface associated 753196864Sqingli * to the destination address (which should probably be one of 754196864Sqingli * our own addresses.) 755196864Sqingli */ 756196864Sqingli if (rt) { 757196864Sqingli if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) && 758196864Sqingli (rt->rt_gateway->sa_family == AF_LINK)) 759196864Sqingli *retifp = 760196864Sqingli ifnet_byindex(((struct sockaddr_dl *) 761196864Sqingli rt->rt_gateway)->sdl_index); 762196864Sqingli } 763196864Sqingli } 764196864Sqingli 765122077Sume if (retrt != NULL) 766122077Sume *retrt = rt; /* rt may be NULL */ 767122077Sume 768122077Sume return (error); 76962587Sitojun} 77062587Sitojun 771148385Sumestatic int 772171259Sdelphijin6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 773232292Sbz struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp, 774232292Sbz struct ifnet *oifp, u_int fibnum) 775148385Sume{ 776148385Sume int error; 777148385Sume struct route_in6 sro; 778148385Sume struct rtentry *rt = NULL; 779148385Sume 780232292Sbz KASSERT(retifp != NULL, ("%s: retifp is NULL", __func__)); 781232292Sbz 782148385Sume if (ro == NULL) { 783148385Sume bzero(&sro, sizeof(sro)); 784148385Sume ro = &sro; 785148385Sume } 786148385Sume 787148385Sume if ((error = selectroute(dstsock, opts, mopts, ro, retifp, 788232292Sbz &rt, 1, fibnum)) != 0) { 789158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 790148385Sume RTFREE(rt); 791232292Sbz /* Help ND. See oifp comment in in6_selectsrc(). */ 792232292Sbz if (oifp != NULL && fibnum == RT_DEFAULT_FIB) { 793232292Sbz *retifp = oifp; 794232292Sbz error = 0; 795232292Sbz } 796148385Sume return (error); 797148385Sume } 798148385Sume 799148385Sume /* 800148385Sume * do not use a rejected or black hole route. 801148385Sume * XXX: this check should be done in the L2 output routine. 802148385Sume * However, if we skipped this check here, we'd see the following 803148385Sume * scenario: 804148385Sume * - install a rejected route for a scoped address prefix 805148385Sume * (like fe80::/10) 806148385Sume * - send a packet to a destination that matches the scoped prefix, 807148385Sume * with ambiguity about the scope zone. 808148385Sume * - pick the outgoing interface from the route, and disambiguate the 809148385Sume * scope zone with the interface. 810148385Sume * - ip6_output() would try to get another route with the "new" 811148385Sume * destination, which may be valid. 812148385Sume * - we'd see no error on output. 813148385Sume * Although this may not be very harmful, it should still be confusing. 814148385Sume * We thus reject the case here. 815148385Sume */ 816148385Sume if (rt && (rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE))) { 817148385Sume int flags = (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 818148385Sume 819158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 820148385Sume RTFREE(rt); 821148385Sume return (flags); 822148385Sume } 823148385Sume 824158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 825148385Sume RTFREE(rt); 826148385Sume return (0); 827148385Sume} 828148385Sume 829171259Sdelphij/* 830232292Sbz * Public wrapper function to selectroute(). 831232292Sbz * 832232292Sbz * XXX-BZ in6_selectroute() should and will grow the FIB argument. The 833232292Sbz * in6_selectroute_fib() function is only there for backward compat on stable. 834171259Sdelphij */ 835148385Sumeint 836171259Sdelphijin6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 837171259Sdelphij struct ip6_moptions *mopts, struct route_in6 *ro, 838186119Sqingli struct ifnet **retifp, struct rtentry **retrt) 839148385Sume{ 840171259Sdelphij 841148385Sume return (selectroute(dstsock, opts, mopts, ro, retifp, 842232292Sbz retrt, 0, RT_DEFAULT_FIB)); 843148385Sume} 844148385Sume 845232292Sbz#ifndef BURN_BRIDGES 846232292Sbzint 847232292Sbzin6_selectroute_fib(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 848232292Sbz struct ip6_moptions *mopts, struct route_in6 *ro, 849232292Sbz struct ifnet **retifp, struct rtentry **retrt, u_int fibnum) 850232292Sbz{ 851232292Sbz 852232292Sbz return (selectroute(dstsock, opts, mopts, ro, retifp, 853232292Sbz retrt, 0, fibnum)); 854232292Sbz} 855232292Sbz#endif 856232292Sbz 85762587Sitojun/* 85862587Sitojun * Default hop limit selection. The precedence is as follows: 85962587Sitojun * 1. Hoplimit value specified via ioctl. 86062587Sitojun * 2. (If the outgoing interface is detected) the current 86162587Sitojun * hop limit of the interface specified by router advertisement. 86262587Sitojun * 3. The system default hoplimit. 863122922Sandre */ 86462587Sitojunint 865186141Sbzin6_selecthlim(struct inpcb *in6p, struct ifnet *ifp) 86662587Sitojun{ 867171259Sdelphij 86862587Sitojun if (in6p && in6p->in6p_hops >= 0) 869120856Sume return (in6p->in6p_hops); 87062587Sitojun else if (ifp) 871121161Sume return (ND_IFINFO(ifp)->chlim); 872122922Sandre else if (in6p && !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 873122922Sandre struct route_in6 ro6; 874122922Sandre struct ifnet *lifp; 875122922Sandre 876122922Sandre bzero(&ro6, sizeof(ro6)); 877122922Sandre ro6.ro_dst.sin6_family = AF_INET6; 878122922Sandre ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6); 879122922Sandre ro6.ro_dst.sin6_addr = in6p->in6p_faddr; 880232292Sbz in6_rtalloc(&ro6, in6p->inp_inc.inc_fibnum); 881122922Sandre if (ro6.ro_rt) { 882122922Sandre lifp = ro6.ro_rt->rt_ifp; 883122922Sandre RTFREE(ro6.ro_rt); 884122922Sandre if (lifp) 885122922Sandre return (ND_IFINFO(lifp)->chlim); 886238232Sbz } 887122922Sandre } 888181803Sbz return (V_ip6_defhlim); 88962587Sitojun} 89062587Sitojun 89162587Sitojun/* 89262587Sitojun * XXX: this is borrowed from in6_pcbbind(). If possible, we should 89362587Sitojun * share this function by all *bsd*... 89462587Sitojun */ 89562587Sitojunint 896171259Sdelphijin6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred) 89762587Sitojun{ 89862587Sitojun struct socket *so = inp->inp_socket; 899219579Sbz u_int16_t lport = 0; 900222215Srwatson int error, lookupflags = 0; 901219579Sbz#ifdef INVARIANTS 90262587Sitojun struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 903219579Sbz#endif 90462587Sitojun 905178285Srwatson INP_WLOCK_ASSERT(inp); 906222488Srwatson INP_HASH_WLOCK_ASSERT(pcbinfo); 907158011Srwatson 908188144Sjamie error = prison_local_ip6(cred, laddr, 909188144Sjamie ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)); 910188144Sjamie if (error) 911188144Sjamie return(error); 912185435Sbz 91362587Sitojun /* XXX: this is redundant when called from in6_pcbbind */ 91462587Sitojun if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) 915222215Srwatson lookupflags = INPLOOKUP_WILDCARD; 91662587Sitojun 91762587Sitojun inp->inp_flags |= INP_ANONPORT; 91862587Sitojun 919222215Srwatson error = in_pcb_lport(inp, NULL, &lport, cred, lookupflags); 920219579Sbz if (error != 0) 921219579Sbz return (error); 922184096Sbz 92362587Sitojun inp->inp_lport = lport; 92462587Sitojun if (in_pcbinshash(inp) != 0) { 92562587Sitojun inp->in6p_laddr = in6addr_any; 92662587Sitojun inp->inp_lport = 0; 92762587Sitojun return (EAGAIN); 92862587Sitojun } 92962587Sitojun 930120856Sume return (0); 93162587Sitojun} 93262587Sitojun 93378064Sumevoid 934171259Sdelphijaddrsel_policy_init(void) 935121742Sume{ 936121742Sume 937121742Sume init_policy_queue(); 938121742Sume 939121742Sume /* initialize the "last resort" policy */ 940181803Sbz bzero(&V_defaultaddrpolicy, sizeof(V_defaultaddrpolicy)); 941181803Sbz V_defaultaddrpolicy.label = ADDR_LABEL_NOTAPP; 942190787Szec 943190787Szec if (!IS_DEFAULT_VNET(curvnet)) 944190787Szec return; 945190787Szec 946190787Szec ADDRSEL_LOCK_INIT(); 947190787Szec ADDRSEL_SXLOCK_INIT(); 948121742Sume} 949121742Sume 950122077Sumestatic struct in6_addrpolicy * 951171259Sdelphijlookup_addrsel_policy(struct sockaddr_in6 *key) 952122077Sume{ 953122077Sume struct in6_addrpolicy *match = NULL; 954122077Sume 955122077Sume ADDRSEL_LOCK(); 956122077Sume match = match_addrsel_policy(key); 957122077Sume 958122077Sume if (match == NULL) 959181803Sbz match = &V_defaultaddrpolicy; 960122077Sume else 961122077Sume match->use++; 962122077Sume ADDRSEL_UNLOCK(); 963122077Sume 964122077Sume return (match); 965122077Sume} 966122077Sume 967121742Sume/* 968121742Sume * Subroutines to manage the address selection policy table via sysctl. 969121742Sume */ 970121742Sumestruct walkarg { 971121742Sume struct sysctl_req *w_req; 972121742Sume}; 973121742Sume 974121742Sumestatic int in6_src_sysctl(SYSCTL_HANDLER_ARGS); 975121742SumeSYSCTL_DECL(_net_inet6_ip6); 976248085Smariusstatic SYSCTL_NODE(_net_inet6_ip6, IPV6CTL_ADDRCTLPOLICY, addrctlpolicy, 977121742Sume CTLFLAG_RD, in6_src_sysctl, ""); 978121742Sume 979121742Sumestatic int 980121742Sumein6_src_sysctl(SYSCTL_HANDLER_ARGS) 981121742Sume{ 982121742Sume struct walkarg w; 983121742Sume 984121742Sume if (req->newptr) 985121742Sume return EPERM; 986121742Sume 987121742Sume bzero(&w, sizeof(w)); 988121742Sume w.w_req = req; 989121742Sume 990121742Sume return (walk_addrsel_policy(dump_addrsel_policyent, &w)); 991121742Sume} 992121742Sume 993121742Sumeint 994171259Sdelphijin6_src_ioctl(u_long cmd, caddr_t data) 995121742Sume{ 996121742Sume int i; 997121742Sume struct in6_addrpolicy ent0; 998121742Sume 999121742Sume if (cmd != SIOCAADDRCTL_POLICY && cmd != SIOCDADDRCTL_POLICY) 1000121742Sume return (EOPNOTSUPP); /* check for safety */ 1001121742Sume 1002121742Sume ent0 = *(struct in6_addrpolicy *)data; 1003121742Sume 1004121742Sume if (ent0.label == ADDR_LABEL_NOTAPP) 1005121742Sume return (EINVAL); 1006121742Sume /* check if the prefix mask is consecutive. */ 1007121742Sume if (in6_mask2len(&ent0.addrmask.sin6_addr, NULL) < 0) 1008121742Sume return (EINVAL); 1009121742Sume /* clear trailing garbages (if any) of the prefix address. */ 1010121742Sume for (i = 0; i < 4; i++) { 1011121742Sume ent0.addr.sin6_addr.s6_addr32[i] &= 1012121742Sume ent0.addrmask.sin6_addr.s6_addr32[i]; 1013121742Sume } 1014121742Sume ent0.use = 0; 1015121742Sume 1016121742Sume switch (cmd) { 1017121742Sume case SIOCAADDRCTL_POLICY: 1018121742Sume return (add_addrsel_policyent(&ent0)); 1019121742Sume case SIOCDADDRCTL_POLICY: 1020121742Sume return (delete_addrsel_policyent(&ent0)); 1021121742Sume } 1022121742Sume 1023121742Sume return (0); /* XXX: compromise compilers */ 1024121742Sume} 1025121742Sume 1026121742Sume/* 1027121742Sume * The followings are implementation of the policy table using a 1028121742Sume * simple tail queue. 1029121742Sume * XXX such details should be hidden. 1030121742Sume * XXX implementation using binary tree should be more efficient. 1031121742Sume */ 1032121742Sumestruct addrsel_policyent { 1033121742Sume TAILQ_ENTRY(addrsel_policyent) ape_entry; 1034121742Sume struct in6_addrpolicy ape_policy; 1035121742Sume}; 1036121742Sume 1037121742SumeTAILQ_HEAD(addrsel_policyhead, addrsel_policyent); 1038121742Sume 1039215701Sdimstatic VNET_DEFINE(struct addrsel_policyhead, addrsel_policytab); 1040195727Srwatson#define V_addrsel_policytab VNET(addrsel_policytab) 1041121742Sume 1042121742Sumestatic void 1043171259Sdelphijinit_policy_queue(void) 1044121742Sume{ 1045171259Sdelphij 1046181803Sbz TAILQ_INIT(&V_addrsel_policytab); 1047121742Sume} 1048121742Sume 1049121742Sumestatic int 1050171259Sdelphijadd_addrsel_policyent(struct in6_addrpolicy *newpolicy) 1051121742Sume{ 1052121742Sume struct addrsel_policyent *new, *pol; 1053121742Sume 1054184205Sdes new = malloc(sizeof(*new), M_IFADDR, 1055121750Sume M_WAITOK); 1056149200Sume ADDRSEL_XLOCK(); 1057121742Sume ADDRSEL_LOCK(); 1058121742Sume 1059121742Sume /* duplication check */ 1060181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1061151478Ssuz if (IN6_ARE_ADDR_EQUAL(&newpolicy->addr.sin6_addr, 1062151478Ssuz &pol->ape_policy.addr.sin6_addr) && 1063151478Ssuz IN6_ARE_ADDR_EQUAL(&newpolicy->addrmask.sin6_addr, 1064151478Ssuz &pol->ape_policy.addrmask.sin6_addr)) { 1065121750Sume ADDRSEL_UNLOCK(); 1066149200Sume ADDRSEL_XUNLOCK(); 1067184205Sdes free(new, M_IFADDR); 1068121742Sume return (EEXIST); /* or override it? */ 1069121742Sume } 1070121742Sume } 1071121742Sume 1072121742Sume bzero(new, sizeof(*new)); 1073121742Sume 1074121742Sume /* XXX: should validate entry */ 1075121742Sume new->ape_policy = *newpolicy; 1076121742Sume 1077181803Sbz TAILQ_INSERT_TAIL(&V_addrsel_policytab, new, ape_entry); 1078121742Sume ADDRSEL_UNLOCK(); 1079149200Sume ADDRSEL_XUNLOCK(); 1080121742Sume 1081121742Sume return (0); 1082121742Sume} 1083121742Sume 1084121742Sumestatic int 1085171259Sdelphijdelete_addrsel_policyent(struct in6_addrpolicy *key) 1086121742Sume{ 1087121742Sume struct addrsel_policyent *pol; 1088121742Sume 1089149200Sume ADDRSEL_XLOCK(); 1090121742Sume ADDRSEL_LOCK(); 1091121742Sume 1092121742Sume /* search for the entry in the table */ 1093181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1094151478Ssuz if (IN6_ARE_ADDR_EQUAL(&key->addr.sin6_addr, 1095151478Ssuz &pol->ape_policy.addr.sin6_addr) && 1096151478Ssuz IN6_ARE_ADDR_EQUAL(&key->addrmask.sin6_addr, 1097151478Ssuz &pol->ape_policy.addrmask.sin6_addr)) { 1098121742Sume break; 1099121742Sume } 1100121742Sume } 1101121750Sume if (pol == NULL) { 1102121750Sume ADDRSEL_UNLOCK(); 1103149200Sume ADDRSEL_XUNLOCK(); 1104121742Sume return (ESRCH); 1105121750Sume } 1106121742Sume 1107181803Sbz TAILQ_REMOVE(&V_addrsel_policytab, pol, ape_entry); 1108121742Sume ADDRSEL_UNLOCK(); 1109149200Sume ADDRSEL_XUNLOCK(); 1110249760Sae free(pol, M_IFADDR); 1111121742Sume 1112121742Sume return (0); 1113121742Sume} 1114121742Sume 1115121742Sumestatic int 1116175162Sobrienwalk_addrsel_policy(int (*callback)(struct in6_addrpolicy *, void *), 1117171259Sdelphij void *w) 1118121742Sume{ 1119121742Sume struct addrsel_policyent *pol; 1120121742Sume int error = 0; 1121121742Sume 1122149200Sume ADDRSEL_SLOCK(); 1123181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1124149200Sume if ((error = (*callback)(&pol->ape_policy, w)) != 0) { 1125149200Sume ADDRSEL_SUNLOCK(); 1126121742Sume return (error); 1127149200Sume } 1128121742Sume } 1129149200Sume ADDRSEL_SUNLOCK(); 1130121742Sume return (error); 1131121742Sume} 1132121742Sume 1133121742Sumestatic int 1134171259Sdelphijdump_addrsel_policyent(struct in6_addrpolicy *pol, void *arg) 1135121742Sume{ 1136121742Sume int error = 0; 1137121742Sume struct walkarg *w = arg; 1138121742Sume 1139121742Sume error = SYSCTL_OUT(w->w_req, pol, sizeof(*pol)); 1140121742Sume 1141121742Sume return (error); 1142121742Sume} 1143122077Sume 1144122077Sumestatic struct in6_addrpolicy * 1145171259Sdelphijmatch_addrsel_policy(struct sockaddr_in6 *key) 1146122077Sume{ 1147122077Sume struct addrsel_policyent *pent; 1148122077Sume struct in6_addrpolicy *bestpol = NULL, *pol; 1149122077Sume int matchlen, bestmatchlen = -1; 1150122077Sume u_char *mp, *ep, *k, *p, m; 1151122077Sume 1152181803Sbz TAILQ_FOREACH(pent, &V_addrsel_policytab, ape_entry) { 1153122077Sume matchlen = 0; 1154122077Sume 1155122077Sume pol = &pent->ape_policy; 1156122077Sume mp = (u_char *)&pol->addrmask.sin6_addr; 1157122077Sume ep = mp + 16; /* XXX: scope field? */ 1158122077Sume k = (u_char *)&key->sin6_addr; 1159122077Sume p = (u_char *)&pol->addr.sin6_addr; 1160122077Sume for (; mp < ep && *mp; mp++, k++, p++) { 1161122077Sume m = *mp; 1162122077Sume if ((*k & m) != *p) 1163122077Sume goto next; /* not match */ 1164122077Sume if (m == 0xff) /* short cut for a typical case */ 1165122077Sume matchlen += 8; 1166122077Sume else { 1167122077Sume while (m >= 0x80) { 1168122077Sume matchlen++; 1169122077Sume m <<= 1; 1170122077Sume } 1171122077Sume } 1172122077Sume } 1173122077Sume 1174122077Sume /* matched. check if this is better than the current best. */ 1175122077Sume if (bestpol == NULL || 1176122077Sume matchlen > bestmatchlen) { 1177122077Sume bestpol = pol; 1178122077Sume bestmatchlen = matchlen; 1179122077Sume } 1180122077Sume 1181122077Sume next: 1182122077Sume continue; 1183122077Sume } 1184122077Sume 1185122077Sume return (bestpol); 1186122077Sume} 1187