The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet6/in6_pcb.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $FreeBSD: src/sys/netinet6/in6_pcb.c,v 1.10.2.9 2003/01/24 05:11:35 sam Exp $   */
    2 /*      $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $        */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  */
   33 
   34 /*
   35  * Copyright (c) 1982, 1986, 1991, 1993
   36  *      The Regents of the University of California.  All rights reserved.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. Neither the name of the University nor the names of its contributors
   47  *    may be used to endorse or promote products derived from this software
   48  *    without specific prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   60  * SUCH DAMAGE.
   61  *
   62  *      @(#)in_pcb.c    8.2 (Berkeley) 1/4/94
   63  */
   64 
   65 #include "opt_inet.h"
   66 #include "opt_inet6.h"
   67 #include "opt_ipsec.h"
   68 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/malloc.h>
   72 #include <sys/mbuf.h>
   73 #include <sys/domain.h>
   74 #include <sys/protosw.h>
   75 #include <sys/socket.h>
   76 #include <sys/socketvar.h>
   77 #include <sys/sockio.h>
   78 #include <sys/errno.h>
   79 #include <sys/time.h>
   80 #include <sys/proc.h>
   81 #include <sys/priv.h>
   82 #include <sys/jail.h>
   83 
   84 #include <sys/thread2.h>
   85 #include <sys/msgport2.h>
   86 
   87 #include <vm/vm_zone.h>
   88 
   89 #include <net/if.h>
   90 #include <net/if_types.h>
   91 #include <net/route.h>
   92 
   93 #include <netinet/in.h>
   94 #include <netinet/in_var.h>
   95 #include <netinet/in_systm.h>
   96 #include <netinet/ip6.h>
   97 #include <netinet/ip_var.h>
   98 #include <netinet6/ip6_var.h>
   99 #include <netinet6/nd6.h>
  100 #include <netinet/in_pcb.h>
  101 #include <netinet6/in6_pcb.h>
  102 
  103 #ifdef IPSEC
  104 #include <netinet6/ipsec.h>
  105 #ifdef INET6
  106 #include <netinet6/ipsec6.h>
  107 #endif
  108 #include <netinet6/ah.h>
  109 #ifdef INET6
  110 #include <netinet6/ah6.h>
  111 #endif
  112 #include <netproto/key/key.h>
  113 #endif /* IPSEC */
  114 
  115 #ifdef FAST_IPSEC
  116 #include <netproto/ipsec/ipsec.h>
  117 #include <netproto/ipsec/ipsec6.h>
  118 #include <netproto/ipsec/key.h>
  119 #define IPSEC
  120 #endif /* FAST_IPSEC */
  121 
  122 struct  in6_addr zeroin6_addr;
  123 
  124 int
  125 in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
  126 {
  127         struct socket *so = inp->inp_socket;
  128         struct sockaddr_in6 *sin6 = NULL;
  129         struct sockaddr_in6 jsin6;
  130         struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
  131         struct proc *p = td->td_proc;
  132         struct ucred *cred = NULL;
  133         u_short lport = 0;
  134         int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
  135 
  136         if (!in6_ifaddr) /* XXX broken! */
  137                 return (EADDRNOTAVAIL);
  138         if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
  139                 return (EINVAL);
  140         if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
  141                 wild = 1;
  142         if (p)
  143                 cred = p->p_ucred;
  144         if (nam) {
  145                 sin6 = (struct sockaddr_in6 *)nam;
  146                 if (nam->sa_len != sizeof(*sin6))
  147                         return (EINVAL);
  148                 /*
  149                  * family check.
  150                  */
  151                 if (nam->sa_family != AF_INET6)
  152                         return (EAFNOSUPPORT);
  153 
  154                 if (!prison_replace_wildcards(td, nam))
  155                         return (EINVAL);
  156 
  157                 /* KAME hack: embed scopeid */
  158                 if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0)
  159                         return EINVAL;
  160                 /* this must be cleared for ifa_ifwithaddr() */
  161                 sin6->sin6_scope_id = 0;
  162 
  163                 lport = sin6->sin6_port;
  164                 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
  165                         /*
  166                          * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
  167                          * allow compepte duplication of binding if
  168                          * SO_REUSEPORT is set, or if SO_REUSEADDR is set
  169                          * and a multicast address is bound on both
  170                          * new and duplicated sockets.
  171                          */
  172                         if (so->so_options & SO_REUSEADDR)
  173                                 reuseport = SO_REUSEADDR|SO_REUSEPORT;
  174                 } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  175                         struct ifaddr *ia = NULL;
  176 
  177                         sin6->sin6_port = 0;            /* yech... */
  178                         if (!prison_replace_wildcards(td, (struct sockaddr *)sin6)) {
  179                                 sin6->sin6_addr = kin6addr_any;
  180                                 return(EINVAL);
  181                         }
  182                         if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == NULL)
  183                                 return (EADDRNOTAVAIL);
  184 
  185                         /*
  186                          * XXX: bind to an anycast address might accidentally
  187                          * cause sending a packet with anycast source address.
  188                          * We should allow to bind to a deprecated address, since
  189                          * the application dare to use it.
  190                          */
  191                         if (ia &&
  192                             ((struct in6_ifaddr *)ia)->ia6_flags &
  193                             (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
  194                                 return (EADDRNOTAVAIL);
  195                         }
  196                 }
  197                 if (lport) {
  198                         struct inpcb *t;
  199 
  200                         /* GROSS */
  201                         if (ntohs(lport) < IPV6PORT_RESERVED && cred &&
  202                             priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0))
  203                                 return (EACCES);
  204                         if (so->so_cred->cr_uid != 0 &&
  205                             !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
  206                                 t = in6_pcblookup_local(pcbinfo,
  207                                     &sin6->sin6_addr, lport,
  208                                     INPLOOKUP_WILDCARD, cred);
  209                                 if (t &&
  210                                     (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
  211                                      !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
  212                                      (t->inp_socket->so_options &
  213                                       SO_REUSEPORT) == 0) &&
  214                                     (so->so_cred->cr_uid !=
  215                                      t->inp_socket->so_cred->cr_uid))
  216                                         return (EADDRINUSE);
  217                                 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
  218                                     IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  219                                         struct sockaddr_in sin;
  220 
  221                                         in6_sin6_2_sin(&sin, sin6);
  222                                         t = in_pcblookup_local(pcbinfo,
  223                                                 sin.sin_addr, lport,
  224                                                 INPLOOKUP_WILDCARD, cred);
  225                                         if (t &&
  226                                             (so->so_cred->cr_uid !=
  227                                              t->inp_socket->so_cred->cr_uid) &&
  228                                             (ntohl(t->inp_laddr.s_addr) !=
  229                                              INADDR_ANY ||
  230                                              INP_SOCKAF(so) ==
  231                                              INP_SOCKAF(t->inp_socket)))
  232                                                 return (EADDRINUSE);
  233                                 }
  234                         }
  235                         if (cred && cred->cr_prison &&
  236                             !prison_replace_wildcards(td, nam))
  237                                 return(EADDRNOTAVAIL);
  238                         t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
  239                                                 lport, wild, cred);
  240                         if (t && (reuseport & t->inp_socket->so_options) == 0)
  241                                 return (EADDRINUSE);
  242                         if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
  243                             IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
  244                                 struct sockaddr_in sin;
  245 
  246                                 in6_sin6_2_sin(&sin, sin6);
  247                                 t = in_pcblookup_local(pcbinfo,
  248                                                        sin.sin_addr, lport,
  249                                                        wild, cred);
  250                                 if (t &&
  251                                     (reuseport & t->inp_socket->so_options)
  252                                     == 0 &&
  253                                     (ntohl(t->inp_laddr.s_addr)
  254                                      != INADDR_ANY ||
  255                                      INP_SOCKAF(so) ==
  256                                      INP_SOCKAF(t->inp_socket)))
  257                                         return (EADDRINUSE);
  258                         }
  259                 }
  260                 inp->in6p_laddr = sin6->sin6_addr;
  261         }
  262         if (lport == 0) {
  263                 int e;
  264 
  265                 jsin6.sin6_addr = inp->in6p_laddr;
  266                 jsin6.sin6_family = AF_INET6;
  267                 if (!prison_replace_wildcards(td, (struct sockaddr*)&jsin6)) {
  268                         inp->in6p_laddr = kin6addr_any;
  269                         inp->inp_lport = 0;
  270                         return (EINVAL);
  271                 }
  272 
  273                 if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, td)) != 0)
  274                         return (e);
  275         }
  276         else {
  277                 inp->inp_lport = lport;
  278                 if (in_pcbinsporthash(inp) != 0) {
  279                         inp->in6p_laddr = kin6addr_any;
  280                         inp->inp_lport = 0;
  281                         return (EAGAIN);
  282                 }
  283         }
  284         return (0);
  285 }
  286 
  287 /*
  288  *   Transform old in6_pcbconnect() into an inner subroutine for new
  289  *   in6_pcbconnect(): Do some validity-checking on the remote
  290  *   address (in mbuf 'nam') and then determine local host address
  291  *   (i.e., which interface) to use to access that remote host.
  292  *
  293  *   This preserves definition of in6_pcbconnect(), while supporting a
  294  *   slightly different version for T/TCP.  (This is more than
  295  *   a bit of a kludge, but cleaning up the internal interfaces would
  296  *   have forced minor changes in every protocol).
  297  */
  298 
  299 int
  300 in6_pcbladdr(struct inpcb *inp, struct sockaddr *nam,
  301              struct in6_addr **plocal_addr6, struct thread *td)
  302 {
  303         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
  304         struct ifnet *ifp = NULL;
  305         int error = 0;
  306 
  307         if (nam->sa_len != sizeof (*sin6))
  308                 return (EINVAL);
  309         if (sin6->sin6_family != AF_INET6)
  310                 return (EAFNOSUPPORT);
  311         if (sin6->sin6_port == 0)
  312                 return (EADDRNOTAVAIL);
  313 
  314         /* KAME hack: embed scopeid */
  315         if (in6_embedscope(&sin6->sin6_addr, sin6, inp, &ifp) != 0)
  316                 return EINVAL;
  317 
  318         if (in6_ifaddr) {
  319                 /*
  320                  * If the destination address is UNSPECIFIED addr,
  321                  * use the loopback addr, e.g ::1.
  322                  */
  323                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
  324                         sin6->sin6_addr = kin6addr_loopback;
  325         }
  326         {
  327                 /*
  328                  * XXX: in6_selectsrc might replace the bound local address
  329                  * with the address specified by setsockopt(IPV6_PKTINFO).
  330                  * Is it the intended behavior?
  331                  */
  332                 *plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
  333                                               inp->in6p_moptions,
  334                                               &inp->in6p_route,
  335                                               &inp->in6p_laddr, &error, td);
  336                 if (*plocal_addr6 == NULL) {
  337                         if (error == 0)
  338                                 error = EADDRNOTAVAIL;
  339                         return (error);
  340                 }
  341                 /*
  342                  * Don't do pcblookup call here; return interface in
  343                  * plocal_addr6
  344                  * and exit to caller, that will do the lookup.
  345                  */
  346         }
  347 
  348         if (inp->in6p_route.ro_rt)
  349                 ifp = inp->in6p_route.ro_rt->rt_ifp;
  350 
  351         return (0);
  352 }
  353 
  354 /*
  355  * Outer subroutine:
  356  * Connect from a socket to a specified address.
  357  * Both address and port must be specified in argument sin.
  358  * If don't have a local address for this socket yet,
  359  * then pick one.
  360  */
  361 int
  362 in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
  363 {
  364         struct in6_addr *addr6;
  365         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
  366         int error;
  367 
  368         /*
  369          * Call inner routine, to assign local interface address.
  370          * in6_pcbladdr() may automatically fill in sin6_scope_id.
  371          */
  372         if ((error = in6_pcbladdr(inp, nam, &addr6, td)) != 0)
  373                 return (error);
  374 
  375         if (in6_pcblookup_hash(inp->inp_cpcbinfo, &sin6->sin6_addr,
  376                                sin6->sin6_port,
  377                               IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
  378                               ? addr6 : &inp->in6p_laddr,
  379                               inp->inp_lport, 0, NULL) != NULL) {
  380                 return (EADDRINUSE);
  381         }
  382         if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
  383                 if (inp->inp_lport == 0) {
  384                         error = in6_pcbbind(inp, NULL, td);
  385                         if (error)
  386                                 return (error);
  387                 }
  388                 inp->in6p_laddr = *addr6;
  389         }
  390         inp->in6p_faddr = sin6->sin6_addr;
  391         inp->inp_fport = sin6->sin6_port;
  392         /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
  393         inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
  394         if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
  395                 inp->in6p_flowinfo |=
  396                     (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
  397 
  398         in_pcbinsconnhash(inp);
  399         return (0);
  400 }
  401 
  402 #if 0
  403 /*
  404  * Return an IPv6 address, which is the most appropriate for given
  405  * destination and user specified options.
  406  * If necessary, this function lookups the routing table and return
  407  * an entry to the caller for later use.
  408  */
  409 struct in6_addr *
  410 in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
  411               struct ip6_moptions *mopts, struct route_in6 *ro,
  412               struct in6_addr *laddr, int *errorp, struct thread *td)
  413 {
  414         struct sockaddr_in6 jsin6;
  415         struct ucred *cred = NULL;
  416         struct in6_addr *dst;
  417         struct in6_ifaddr *ia6 = 0;
  418         struct in6_pktinfo *pi = NULL;
  419         int jailed = 0;
  420 
  421         if (td && td->td_proc && td->td_proc->p_ucred)
  422                 cred = td->td_proc->p_ucred;
  423         if (cred && cred->cr_prison)
  424                 jailed = 1;
  425         jsin6.sin6_family = AF_INET6;
  426         dst = &dstsock->sin6_addr;
  427         *errorp = 0;
  428 
  429         /*
  430          * If the source address is explicitly specified by the caller,
  431          * use it.
  432          */
  433         if (opts && (pi = opts->ip6po_pktinfo) &&
  434             !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
  435                 jsin6.sin6_addr = pi->ipi6_addr;
  436                 if (jailed && !jailed_ip(cred->cr_prison,
  437                     (struct sockaddr *)&jsin6)) {
  438                         return(0);
  439                 } else {
  440                         return (&pi->ipi6_addr);
  441                 }
  442         }
  443 
  444         /*
  445          * If the source address is not specified but the socket(if any)
  446          * is already bound, use the bound address.
  447          */
  448         if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) {
  449                 jsin6.sin6_addr = *laddr;
  450                 if (jailed && !jailed_ip(cred->cr_prison,
  451                     (struct sockaddr *)&jsin6)) {
  452                         return(0);
  453                 } else {
  454                         return (laddr);
  455                 }
  456         }
  457 
  458         /*
  459          * If the caller doesn't specify the source address but
  460          * the outgoing interface, use an address associated with
  461          * the interface.
  462          */
  463         if (pi && pi->ipi6_ifindex) {
  464                 /* XXX boundary check is assumed to be already done. */
  465                 ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
  466                                        dst);
  467 
  468                 if (ia6 && jailed) {
  469                         jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
  470                         if (!jailed_ip(cred->cr_prison,
  471                                 (struct sockaddr *)&jsin6))
  472                                 ia6 = 0;
  473                 }
  474 
  475                 if (ia6 == 0) {
  476                         *errorp = EADDRNOTAVAIL;
  477                         return (0);
  478                 }
  479                 return (&satosin6(&ia6->ia_addr)->sin6_addr);
  480         }
  481 
  482         /*
  483          * If the destination address is a link-local unicast address or
  484          * a multicast address, and if the outgoing interface is specified
  485          * by the sin6_scope_id filed, use an address associated with the
  486          * interface.
  487          * XXX: We're now trying to define more specific semantics of
  488          *      sin6_scope_id field, so this part will be rewritten in
  489          *      the near future.
  490          */
  491         if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
  492             dstsock->sin6_scope_id) {
  493                 /*
  494                  * I'm not sure if boundary check for scope_id is done
  495                  * somewhere...
  496                  */
  497                 if (dstsock->sin6_scope_id < 0 ||
  498                     if_index < dstsock->sin6_scope_id) {
  499                         *errorp = ENXIO; /* XXX: better error? */
  500                         return (0);
  501                 }
  502                 ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
  503                                        dst);
  504 
  505                 if (ia6 && jailed) {
  506                         jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
  507                         if (!jailed_ip(cred->cr_prison,
  508                                 (struct sockaddr *)&jsin6))
  509                                 ia6 = 0;
  510                 }
  511 
  512                 if (ia6 == 0) {
  513                         *errorp = EADDRNOTAVAIL;
  514                         return (0);
  515                 }
  516                 return (&satosin6(&ia6->ia_addr)->sin6_addr);
  517         }
  518 
  519         /*
  520          * If the destination address is a multicast address and
  521          * the outgoing interface for the address is specified
  522          * by the caller, use an address associated with the interface.
  523          * There is a sanity check here; if the destination has node-local
  524          * scope, the outgoing interfacde should be a loopback address.
  525          * Even if the outgoing interface is not specified, we also
  526          * choose a loopback interface as the outgoing interface.
  527          */
  528         if (!jailed && IN6_IS_ADDR_MULTICAST(dst)) {
  529                 struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
  530 
  531                 if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
  532                         ifp = &loif[0];
  533                 }
  534 
  535                 if (ifp) {
  536                         ia6 = in6_ifawithscope(ifp, dst);
  537                         if (ia6 == 0) {
  538                                 *errorp = EADDRNOTAVAIL;
  539                                 return (0);
  540                         }
  541                         return (&ia6->ia_addr.sin6_addr);
  542                 }
  543         }
  544 
  545         /*
  546          * If the next hop address for the packet is specified
  547          * by caller, use an address associated with the route
  548          * to the next hop.
  549          */
  550         {
  551                 struct sockaddr_in6 *sin6_next;
  552                 struct rtentry *rt;
  553 
  554                 if (opts && opts->ip6po_nexthop) {
  555                         sin6_next = satosin6(opts->ip6po_nexthop);
  556                         rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
  557                         if (rt) {
  558                                 ia6 = in6_ifawithscope(rt->rt_ifp, dst);
  559                                 if (ia6 == 0)
  560                                         ia6 = ifatoia6(rt->rt_ifa);
  561                         }
  562                         if (ia6 && jailed) {
  563                                 jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
  564                                 if (!jailed_ip(cred->cr_prison,
  565                                         (struct sockaddr *)&jsin6))
  566                                         ia6 = 0;
  567                         }
  568 
  569                         if (ia6 == 0) {
  570                                 *errorp = EADDRNOTAVAIL;
  571                                 return (0);
  572                         }
  573                         return (&satosin6(&ia6->ia_addr)->sin6_addr);
  574                 }
  575         }
  576 
  577         /*
  578          * If route is known or can be allocated now,
  579          * our src addr is taken from the i/f, else punt.
  580          */
  581         if (ro) {
  582                 if (ro->ro_rt &&
  583                     !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
  584                         RTFREE(ro->ro_rt);
  585                         ro->ro_rt = NULL;
  586                 }
  587                 if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL) {
  588                         struct sockaddr_in6 *dst6;
  589 
  590                         /* No route yet, so try to acquire one */
  591                         bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
  592                         dst6 = &ro->ro_dst;
  593                         dst6->sin6_family = AF_INET6;
  594                         dst6->sin6_len = sizeof(struct sockaddr_in6);
  595                         dst6->sin6_addr = *dst;
  596                         if (!jailed && IN6_IS_ADDR_MULTICAST(dst)) {
  597                                 ro->ro_rt =
  598                                   rtpurelookup((struct sockaddr *)&ro->ro_dst);
  599                         } else {
  600                                 rtalloc((struct route *)ro);
  601                         }
  602                 }
  603 
  604                 /*
  605                  * in_pcbconnect() checks out IFF_LOOPBACK to skip using
  606                  * the address. But we don't know why it does so.
  607                  * It is necessary to ensure the scope even for lo0
  608                  * so doesn't check out IFF_LOOPBACK.
  609                  */
  610 
  611                 if (ro->ro_rt) {
  612                         ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
  613                         if (ia6 && jailed) {
  614                                 jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
  615                                 if (!jailed_ip(cred->cr_prison,
  616                                         (struct sockaddr *)&jsin6))
  617                                         ia6 = 0;
  618                         }
  619 
  620                         if (ia6 == 0) /* xxx scope error ?*/
  621                                 ia6 = ifatoia6(ro->ro_rt->rt_ifa);
  622 
  623                         if (ia6 && jailed) {
  624                                 jsin6.sin6_addr = (&ia6->ia_addr)->sin6_addr;
  625                                 if (!jailed_ip(cred->cr_prison,
  626                                         (struct sockaddr *)&jsin6))
  627                                         ia6 = 0;
  628                         }
  629                 }
  630                 if (ia6 == 0) {
  631                         *errorp = EHOSTUNREACH; /* no route */
  632                         return (0);
  633                 }
  634                 return (&satosin6(&ia6->ia_addr)->sin6_addr);
  635         }
  636 
  637         *errorp = EADDRNOTAVAIL;
  638         return (0);
  639 }
  640 
  641 /*
  642  * Default hop limit selection. The precedence is as follows:
  643  * 1. Hoplimit valued specified via ioctl.
  644  * 2. (If the outgoing interface is detected) the current
  645  *     hop limit of the interface specified by router advertisement.
  646  * 3. The system default hoplimit.
  647 */
  648 int
  649 in6_selecthlim(struct in6pcb *in6p, struct ifnet *ifp)
  650 {
  651         if (in6p && in6p->in6p_hops >= 0)
  652                 return (in6p->in6p_hops);
  653         else if (ifp)
  654                 return (ND_IFINFO(ifp)->chlim);
  655         else
  656                 return (ip6_defhlim);
  657 }
  658 #endif
  659 
  660 void
  661 in6_pcbdisconnect(struct inpcb *inp)
  662 {
  663         bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
  664         inp->inp_fport = 0;
  665         /* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
  666         inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
  667         in_pcbremconnhash(inp);
  668         if (inp->inp_socket->so_state & SS_NOFDREF)
  669                 in6_pcbdetach(inp);
  670 }
  671 
  672 void
  673 in6_pcbdetach(struct inpcb *inp)
  674 {
  675         struct socket *so = inp->inp_socket;
  676         struct inpcbinfo *ipi = inp->inp_pcbinfo;
  677 
  678 #ifdef IPSEC
  679         if (inp->in6p_sp != NULL)
  680                 ipsec6_delete_pcbpolicy(inp);
  681 #endif /* IPSEC */
  682         inp->inp_gencnt = ++ipi->ipi_gencnt;
  683         in_pcbremlists(inp);
  684         so->so_pcb = NULL;
  685         KKASSERT((so->so_state & SS_ASSERTINPROG) == 0);
  686         sofree(so);             /* remove pcb ref */
  687 
  688         if (inp->in6p_options)
  689                 m_freem(inp->in6p_options);
  690         ip6_freepcbopts(inp->in6p_outputopts);
  691         ip6_freemoptions(inp->in6p_moptions);
  692         if (inp->in6p_route.ro_rt)
  693                 rtfree(inp->in6p_route.ro_rt);
  694         /* Check and free IPv4 related resources in case of mapped addr */
  695         if (inp->inp_options)
  696                 m_free(inp->inp_options);
  697         ip_freemoptions(inp->inp_moptions);
  698 
  699         inp->inp_vflag = 0;
  700         kfree(inp, M_PCB);
  701 }
  702 
  703 /*
  704  * The calling convention of in6_setsockaddr() and in6_setpeeraddr() was
  705  * modified to match the pru_sockaddr() and pru_peeraddr() entry points
  706  * in struct pr_usrreqs, so that protocols can just reference then directly
  707  * without the need for a wrapper function.  The socket must have a valid
  708  * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
  709  * except through a kernel programming error, so it is acceptable to panic
  710  * (or in this case trap) if the PCB is invalid.  (Actually, we don't trap
  711  * because there actually /is/ a programming error somewhere... XXX)
  712  */
  713 void
  714 in6_setsockaddr_dispatch(netmsg_t msg)
  715 {
  716         int error;
  717 
  718         error = in6_setsockaddr(msg->sockaddr.base.nm_so, msg->sockaddr.nm_nam);
  719         lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
  720 }
  721 
  722 int
  723 in6_setsockaddr(struct socket *so, struct sockaddr **nam)
  724 {
  725         struct inpcb *inp;
  726         struct sockaddr_in6 *sin6;
  727 
  728         /*
  729          * Do the malloc first in case it blocks.
  730          */
  731         sin6 = kmalloc(sizeof *sin6, M_SONAME, M_WAITOK | M_ZERO);
  732         sin6->sin6_family = AF_INET6;
  733         sin6->sin6_len = sizeof(*sin6);
  734 
  735         crit_enter();
  736         inp = so->so_pcb;
  737         if (!inp) {
  738                 crit_exit();
  739                 kfree(sin6, M_SONAME);
  740                 return EINVAL;
  741         }
  742         sin6->sin6_port = inp->inp_lport;
  743         sin6->sin6_addr = inp->in6p_laddr;
  744         crit_exit();
  745         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  746                 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
  747         else
  748                 sin6->sin6_scope_id = 0;        /*XXX*/
  749         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  750                 sin6->sin6_addr.s6_addr16[1] = 0;
  751 
  752         *nam = (struct sockaddr *)sin6;
  753         return 0;
  754 }
  755 
  756 void
  757 in6_setpeeraddr_dispatch(netmsg_t msg)
  758 {
  759         int error;
  760 
  761         error = in6_setpeeraddr(msg->peeraddr.base.nm_so, msg->peeraddr.nm_nam);
  762         lwkt_replymsg(&msg->peeraddr.base.lmsg, error);
  763 }
  764 
  765 int
  766 in6_setpeeraddr(struct socket *so, struct sockaddr **nam)
  767 {
  768         struct inpcb *inp;
  769         struct sockaddr_in6 *sin6;
  770 
  771         /*
  772          * Do the malloc first in case it blocks.
  773          */
  774         sin6 = kmalloc(sizeof(*sin6), M_SONAME, M_WAITOK | M_ZERO);
  775         sin6->sin6_family = AF_INET6;
  776         sin6->sin6_len = sizeof(struct sockaddr_in6);
  777 
  778         crit_enter();
  779         inp = so->so_pcb;
  780         if (!inp) {
  781                 crit_exit();
  782                 kfree(sin6, M_SONAME);
  783                 return EINVAL;
  784         }
  785         sin6->sin6_port = inp->inp_fport;
  786         sin6->sin6_addr = inp->in6p_faddr;
  787         crit_exit();
  788         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  789                 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
  790         else
  791                 sin6->sin6_scope_id = 0;        /*XXX*/
  792         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
  793                 sin6->sin6_addr.s6_addr16[1] = 0;
  794 
  795         *nam = (struct sockaddr *)sin6;
  796         return 0;
  797 }
  798 
  799 void
  800 in6_mapped_sockaddr_dispatch(netmsg_t msg)
  801 {
  802         int error;
  803 
  804         error = in6_mapped_sockaddr(msg->sockaddr.base.nm_so,
  805                                     msg->sockaddr.nm_nam);
  806         lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
  807 }
  808 
  809 int
  810 in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
  811 {
  812         struct  inpcb *inp = so->so_pcb;
  813         int     error;
  814 
  815         if (inp == NULL)
  816                 return EINVAL;
  817         if (inp->inp_vflag & INP_IPV4) {
  818                 error = in_setsockaddr(so, nam);
  819                 if (error == 0)
  820                         in6_sin_2_v4mapsin6_in_sock(nam);
  821         } else
  822         /* scope issues will be handled in in6_setsockaddr(). */
  823         error = in6_setsockaddr(so, nam);
  824 
  825         return error;
  826 }
  827 
  828 int
  829 in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
  830 {
  831         struct  inpcb *inp = so->so_pcb;
  832         int     error;
  833 
  834         if (inp == NULL)
  835                 return EINVAL;
  836         if (inp->inp_vflag & INP_IPV4) {
  837                 error = in_setpeeraddr(so, nam);
  838                 if (error == 0)
  839                         in6_sin_2_v4mapsin6_in_sock(nam);
  840         } else
  841         /* scope issues will be handled in in6_setpeeraddr(). */
  842         error = in6_setpeeraddr(so, nam);
  843 
  844         return error;
  845 }
  846 
  847 void
  848 in6_mapped_peeraddr_dispatch(netmsg_t msg)
  849 {
  850         int error;
  851 
  852         error = in6_mapped_peeraddr(msg->base.nm_so, msg->peeraddr.nm_nam);
  853         lwkt_replymsg(&msg->base.lmsg, error);
  854 }
  855 
  856 /*
  857  * Pass some notification to all connections of a protocol
  858  * associated with address dst.  The local address and/or port numbers
  859  * may be specified to limit the search.  The "usual action" will be
  860  * taken, depending on the ctlinput cmd.  The caller must filter any
  861  * cmds that are uninteresting (e.g., no error in the map).
  862  * Call the protocol specific routine (if any) to report
  863  * any errors for each matching socket.
  864  *
  865  * Must be called under crit_enter().
  866  */
  867 void
  868 in6_pcbnotify(struct inpcbhead *head, struct sockaddr *dst, in_port_t fport,
  869               const struct sockaddr *src, in_port_t lport, int cmd, int arg,
  870               void (*notify) (struct inpcb *, int))
  871 {
  872         struct inpcb *inp, *ninp;
  873         struct sockaddr_in6 sa6_src, *sa6_dst;
  874         u_int32_t flowinfo;
  875 
  876         if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6)
  877                 return;
  878 
  879         sa6_dst = (struct sockaddr_in6 *)dst;
  880         if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
  881                 return;
  882 
  883         /*
  884          * note that src can be NULL when we get notify by local fragmentation.
  885          */
  886         sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src;
  887         flowinfo = sa6_src.sin6_flowinfo;
  888 
  889         /*
  890          * Redirects go to all references to the destination,
  891          * and use in6_rtchange to invalidate the route cache.
  892          * Dead host indications: also use in6_rtchange to invalidate
  893          * the cache, and deliver the error to all the sockets.
  894          * Otherwise, if we have knowledge of the local port and address,
  895          * deliver only to that socket.
  896          */
  897         if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
  898                 fport = 0;
  899                 lport = 0;
  900                 bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
  901 
  902                 if (cmd != PRC_HOSTDEAD)
  903                         notify = in6_rtchange;
  904         }
  905         if (cmd != PRC_MSGSIZE)
  906                 arg = inet6ctlerrmap[cmd];
  907         crit_enter();
  908         for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
  909                 ninp = LIST_NEXT(inp, inp_list);
  910 
  911                 if (inp->inp_flags & INP_PLACEMARKER)
  912                         continue;
  913 
  914                 if ((inp->inp_vflag & INP_IPV6) == 0)
  915                         continue;
  916                 /*
  917                  * If the error designates a new path MTU for a destination
  918                  * and the application (associated with this socket) wanted to
  919                  * know the value, notify. Note that we notify for all
  920                  * disconnected sockets if the corresponding application
  921                  * wanted. This is because some UDP applications keep sending
  922                  * sockets disconnected.
  923                  * XXX: should we avoid to notify the value to TCP sockets?
  924                  */
  925                 if (cmd == PRC_MSGSIZE && (inp->inp_flags & IN6P_MTU) != 0 &&
  926                     (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
  927                      IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &sa6_dst->sin6_addr))) {
  928                         ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst, &arg);
  929                 }
  930 
  931                 /*
  932                  * Detect if we should notify the error. If no source and
  933                  * destination ports are specifed, but non-zero flowinfo and
  934                  * local address match, notify the error. This is the case
  935                  * when the error is delivered with an encrypted buffer
  936                  * by ESP. Otherwise, just compare addresses and ports
  937                  * as usual.
  938                  */
  939                 if (lport == 0 && fport == 0 && flowinfo &&
  940                     inp->inp_socket != NULL &&
  941                     flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
  942                     IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
  943                         goto do_notify;
  944                 else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
  945                                              &sa6_dst->sin6_addr) ||
  946                          inp->inp_socket == 0 ||
  947                          (lport && inp->inp_lport != lport) ||
  948                          (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
  949                           !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
  950                                               &sa6_src.sin6_addr)) ||
  951                          (fport && inp->inp_fport != fport))
  952                         continue;
  953 
  954 do_notify:
  955                 if (notify)
  956                         (*notify)(inp, arg);
  957         }
  958         crit_exit();
  959 }
  960 
  961 /*
  962  * Lookup a PCB based on the local address and port.
  963  */
  964 struct inpcb *
  965 in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
  966                     u_int lport_arg, int wild_okay, struct ucred *cred)
  967 {
  968         struct inpcb *inp;
  969         int matchwild = 3, wildcard;
  970         u_short lport = lport_arg;
  971         struct inpcbporthead *porthash;
  972         struct inpcbport *phd;
  973         struct inpcb *match = NULL;
  974 
  975         /*
  976          * If the porthashbase is shared across several cpus we need
  977          * to lock.
  978          */
  979         if (pcbinfo->porttoken)
  980                 lwkt_gettoken(pcbinfo->porttoken);
  981 
  982         /*
  983          * Best fit PCB lookup.
  984          *
  985          * First see if this local port is in use by looking on the
  986          * port hash list.
  987          */
  988         porthash = &pcbinfo->porthashbase[
  989                                 INP_PCBPORTHASH(lport, pcbinfo->porthashmask)];
  990         LIST_FOREACH(phd, porthash, phd_hash) {
  991                 if (phd->phd_port == lport)
  992                         break;
  993         }
  994 
  995         if (phd != NULL) {
  996                 /*
  997                  * Port is in use by one or more PCBs. Look for best
  998                  * fit.
  999                  */
 1000                 LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
 1001                         wildcard = 0;
 1002                         if ((inp->inp_vflag & INP_IPV6) == 0)
 1003                                 continue;
 1004                         if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
 1005                                 wildcard++;
 1006                         if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
 1007                                 if (IN6_IS_ADDR_UNSPECIFIED(laddr))
 1008                                         wildcard++;
 1009                                 else if (!IN6_ARE_ADDR_EQUAL(
 1010                                         &inp->in6p_laddr, laddr))
 1011                                         continue;
 1012                         } else {
 1013                                 if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
 1014                                         wildcard++;
 1015                         }
 1016                         if (wildcard && !wild_okay)
 1017                                 continue;
 1018                         if (wildcard < matchwild &&
 1019                             (cred == NULL ||
 1020                              cred->cr_prison == 
 1021                                         inp->inp_socket->so_cred->cr_prison)) {
 1022                                 match = inp;
 1023                                 matchwild = wildcard;
 1024                                 if (wildcard == 0)
 1025                                         break;
 1026                                 else
 1027                                         matchwild = wildcard;
 1028                         }
 1029                 }
 1030         }
 1031         if (pcbinfo->porttoken)
 1032                 lwkt_reltoken(pcbinfo->porttoken);
 1033 
 1034         return (match);
 1035 }
 1036 
 1037 void
 1038 in6_pcbpurgeif0(struct in6pcb *head, struct ifnet *ifp)
 1039 {
 1040         struct in6pcb *in6p;
 1041         struct ip6_moptions *im6o;
 1042         struct in6_multi_mship *imm, *nimm;
 1043 
 1044         for (in6p = head; in6p != NULL; in6p = LIST_NEXT(in6p, inp_list)) {
 1045                 if (in6p->in6p_flags & INP_PLACEMARKER)
 1046                         continue;
 1047                 im6o = in6p->in6p_moptions;
 1048                 if ((in6p->inp_vflag & INP_IPV6) &&
 1049                     im6o) {
 1050                         /*
 1051                          * Unselect the outgoing interface if it is being
 1052                          * detached.
 1053                          */
 1054                         if (im6o->im6o_multicast_ifp == ifp)
 1055                                 im6o->im6o_multicast_ifp = NULL;
 1056 
 1057                         /*
 1058                          * Drop multicast group membership if we joined
 1059                          * through the interface being detached.
 1060                          * XXX controversial - is it really legal for kernel
 1061                          * to force this?
 1062                          */
 1063                         for (imm = im6o->im6o_memberships.lh_first;
 1064                              imm != NULL; imm = nimm) {
 1065                                 nimm = imm->i6mm_chain.le_next;
 1066                                 if (imm->i6mm_maddr->in6m_ifp == ifp) {
 1067                                         LIST_REMOVE(imm, i6mm_chain);
 1068                                         in6_delmulti(imm->i6mm_maddr);
 1069                                         kfree(imm, M_IPMADDR);
 1070                                 }
 1071                         }
 1072                 }
 1073         }
 1074 }
 1075 
 1076 /*
 1077  * Check for alternatives when higher level complains
 1078  * about service problems.  For now, invalidate cached
 1079  * routing information.  If the route was created dynamically
 1080  * (by a redirect), time to try a default gateway again.
 1081  */
 1082 void
 1083 in6_losing(struct inpcb *in6p)
 1084 {
 1085         struct rtentry *rt;
 1086         struct rt_addrinfo info;
 1087 
 1088         if ((rt = in6p->in6p_route.ro_rt) != NULL) {
 1089                 bzero((caddr_t)&info, sizeof(info));
 1090                 info.rti_flags = rt->rt_flags;
 1091                 info.rti_info[RTAX_DST] = rt_key(rt);
 1092                 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
 1093                 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
 1094                 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
 1095                 if (rt->rt_flags & RTF_DYNAMIC) {
 1096                         rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
 1097                             rt_mask(rt), rt->rt_flags, NULL);
 1098                 }
 1099                 in6p->in6p_route.ro_rt = NULL;
 1100                 rtfree(rt);
 1101                 /*
 1102                  * A new route can be allocated
 1103                  * the next time output is attempted.
 1104                  */
 1105         }
 1106 }
 1107 
 1108 /*
 1109  * After a routing change, flush old routing
 1110  * and allocate a (hopefully) better one.
 1111  */
 1112 void
 1113 in6_rtchange(struct inpcb *inp, int error)
 1114 {
 1115         if (inp->in6p_route.ro_rt) {
 1116                 rtfree(inp->in6p_route.ro_rt);
 1117                 inp->in6p_route.ro_rt = 0;
 1118                 /*
 1119                  * A new route can be allocated the next time
 1120                  * output is attempted.
 1121                  */
 1122         }
 1123 }
 1124 
 1125 /*
 1126  * Lookup PCB in hash list.
 1127  */
 1128 struct inpcb *
 1129 in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
 1130                    u_int fport_arg, struct in6_addr *laddr, u_int lport_arg,
 1131                    int wildcard, struct ifnet *ifp)
 1132 {
 1133         struct inpcbhead *head;
 1134         struct inpcb *inp;
 1135         struct inpcb *jinp = NULL;
 1136         u_short fport = fport_arg, lport = lport_arg;
 1137         int faith;
 1138 
 1139         if (faithprefix_p != NULL)
 1140                 faith = (*faithprefix_p)(laddr);
 1141         else
 1142                 faith = 0;
 1143 
 1144         /*
 1145          * First look for an exact match.
 1146          */
 1147         head = &pcbinfo->hashbase[INP_PCBCONNHASH(faddr->s6_addr32[3] /* XXX */,
 1148                                               fport,
 1149                                               laddr->s6_addr32[3], /* XXX JH */
 1150                                               lport,
 1151                                               pcbinfo->hashmask)];
 1152         LIST_FOREACH(inp, head, inp_hash) {
 1153                 if ((inp->inp_vflag & INP_IPV6) == 0)
 1154                         continue;
 1155                 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
 1156                     IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
 1157                     inp->inp_fport == fport &&
 1158                     inp->inp_lport == lport) {
 1159                         /*
 1160                          * Found.
 1161                          */
 1162                         if (inp->inp_socket == NULL ||
 1163                         inp->inp_socket->so_cred->cr_prison == NULL) {
 1164                                 return (inp);
 1165                         } else {
 1166                                 if  (jinp == NULL)
 1167                                         jinp = inp;
 1168                         }
 1169                 }
 1170         }
 1171         if (jinp != NULL)
 1172                 return(jinp);
 1173         if (wildcard) {
 1174                 struct inpcontainerhead *chead;
 1175                 struct inpcontainer *ic;
 1176                 struct inpcb *local_wild = NULL;
 1177                 struct inpcb *jinp_wild = NULL;
 1178                 struct sockaddr_in6 jsin6;
 1179                 struct ucred *cred;
 1180 
 1181                 /*
 1182                  * Order of socket selection:
 1183                  * 1. non-jailed, non-wild.
 1184                  * 2. non-jailed, wild.
 1185                  * 3. jailed, non-wild.
 1186                  * 4. jailed, wild.
 1187                  */
 1188                 jsin6.sin6_family = AF_INET6;
 1189                 chead = &pcbinfo->wildcardhashbase[INP_PCBWILDCARDHASH(lport,
 1190                     pcbinfo->wildcardhashmask)];
 1191                 LIST_FOREACH(ic, chead, ic_list) {
 1192                         inp = ic->ic_inp;
 1193 
 1194                         if (!(inp->inp_vflag & INP_IPV6))
 1195                                 continue;
 1196                         if (inp->inp_socket != NULL)
 1197                                 cred = inp->inp_socket->so_cred;
 1198                         else
 1199                                 cred = NULL;
 1200 
 1201                         if (cred != NULL && jailed(cred)) {
 1202                                 if (jinp != NULL) {
 1203                                         continue;
 1204                                 } else {
 1205                                         jsin6.sin6_addr = *laddr;
 1206                                         if (!jailed_ip(cred->cr_prison,
 1207                                             (struct sockaddr *)&jsin6))
 1208                                                 continue;
 1209                                 }
 1210                         }
 1211                         if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
 1212                             inp->inp_lport == lport) {
 1213                                 if (faith && (inp->inp_flags & INP_FAITH) == 0)
 1214                                         continue;
 1215                                 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
 1216                                                        laddr)) {
 1217                                         if (cred != NULL && jailed(cred))
 1218                                                 jinp = inp;
 1219                                         else
 1220                                                 return (inp);
 1221                                 } else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
 1222                                         if (cred != NULL && jailed(cred))
 1223                                                 jinp_wild = inp;
 1224                                         else
 1225                                                 local_wild = inp;
 1226                                 }
 1227                         }
 1228                 }
 1229                 if (local_wild != NULL)
 1230                         return (local_wild);
 1231                 if (jinp != NULL)
 1232                         return (jinp);
 1233                 return (jinp_wild);
 1234         }
 1235 
 1236         /*
 1237          * Not found.
 1238          */
 1239         return (NULL);
 1240 }
 1241 
 1242 void
 1243 init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
 1244 {
 1245         struct ip6_hdr *ip;
 1246 
 1247         ip = mtod(m, struct ip6_hdr *);
 1248         bzero(sin6, sizeof(*sin6));
 1249         sin6->sin6_len = sizeof(*sin6);
 1250         sin6->sin6_family = AF_INET6;
 1251         sin6->sin6_addr = ip->ip6_src;
 1252         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
 1253                 sin6->sin6_addr.s6_addr16[1] = 0;
 1254         sin6->sin6_scope_id =
 1255                 (m->m_pkthdr.rcvif && IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
 1256                 ? m->m_pkthdr.rcvif->if_index : 0;
 1257 
 1258         return;
 1259 }
 1260 
 1261 static void
 1262 in6_savefaddr(struct socket *so, const struct sockaddr *faddr)
 1263 {
 1264         struct sockaddr_in6 *sin6;
 1265 
 1266         KASSERT(faddr->sa_family == AF_INET6,
 1267             ("not AF_INET6 faddr %d", faddr->sa_family));
 1268 
 1269         sin6 = kmalloc(sizeof(*sin6), M_SONAME, M_WAITOK | M_ZERO);
 1270         sin6->sin6_family = AF_INET6;
 1271         sin6->sin6_len = sizeof(*sin6);
 1272 
 1273         sin6->sin6_port = ((const struct sockaddr_in6 *)faddr)->sin6_port;
 1274         sin6->sin6_addr = ((const struct sockaddr_in6 *)faddr)->sin6_addr;
 1275 
 1276         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
 1277                 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
 1278         else
 1279                 sin6->sin6_scope_id = 0;        /*XXX*/
 1280         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
 1281                 sin6->sin6_addr.s6_addr16[1] = 0;
 1282 
 1283         so->so_faddr = (struct sockaddr *)sin6;
 1284 }
 1285 
 1286 void
 1287 in6_mapped_savefaddr(struct socket *so, const struct sockaddr *faddr)
 1288 {
 1289         if (faddr->sa_family == AF_INET) {
 1290                 in_savefaddr(so, faddr);
 1291                 in6_sin_2_v4mapsin6_in_sock(&so->so_faddr);
 1292         } else {
 1293                 in6_savefaddr(so, faddr);
 1294         }
 1295 }

Cache object: a2247bcc002d6d51557ab6fe4739dd7a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.