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 /* 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(); 486249528Sae 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(); 503249528Sae IP6STAT_INC(ip6s_sources_none); 504207276Sbz return (EADDRNOTAVAIL); 505207276Sbz } 506207276Sbz 507148385Sume if (ifpp) 508148385Sume *ifpp = ifp; 509148385Sume 510207276Sbz bcopy(&tmp, srcp, sizeof(*srcp)); 511249546Sae if (ia->ia_ifp == ifp) 512249546Sae IP6STAT_INC(ip6s_sources_sameif[best_scope]); 513249546Sae else 514249546Sae IP6STAT_INC(ip6s_sources_otherif[best_scope]); 515249546Sae if (dst_scope == best_scope) 516249546Sae IP6STAT_INC(ip6s_sources_samescope[best_scope]); 517249546Sae else 518249546Sae IP6STAT_INC(ip6s_sources_otherscope[best_scope]); 519249546Sae if (IFA6_IS_DEPRECATED(ia)) 520249546Sae 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, 531232127Sbz 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) { 608231852Sbz in6_rtalloc(ron, fibnum); /* multi path case? */ 609186119Sqingli if (ron->ro_rt == NULL) { 610237459Sbz /* XXX-BZ WT.? */ 611186119Sqingli if (ron->ro_rt) { 612186119Sqingli RTFREE(ron->ro_rt); 613186119Sqingli ron->ro_rt = NULL; 614186119Sqingli } 615186119Sqingli error = EHOSTUNREACH; 616186119Sqingli goto done; 617186119Sqingli } 618186119Sqingli } 619186119Sqingli 620186119Sqingli rt = ron->ro_rt; 621186119Sqingli ifp = rt->rt_ifp; 622243148Sae IF_AFDATA_RLOCK(ifp); 623186119Sqingli la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6_next->sin6_addr); 624243148Sae IF_AFDATA_RUNLOCK(ifp); 625186158Skmacy if (la != NULL) 626186119Sqingli LLE_RUNLOCK(la); 627186119Sqingli else { 628186119Sqingli error = EHOSTUNREACH; 629186119Sqingli goto done; 630186119Sqingli } 631186119Sqingli#if 0 632122077Sume if ((ron->ro_rt && 633122077Sume (ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) != 634122077Sume (RTF_UP | RTF_LLINFO)) || 635151478Ssuz !IN6_ARE_ADDR_EQUAL(&satosin6(&ron->ro_dst)->sin6_addr, 636151478Ssuz &sin6_next->sin6_addr)) { 637122077Sume if (ron->ro_rt) { 638122077Sume RTFREE(ron->ro_rt); 639122077Sume ron->ro_rt = NULL; 64062587Sitojun } 641122077Sume *satosin6(&ron->ro_dst) = *sin6_next; 642122077Sume } 643122077Sume if (ron->ro_rt == NULL) { 644232127Sbz in6_rtalloc(ron, fibnum); /* multi path case? */ 645122077Sume if (ron->ro_rt == NULL || 646122077Sume !(ron->ro_rt->rt_flags & RTF_LLINFO)) { 647122077Sume if (ron->ro_rt) { 648122077Sume RTFREE(ron->ro_rt); 649122077Sume ron->ro_rt = NULL; 650122077Sume } 651122077Sume error = EHOSTUNREACH; 652122077Sume goto done; 65362587Sitojun } 65462587Sitojun } 655186119Sqingli#endif 656122077Sume 657122077Sume /* 658122077Sume * When cloning is required, try to allocate a route to the 659122077Sume * destination so that the caller can store path MTU 660122077Sume * information. 661122077Sume */ 662186119Sqingli goto done; 66362587Sitojun } 66462587Sitojun 66562587Sitojun /* 666122077Sume * Use a cached route if it exists and is valid, else try to allocate 667122077Sume * a new one. Note that we should check the address family of the 668122077Sume * cached destination, in case of sharing the cache with IPv4. 66962587Sitojun */ 67062587Sitojun if (ro) { 67162587Sitojun if (ro->ro_rt && 67289623Sume (!(ro->ro_rt->rt_flags & RTF_UP) || 673122077Sume ((struct sockaddr *)(&ro->ro_dst))->sa_family != AF_INET6 || 67489623Sume !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, 675125436Sume dst))) { 67662587Sitojun RTFREE(ro->ro_rt); 677122077Sume ro->ro_rt = (struct rtentry *)NULL; 67862587Sitojun } 679122077Sume if (ro->ro_rt == (struct rtentry *)NULL) { 68078064Sume struct sockaddr_in6 *sa6; 68178064Sume 68262587Sitojun /* No route yet, so try to acquire one */ 68362587Sitojun bzero(&ro->ro_dst, sizeof(struct sockaddr_in6)); 68478064Sume sa6 = (struct sockaddr_in6 *)&ro->ro_dst; 685122077Sume *sa6 = *dstsock; 686122122Sume sa6->sin6_scope_id = 0; 687122922Sandre 688178167Sqingli#ifdef RADIX_MPATH 689231852Sbz rtalloc_mpath_fib((struct route *)ro, 690231852Sbz ntohl(sa6->sin6_addr.s6_addr32[3]), fibnum); 691186119Sqingli#else 692231852Sbz ro->ro_rt = in6_rtalloc1((struct sockaddr *) 693231852Sbz &ro->ro_dst, 0, 0UL, fibnum); 694121445Ssam if (ro->ro_rt) 695121445Ssam RT_UNLOCK(ro->ro_rt); 696186119Sqingli#endif 69762587Sitojun } 698186119Sqingli 69962587Sitojun /* 700122077Sume * do not care about the result if we have the nexthop 701122077Sume * explicitly specified. 70262587Sitojun */ 703122077Sume if (opts && opts->ip6po_nexthop) 704122077Sume goto done; 70562587Sitojun 70662587Sitojun if (ro->ro_rt) { 707122077Sume ifp = ro->ro_rt->rt_ifp; 708122077Sume 709122077Sume if (ifp == NULL) { /* can this really happen? */ 710122077Sume RTFREE(ro->ro_rt); 711122077Sume ro->ro_rt = NULL; 712122077Sume } 71362587Sitojun } 714122077Sume if (ro->ro_rt == NULL) 715122077Sume error = EHOSTUNREACH; 716122077Sume rt = ro->ro_rt; 717122077Sume 718122077Sume /* 719122077Sume * Check if the outgoing interface conflicts with 720122077Sume * the interface specified by ipi6_ifindex (if specified). 721122077Sume * Note that loopback interface is always okay. 722122077Sume * (this may happen when we are sending a packet to one of 723122077Sume * our own addresses.) 724122077Sume */ 725146228Sgnn if (ifp && opts && opts->ip6po_pktinfo && 726125436Sume opts->ip6po_pktinfo->ipi6_ifindex) { 727122077Sume if (!(ifp->if_flags & IFF_LOOPBACK) && 728122077Sume ifp->if_index != 729122077Sume opts->ip6po_pktinfo->ipi6_ifindex) { 730122077Sume error = EHOSTUNREACH; 731122077Sume goto done; 732122077Sume } 73362587Sitojun } 73462587Sitojun } 73562587Sitojun 736122077Sume done: 737122077Sume if (ifp == NULL && rt == NULL) { 738122077Sume /* 739122077Sume * This can happen if the caller did not pass a cached route 740122077Sume * nor any other hints. We treat this case an error. 741122077Sume */ 742122077Sume error = EHOSTUNREACH; 743122077Sume } 744122077Sume if (error == EHOSTUNREACH) 745249294Sae IP6STAT_INC(ip6s_noroute); 746122077Sume 747196864Sqingli if (retifp != NULL) { 748122077Sume *retifp = ifp; 749196864Sqingli 750196864Sqingli /* 751196864Sqingli * Adjust the "outgoing" interface. If we're going to loop 752196864Sqingli * the packet back to ourselves, the ifp would be the loopback 753196864Sqingli * interface. However, we'd rather know the interface associated 754196864Sqingli * to the destination address (which should probably be one of 755196864Sqingli * our own addresses.) 756196864Sqingli */ 757196864Sqingli if (rt) { 758196864Sqingli if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) && 759196864Sqingli (rt->rt_gateway->sa_family == AF_LINK)) 760196864Sqingli *retifp = 761196864Sqingli ifnet_byindex(((struct sockaddr_dl *) 762196864Sqingli rt->rt_gateway)->sdl_index); 763196864Sqingli } 764196864Sqingli } 765196864Sqingli 766122077Sume if (retrt != NULL) 767122077Sume *retrt = rt; /* rt may be NULL */ 768122077Sume 769122077Sume return (error); 77062587Sitojun} 77162587Sitojun 772148385Sumestatic int 773171259Sdelphijin6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 774231852Sbz struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp, 775232127Sbz struct ifnet *oifp, u_int fibnum) 776148385Sume{ 777148385Sume int error; 778148385Sume struct route_in6 sro; 779148385Sume struct rtentry *rt = NULL; 780148385Sume 781231852Sbz KASSERT(retifp != NULL, ("%s: retifp is NULL", __func__)); 782231852Sbz 783148385Sume if (ro == NULL) { 784148385Sume bzero(&sro, sizeof(sro)); 785148385Sume ro = &sro; 786148385Sume } 787148385Sume 788148385Sume if ((error = selectroute(dstsock, opts, mopts, ro, retifp, 789231852Sbz &rt, 1, fibnum)) != 0) { 790158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 791148385Sume RTFREE(rt); 792231852Sbz /* Help ND. See oifp comment in in6_selectsrc(). */ 793231852Sbz if (oifp != NULL && fibnum == RT_DEFAULT_FIB) { 794231852Sbz *retifp = oifp; 795231852Sbz error = 0; 796231852Sbz } 797148385Sume return (error); 798148385Sume } 799148385Sume 800148385Sume /* 801148385Sume * do not use a rejected or black hole route. 802148385Sume * XXX: this check should be done in the L2 output routine. 803148385Sume * However, if we skipped this check here, we'd see the following 804148385Sume * scenario: 805148385Sume * - install a rejected route for a scoped address prefix 806148385Sume * (like fe80::/10) 807148385Sume * - send a packet to a destination that matches the scoped prefix, 808148385Sume * with ambiguity about the scope zone. 809148385Sume * - pick the outgoing interface from the route, and disambiguate the 810148385Sume * scope zone with the interface. 811148385Sume * - ip6_output() would try to get another route with the "new" 812148385Sume * destination, which may be valid. 813148385Sume * - we'd see no error on output. 814148385Sume * Although this may not be very harmful, it should still be confusing. 815148385Sume * We thus reject the case here. 816148385Sume */ 817148385Sume if (rt && (rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE))) { 818148385Sume int flags = (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 819148385Sume 820158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 821148385Sume RTFREE(rt); 822148385Sume return (flags); 823148385Sume } 824148385Sume 825158843Stanimura if (ro == &sro && rt && rt == sro.ro_rt) 826148385Sume RTFREE(rt); 827148385Sume return (0); 828148385Sume} 829148385Sume 830171259Sdelphij/* 831231852Sbz * Public wrapper function to selectroute(). 832231852Sbz * 833231852Sbz * XXX-BZ in6_selectroute() should and will grow the FIB argument. The 834231852Sbz * in6_selectroute_fib() function is only there for backward compat on stable. 835171259Sdelphij */ 836148385Sumeint 837171259Sdelphijin6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 838171259Sdelphij struct ip6_moptions *mopts, struct route_in6 *ro, 839186119Sqingli struct ifnet **retifp, struct rtentry **retrt) 840148385Sume{ 841171259Sdelphij 842148385Sume return (selectroute(dstsock, opts, mopts, ro, retifp, 843231852Sbz retrt, 0, RT_DEFAULT_FIB)); 844148385Sume} 845148385Sume 846231852Sbz#ifndef BURN_BRIDGES 847231852Sbzint 848231852Sbzin6_selectroute_fib(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 849231852Sbz struct ip6_moptions *mopts, struct route_in6 *ro, 850232127Sbz struct ifnet **retifp, struct rtentry **retrt, u_int fibnum) 851231852Sbz{ 852231852Sbz 853231852Sbz return (selectroute(dstsock, opts, mopts, ro, retifp, 854231852Sbz retrt, 0, fibnum)); 855231852Sbz} 856231852Sbz#endif 857231852Sbz 85862587Sitojun/* 85962587Sitojun * Default hop limit selection. The precedence is as follows: 86062587Sitojun * 1. Hoplimit value specified via ioctl. 86162587Sitojun * 2. (If the outgoing interface is detected) the current 86262587Sitojun * hop limit of the interface specified by router advertisement. 86362587Sitojun * 3. The system default hoplimit. 864122922Sandre */ 86562587Sitojunint 866186141Sbzin6_selecthlim(struct inpcb *in6p, struct ifnet *ifp) 86762587Sitojun{ 868171259Sdelphij 86962587Sitojun if (in6p && in6p->in6p_hops >= 0) 870120856Sume return (in6p->in6p_hops); 87162587Sitojun else if (ifp) 872121161Sume return (ND_IFINFO(ifp)->chlim); 873122922Sandre else if (in6p && !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { 874122922Sandre struct route_in6 ro6; 875122922Sandre struct ifnet *lifp; 876122922Sandre 877122922Sandre bzero(&ro6, sizeof(ro6)); 878122922Sandre ro6.ro_dst.sin6_family = AF_INET6; 879122922Sandre ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6); 880122922Sandre ro6.ro_dst.sin6_addr = in6p->in6p_faddr; 881232127Sbz in6_rtalloc(&ro6, in6p->inp_inc.inc_fibnum); 882122922Sandre if (ro6.ro_rt) { 883122922Sandre lifp = ro6.ro_rt->rt_ifp; 884122922Sandre RTFREE(ro6.ro_rt); 885122922Sandre if (lifp) 886122922Sandre return (ND_IFINFO(lifp)->chlim); 887235955Sbz } 888122922Sandre } 889181803Sbz return (V_ip6_defhlim); 89062587Sitojun} 89162587Sitojun 89262587Sitojun/* 89362587Sitojun * XXX: this is borrowed from in6_pcbbind(). If possible, we should 89462587Sitojun * share this function by all *bsd*... 89562587Sitojun */ 89662587Sitojunint 897171259Sdelphijin6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred) 89862587Sitojun{ 89962587Sitojun struct socket *so = inp->inp_socket; 900219579Sbz u_int16_t lport = 0; 901222215Srwatson int error, lookupflags = 0; 902219579Sbz#ifdef INVARIANTS 90362587Sitojun struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 904219579Sbz#endif 90562587Sitojun 906178285Srwatson INP_WLOCK_ASSERT(inp); 907222488Srwatson INP_HASH_WLOCK_ASSERT(pcbinfo); 908158011Srwatson 909188144Sjamie error = prison_local_ip6(cred, laddr, 910188144Sjamie ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)); 911188144Sjamie if (error) 912188144Sjamie return(error); 913185435Sbz 91462587Sitojun /* XXX: this is redundant when called from in6_pcbbind */ 91562587Sitojun if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) 916222215Srwatson lookupflags = INPLOOKUP_WILDCARD; 91762587Sitojun 91862587Sitojun inp->inp_flags |= INP_ANONPORT; 91962587Sitojun 920222215Srwatson error = in_pcb_lport(inp, NULL, &lport, cred, lookupflags); 921219579Sbz if (error != 0) 922219579Sbz return (error); 923184096Sbz 92462587Sitojun inp->inp_lport = lport; 92562587Sitojun if (in_pcbinshash(inp) != 0) { 92662587Sitojun inp->in6p_laddr = in6addr_any; 92762587Sitojun inp->inp_lport = 0; 92862587Sitojun return (EAGAIN); 92962587Sitojun } 93062587Sitojun 931120856Sume return (0); 93262587Sitojun} 93362587Sitojun 93478064Sumevoid 935171259Sdelphijaddrsel_policy_init(void) 936121742Sume{ 937121742Sume 938121742Sume init_policy_queue(); 939121742Sume 940121742Sume /* initialize the "last resort" policy */ 941181803Sbz bzero(&V_defaultaddrpolicy, sizeof(V_defaultaddrpolicy)); 942181803Sbz V_defaultaddrpolicy.label = ADDR_LABEL_NOTAPP; 943190787Szec 944190787Szec if (!IS_DEFAULT_VNET(curvnet)) 945190787Szec return; 946190787Szec 947190787Szec ADDRSEL_LOCK_INIT(); 948190787Szec ADDRSEL_SXLOCK_INIT(); 949121742Sume} 950121742Sume 951122077Sumestatic struct in6_addrpolicy * 952171259Sdelphijlookup_addrsel_policy(struct sockaddr_in6 *key) 953122077Sume{ 954122077Sume struct in6_addrpolicy *match = NULL; 955122077Sume 956122077Sume ADDRSEL_LOCK(); 957122077Sume match = match_addrsel_policy(key); 958122077Sume 959122077Sume if (match == NULL) 960181803Sbz match = &V_defaultaddrpolicy; 961122077Sume else 962122077Sume match->use++; 963122077Sume ADDRSEL_UNLOCK(); 964122077Sume 965122077Sume return (match); 966122077Sume} 967122077Sume 968121742Sume/* 969121742Sume * Subroutines to manage the address selection policy table via sysctl. 970121742Sume */ 971121742Sumestruct walkarg { 972121742Sume struct sysctl_req *w_req; 973121742Sume}; 974121742Sume 975121742Sumestatic int in6_src_sysctl(SYSCTL_HANDLER_ARGS); 976121742SumeSYSCTL_DECL(_net_inet6_ip6); 977227309Sedstatic SYSCTL_NODE(_net_inet6_ip6, IPV6CTL_ADDRCTLPOLICY, addrctlpolicy, 978121742Sume CTLFLAG_RD, in6_src_sysctl, ""); 979121742Sume 980121742Sumestatic int 981121742Sumein6_src_sysctl(SYSCTL_HANDLER_ARGS) 982121742Sume{ 983121742Sume struct walkarg w; 984121742Sume 985121742Sume if (req->newptr) 986121742Sume return EPERM; 987121742Sume 988121742Sume bzero(&w, sizeof(w)); 989121742Sume w.w_req = req; 990121742Sume 991121742Sume return (walk_addrsel_policy(dump_addrsel_policyent, &w)); 992121742Sume} 993121742Sume 994121742Sumeint 995171259Sdelphijin6_src_ioctl(u_long cmd, caddr_t data) 996121742Sume{ 997121742Sume int i; 998121742Sume struct in6_addrpolicy ent0; 999121742Sume 1000121742Sume if (cmd != SIOCAADDRCTL_POLICY && cmd != SIOCDADDRCTL_POLICY) 1001121742Sume return (EOPNOTSUPP); /* check for safety */ 1002121742Sume 1003121742Sume ent0 = *(struct in6_addrpolicy *)data; 1004121742Sume 1005121742Sume if (ent0.label == ADDR_LABEL_NOTAPP) 1006121742Sume return (EINVAL); 1007121742Sume /* check if the prefix mask is consecutive. */ 1008121742Sume if (in6_mask2len(&ent0.addrmask.sin6_addr, NULL) < 0) 1009121742Sume return (EINVAL); 1010121742Sume /* clear trailing garbages (if any) of the prefix address. */ 1011121742Sume for (i = 0; i < 4; i++) { 1012121742Sume ent0.addr.sin6_addr.s6_addr32[i] &= 1013121742Sume ent0.addrmask.sin6_addr.s6_addr32[i]; 1014121742Sume } 1015121742Sume ent0.use = 0; 1016121742Sume 1017121742Sume switch (cmd) { 1018121742Sume case SIOCAADDRCTL_POLICY: 1019121742Sume return (add_addrsel_policyent(&ent0)); 1020121742Sume case SIOCDADDRCTL_POLICY: 1021121742Sume return (delete_addrsel_policyent(&ent0)); 1022121742Sume } 1023121742Sume 1024121742Sume return (0); /* XXX: compromise compilers */ 1025121742Sume} 1026121742Sume 1027121742Sume/* 1028121742Sume * The followings are implementation of the policy table using a 1029121742Sume * simple tail queue. 1030121742Sume * XXX such details should be hidden. 1031121742Sume * XXX implementation using binary tree should be more efficient. 1032121742Sume */ 1033121742Sumestruct addrsel_policyent { 1034121742Sume TAILQ_ENTRY(addrsel_policyent) ape_entry; 1035121742Sume struct in6_addrpolicy ape_policy; 1036121742Sume}; 1037121742Sume 1038121742SumeTAILQ_HEAD(addrsel_policyhead, addrsel_policyent); 1039121742Sume 1040215701Sdimstatic VNET_DEFINE(struct addrsel_policyhead, addrsel_policytab); 1041195727Srwatson#define V_addrsel_policytab VNET(addrsel_policytab) 1042121742Sume 1043121742Sumestatic void 1044171259Sdelphijinit_policy_queue(void) 1045121742Sume{ 1046171259Sdelphij 1047181803Sbz TAILQ_INIT(&V_addrsel_policytab); 1048121742Sume} 1049121742Sume 1050121742Sumestatic int 1051171259Sdelphijadd_addrsel_policyent(struct in6_addrpolicy *newpolicy) 1052121742Sume{ 1053121742Sume struct addrsel_policyent *new, *pol; 1054121742Sume 1055184205Sdes new = malloc(sizeof(*new), M_IFADDR, 1056121750Sume M_WAITOK); 1057149200Sume ADDRSEL_XLOCK(); 1058121742Sume ADDRSEL_LOCK(); 1059121742Sume 1060121742Sume /* duplication check */ 1061181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1062151478Ssuz if (IN6_ARE_ADDR_EQUAL(&newpolicy->addr.sin6_addr, 1063151478Ssuz &pol->ape_policy.addr.sin6_addr) && 1064151478Ssuz IN6_ARE_ADDR_EQUAL(&newpolicy->addrmask.sin6_addr, 1065151478Ssuz &pol->ape_policy.addrmask.sin6_addr)) { 1066121750Sume ADDRSEL_UNLOCK(); 1067149200Sume ADDRSEL_XUNLOCK(); 1068184205Sdes free(new, M_IFADDR); 1069121742Sume return (EEXIST); /* or override it? */ 1070121742Sume } 1071121742Sume } 1072121742Sume 1073121742Sume bzero(new, sizeof(*new)); 1074121742Sume 1075121742Sume /* XXX: should validate entry */ 1076121742Sume new->ape_policy = *newpolicy; 1077121742Sume 1078181803Sbz TAILQ_INSERT_TAIL(&V_addrsel_policytab, new, ape_entry); 1079121742Sume ADDRSEL_UNLOCK(); 1080149200Sume ADDRSEL_XUNLOCK(); 1081121742Sume 1082121742Sume return (0); 1083121742Sume} 1084121742Sume 1085121742Sumestatic int 1086171259Sdelphijdelete_addrsel_policyent(struct in6_addrpolicy *key) 1087121742Sume{ 1088121742Sume struct addrsel_policyent *pol; 1089121742Sume 1090149200Sume ADDRSEL_XLOCK(); 1091121742Sume ADDRSEL_LOCK(); 1092121742Sume 1093121742Sume /* search for the entry in the table */ 1094181803Sbz TAILQ_FOREACH(pol, &V_addrsel_policytab, ape_entry) { 1095151478Ssuz if (IN6_ARE_ADDR_EQUAL(&key->addr.sin6_addr, 1096151478Ssuz &pol->ape_policy.addr.sin6_addr) && 1097151478Ssuz IN6_ARE_ADDR_EQUAL(&key->addrmask.sin6_addr, 1098151478Ssuz &pol->ape_policy.addrmask.sin6_addr)) { 1099121742Sume break; 1100121742Sume } 1101121742Sume } 1102121750Sume if (pol == NULL) { 1103121750Sume ADDRSEL_UNLOCK(); 1104149200Sume ADDRSEL_XUNLOCK(); 1105121742Sume return (ESRCH); 1106121750Sume } 1107121742Sume 1108181803Sbz TAILQ_REMOVE(&V_addrsel_policytab, pol, ape_entry); 1109121742Sume ADDRSEL_UNLOCK(); 1110149200Sume ADDRSEL_XUNLOCK(); 1111249398Sae free(pol, M_IFADDR); 1112121742Sume 1113121742Sume return (0); 1114121742Sume} 1115121742Sume 1116121742Sumestatic int 1117242938Sobrienwalk_addrsel_policy(int (*callback)(struct in6_addrpolicy *, void *), 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