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 130241916Sdelphijstatic int selectroute(struct sockaddr_in6 *, struct ip6_pktopts *, 131148385Sume struct ip6_moptions *, struct route_in6 *, struct ifnet **, 132241916Sdelphij struct rtentry **, int, u_int); 133241916Sdelphijstatic int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *, 134231852Sbz struct ip6_moptions *, struct route_in6 *ro, struct ifnet **, 135241916Sdelphij 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 *); 142241916Sdelphijstatic int walk_addrsel_policy(int (*)(struct in6_addrpolicy *, void *), 143242938Sobrien 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 {\ 154249546Sae IP6STAT_INC(ip6s_sources_rule[(r)]); \ 155249528Sae 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 { \ 170249546Sae IP6STAT_INC(ip6s_sources_rule[(r)]); \ 171249528Sae 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; 181231852Sbz 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; 188249528Sae 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 */ 194231852Sbz if (ifpp) { 195231852Sbz /* 196231852Sbz * Save a possibly passed in ifp for in6_selectsrc. Only 197231852Sbz * neighbor discovery code should use this feature, where 198231852Sbz * we may know the interface but not the FIB number holding 199231852Sbz * the connected subnet in case someone deleted it from the 200231852Sbz * default FIB and we need to check the interface. 201231852Sbz */ 202231852Sbz if (*ifpp != NULL) 203231852Sbz oifp = *ifpp; 204148385Sume *ifpp = NULL; 205231852Sbz } 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 */ 226231852Sbz if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp, oifp, 227231852Sbz (inp != NULL) ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB)) 228231852Sbz != 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 */ 292231852Sbz if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp, oifp, 293231852Sbz (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 304249528Sae 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 */ 382245230Sume if (!(ND_IFINFO(ifp)->flags & ND6_IFF_NO_PREFER_IFACE)) { 383245230Sume if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp) 384245230Sume NEXT(5); 385245230Sume if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp) 386245230Sume REPLACE(5); 387245230Sume } 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 /* 446269944Sae * Rule 9: prefer address with better virtual status. 447269944Sae */ 448269944Sae if (ifa_preferred(&ia_best->ia_ifa, &ia->ia_ifa)) 449269944Sae REPLACE(9); 450271288Sae if (ifa_preferred(&ia->ia_ifa, &ia_best->ia_ifa)) 451271288Sae NEXT(9); 452269944Sae 453269944Sae /* 454122077Sume * Rule 14: Use longest matching prefix. 455122077Sume * Note: in the address selection draft, this rule is 456122077Sume * documented as "Rule 8". However, since it is also 457122077Sume * documented that this rule can be overridden, we assign 458122077Sume * a large number so that it is easy to assign smaller numbers 459122077Sume * to more preferred rules. 460122077Sume */ 461148385Sume new_matchlen = in6_matchlen(&ia->ia_addr.sin6_addr, &dst); 462122077Sume if (best_matchlen < new_matchlen) 463122077Sume REPLACE(14); 464122077Sume if (new_matchlen < best_matchlen) 465122077Sume NEXT(14); 466122077Sume 467122077Sume /* Rule 15 is reserved. */ 468122077Sume 469122077Sume /* 470122077Sume * Last resort: just keep the current candidate. 471122077Sume * Or, do we need more rules? 472122077Sume */ 473122077Sume continue; 474122077Sume 475122077Sume replace: 476122077Sume ia_best = ia; 477122077Sume best_scope = (new_scope >= 0 ? new_scope : 478122077Sume in6_addrscope(&ia_best->ia_addr.sin6_addr)); 479122077Sume best_policy = (new_policy ? new_policy : 480122077Sume lookup_addrsel_policy(&ia_best->ia_addr)); 481122077Sume best_matchlen = (new_matchlen >= 0 ? new_matchlen : 482122077Sume in6_matchlen(&ia_best->ia_addr.sin6_addr, 483148385Sume &dst)); 484122077Sume 485122077Sume next: 486122077Sume continue; 487122077Sume 488122077Sume out: 489122077Sume break; 49062587Sitojun } 49162587Sitojun 492194971Srwatson if ((ia = ia_best) == NULL) { 493194971Srwatson IN6_IFADDR_RUNLOCK(); 494249528Sae IP6STAT_INC(ip6s_sources_none); 495194777Sbz return (EADDRNOTAVAIL); 496194971Srwatson } 497122077Sume 498207276Sbz /* 499207276Sbz * At this point at least one of the addresses belonged to the jail 500207276Sbz * but it could still be, that we want to further restrict it, e.g. 501207276Sbz * theoratically IN6_IS_ADDR_LOOPBACK. 502207276Sbz * It must not be IN6_IS_ADDR_UNSPECIFIED anymore. 503207276Sbz * prison_local_ip6() will fix an IN6_IS_ADDR_LOOPBACK but should 504207276Sbz * let all others previously selected pass. 505207276Sbz * Use tmp to not change ::1 on lo0 to the primary jail address. 506207276Sbz */ 507207276Sbz tmp = ia->ia_addr.sin6_addr; 508207276Sbz if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL && 509207276Sbz (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { 510207276Sbz IN6_IFADDR_RUNLOCK(); 511249528Sae IP6STAT_INC(ip6s_sources_none); 512207276Sbz return (EADDRNOTAVAIL); 513207276Sbz } 514207276Sbz 515148385Sume if (ifpp) 516148385Sume *ifpp = ifp; 517148385Sume 518207276Sbz bcopy(&tmp, srcp, sizeof(*srcp)); 519249546Sae if (ia->ia_ifp == ifp) 520249546Sae IP6STAT_INC(ip6s_sources_sameif[best_scope]); 521249546Sae else 522249546Sae IP6STAT_INC(ip6s_sources_otherif[best_scope]); 523249546Sae if (dst_scope == best_scope) 524249546Sae IP6STAT_INC(ip6s_sources_samescope[best_scope]); 525249546Sae else 526249546Sae IP6STAT_INC(ip6s_sources_otherscope[best_scope]); 527249546Sae if (IFA6_IS_DEPRECATED(ia)) 528249546Sae IP6STAT_INC(ip6s_sources_deprecated[best_scope]); 529194971Srwatson IN6_IFADDR_RUNLOCK(); 530194777Sbz return (0); 531122077Sume} 532122077Sume 533171259Sdelphij/* 534171259Sdelphij * clone - meaningful only for bsdi and freebsd 535171259Sdelphij */ 536122077Sumestatic int 537171259Sdelphijselectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 538171259Sdelphij struct ip6_moptions *mopts, struct route_in6 *ro, 539232127Sbz struct ifnet **retifp, struct rtentry **retrt, int norouteok, u_int fibnum) 540122077Sume{ 541122077Sume int error = 0; 542122077Sume struct ifnet *ifp = NULL; 543122077Sume struct rtentry *rt = NULL; 544122077Sume struct sockaddr_in6 *sin6_next; 545122077Sume struct in6_pktinfo *pi = NULL; 546122077Sume struct in6_addr *dst = &dstsock->sin6_addr; 547165118Sbz#if 0 548165118Sbz char ip6buf[INET6_ADDRSTRLEN]; 549122077Sume 550122077Sume if (dstsock->sin6_addr.s6_addr32[0] == 0 && 551122077Sume dstsock->sin6_addr.s6_addr32[1] == 0 && 552122077Sume !IN6_IS_ADDR_LOOPBACK(&dstsock->sin6_addr)) { 553122077Sume printf("in6_selectroute: strange destination %s\n", 554165118Sbz ip6_sprintf(ip6buf, &dstsock->sin6_addr)); 555122077Sume } else { 556122077Sume printf("in6_selectroute: destination = %s%%%d\n", 557165118Sbz ip6_sprintf(ip6buf, &dstsock->sin6_addr), 558122077Sume dstsock->sin6_scope_id); /* for debug */ 559122077Sume } 560122077Sume#endif 561122077Sume 562122077Sume /* If the caller specify the outgoing interface explicitly, use it. */ 563122077Sume if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) { 564122077Sume /* XXX boundary check is assumed to be already done. */ 565122077Sume ifp = ifnet_byindex(pi->ipi6_ifindex); 566122077Sume if (ifp != NULL && 567148385Sume (norouteok || retrt == NULL || 568148385Sume IN6_IS_ADDR_MULTICAST(dst))) { 569122077Sume /* 570148987Sume * we do not have to check or get the route for 571122077Sume * multicast. 572122077Sume */ 573122077Sume goto done; 574122077Sume } else 575122077Sume goto getroute; 576122077Sume } 577122077Sume 578122077Sume /* 579122077Sume * If the destination address is a multicast address and the outgoing 580122077Sume * interface for the address is specified by the caller, use it. 581122077Sume */ 582122077Sume if (IN6_IS_ADDR_MULTICAST(dst) && 583122077Sume mopts != NULL && (ifp = mopts->im6o_multicast_ifp) != NULL) { 584122077Sume goto done; /* we do not need a route for multicast. */ 585122077Sume } 586122077Sume 587122077Sume getroute: 588122077Sume /* 589122077Sume * If the next hop address for the packet is specified by the caller, 590122077Sume * use it as the gateway. 591122077Sume */ 592122077Sume if (opts && opts->ip6po_nexthop) { 593122077Sume struct route_in6 *ron; 594186119Sqingli struct llentry *la; 595186119Sqingli 596122077Sume sin6_next = satosin6(opts->ip6po_nexthop); 597186119Sqingli 598122077Sume /* at this moment, we only support AF_INET6 next hops */ 599122077Sume if (sin6_next->sin6_family != AF_INET6) { 600122077Sume error = EAFNOSUPPORT; /* or should we proceed? */ 601122077Sume goto done; 602122077Sume } 603122077Sume 604122077Sume /* 605122077Sume * If the next hop is an IPv6 address, then the node identified 606122077Sume * by that address must be a neighbor of the sending host. 607122077Sume */ 608122077Sume ron = &opts->ip6po_nextroute; 609186119Sqingli /* 610186119Sqingli * XXX what do we do here? 611186119Sqingli * PLZ to be fixing 612186119Sqingli */ 613186119Sqingli 614186119Sqingli 615186119Sqingli if (ron->ro_rt == NULL) { 616231852Sbz in6_rtalloc(ron, fibnum); /* multi path case? */ 617186119Sqingli if (ron->ro_rt == NULL) { 618237459Sbz /* XXX-BZ WT.? */ 619186119Sqingli if (ron->ro_rt) { 620186119Sqingli RTFREE(ron->ro_rt); 621186119Sqingli ron->ro_rt = NULL; 622186119Sqingli } 623186119Sqingli error = EHOSTUNREACH; 624186119Sqingli goto done; 625186119Sqingli } 626186119Sqingli } 627186119Sqingli 628186119Sqingli rt = ron->ro_rt; 629186119Sqingli ifp = rt->rt_ifp; 630243148Sae IF_AFDATA_RLOCK(ifp); 631186119Sqingli la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6_next->sin6_addr); 632243148Sae IF_AFDATA_RUNLOCK(ifp); 633186158Skmacy if (la != NULL) 634186119Sqingli LLE_RUNLOCK(la); 635186119Sqingli else { 636186119Sqingli error = EHOSTUNREACH; 637186119Sqingli goto done; 638186119Sqingli } 639186119Sqingli#if 0 640122077Sume if ((ron->ro_rt && 641122077Sume (ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) != 642122077Sume (RTF_UP | RTF_LLINFO)) || 643151478Ssuz !IN6_ARE_ADDR_EQUAL(&satosin6(&ron->ro_dst)->sin6_addr, 644151478Ssuz &sin6_next->sin6_addr)) { 645122077Sume if (ron->ro_rt) { 646122077Sume RTFREE(ron->ro_rt); 647122077Sume ron->ro_rt = NULL; 64862587Sitojun } 649122077Sume *satosin6(&ron->ro_dst) = *sin6_next; 650122077Sume } 651122077Sume if (ron->ro_rt == NULL) { 652232127Sbz in6_rtalloc(ron, fibnum); /* multi path case? */ 653122077Sume if (ron->ro_rt == NULL || 654122077Sume !(ron->ro_rt->rt_flags & RTF_LLINFO)) { 655122077Sume if (ron->ro_rt) { 656122077Sume RTFREE(ron->ro_rt); 657122077Sume ron->ro_rt = NULL; 658122077Sume } 659122077Sume error = EHOSTUNREACH; 660122077Sume goto done; 66162587Sitojun } 66262587Sitojun } 663186119Sqingli#endif 664122077Sume 665122077Sume /* 666122077Sume * When cloning is required, try to allocate a route to the 667122077Sume * destination so that the caller can store path MTU 668122077Sume * information. 669122077Sume */ 670186119Sqingli goto done; 67162587Sitojun } 67262587Sitojun 67362587Sitojun /* 674122077Sume * Use a cached route if it exists and is valid, else try to allocate 675122077Sume * a new one. Note that we should check the address family of the 676122077Sume * cached destination, in case of sharing the cache with IPv4. 67762587Sitojun */ 67862587Sitojun if (ro) { 67962587Sitojun if (ro->ro_rt && 68089623Sume (!(ro->ro_rt->rt_flags & RTF_UP) || 681122077Sume ((struct sockaddr *)(&ro->ro_dst))->sa_family != AF_INET6 || 68289623Sume !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, 683125436Sume dst))) { 68462587Sitojun RTFREE(ro->ro_rt); 685122077Sume ro->ro_rt = (struct rtentry *)NULL; 68662587Sitojun } 687122077Sume if (ro->ro_rt == (struct rtentry *)NULL) { 68878064Sume struct sockaddr_in6 *sa6; 68978064Sume 69062587Sitojun /* No route yet, so try to acquire one */ 69162587Sitojun bzero(&ro->ro_dst, sizeof(struct sockaddr_in6)); 69278064Sume sa6 = (struct sockaddr_in6 *)&ro->ro_dst; 693122077Sume *sa6 = *dstsock; 694122122Sume sa6->sin6_scope_id = 0; 695122922Sandre 696178167Sqingli#ifdef RADIX_MPATH 697231852Sbz rtalloc_mpath_fib((struct route *)ro, 698231852Sbz ntohl(sa6->sin6_addr.s6_addr32[3]), fibnum); 699186119Sqingli#else 700231852Sbz ro->ro_rt = in6_rtalloc1((struct sockaddr *) 701231852Sbz &ro->ro_dst, 0, 0UL, fibnum); 702121445Ssam if (ro->ro_rt) 703121445Ssam RT_UNLOCK(ro->ro_rt); 704186119Sqingli#endif 70562587Sitojun } 706186119Sqingli 70762587Sitojun /* 708122077Sume * do not care about the result if we have the nexthop 709122077Sume * explicitly specified. 71062587Sitojun */ 711122077Sume if (opts && opts->ip6po_nexthop) 712122077Sume goto done; 71362587Sitojun 71462587Sitojun if (ro->ro_rt) { 715122077Sume ifp = ro->ro_rt->rt_ifp; 716122077Sume 717122077Sume if (ifp == NULL) { /* can this really happen? */ 718122077Sume RTFREE(ro->ro_rt); 719122077Sume ro->ro_rt = NULL; 720122077Sume } 72162587Sitojun } 722122077Sume if (ro->ro_rt == NULL) 723122077Sume error = EHOSTUNREACH; 724122077Sume rt = ro->ro_rt; 725122077Sume 726122077Sume /* 727122077Sume * Check if the outgoing interface conflicts with 728122077Sume * the interface specified by ipi6_ifindex (if specified). 729122077Sume * Note that loopback interface is always okay. 730122077Sume * (this may happen when we are sending a packet to one of 731122077Sume * our own addresses.) 732122077Sume */ 733146228Sgnn if (ifp && opts && opts->ip6po_pktinfo && 734125436Sume opts->ip6po_pktinfo->ipi6_ifindex) { 735122077Sume if (!(ifp->if_flags & IFF_LOOPBACK) && 736122077Sume ifp->if_index != 737122077Sume opts->ip6po_pktinfo->ipi6_ifindex) { 738122077Sume error = EHOSTUNREACH; 739122077Sume goto done; 740122077Sume } 74162587Sitojun } 74262587Sitojun } 74362587Sitojun 744122077Sume done: 745122077Sume if (ifp == NULL && rt == NULL) { 746122077Sume /* 747122077Sume * This can happen if the caller did not pass a cached route 748122077Sume * nor any other hints. We treat this case an error. 749122077Sume */ 750122077Sume error = EHOSTUNREACH; 751122077Sume } 752122077Sume if (error == EHOSTUNREACH) 753249294Sae IP6STAT_INC(ip6s_noroute); 754122077Sume 755196864Sqingli if (retifp != NULL) { 756122077Sume *retifp = ifp; 757196864Sqingli 758196864Sqingli /* 759196864Sqingli * Adjust the "outgoing" interface. If we're going to loop 760196864Sqingli * the packet back to ourselves, the ifp would be the loopback 761196864Sqingli * interface. However, we'd rather know the interface associated 762196864Sqingli * to the destination address (which should probably be one of 763196864Sqingli * our own addresses.) 764196864Sqingli */ 765196864Sqingli if (rt) { 766196864Sqingli if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) && 767196864Sqingli (rt->rt_gateway->sa_family == AF_LINK)) 768196864Sqingli *retifp = 769196864Sqingli ifnet_byindex(((struct sockaddr_dl *) 770196864Sqingli rt->rt_gateway)->sdl_index); 771196864Sqingli } 772196864Sqingli } 773196864Sqingli 774122077Sume if (retrt != NULL) 775122077Sume *retrt = rt; /* rt may be NULL */ 776122077Sume 777122077Sume return (error); 77862587Sitojun} 77962587Sitojun 780148385Sumestatic int 781171259Sdelphijin6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 782231852Sbz struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp, 783232127Sbz struct ifnet *oifp, u_int fibnum) 784148385Sume{ 785148385Sume int error; 786148385Sume struct route_in6 sro; 787148385Sume struct rtentry *rt = NULL; 788148385Sume 789231852Sbz KASSERT(retifp != NULL, ("%s: retifp is NULL", __func__)); 790231852Sbz 791148385Sume if (ro == NULL) { 792148385Sume bzero(&sro, sizeof(sro)); 793148385Sume ro = &sro; 794148385Sume } 795148385Sume 796148385Sume if ((error = selectroute(dstsock, opts, mopts, ro, retifp, 797231852Sbz &rt, 1, fibnum)) != 0) { 798158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 799148385Sume RTFREE(rt); 800231852Sbz /* Help ND. See oifp comment in in6_selectsrc(). */ 801231852Sbz if (oifp != NULL && fibnum == RT_DEFAULT_FIB) { 802231852Sbz *retifp = oifp; 803231852Sbz error = 0; 804231852Sbz } 805148385Sume return (error); 806148385Sume } 807148385Sume 808148385Sume /* 809148385Sume * do not use a rejected or black hole route. 810148385Sume * XXX: this check should be done in the L2 output routine. 811148385Sume * However, if we skipped this check here, we'd see the following 812148385Sume * scenario: 813148385Sume * - install a rejected route for a scoped address prefix 814148385Sume * (like fe80::/10) 815148385Sume * - send a packet to a destination that matches the scoped prefix, 816148385Sume * with ambiguity about the scope zone. 817148385Sume * - pick the outgoing interface from the route, and disambiguate the 818148385Sume * scope zone with the interface. 819148385Sume * - ip6_output() would try to get another route with the "new" 820148385Sume * destination, which may be valid. 821148385Sume * - we'd see no error on output. 822148385Sume * Although this may not be very harmful, it should still be confusing. 823148385Sume * We thus reject the case here. 824148385Sume */ 825148385Sume if (rt && (rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE))) { 826148385Sume int flags = (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 827148385Sume 828158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 829148385Sume RTFREE(rt); 830148385Sume return (flags); 831148385Sume } 832148385Sume 833158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 834148385Sume RTFREE(rt); 835148385Sume return (0); 836148385Sume} 837148385Sume 838171259Sdelphij/* 839231852Sbz * Public wrapper function to selectroute(). 840231852Sbz * 841231852Sbz * XXX-BZ in6_selectroute() should and will grow the FIB argument. The 842231852Sbz * in6_selectroute_fib() function is only there for backward compat on stable. 843171259Sdelphij */ 844148385Sumeint 845171259Sdelphijin6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 846171259Sdelphij struct ip6_moptions *mopts, struct route_in6 *ro, 847186119Sqingli struct ifnet **retifp, struct rtentry **retrt) 848148385Sume{ 849171259Sdelphij 850148385Sume return (selectroute(dstsock, opts, mopts, ro, retifp, 851231852Sbz retrt, 0, RT_DEFAULT_FIB)); 852148385Sume} 853148385Sume 854231852Sbz#ifndef BURN_BRIDGES 855231852Sbzint 856231852Sbzin6_selectroute_fib(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 857231852Sbz struct ip6_moptions *mopts, struct route_in6 *ro, 858232127Sbz struct ifnet **retifp, struct rtentry **retrt, u_int fibnum) 859231852Sbz{ 860231852Sbz 861231852Sbz return (selectroute(dstsock, opts, mopts, ro, retifp, 862231852Sbz retrt, 0, fibnum)); 863231852Sbz} 864231852Sbz#endif 865231852Sbz 86662587Sitojun/* 86762587Sitojun * Default hop limit selection. The precedence is as follows: 86862587Sitojun * 1. Hoplimit value specified via ioctl. 86962587Sitojun * 2. (If the outgoing interface is detected) the current 87062587Sitojun * hop limit of the interface specified by router advertisement. 87162587Sitojun * 3. The system default hoplimit. 872122922Sandre */ 87362587Sitojunint 874186141Sbzin6_selecthlim(struct inpcb *in6p, struct ifnet *ifp) 87562587Sitojun{ 876171259Sdelphij 87762587Sitojun if (in6p && in6p->in6p_hops >= 0) 878120856Sume return (in6p->in6p_hops); 87962587Sitojun else if (ifp) 880121161Sume return (ND_IFINFO(ifp)->chlim); 881122922Sandre else if (in6p && !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 882122922Sandre struct route_in6 ro6; 883122922Sandre struct ifnet *lifp; 884122922Sandre 885122922Sandre bzero(&ro6, sizeof(ro6)); 886122922Sandre ro6.ro_dst.sin6_family = AF_INET6; 887122922Sandre ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6); 888122922Sandre ro6.ro_dst.sin6_addr = in6p->in6p_faddr; 889232127Sbz in6_rtalloc(&ro6, in6p->inp_inc.inc_fibnum); 890122922Sandre if (ro6.ro_rt) { 891122922Sandre lifp = ro6.ro_rt->rt_ifp; 892122922Sandre RTFREE(ro6.ro_rt); 893122922Sandre if (lifp) 894122922Sandre return (ND_IFINFO(lifp)->chlim); 895235955Sbz } 896122922Sandre } 897181803Sbz return (V_ip6_defhlim); 89862587Sitojun} 89962587Sitojun 90062587Sitojun/* 90162587Sitojun * XXX: this is borrowed from in6_pcbbind(). If possible, we should 90262587Sitojun * share this function by all *bsd*... 90362587Sitojun */ 90462587Sitojunint 905171259Sdelphijin6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred) 90662587Sitojun{ 90762587Sitojun struct socket *so = inp->inp_socket; 908219579Sbz u_int16_t lport = 0; 909222215Srwatson int error, lookupflags = 0; 910219579Sbz#ifdef INVARIANTS 91162587Sitojun struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 912219579Sbz#endif 91362587Sitojun 914178285Srwatson INP_WLOCK_ASSERT(inp); 915222488Srwatson INP_HASH_WLOCK_ASSERT(pcbinfo); 916158011Srwatson 917188144Sjamie error = prison_local_ip6(cred, laddr, 918188144Sjamie ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)); 919188144Sjamie if (error) 920188144Sjamie return(error); 921185435Sbz 92262587Sitojun /* XXX: this is redundant when called from in6_pcbbind */ 92362587Sitojun if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) 924222215Srwatson lookupflags = INPLOOKUP_WILDCARD; 92562587Sitojun 92662587Sitojun inp->inp_flags |= INP_ANONPORT; 92762587Sitojun 928222215Srwatson error = in_pcb_lport(inp, NULL, &lport, cred, lookupflags); 929219579Sbz if (error != 0) 930219579Sbz return (error); 931184096Sbz 93262587Sitojun inp->inp_lport = lport; 93362587Sitojun if (in_pcbinshash(inp) != 0) { 93462587Sitojun inp->in6p_laddr = in6addr_any; 93562587Sitojun inp->inp_lport = 0; 93662587Sitojun return (EAGAIN); 93762587Sitojun } 93862587Sitojun 939120856Sume return (0); 94062587Sitojun} 94162587Sitojun 94278064Sumevoid 943171259Sdelphijaddrsel_policy_init(void) 944121742Sume{ 945121742Sume 946121742Sume init_policy_queue(); 947121742Sume 948121742Sume /* initialize the "last resort" policy */ 949181803Sbz bzero(&V_defaultaddrpolicy, sizeof(V_defaultaddrpolicy)); 950181803Sbz V_defaultaddrpolicy.label = ADDR_LABEL_NOTAPP; 951190787Szec 952190787Szec if (!IS_DEFAULT_VNET(curvnet)) 953190787Szec return; 954190787Szec 955190787Szec ADDRSEL_LOCK_INIT(); 956190787Szec ADDRSEL_SXLOCK_INIT(); 957121742Sume} 958121742Sume 959122077Sumestatic struct in6_addrpolicy * 960171259Sdelphijlookup_addrsel_policy(struct sockaddr_in6 *key) 961122077Sume{ 962122077Sume struct in6_addrpolicy *match = NULL; 963122077Sume 964122077Sume ADDRSEL_LOCK(); 965122077Sume match = match_addrsel_policy(key); 966122077Sume 967122077Sume if (match == NULL) 968181803Sbz match = &V_defaultaddrpolicy; 969122077Sume else 970122077Sume match->use++; 971122077Sume ADDRSEL_UNLOCK(); 972122077Sume 973122077Sume return (match); 974122077Sume} 975122077Sume 976121742Sume/* 977121742Sume * Subroutines to manage the address selection policy table via sysctl. 978121742Sume */ 979121742Sumestruct walkarg { 980121742Sume struct sysctl_req *w_req; 981121742Sume}; 982121742Sume 983121742Sumestatic int in6_src_sysctl(SYSCTL_HANDLER_ARGS); 984121742SumeSYSCTL_DECL(_net_inet6_ip6); 985227309Sedstatic SYSCTL_NODE(_net_inet6_ip6, IPV6CTL_ADDRCTLPOLICY, addrctlpolicy, 986121742Sume CTLFLAG_RD, in6_src_sysctl, ""); 987121742Sume 988121742Sumestatic int 989121742Sumein6_src_sysctl(SYSCTL_HANDLER_ARGS) 990121742Sume{ 991121742Sume struct walkarg w; 992121742Sume 993121742Sume if (req->newptr) 994121742Sume return EPERM; 995121742Sume 996121742Sume bzero(&w, sizeof(w)); 997121742Sume w.w_req = req; 998121742Sume 999121742Sume return (walk_addrsel_policy(dump_addrsel_policyent, &w)); 1000121742Sume} 1001121742Sume 1002121742Sumeint 1003171259Sdelphijin6_src_ioctl(u_long cmd, caddr_t data) 1004121742Sume{ 1005121742Sume int i; 1006121742Sume struct in6_addrpolicy ent0; 1007121742Sume 1008121742Sume if (cmd != SIOCAADDRCTL_POLICY && cmd != SIOCDADDRCTL_POLICY) 1009121742Sume return (EOPNOTSUPP); /* check for safety */ 1010121742Sume 1011121742Sume ent0 = *(struct in6_addrpolicy *)data; 1012121742Sume 1013121742Sume if (ent0.label == ADDR_LABEL_NOTAPP) 1014121742Sume return (EINVAL); 1015121742Sume /* check if the prefix mask is consecutive. */ 1016121742Sume if (in6_mask2len(&ent0.addrmask.sin6_addr, NULL) < 0) 1017121742Sume return (EINVAL); 1018121742Sume /* clear trailing garbages (if any) of the prefix address. */ 1019121742Sume for (i = 0; i < 4; i++) { 1020121742Sume ent0.addr.sin6_addr.s6_addr32[i] &= 1021121742Sume ent0.addrmask.sin6_addr.s6_addr32[i]; 1022121742Sume } 1023121742Sume ent0.use = 0; 1024121742Sume 1025121742Sume switch (cmd) { 1026121742Sume case SIOCAADDRCTL_POLICY: 1027121742Sume return (add_addrsel_policyent(&ent0)); 1028121742Sume case SIOCDADDRCTL_POLICY: 1029121742Sume return (delete_addrsel_policyent(&ent0)); 1030121742Sume } 1031121742Sume 1032121742Sume return (0); /* XXX: compromise compilers */ 1033121742Sume} 1034121742Sume 1035121742Sume/* 1036121742Sume * The followings are implementation of the policy table using a 1037121742Sume * simple tail queue. 1038121742Sume * XXX such details should be hidden. 1039121742Sume * XXX implementation using binary tree should be more efficient. 1040121742Sume */ 1041121742Sumestruct addrsel_policyent { 1042121742Sume TAILQ_ENTRY(addrsel_policyent) ape_entry; 1043121742Sume struct in6_addrpolicy ape_policy; 1044121742Sume}; 1045121742Sume 1046121742SumeTAILQ_HEAD(addrsel_policyhead, addrsel_policyent); 1047121742Sume 1048215701Sdimstatic VNET_DEFINE(struct addrsel_policyhead, addrsel_policytab); 1049195727Srwatson#define V_addrsel_policytab VNET(addrsel_policytab) 1050121742Sume 1051121742Sumestatic void 1052171259Sdelphijinit_policy_queue(void) 1053121742Sume{ 1054171259Sdelphij 1055181803Sbz TAILQ_INIT(&V_addrsel_policytab); 1056121742Sume} 1057121742Sume 1058121742Sumestatic int 1059171259Sdelphijadd_addrsel_policyent(struct in6_addrpolicy *newpolicy) 1060121742Sume{ 1061121742Sume struct addrsel_policyent *new, *pol; 1062121742Sume 1063184205Sdes new = malloc(sizeof(*new), M_IFADDR, 1064121750Sume M_WAITOK); 1065149200Sume ADDRSEL_XLOCK(); 1066121742Sume ADDRSEL_LOCK(); 1067121742Sume 1068121742Sume /* duplication check */ 1069181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1070151478Ssuz if (IN6_ARE_ADDR_EQUAL(&newpolicy->addr.sin6_addr, 1071151478Ssuz &pol->ape_policy.addr.sin6_addr) && 1072151478Ssuz IN6_ARE_ADDR_EQUAL(&newpolicy->addrmask.sin6_addr, 1073151478Ssuz &pol->ape_policy.addrmask.sin6_addr)) { 1074121750Sume ADDRSEL_UNLOCK(); 1075149200Sume ADDRSEL_XUNLOCK(); 1076184205Sdes free(new, M_IFADDR); 1077121742Sume return (EEXIST); /* or override it? */ 1078121742Sume } 1079121742Sume } 1080121742Sume 1081121742Sume bzero(new, sizeof(*new)); 1082121742Sume 1083121742Sume /* XXX: should validate entry */ 1084121742Sume new->ape_policy = *newpolicy; 1085121742Sume 1086181803Sbz TAILQ_INSERT_TAIL(&V_addrsel_policytab, new, ape_entry); 1087121742Sume ADDRSEL_UNLOCK(); 1088149200Sume ADDRSEL_XUNLOCK(); 1089121742Sume 1090121742Sume return (0); 1091121742Sume} 1092121742Sume 1093121742Sumestatic int 1094171259Sdelphijdelete_addrsel_policyent(struct in6_addrpolicy *key) 1095121742Sume{ 1096121742Sume struct addrsel_policyent *pol; 1097121742Sume 1098149200Sume ADDRSEL_XLOCK(); 1099121742Sume ADDRSEL_LOCK(); 1100121742Sume 1101121742Sume /* search for the entry in the table */ 1102181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1103151478Ssuz if (IN6_ARE_ADDR_EQUAL(&key->addr.sin6_addr, 1104151478Ssuz &pol->ape_policy.addr.sin6_addr) && 1105151478Ssuz IN6_ARE_ADDR_EQUAL(&key->addrmask.sin6_addr, 1106151478Ssuz &pol->ape_policy.addrmask.sin6_addr)) { 1107121742Sume break; 1108121742Sume } 1109121742Sume } 1110121750Sume if (pol == NULL) { 1111121750Sume ADDRSEL_UNLOCK(); 1112149200Sume ADDRSEL_XUNLOCK(); 1113121742Sume return (ESRCH); 1114121750Sume } 1115121742Sume 1116181803Sbz TAILQ_REMOVE(&V_addrsel_policytab, pol, ape_entry); 1117121742Sume ADDRSEL_UNLOCK(); 1118149200Sume ADDRSEL_XUNLOCK(); 1119249398Sae free(pol, M_IFADDR); 1120121742Sume 1121121742Sume return (0); 1122121742Sume} 1123121742Sume 1124121742Sumestatic int 1125242938Sobrienwalk_addrsel_policy(int (*callback)(struct in6_addrpolicy *, void *), void *w) 1126121742Sume{ 1127121742Sume struct addrsel_policyent *pol; 1128121742Sume int error = 0; 1129121742Sume 1130149200Sume ADDRSEL_SLOCK(); 1131181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1132149200Sume if ((error = (*callback)(&pol->ape_policy, w)) != 0) { 1133149200Sume ADDRSEL_SUNLOCK(); 1134121742Sume return (error); 1135149200Sume } 1136121742Sume } 1137149200Sume ADDRSEL_SUNLOCK(); 1138121742Sume return (error); 1139121742Sume} 1140121742Sume 1141121742Sumestatic int 1142171259Sdelphijdump_addrsel_policyent(struct in6_addrpolicy *pol, void *arg) 1143121742Sume{ 1144121742Sume int error = 0; 1145121742Sume struct walkarg *w = arg; 1146121742Sume 1147121742Sume error = SYSCTL_OUT(w->w_req, pol, sizeof(*pol)); 1148121742Sume 1149121742Sume return (error); 1150121742Sume} 1151122077Sume 1152122077Sumestatic struct in6_addrpolicy * 1153171259Sdelphijmatch_addrsel_policy(struct sockaddr_in6 *key) 1154122077Sume{ 1155122077Sume struct addrsel_policyent *pent; 1156122077Sume struct in6_addrpolicy *bestpol = NULL, *pol; 1157122077Sume int matchlen, bestmatchlen = -1; 1158122077Sume u_char *mp, *ep, *k, *p, m; 1159122077Sume 1160181803Sbz TAILQ_FOREACH(pent, &V_addrsel_policytab, ape_entry) { 1161122077Sume matchlen = 0; 1162122077Sume 1163122077Sume pol = &pent->ape_policy; 1164122077Sume mp = (u_char *)&pol->addrmask.sin6_addr; 1165122077Sume ep = mp + 16; /* XXX: scope field? */ 1166122077Sume k = (u_char *)&key->sin6_addr; 1167122077Sume p = (u_char *)&pol->addr.sin6_addr; 1168122077Sume for (; mp < ep && *mp; mp++, k++, p++) { 1169122077Sume m = *mp; 1170122077Sume if ((*k & m) != *p) 1171122077Sume goto next; /* not match */ 1172122077Sume if (m == 0xff) /* short cut for a typical case */ 1173122077Sume matchlen += 8; 1174122077Sume else { 1175122077Sume while (m >= 0x80) { 1176122077Sume matchlen++; 1177122077Sume m <<= 1; 1178122077Sume } 1179122077Sume } 1180122077Sume } 1181122077Sume 1182122077Sume /* matched. check if this is better than the current best. */ 1183122077Sume if (bestpol == NULL || 1184122077Sume matchlen > bestmatchlen) { 1185122077Sume bestpol = pol; 1186122077Sume bestmatchlen = matchlen; 1187122077Sume } 1188122077Sume 1189122077Sume next: 1190122077Sume continue; 1191122077Sume } 1192122077Sume 1193122077Sume return (bestpol); 1194122077Sume} 1195