in6_pcb.c revision 85074
11573Srgrimes/* $FreeBSD: head/sys/netinet6/in6_pcb.c 85074 2001-10-17 18:07:05Z ru $ */ 21573Srgrimes/* $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $ */ 31573Srgrimes 41573Srgrimes/* 51573Srgrimes * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 61573Srgrimes * All rights reserved. 71573Srgrimes * 81573Srgrimes * Redistribution and use in source and binary forms, with or without 91573Srgrimes * modification, are permitted provided that the following conditions 101573Srgrimes * are met: 111573Srgrimes * 1. Redistributions of source code must retain the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer. 131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer in the 151573Srgrimes * documentation and/or other materials provided with the distribution. 161573Srgrimes * 3. Neither the name of the project nor the names of its contributors 171573Srgrimes * may be used to endorse or promote products derived from this software 181573Srgrimes * without specific prior written permission. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301573Srgrimes * SUCH DAMAGE. 311573Srgrimes * 321573Srgrimes */ 331573Srgrimes 3423668Speter/* 351573Srgrimes * Copyright (c) 1982, 1986, 1991, 1993 3690041Sobrien * The Regents of the University of California. All rights reserved. 3790041Sobrien * 381573Srgrimes * Redistribution and use in source and binary forms, with or without 39108626Stjr * modification, are permitted provided that the following conditions 401573Srgrimes * are met: 417615Swpaul * 1. Redistributions of source code must retain the above copyright 4295459Sdes * notice, this list of conditions and the following disclaimer. 437615Swpaul * 2. Redistributions in binary form must reproduce the above copyright 441573Srgrimes * notice, this list of conditions and the following disclaimer in the 457615Swpaul * documentation and/or other materials provided with the distribution. 469978Swpaul * 3. All advertising materials mentioning features or use of this software 479978Swpaul * must display the following acknowledgement: 489978Swpaul * This product includes software developed by the University of 499978Swpaul * California, Berkeley and its contributors. 509978Swpaul * 4. Neither the name of the University nor the names of its contributors 519978Swpaul * may be used to endorse or promote products derived from this software 529978Swpaul * without specific prior written permission. 539978Swpaul * 549978Swpaul * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 559978Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 569978Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 579978Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 589978Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 599978Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 609978Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 619978Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 629978Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 639978Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 649978Swpaul * SUCH DAMAGE. 659978Swpaul * 669978Swpaul * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94 679978Swpaul */ 689978Swpaul 699978Swpaul#include "opt_inet.h" 709978Swpaul#include "opt_inet6.h" 719978Swpaul#include "opt_ipsec.h" 729978Swpaul 739978Swpaul#include <sys/param.h> 749978Swpaul#include <sys/systm.h> 759978Swpaul#include <sys/malloc.h> 769978Swpaul#include <sys/mbuf.h> 779978Swpaul#include <sys/domain.h> 789978Swpaul#include <sys/protosw.h> 799978Swpaul#include <sys/socket.h> 809978Swpaul#include <sys/socketvar.h> 819978Swpaul#include <sys/sockio.h> 829978Swpaul#include <sys/errno.h> 839978Swpaul#include <sys/time.h> 8430288Swpaul#include <sys/proc.h> 857615Swpaul#include <sys/jail.h> 867615Swpaul 877615Swpaul#include <vm/vm_zone.h> 889978Swpaul 899978Swpaul#include <net/if.h> 909978Swpaul#include <net/if_types.h> 919978Swpaul#include <net/route.h> 929978Swpaul 9310521Swpaul#include <netinet/in.h> 947615Swpaul#include <netinet/in_var.h> 959978Swpaul#include <netinet/in_systm.h> 967615Swpaul#include <netinet/ip6.h> 977615Swpaul#include <netinet/ip_var.h> 989978Swpaul#include <netinet6/ip6_var.h> 991573Srgrimes#include <netinet6/nd6.h> 1009978Swpaul#include <netinet/in_pcb.h> 1011573Srgrimes#include <netinet6/in6_pcb.h> 1021573Srgrimes 1031573Srgrimes#ifdef IPSEC 1041573Srgrimes#include <netinet6/ipsec.h> 1051573Srgrimes#ifdef INET6 1061573Srgrimes#include <netinet6/ipsec6.h> 1071573Srgrimes#endif 1081573Srgrimes#include <netinet6/ah.h> 1091573Srgrimes#ifdef INET6 1101573Srgrimes#include <netinet6/ah6.h> 1111573Srgrimes#endif 1121573Srgrimes#include <netkey/key.h> 1131573Srgrimes#endif /* IPSEC */ 1141573Srgrimes 1151573Srgrimesstruct in6_addr zeroin6_addr; 1161573Srgrimes 1171573Srgrimesint 1181573Srgrimesin6_pcbbind(inp, nam, td) 1191573Srgrimes register struct inpcb *inp; 1201573Srgrimes struct sockaddr *nam; 1211573Srgrimes struct thread *td; 1221573Srgrimes{ 1231573Srgrimes struct socket *so = inp->inp_socket; 1241573Srgrimes struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; 1251573Srgrimes struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; 1261573Srgrimes u_short lport = 0; 1271573Srgrimes int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); 1281573Srgrimes 1291573Srgrimes if (!in6_ifaddr) /* XXX broken! */ 1301573Srgrimes return (EADDRNOTAVAIL); 1311573Srgrimes if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 1321573Srgrimes return(EINVAL); 1331573Srgrimes if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) 1341573Srgrimes wild = 1; 1351573Srgrimes if (nam) { 136132793Sdes sin6 = (struct sockaddr_in6 *)nam; 137132793Sdes if (nam->sa_len != sizeof(*sin6)) 138132793Sdes return(EINVAL); 139132793Sdes /* 140132793Sdes * family check. 141132793Sdes */ 142132793Sdes if (nam->sa_family != AF_INET6) 1431573Srgrimes return(EAFNOSUPPORT); 1441573Srgrimes 1451573Srgrimes /* KAME hack: embed scopeid */ 1461573Srgrimes if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0) 1471573Srgrimes return EINVAL; 1481573Srgrimes /* this must be cleared for ifa_ifwithaddr() */ 1491573Srgrimes sin6->sin6_scope_id = 0; 1501573Srgrimes 1511573Srgrimes lport = sin6->sin6_port; 152132793Sdes if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 1531573Srgrimes /* 1549978Swpaul * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; 1559978Swpaul * allow compepte duplication of binding if 1569978Swpaul * SO_REUSEPORT is set, or if SO_REUSEADDR is set 1579978Swpaul * and a multicast address is bound on both 1589978Swpaul * new and duplicated sockets. 1597336Swpaul */ 1607289Swpaul if (so->so_options & SO_REUSEADDR) 1617336Swpaul reuseport = SO_REUSEADDR|SO_REUSEPORT; 1627289Swpaul } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1637336Swpaul struct ifaddr *ia = NULL; 164237160Skib 1651573Srgrimes sin6->sin6_port = 0; /* yech... */ 1669978Swpaul if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0) 16710521Swpaul return(EADDRNOTAVAIL); 16810521Swpaul 1699978Swpaul /* 17015264Swpaul * XXX: bind to an anycast address might accidentally 1719978Swpaul * cause sending a packet with anycast source address. 1729978Swpaul * We should allow to bind to a deprecated address, since 1739978Swpaul * the application dare to use it. 174237160Skib */ 1759978Swpaul if (ia && 176244092Sjilles ((struct in6_ifaddr *)ia)->ia6_flags & 1779978Swpaul (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) { 1789978Swpaul return(EADDRNOTAVAIL); 1799978Swpaul } 1809978Swpaul } 1819978Swpaul if (lport) { 1829978Swpaul struct inpcb *t; 1839978Swpaul 1849978Swpaul /* GROSS */ 1859978Swpaul if (ntohs(lport) < IPV6PORT_RESERVED && td && 1869978Swpaul suser_xxx(0, td->td_proc, PRISON_ROOT)) 1879978Swpaul return(EACCES); 1889978Swpaul if (so->so_cred->cr_uid != 0 && 1899978Swpaul !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 1909978Swpaul t = in6_pcblookup_local(pcbinfo, 1919978Swpaul &sin6->sin6_addr, lport, 1929978Swpaul INPLOOKUP_WILDCARD); 19310521Swpaul if (t && 19410521Swpaul (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 19512585Swpaul !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) || 19612585Swpaul (t->inp_socket->so_options & 1979978Swpaul SO_REUSEPORT) == 0) && 19810521Swpaul (so->so_cred->cr_uid != 1999978Swpaul t->inp_socket->so_cred->cr_uid)) 200244092Sjilles return (EADDRINUSE); 2019978Swpaul if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && 2021573Srgrimes IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2031573Srgrimes struct sockaddr_in sin; 2041573Srgrimes 205235740Sghelmer in6_sin6_2_sin(&sin, sin6); 2061573Srgrimes t = in_pcblookup_local(pcbinfo, 2079978Swpaul sin.sin_addr, lport, 2089978Swpaul INPLOOKUP_WILDCARD); 2091573Srgrimes if (t && 2101573Srgrimes (so->so_cred->cr_uid != 2111573Srgrimes t->inp_socket->so_cred->cr_uid) && 2121573Srgrimes (ntohl(t->inp_laddr.s_addr) != 2131573Srgrimes INADDR_ANY || 2141573Srgrimes INP_SOCKAF(so) == 2151573Srgrimes INP_SOCKAF(t->inp_socket))) 2161573Srgrimes return (EADDRINUSE); 2171573Srgrimes } 218132793Sdes } 2191573Srgrimes t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, 2209978Swpaul lport, wild); 2219978Swpaul if (t && (reuseport & t->inp_socket->so_options) == 0) 2229978Swpaul return(EADDRINUSE); 2231573Srgrimes if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 && 2241573Srgrimes IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2251573Srgrimes struct sockaddr_in sin; 2261573Srgrimes 2271573Srgrimes in6_sin6_2_sin(&sin, sin6); 2281573Srgrimes t = in_pcblookup_local(pcbinfo, sin.sin_addr, 2291573Srgrimes lport, wild); 2301573Srgrimes if (t && 2311573Srgrimes (reuseport & t->inp_socket->so_options) 2321573Srgrimes == 0 && 2331573Srgrimes (ntohl(t->inp_laddr.s_addr) 2341573Srgrimes != INADDR_ANY || 2351573Srgrimes INP_SOCKAF(so) == 2361573Srgrimes INP_SOCKAF(t->inp_socket))) 2371573Srgrimes return (EADDRINUSE); 238132793Sdes } 2391573Srgrimes } 24090041Sobrien inp->in6p_laddr = sin6->sin6_addr; 24190041Sobrien } 2421573Srgrimes if (lport == 0) { 2431573Srgrimes int e; 2441573Srgrimes if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, td)) != 0) 2451573Srgrimes return(e); 2461573Srgrimes } 2471573Srgrimes else { 2481573Srgrimes inp->inp_lport = lport; 249237160Skib if (in_pcbinshash(inp) != 0) { 2501573Srgrimes inp->in6p_laddr = in6addr_any; 251237160Skib inp->inp_lport = 0; 2521573Srgrimes return (EAGAIN); 2531573Srgrimes } 254237160Skib } 2551573Srgrimes return(0); 2561573Srgrimes} 2571573Srgrimes 2581573Srgrimes/* 2591573Srgrimes * Transform old in6_pcbconnect() into an inner subroutine for new 260237160Skib * in6_pcbconnect(): Do some validity-checking on the remote 261237160Skib * address (in mbuf 'nam') and then determine local host address 262237160Skib * (i.e., which interface) to use to access that remote host. 263237160Skib * 2641573Srgrimes * This preserves definition of in6_pcbconnect(), while supporting a 265237160Skib * slightly different version for T/TCP. (This is more than 266237160Skib * a bit of a kludge, but cleaning up the internal interfaces would 2677149Swpaul * have forced minor changes in every protocol). 2687223Swpaul */ 2697149Swpaul 2701573Srgrimesint 2711573Srgrimesin6_pcbladdr(inp, nam, plocal_addr6) 2729978Swpaul register struct inpcb *inp; 273132793Sdes struct sockaddr *nam; 274132793Sdes struct in6_addr **plocal_addr6; 2759978Swpaul{ 276132793Sdes register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; 277132793Sdes struct ifnet *ifp = NULL; 27831180Swpaul int error = 0; 2799978Swpaul 28031180Swpaul if (nam->sa_len != sizeof (*sin6)) 281237160Skib return (EINVAL); 28231180Swpaul if (sin6->sin6_family != AF_INET6) 28315264Swpaul return (EAFNOSUPPORT); 28433950Ssteve if (sin6->sin6_port == 0) 28533950Ssteve return (EADDRNOTAVAIL); 28652856Sache 28733950Ssteve /* KAME hack: embed scopeid */ 28833950Ssteve if (in6_embedscope(&sin6->sin6_addr, sin6, inp, &ifp) != 0) 289235739Sghelmer return EINVAL; 290237160Skib 29133950Ssteve if (in6_ifaddr) { 29215839Swpaul /* 29315839Swpaul * If the destination address is UNSPECIFIED addr, 294235739Sghelmer * use the loopback addr, e.g ::1. 2959978Swpaul */ 2969978Swpaul if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 297132793Sdes sin6->sin6_addr = in6addr_loopback; 298148317Sjon } 299148317Sjon { 3009978Swpaul /* 301148317Sjon * XXX: in6_selectsrc might replace the bound local address 302148317Sjon * with the address specified by setsockopt(IPV6_PKTINFO). 303148317Sjon * Is it the intended behavior? 304148317Sjon */ 305148317Sjon *plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts, 306148317Sjon inp->in6p_moptions, 307148317Sjon &inp->in6p_route, 308236402Sghelmer &inp->in6p_laddr, &error); 309235739Sghelmer if (*plocal_addr6 == 0) { 310235739Sghelmer if (error == 0) 311235739Sghelmer error = EADDRNOTAVAIL; 312236402Sghelmer return(error); 313235739Sghelmer } 314235739Sghelmer /* 315236402Sghelmer * Don't do pcblookup call here; return interface in 316235739Sghelmer * plocal_addr6 317235739Sghelmer * and exit to caller, that will do the lookup. 318235739Sghelmer */ 319236402Sghelmer } 320235739Sghelmer 321235739Sghelmer if (inp->in6p_route.ro_rt) 322236402Sghelmer ifp = inp->in6p_route.ro_rt->rt_ifp; 323236402Sghelmer 324148317Sjon return(0); 325148317Sjon} 326236402Sghelmer 327148317Sjon/* 328148317Sjon * Outer subroutine: 329148317Sjon * Connect from a socket to a specified address. 330236402Sghelmer * Both address and port must be specified in argument sin. 331236402Sghelmer * If don't have a local address for this socket yet, 332148317Sjon * then pick one. 333148317Sjon */ 334148317Sjonint 335148317Sjonin6_pcbconnect(inp, nam, td) 336148317Sjon register struct inpcb *inp; 337148317Sjon struct sockaddr *nam; 338235739Sghelmer struct thread *td; 339148317Sjon{ 3409978Swpaul struct in6_addr *addr6; 3419978Swpaul register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; 3429978Swpaul int error; 3439978Swpaul 3441573Srgrimes /* 3451573Srgrimes * Call inner routine, to assign local interface address. 3461573Srgrimes */ 3471573Srgrimes if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0) 348132793Sdes return(error); 3491573Srgrimes 3501573Srgrimes if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr, 3517336Swpaul sin6->sin6_port, 3529287Swpaul IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) 3537336Swpaul ? addr6 : &inp->in6p_laddr, 3547336Swpaul inp->inp_lport, 0, NULL) != NULL) { 3557336Swpaul return (EADDRINUSE); 3569978Swpaul } 3579978Swpaul if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 3589978Swpaul if (inp->inp_lport == 0) { 3591573Srgrimes error = in6_pcbbind(inp, (struct sockaddr *)0, td); 3609978Swpaul if (error) 36115264Swpaul return (error); 3629978Swpaul } 3639978Swpaul inp->in6p_laddr = *addr6; 3649978Swpaul } 365148317Sjon inp->in6p_faddr = sin6->sin6_addr; 366148317Sjon inp->inp_fport = sin6->sin6_port; 367148317Sjon /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ 368148317Sjon inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 369148317Sjon if (inp->in6p_flags & IN6P_AUTOFLOWLABEL) 370148317Sjon inp->in6p_flowinfo |= 371148317Sjon (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK); 372148317Sjon 373148317Sjon in_pcbrehash(inp); 374148317Sjon return (0); 375148317Sjon} 376148317Sjon 377148317Sjon#if 0 378148317Sjon/* 379148317Sjon * Return an IPv6 address, which is the most appropriate for given 380148317Sjon * destination and user specified options. 381148317Sjon * If necessary, this function lookups the routing table and return 382148317Sjon * an entry to the caller for later use. 383148317Sjon */ 3849978Swpaulstruct in6_addr * 385148317Sjonin6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp) 386148317Sjon struct sockaddr_in6 *dstsock; 3879978Swpaul struct ip6_pktopts *opts; 388235739Sghelmer struct ip6_moptions *mopts; 389148317Sjon struct route_in6 *ro; 390148317Sjon struct in6_addr *laddr; 391148317Sjon int *errorp; 392148317Sjon{ 393235739Sghelmer struct in6_addr *dst; 394148317Sjon struct in6_ifaddr *ia6 = 0; 395235739Sghelmer struct in6_pktinfo *pi = NULL; 3969978Swpaul 39730390Swpaul dst = &dstsock->sin6_addr; 3989978Swpaul *errorp = 0; 3999978Swpaul 40030390Swpaul /* 4011573Srgrimes * If the source address is explicitly specified by the caller, 4029978Swpaul * use it. 4039978Swpaul */ 4049978Swpaul if (opts && (pi = opts->ip6po_pktinfo) && 4051573Srgrimes !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) 4061573Srgrimes return(&pi->ipi6_addr); 4071573Srgrimes 4081573Srgrimes /* 4091573Srgrimes * If the source address is not specified but the socket(if any) 4101573Srgrimes * is already bound, use the bound address. 4111573Srgrimes */ 4121573Srgrimes if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) 4131573Srgrimes return(laddr); 4141573Srgrimes 4151573Srgrimes /* 416132793Sdes * If the caller doesn't specify the source address but 4171573Srgrimes * the outgoing interface, use an address associated with 418236402Sghelmer * the interface. 419236402Sghelmer */ 420236402Sghelmer if (pi && pi->ipi6_ifindex) { 421236402Sghelmer /* XXX boundary check is assumed to be already done. */ 422236402Sghelmer ia6 = in6_ifawithscope(ifnet_byindex(pi->ipi6_ifindex), dst); 4239287Swpaul if (ia6 == 0) { 42490041Sobrien *errorp = EADDRNOTAVAIL; 4259287Swpaul return(0); 4261573Srgrimes } 4271573Srgrimes return(&satosin6(&ia6->ia_addr)->sin6_addr); 4281573Srgrimes } 4291573Srgrimes 4301573Srgrimes /* 4311573Srgrimes * If the destination address is a link-local unicast address or 4321573Srgrimes * a multicast address, and if the outgoing interface is specified 4331573Srgrimes * by the sin6_scope_id filed, use an address associated with the 4341573Srgrimes * interface. 435237160Skib * XXX: We're now trying to define more specific semantics of 4361573Srgrimes * sin6_scope_id field, so this part will be rewritten in 4371573Srgrimes * the near future. 4389287Swpaul */ 4399287Swpaul if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) && 4409287Swpaul dstsock->sin6_scope_id) { 4419287Swpaul /* 4429287Swpaul * I'm not sure if boundary check for scope_id is done 4439287Swpaul * somewhere... 4449287Swpaul */ 4451573Srgrimes if (dstsock->sin6_scope_id < 0 || 4469287Swpaul if_index < dstsock->sin6_scope_id) { 4471573Srgrimes *errorp = ENXIO; /* XXX: better error? */ 4481573Srgrimes return(0); 4491573Srgrimes } 4501573Srgrimes ia6 = in6_ifawithscope(ifnet_byindex(dstsock->sin6_scope_id), 4517149Swpaul dst); 4527149Swpaul if (ia6 == 0) { 4531573Srgrimes *errorp = EADDRNOTAVAIL; 454236402Sghelmer return(0); 455235740Sghelmer } 456235740Sghelmer return(&satosin6(&ia6->ia_addr)->sin6_addr); 457236402Sghelmer } 458236402Sghelmer 4591573Srgrimes /* 4601573Srgrimes * If the destination address is a multicast address and 4619287Swpaul * the outgoing interface for the address is specified 4629287Swpaul * by the caller, use an address associated with the interface. 4639287Swpaul * There is a sanity check here; if the destination has node-local 4641573Srgrimes * scope, the outgoing interfacde should be a loopback address. 465236402Sghelmer * Even if the outgoing interface is not specified, we also 4669287Swpaul * choose a loopback interface as the outgoing interface. 4679287Swpaul */ 4689287Swpaul if (IN6_IS_ADDR_MULTICAST(dst)) { 4699287Swpaul struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL; 4709287Swpaul 4719287Swpaul if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) { 472236402Sghelmer ifp = &loif[0]; 473236402Sghelmer } 4749287Swpaul 475236402Sghelmer if (ifp) { 476236402Sghelmer ia6 = in6_ifawithscope(ifp, dst); 477236402Sghelmer if (ia6 == 0) { 478236402Sghelmer *errorp = EADDRNOTAVAIL; 479236402Sghelmer return(0); 480236402Sghelmer } 481236402Sghelmer return(&ia6->ia_addr.sin6_addr); 482236402Sghelmer } 483236402Sghelmer } 484236402Sghelmer 485236402Sghelmer /* 486236402Sghelmer * If the next hop address for the packet is specified 487236402Sghelmer * by caller, use an address associated with the route 488236402Sghelmer * to the next hop. 489236402Sghelmer */ 490236402Sghelmer { 491236402Sghelmer struct sockaddr_in6 *sin6_next; 492236402Sghelmer struct rtentry *rt; 493236402Sghelmer 494236402Sghelmer if (opts && opts->ip6po_nexthop) { 495236402Sghelmer sin6_next = satosin6(opts->ip6po_nexthop); 4961573Srgrimes rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL); 497235740Sghelmer if (rt) { 498235740Sghelmer ia6 = in6_ifawithscope(rt->rt_ifp, dst); 4999287Swpaul if (ia6 == 0) 5009287Swpaul ia6 = ifatoia6(rt->rt_ifa); 5019287Swpaul } 5029287Swpaul if (ia6 == 0) { 5039287Swpaul *errorp = EADDRNOTAVAIL; 5049287Swpaul return(0); 5059287Swpaul } 506236402Sghelmer return(&satosin6(&ia6->ia_addr)->sin6_addr); 507236402Sghelmer } 508236402Sghelmer } 509236402Sghelmer 510236402Sghelmer /* 511236402Sghelmer * If route is known or can be allocated now, 512236402Sghelmer * our src addr is taken from the i/f, else punt. 513236402Sghelmer */ 514236402Sghelmer if (ro) { 5159287Swpaul if (ro->ro_rt && 5161573Srgrimes !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) { 5171573Srgrimes RTFREE(ro->ro_rt); 5181573Srgrimes ro->ro_rt = (struct rtentry *)0; 5197175Swpaul } 5201573Srgrimes if (ro->ro_rt == (struct rtentry *)0 || 52123668Speter ro->ro_rt->rt_ifp == (struct ifnet *)0) { 52223668Speter struct sockaddr_in6 *dst6; 52323668Speter 52423668Speter /* No route yet, so try to acquire one */ 5251573Srgrimes bzero(&ro->ro_dst, sizeof(struct sockaddr_in6)); 5261573Srgrimes dst6 = (struct sockaddr_in6 *)&ro->ro_dst; 5271573Srgrimes dst6->sin6_family = AF_INET6; 5281573Srgrimes dst6->sin6_len = sizeof(struct sockaddr_in6); 5291573Srgrimes dst6->sin6_addr = *dst; 5301573Srgrimes if (IN6_IS_ADDR_MULTICAST(dst)) { 5311573Srgrimes ro->ro_rt = rtalloc1(&((struct route *)ro) 5321573Srgrimes ->ro_dst, 0, 0UL); 5331573Srgrimes } else { 534132793Sdes rtalloc((struct route *)ro); 5351573Srgrimes } 536237159Skib } 53790041Sobrien 5381573Srgrimes /* 5391573Srgrimes * in_pcbconnect() checks out IFF_LOOPBACK to skip using 54020957Swpaul * the address. But we don't know why it does so. 5417149Swpaul * It is necessary to ensure the scope even for lo0 5427149Swpaul * so doesn't check out IFF_LOOPBACK. 5437149Swpaul */ 544235740Sghelmer 5451573Srgrimes if (ro->ro_rt) { 5467149Swpaul ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst); 5477149Swpaul if (ia6 == 0) /* xxx scope error ?*/ 5487149Swpaul ia6 = ifatoia6(ro->ro_rt->rt_ifa); 5497223Swpaul } 5507149Swpaul if (ia6 == 0) { 5517223Swpaul *errorp = EHOSTUNREACH; /* no route */ 552236402Sghelmer return(0); 5537223Swpaul } 5549978Swpaul return(&satosin6(&ia6->ia_addr)->sin6_addr); 5559978Swpaul } 5569978Swpaul 5579978Swpaul *errorp = EADDRNOTAVAIL; 5589978Swpaul return(0); 5599978Swpaul} 5607149Swpaul 56120957Swpaul/* 5627149Swpaul * Default hop limit selection. The precedence is as follows: 5637149Swpaul * 1. Hoplimit valued specified via ioctl. 5647149Swpaul * 2. (If the outgoing interface is detected) the current 565235740Sghelmer * hop limit of the interface specified by router advertisement. 5661573Srgrimes * 3. The system default hoplimit. 5677149Swpaul*/ 5687149Swpaulint 5697149Swpaulin6_selecthlim(in6p, ifp) 5707149Swpaul struct in6pcb *in6p; 5717149Swpaul struct ifnet *ifp; 5727149Swpaul{ 5737149Swpaul if (in6p && in6p->in6p_hops >= 0) 5747149Swpaul return(in6p->in6p_hops); 5751573Srgrimes else if (ifp) 5761573Srgrimes return(nd_ifinfo[ifp->if_index].chlim); 5771573Srgrimes else 5781573Srgrimes return(ip6_defhlim); 5791573Srgrimes} 5801573Srgrimes#endif 5811573Srgrimes 5821573Srgrimesvoid 5831573Srgrimesin6_pcbdisconnect(inp) 5841573Srgrimes struct inpcb *inp; 5851573Srgrimes{ 5861573Srgrimes bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr)); 5871573Srgrimes inp->inp_fport = 0; 588235740Sghelmer /* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ 589235740Sghelmer inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 5901573Srgrimes in_pcbrehash(inp); 5911573Srgrimes if (inp->inp_socket->so_state & SS_NOFDREF) 592235740Sghelmer in6_pcbdetach(inp); 593235740Sghelmer} 594235740Sghelmer 595235740Sghelmervoid 5961573Srgrimesin6_pcbdetach(inp) 5971573Srgrimes struct inpcb *inp; 5981573Srgrimes{ 5991573Srgrimes struct socket *so = inp->inp_socket; 6001573Srgrimes struct inpcbinfo *ipi = inp->inp_pcbinfo; 6011573Srgrimes 6021573Srgrimes#ifdef IPSEC 6031573Srgrimes if (inp->in6p_sp != NULL) 6041573Srgrimes ipsec6_delete_pcbpolicy(inp); 6051573Srgrimes#endif /* IPSEC */ 6061573Srgrimes inp->inp_gencnt = ++ipi->ipi_gencnt; 6071573Srgrimes in_pcbremlists(inp); 6081573Srgrimes sotoinpcb(so) = 0; 6091573Srgrimes sofree(so); 6101573Srgrimes 6111573Srgrimes if (inp->in6p_options) 6121573Srgrimes m_freem(inp->in6p_options); 613237159Skib ip6_freepcbopts(inp->in6p_outputopts); 614235740Sghelmer ip6_freemoptions(inp->in6p_moptions); 615235740Sghelmer if (inp->in6p_route.ro_rt) 616235740Sghelmer rtfree(inp->in6p_route.ro_rt); 617235740Sghelmer /* Check and free IPv4 related resources in case of mapped addr */ 6181573Srgrimes if (inp->inp_options) 619237159Skib (void)m_free(inp->inp_options); 620237159Skib ip_freemoptions(inp->inp_moptions); 621237159Skib 622237159Skib inp->inp_vflag = 0; 6231573Srgrimes zfree(ipi->ipi_zone, inp); 6241573Srgrimes} 6251573Srgrimes 626237159Skib/* 6271573Srgrimes * The calling convention of in6_setsockaddr() and in6_setpeeraddr() was 6281573Srgrimes * modified to match the pru_sockaddr() and pru_peeraddr() entry points 6291573Srgrimes * in struct pr_usrreqs, so that protocols can just reference then directly 6301573Srgrimes * without the need for a wrapper function. The socket must have a valid 6311573Srgrimes * (i.e., non-nil) PCB, but it should be impossible to get an invalid one 6321573Srgrimes * except through a kernel programming error, so it is acceptable to panic 6331573Srgrimes * (or in this case trap) if the PCB is invalid. (Actually, we don't trap 6341573Srgrimes * because there actually /is/ a programming error somewhere... XXX) 6351573Srgrimes */ 6361573Srgrimesint 6371573Srgrimesin6_setsockaddr(so, nam) 6381573Srgrimes struct socket *so; 6391573Srgrimes struct sockaddr **nam; 6401573Srgrimes{ 6411573Srgrimes int s; 6421573Srgrimes register struct inpcb *inp; 6431573Srgrimes register struct sockaddr_in6 *sin6; 6441573Srgrimes 6451573Srgrimes /* 6461573Srgrimes * Do the malloc first in case it blocks. 6479978Swpaul */ 6489978Swpaul MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME, M_WAITOK); 6499978Swpaul bzero(sin6, sizeof *sin6); 6509978Swpaul sin6->sin6_family = AF_INET6; 6519978Swpaul sin6->sin6_len = sizeof(*sin6); 6529978Swpaul 6539978Swpaul s = splnet(); 6549978Swpaul inp = sotoinpcb(so); 6559978Swpaul if (!inp) { 6569978Swpaul splx(s); 657235740Sghelmer free(sin6, M_SONAME); 6581573Srgrimes return EINVAL; 659 } 660 sin6->sin6_port = inp->inp_lport; 661 sin6->sin6_addr = inp->in6p_laddr; 662 splx(s); 663 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) 664 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]); 665 else 666 sin6->sin6_scope_id = 0; /*XXX*/ 667 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) 668 sin6->sin6_addr.s6_addr16[1] = 0; 669 670 *nam = (struct sockaddr *)sin6; 671 return 0; 672} 673 674int 675in6_setpeeraddr(so, nam) 676 struct socket *so; 677 struct sockaddr **nam; 678{ 679 int s; 680 struct inpcb *inp; 681 register struct sockaddr_in6 *sin6; 682 683 /* 684 * Do the malloc first in case it blocks. 685 */ 686 MALLOC(sin6, struct sockaddr_in6 *, sizeof(*sin6), M_SONAME, M_WAITOK); 687 bzero((caddr_t)sin6, sizeof (*sin6)); 688 sin6->sin6_family = AF_INET6; 689 sin6->sin6_len = sizeof(struct sockaddr_in6); 690 691 s = splnet(); 692 inp = sotoinpcb(so); 693 if (!inp) { 694 splx(s); 695 free(sin6, M_SONAME); 696 return EINVAL; 697 } 698 sin6->sin6_port = inp->inp_fport; 699 sin6->sin6_addr = inp->in6p_faddr; 700 splx(s); 701 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) 702 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]); 703 else 704 sin6->sin6_scope_id = 0; /*XXX*/ 705 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) 706 sin6->sin6_addr.s6_addr16[1] = 0; 707 708 *nam = (struct sockaddr *)sin6; 709 return 0; 710} 711 712int 713in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam) 714{ 715 struct inpcb *inp = sotoinpcb(so); 716 int error; 717 718 if (inp == NULL) 719 return EINVAL; 720 if (inp->inp_vflag & INP_IPV4) { 721 error = in_setsockaddr(so, nam); 722 if (error == 0) 723 in6_sin_2_v4mapsin6_in_sock(nam); 724 } else 725 error = in6_setsockaddr(so, nam); 726 727 return error; 728} 729 730int 731in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam) 732{ 733 struct inpcb *inp = sotoinpcb(so); 734 int error; 735 736 if (inp == NULL) 737 return EINVAL; 738 if (inp->inp_vflag & INP_IPV4) { 739 error = in_setpeeraddr(so, nam); 740 if (error == 0) 741 in6_sin_2_v4mapsin6_in_sock(nam); 742 } else 743 error = in6_setpeeraddr(so, nam); 744 745 return error; 746} 747 748/* 749 * Pass some notification to all connections of a protocol 750 * associated with address dst. The local address and/or port numbers 751 * may be specified to limit the search. The "usual action" will be 752 * taken, depending on the ctlinput cmd. The caller must filter any 753 * cmds that are uninteresting (e.g., no error in the map). 754 * Call the protocol specific routine (if any) to report 755 * any errors for each matching socket. 756 * 757 * Must be called at splnet. 758 */ 759void 760in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, notify) 761 struct inpcbhead *head; 762 struct sockaddr *dst, *src; 763 u_int fport_arg, lport_arg; 764 int cmd; 765 void (*notify) __P((struct inpcb *, int)); 766{ 767 struct inpcb *inp, *ninp; 768 struct sockaddr_in6 sa6_src, *sa6_dst; 769 u_short fport = fport_arg, lport = lport_arg; 770 u_int32_t flowinfo; 771 int errno, s; 772 773 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6) 774 return; 775 776 sa6_dst = (struct sockaddr_in6 *)dst; 777 if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr)) 778 return; 779 780 /* 781 * note that src can be NULL when we get notify by local fragmentation. 782 */ 783 sa6_src = (src == NULL) ? sa6_any : *(struct sockaddr_in6 *)src; 784 flowinfo = sa6_src.sin6_flowinfo; 785 786 /* 787 * Redirects go to all references to the destination, 788 * and use in6_rtchange to invalidate the route cache. 789 * Dead host indications: also use in6_rtchange to invalidate 790 * the cache, and deliver the error to all the sockets. 791 * Otherwise, if we have knowledge of the local port and address, 792 * deliver only to that socket. 793 */ 794 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { 795 fport = 0; 796 lport = 0; 797 bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr)); 798 799 if (cmd != PRC_HOSTDEAD) 800 notify = in6_rtchange; 801 } 802 errno = inet6ctlerrmap[cmd]; 803 s = splnet(); 804 for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) { 805 ninp = LIST_NEXT(inp, inp_list); 806 807 if ((inp->inp_vflag & INP_IPV6) == 0) 808 continue; 809 810 /* 811 * Detect if we should notify the error. If no source and 812 * destination ports are specifed, but non-zero flowinfo and 813 * local address match, notify the error. This is the case 814 * when the error is delivered with an encrypted buffer 815 * by ESP. Otherwise, just compare addresses and ports 816 * as usual. 817 */ 818 if (lport == 0 && fport == 0 && flowinfo && 819 inp->inp_socket != NULL && 820 flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) && 821 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr)) 822 goto do_notify; 823 else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, 824 &sa6_dst->sin6_addr) || 825 inp->inp_socket == 0 || 826 (lport && inp->inp_lport != lport) || 827 (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) && 828 !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, 829 &sa6_src.sin6_addr)) || 830 (fport && inp->inp_fport != fport)) 831 continue; 832 833 do_notify: 834 if (notify) 835 (*notify)(inp, errno); 836 } 837 splx(s); 838} 839 840/* 841 * Lookup a PCB based on the local address and port. 842 */ 843struct inpcb * 844in6_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay) 845 struct inpcbinfo *pcbinfo; 846 struct in6_addr *laddr; 847 u_int lport_arg; 848 int wild_okay; 849{ 850 register struct inpcb *inp; 851 int matchwild = 3, wildcard; 852 u_short lport = lport_arg; 853 854 if (!wild_okay) { 855 struct inpcbhead *head; 856 /* 857 * Look for an unconnected (wildcard foreign addr) PCB that 858 * matches the local address and port we're looking for. 859 */ 860 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, 861 pcbinfo->hashmask)]; 862 LIST_FOREACH(inp, head, inp_hash) { 863 if ((inp->inp_vflag & INP_IPV6) == 0) 864 continue; 865 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && 866 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 867 inp->inp_lport == lport) { 868 /* 869 * Found. 870 */ 871 return (inp); 872 } 873 } 874 /* 875 * Not found. 876 */ 877 return (NULL); 878 } else { 879 struct inpcbporthead *porthash; 880 struct inpcbport *phd; 881 struct inpcb *match = NULL; 882 /* 883 * Best fit PCB lookup. 884 * 885 * First see if this local port is in use by looking on the 886 * port hash list. 887 */ 888 porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport, 889 pcbinfo->porthashmask)]; 890 LIST_FOREACH(phd, porthash, phd_hash) { 891 if (phd->phd_port == lport) 892 break; 893 } 894 if (phd != NULL) { 895 /* 896 * Port is in use by one or more PCBs. Look for best 897 * fit. 898 */ 899 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) { 900 wildcard = 0; 901 if ((inp->inp_vflag & INP_IPV6) == 0) 902 continue; 903 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) 904 wildcard++; 905 if (!IN6_IS_ADDR_UNSPECIFIED( 906 &inp->in6p_laddr)) { 907 if (IN6_IS_ADDR_UNSPECIFIED(laddr)) 908 wildcard++; 909 else if (!IN6_ARE_ADDR_EQUAL( 910 &inp->in6p_laddr, laddr)) 911 continue; 912 } else { 913 if (!IN6_IS_ADDR_UNSPECIFIED(laddr)) 914 wildcard++; 915 } 916 if (wildcard < matchwild) { 917 match = inp; 918 matchwild = wildcard; 919 if (matchwild == 0) { 920 break; 921 } 922 } 923 } 924 } 925 return (match); 926 } 927} 928 929void 930in6_pcbpurgeif0(head, ifp) 931 struct in6pcb *head; 932 struct ifnet *ifp; 933{ 934 struct in6pcb *in6p; 935 struct ip6_moptions *im6o; 936 struct in6_multi_mship *imm, *nimm; 937 938 for (in6p = head; in6p != NULL; in6p = LIST_NEXT(in6p, inp_list)) { 939 im6o = in6p->in6p_moptions; 940 if ((in6p->inp_vflag & INP_IPV6) && 941 im6o) { 942 /* 943 * Unselect the outgoing interface if it is being 944 * detached. 945 */ 946 if (im6o->im6o_multicast_ifp == ifp) 947 im6o->im6o_multicast_ifp = NULL; 948 949 /* 950 * Drop multicast group membership if we joined 951 * through the interface being detached. 952 * XXX controversial - is it really legal for kernel 953 * to force this? 954 */ 955 for (imm = im6o->im6o_memberships.lh_first; 956 imm != NULL; imm = nimm) { 957 nimm = imm->i6mm_chain.le_next; 958 if (imm->i6mm_maddr->in6m_ifp == ifp) { 959 LIST_REMOVE(imm, i6mm_chain); 960 in6_delmulti(imm->i6mm_maddr); 961 free(imm, M_IPMADDR); 962 } 963 } 964 } 965 } 966} 967 968/* 969 * Check for alternatives when higher level complains 970 * about service problems. For now, invalidate cached 971 * routing information. If the route was created dynamically 972 * (by a redirect), time to try a default gateway again. 973 */ 974void 975in6_losing(in6p) 976 struct inpcb *in6p; 977{ 978 struct rtentry *rt; 979 struct rt_addrinfo info; 980 981 if ((rt = in6p->in6p_route.ro_rt) != NULL) { 982 bzero((caddr_t)&info, sizeof(info)); 983 info.rti_flags = rt->rt_flags; 984 info.rti_info[RTAX_DST] = rt_key(rt); 985 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 986 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 987 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0); 988 if (rt->rt_flags & RTF_DYNAMIC) 989 (void)rtrequest1(RTM_DELETE, &info, NULL); 990 in6p->in6p_route.ro_rt = NULL; 991 rtfree(rt); 992 /* 993 * A new route can be allocated 994 * the next time output is attempted. 995 */ 996 } 997} 998 999/* 1000 * After a routing change, flush old routing 1001 * and allocate a (hopefully) better one. 1002 */ 1003void 1004in6_rtchange(inp, errno) 1005 struct inpcb *inp; 1006 int errno; 1007{ 1008 if (inp->in6p_route.ro_rt) { 1009 rtfree(inp->in6p_route.ro_rt); 1010 inp->in6p_route.ro_rt = 0; 1011 /* 1012 * A new route can be allocated the next time 1013 * output is attempted. 1014 */ 1015 } 1016} 1017 1018/* 1019 * Lookup PCB in hash list. 1020 */ 1021struct inpcb * 1022in6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp) 1023 struct inpcbinfo *pcbinfo; 1024 struct in6_addr *faddr, *laddr; 1025 u_int fport_arg, lport_arg; 1026 int wildcard; 1027 struct ifnet *ifp; 1028{ 1029 struct inpcbhead *head; 1030 register struct inpcb *inp; 1031 u_short fport = fport_arg, lport = lport_arg; 1032 int faith; 1033 1034 if (faithprefix_p != NULL) 1035 faith = (*faithprefix_p)(laddr); 1036 else 1037 faith = 0; 1038 1039 /* 1040 * First look for an exact match. 1041 */ 1042 head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */, 1043 lport, fport, 1044 pcbinfo->hashmask)]; 1045 LIST_FOREACH(inp, head, inp_hash) { 1046 if ((inp->inp_vflag & INP_IPV6) == 0) 1047 continue; 1048 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) && 1049 IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) && 1050 inp->inp_fport == fport && 1051 inp->inp_lport == lport) { 1052 /* 1053 * Found. 1054 */ 1055 return (inp); 1056 } 1057 } 1058 if (wildcard) { 1059 struct inpcb *local_wild = NULL; 1060 1061 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, 1062 pcbinfo->hashmask)]; 1063 LIST_FOREACH(inp, head, inp_hash) { 1064 if ((inp->inp_vflag & INP_IPV6) == 0) 1065 continue; 1066 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && 1067 inp->inp_lport == lport) { 1068 if (faith && (inp->inp_flags & INP_FAITH) == 0) 1069 continue; 1070 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, 1071 laddr)) 1072 return (inp); 1073 else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 1074 local_wild = inp; 1075 } 1076 } 1077 return (local_wild); 1078 } 1079 1080 /* 1081 * Not found. 1082 */ 1083 return (NULL); 1084} 1085 1086void 1087init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m) 1088{ 1089 struct ip6_hdr *ip; 1090 1091 ip = mtod(m, struct ip6_hdr *); 1092 bzero(sin6, sizeof(*sin6)); 1093 sin6->sin6_len = sizeof(*sin6); 1094 sin6->sin6_family = AF_INET6; 1095 sin6->sin6_addr = ip->ip6_src; 1096 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) 1097 sin6->sin6_addr.s6_addr16[1] = 0; 1098 sin6->sin6_scope_id = 1099 (m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) 1100 ? m->m_pkthdr.rcvif->if_index : 0; 1101 1102 return; 1103} 1104