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/netinet/in_pcb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1982, 1986, 1991, 1993, 1995
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)in_pcb.c    8.4 (Berkeley) 5/24/95
   30  * $FreeBSD: src/sys/netinet/in_pcb.c,v 1.153.2.11 2006/02/11 09:02:59 ume Exp $
   31  */
   32 
   33 #include "opt_ipsec.h"
   34 #include "opt_inet6.h"
   35 #include "opt_mac.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/mac.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/domain.h>
   43 #include <sys/protosw.h>
   44 #include <sys/socket.h>
   45 #include <sys/socketvar.h>
   46 #include <sys/proc.h>
   47 #include <sys/jail.h>
   48 #include <sys/kernel.h>
   49 #include <sys/sysctl.h>
   50 
   51 #include <vm/uma.h>
   52 
   53 #include <net/if.h>
   54 #include <net/if_types.h>
   55 #include <net/route.h>
   56 
   57 #include <netinet/in.h>
   58 #include <netinet/in_pcb.h>
   59 #include <netinet/in_var.h>
   60 #include <netinet/ip_var.h>
   61 #include <netinet/tcp_var.h>
   62 #include <netinet/udp.h>
   63 #include <netinet/udp_var.h>
   64 #ifdef INET6
   65 #include <netinet/ip6.h>
   66 #include <netinet6/ip6_var.h>
   67 #endif /* INET6 */
   68 
   69 #ifdef IPSEC
   70 #include <netinet6/ipsec.h>
   71 #include <netkey/key.h>
   72 #endif /* IPSEC */
   73 
   74 #ifdef FAST_IPSEC
   75 #if defined(IPSEC) || defined(IPSEC_ESP)
   76 #error "Bad idea: don't compile with both IPSEC and FAST_IPSEC!"
   77 #endif
   78 
   79 #include <netipsec/ipsec.h>
   80 #include <netipsec/key.h>
   81 #endif /* FAST_IPSEC */
   82 
   83 /*
   84  * These configure the range of local port addresses assigned to
   85  * "unspecified" outgoing connections/packets/whatever.
   86  */
   87 int     ipport_lowfirstauto  = IPPORT_RESERVED - 1;     /* 1023 */
   88 int     ipport_lowlastauto = IPPORT_RESERVEDSTART;      /* 600 */
   89 int     ipport_firstauto = IPPORT_HIFIRSTAUTO;          /* 49152 */
   90 int     ipport_lastauto  = IPPORT_HILASTAUTO;           /* 65535 */
   91 int     ipport_hifirstauto = IPPORT_HIFIRSTAUTO;        /* 49152 */
   92 int     ipport_hilastauto  = IPPORT_HILASTAUTO;         /* 65535 */
   93 
   94 /*
   95  * Reserved ports accessible only to root. There are significant
   96  * security considerations that must be accounted for when changing these,
   97  * but the security benefits can be great. Please be careful.
   98  */
   99 int     ipport_reservedhigh = IPPORT_RESERVED - 1;      /* 1023 */
  100 int     ipport_reservedlow = 0;
  101 
  102 /* Variables dealing with random ephemeral port allocation. */
  103 int     ipport_randomized = 1;  /* user controlled via sysctl */
  104 int     ipport_randomcps = 10;  /* user controlled via sysctl */
  105 int     ipport_randomtime = 45; /* user controlled via sysctl */
  106 int     ipport_stoprandom = 0;  /* toggled by ipport_tick */
  107 int     ipport_tcpallocs;
  108 int     ipport_tcplastcount;
  109 
  110 #define RANGECHK(var, min, max) \
  111         if ((var) < (min)) { (var) = (min); } \
  112         else if ((var) > (max)) { (var) = (max); }
  113 
  114 static int
  115 sysctl_net_ipport_check(SYSCTL_HANDLER_ARGS)
  116 {
  117         int error;
  118 
  119         error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
  120         if (error == 0) {
  121                 RANGECHK(ipport_lowfirstauto, 1, IPPORT_RESERVED - 1);
  122                 RANGECHK(ipport_lowlastauto, 1, IPPORT_RESERVED - 1);
  123                 RANGECHK(ipport_firstauto, IPPORT_RESERVED, IPPORT_MAX);
  124                 RANGECHK(ipport_lastauto, IPPORT_RESERVED, IPPORT_MAX);
  125                 RANGECHK(ipport_hifirstauto, IPPORT_RESERVED, IPPORT_MAX);
  126                 RANGECHK(ipport_hilastauto, IPPORT_RESERVED, IPPORT_MAX);
  127         }
  128         return (error);
  129 }
  130 
  131 #undef RANGECHK
  132 
  133 SYSCTL_NODE(_net_inet_ip, IPPROTO_IP, portrange, CTLFLAG_RW, 0, "IP Ports");
  134 
  135 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowfirst, CTLTYPE_INT|CTLFLAG_RW,
  136            &ipport_lowfirstauto, 0, &sysctl_net_ipport_check, "I", "");
  137 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowlast, CTLTYPE_INT|CTLFLAG_RW,
  138            &ipport_lowlastauto, 0, &sysctl_net_ipport_check, "I", "");
  139 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, first, CTLTYPE_INT|CTLFLAG_RW,
  140            &ipport_firstauto, 0, &sysctl_net_ipport_check, "I", "");
  141 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, last, CTLTYPE_INT|CTLFLAG_RW,
  142            &ipport_lastauto, 0, &sysctl_net_ipport_check, "I", "");
  143 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hifirst, CTLTYPE_INT|CTLFLAG_RW,
  144            &ipport_hifirstauto, 0, &sysctl_net_ipport_check, "I", "");
  145 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hilast, CTLTYPE_INT|CTLFLAG_RW,
  146            &ipport_hilastauto, 0, &sysctl_net_ipport_check, "I", "");
  147 SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, reservedhigh,
  148            CTLFLAG_RW|CTLFLAG_SECURE, &ipport_reservedhigh, 0, "");
  149 SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, reservedlow,
  150            CTLFLAG_RW|CTLFLAG_SECURE, &ipport_reservedlow, 0, "");
  151 SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomized, CTLFLAG_RW,
  152            &ipport_randomized, 0, "Enable random port allocation");
  153 SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomcps, CTLFLAG_RW,
  154            &ipport_randomcps, 0, "Maximum number of random port "
  155            "allocations before switching to a sequental one");
  156 SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomtime, CTLFLAG_RW,
  157            &ipport_randomtime, 0, "Minimum time to keep sequental port "
  158            "allocation before switching to a random one");
  159 
  160 /*
  161  * in_pcb.c: manage the Protocol Control Blocks.
  162  *
  163  * NOTE: It is assumed that most of these functions will be called at
  164  * splnet(). XXX - There are, unfortunately, a few exceptions to this
  165  * rule that should be fixed.
  166  */
  167 
  168 /*
  169  * Allocate a PCB and associate it with the socket.
  170  */
  171 int
  172 in_pcballoc(so, pcbinfo, type)
  173         struct socket *so;
  174         struct inpcbinfo *pcbinfo;
  175         const char *type;
  176 {
  177         register struct inpcb *inp;
  178         int error;
  179 
  180         INP_INFO_WLOCK_ASSERT(pcbinfo);
  181         error = 0;
  182         inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT | M_ZERO);
  183         if (inp == NULL)
  184                 return (ENOBUFS);
  185         inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
  186         inp->inp_pcbinfo = pcbinfo;
  187         inp->inp_socket = so;
  188 #ifdef MAC
  189         error = mac_init_inpcb(inp, M_NOWAIT);
  190         if (error != 0)
  191                 goto out;
  192         SOCK_LOCK(so);
  193         mac_create_inpcb_from_socket(so, inp);
  194         SOCK_UNLOCK(so);
  195 #endif
  196 #if defined(IPSEC) || defined(FAST_IPSEC)
  197 #ifdef FAST_IPSEC
  198         error = ipsec_init_policy(so, &inp->inp_sp);
  199 #else
  200         error = ipsec_init_pcbpolicy(so, &inp->inp_sp);
  201 #endif
  202         if (error != 0)
  203                 goto out;
  204 #endif /*IPSEC*/
  205 #if defined(INET6)
  206         if (INP_SOCKAF(so) == AF_INET6) {
  207                 inp->inp_vflag |= INP_IPV6PROTO;
  208                 if (ip6_v6only)
  209                         inp->inp_flags |= IN6P_IPV6_V6ONLY;
  210         }
  211 #endif
  212         LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);
  213         pcbinfo->ipi_count++;
  214         so->so_pcb = (caddr_t)inp;
  215         INP_LOCK_INIT(inp, "inp", type);
  216 #ifdef INET6
  217         if (ip6_auto_flowlabel)
  218                 inp->inp_flags |= IN6P_AUTOFLOWLABEL;
  219 #endif
  220 #if defined(IPSEC) || defined(FAST_IPSEC) || defined(MAC)
  221 out:
  222         if (error != 0)
  223                 uma_zfree(pcbinfo->ipi_zone, inp);
  224 #endif
  225         return (error);
  226 }
  227 
  228 int
  229 in_pcbbind(inp, nam, cred)
  230         register struct inpcb *inp;
  231         struct sockaddr *nam;
  232         struct ucred *cred;
  233 {
  234         int anonport, error;
  235 
  236         INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
  237         INP_LOCK_ASSERT(inp);
  238 
  239         if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY)
  240                 return (EINVAL);
  241         anonport = inp->inp_lport == 0 && (nam == NULL ||
  242             ((struct sockaddr_in *)nam)->sin_port == 0);
  243         error = in_pcbbind_setup(inp, nam, &inp->inp_laddr.s_addr,
  244             &inp->inp_lport, cred);
  245         if (error)
  246                 return (error);
  247         if (in_pcbinshash(inp) != 0) {
  248                 inp->inp_laddr.s_addr = INADDR_ANY;
  249                 inp->inp_lport = 0;
  250                 return (EAGAIN);
  251         }
  252         if (anonport)
  253                 inp->inp_flags |= INP_ANONPORT;
  254         return (0);
  255 }
  256 
  257 /*
  258  * Set up a bind operation on a PCB, performing port allocation
  259  * as required, but do not actually modify the PCB. Callers can
  260  * either complete the bind by setting inp_laddr/inp_lport and
  261  * calling in_pcbinshash(), or they can just use the resulting
  262  * port and address to authorise the sending of a once-off packet.
  263  *
  264  * On error, the values of *laddrp and *lportp are not changed.
  265  */
  266 int
  267 in_pcbbind_setup(inp, nam, laddrp, lportp, cred)
  268         struct inpcb *inp;
  269         struct sockaddr *nam;
  270         in_addr_t *laddrp;
  271         u_short *lportp;
  272         struct ucred *cred;
  273 {
  274         struct socket *so = inp->inp_socket;
  275         unsigned short *lastport;
  276         struct sockaddr_in *sin;
  277         struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
  278         struct in_addr laddr;
  279         u_short lport = 0;
  280         int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
  281         int error, prison = 0;
  282         int dorandom;
  283 
  284         INP_INFO_WLOCK_ASSERT(pcbinfo);
  285         INP_LOCK_ASSERT(inp);
  286 
  287         if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */
  288                 return (EADDRNOTAVAIL);
  289         laddr.s_addr = *laddrp;
  290         if (nam != NULL && laddr.s_addr != INADDR_ANY)
  291                 return (EINVAL);
  292         if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
  293                 wild = 1;
  294         if (nam) {
  295                 sin = (struct sockaddr_in *)nam;
  296                 if (nam->sa_len != sizeof (*sin))
  297                         return (EINVAL);
  298 #ifdef notdef
  299                 /*
  300                  * We should check the family, but old programs
  301                  * incorrectly fail to initialize it.
  302                  */
  303                 if (sin->sin_family != AF_INET)
  304                         return (EAFNOSUPPORT);
  305 #endif
  306                 if (sin->sin_addr.s_addr != INADDR_ANY)
  307                         if (prison_ip(cred, 0, &sin->sin_addr.s_addr))
  308                                 return(EINVAL);
  309                 if (sin->sin_port != *lportp) {
  310                         /* Don't allow the port to change. */
  311                         if (*lportp != 0)
  312                                 return (EINVAL);
  313                         lport = sin->sin_port;
  314                 }
  315                 /* NB: lport is left as 0 if the port isn't being changed. */
  316                 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
  317                         /*
  318                          * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
  319                          * allow complete duplication of binding if
  320                          * SO_REUSEPORT is set, or if SO_REUSEADDR is set
  321                          * and a multicast address is bound on both
  322                          * new and duplicated sockets.
  323                          */
  324                         if (so->so_options & SO_REUSEADDR)
  325                                 reuseport = SO_REUSEADDR|SO_REUSEPORT;
  326                 } else if (sin->sin_addr.s_addr != INADDR_ANY) {
  327                         sin->sin_port = 0;              /* yech... */
  328                         bzero(&sin->sin_zero, sizeof(sin->sin_zero));
  329                         if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
  330                                 return (EADDRNOTAVAIL);
  331                 }
  332                 laddr = sin->sin_addr;
  333                 if (lport) {
  334                         struct inpcb *t;
  335                         /* GROSS */
  336                         if (ntohs(lport) <= ipport_reservedhigh &&
  337                             ntohs(lport) >= ipport_reservedlow &&
  338                             suser_cred(cred, SUSER_ALLOWJAIL))
  339                                 return (EACCES);
  340                         if (jailed(cred))
  341                                 prison = 1;
  342                         if (so->so_cred->cr_uid != 0 &&
  343                             !IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
  344                                 t = in_pcblookup_local(inp->inp_pcbinfo,
  345                                     sin->sin_addr, lport,
  346                                     prison ? 0 :  INPLOOKUP_WILDCARD);
  347         /*
  348          * XXX
  349          * This entire block sorely needs a rewrite.
  350          */
  351                                 if (t &&
  352                                     ((t->inp_vflag & INP_TIMEWAIT) == 0) &&
  353                                     (so->so_type != SOCK_STREAM ||
  354                                      ntohl(t->inp_faddr.s_addr) == INADDR_ANY) &&
  355                                     (ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
  356                                      ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
  357                                      (t->inp_socket->so_options &
  358                                          SO_REUSEPORT) == 0) &&
  359                                     (so->so_cred->cr_uid !=
  360                                      t->inp_socket->so_cred->cr_uid))
  361                                         return (EADDRINUSE);
  362                         }
  363                         if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))
  364                                 return (EADDRNOTAVAIL);
  365                         t = in_pcblookup_local(pcbinfo, sin->sin_addr,
  366                             lport, prison ? 0 : wild);
  367                         if (t && (t->inp_vflag & INP_TIMEWAIT)) {
  368                                 if ((reuseport & intotw(t)->tw_so_options) == 0)
  369                                         return (EADDRINUSE);
  370                         } else
  371                         if (t &&
  372                             (reuseport & t->inp_socket->so_options) == 0) {
  373 #if defined(INET6)
  374                                 if (ntohl(sin->sin_addr.s_addr) !=
  375                                     INADDR_ANY ||
  376                                     ntohl(t->inp_laddr.s_addr) !=
  377                                     INADDR_ANY ||
  378                                     INP_SOCKAF(so) ==
  379                                     INP_SOCKAF(t->inp_socket))
  380 #endif /* defined(INET6) */
  381                                 return (EADDRINUSE);
  382                         }
  383                 }
  384         }
  385         if (*lportp != 0)
  386                 lport = *lportp;
  387         if (lport == 0) {
  388                 u_short first, last;
  389                 int count;
  390 
  391                 if (laddr.s_addr != INADDR_ANY)
  392                         if (prison_ip(cred, 0, &laddr.s_addr))
  393                                 return (EINVAL);
  394 
  395                 if (inp->inp_flags & INP_HIGHPORT) {
  396                         first = ipport_hifirstauto;     /* sysctl */
  397                         last  = ipport_hilastauto;
  398                         lastport = &pcbinfo->lasthi;
  399                 } else if (inp->inp_flags & INP_LOWPORT) {
  400                         if ((error = suser_cred(cred, SUSER_ALLOWJAIL)) != 0)
  401                                 return error;
  402                         first = ipport_lowfirstauto;    /* 1023 */
  403                         last  = ipport_lowlastauto;     /* 600 */
  404                         lastport = &pcbinfo->lastlow;
  405                 } else {
  406                         first = ipport_firstauto;       /* sysctl */
  407                         last  = ipport_lastauto;
  408                         lastport = &pcbinfo->lastport;
  409                 }
  410                 /*
  411                  * For UDP, use random port allocation as long as the user
  412                  * allows it.  For TCP (and as of yet unknown) connections,
  413                  * use random port allocation only if the user allows it AND
  414                  * ipport_tick() allows it.
  415                  */
  416                 if (ipport_randomized &&
  417                         (!ipport_stoprandom || pcbinfo == &udbinfo))
  418                         dorandom = 1;
  419                 else
  420                         dorandom = 0;
  421                 /*
  422                  * It makes no sense to do random port allocation if
  423                  * we have the only port available.
  424                  */
  425                 if (first == last)
  426                         dorandom = 0;
  427                 /* Make sure to not include UDP packets in the count. */
  428                 if (pcbinfo != &udbinfo)
  429                         ipport_tcpallocs++;
  430                 /*
  431                  * Simple check to ensure all ports are not used up causing
  432                  * a deadlock here.
  433                  *
  434                  * We split the two cases (up and down) so that the direction
  435                  * is not being tested on each round of the loop.
  436                  */
  437                 if (first > last) {
  438                         /*
  439                          * counting down
  440                          */
  441                         if (dorandom)
  442                                 *lastport = first -
  443                                             (arc4random() % (first - last));
  444                         count = first - last;
  445 
  446                         do {
  447                                 if (count-- < 0)        /* completely used? */
  448                                         return (EADDRNOTAVAIL);
  449                                 --*lastport;
  450                                 if (*lastport > first || *lastport < last)
  451                                         *lastport = first;
  452                                 lport = htons(*lastport);
  453                         } while (in_pcblookup_local(pcbinfo, laddr, lport,
  454                             wild));
  455                 } else {
  456                         /*
  457                          * counting up
  458                          */
  459                         if (dorandom)
  460                                 *lastport = first +
  461                                             (arc4random() % (last - first));
  462                         count = last - first;
  463 
  464                         do {
  465                                 if (count-- < 0)        /* completely used? */
  466                                         return (EADDRNOTAVAIL);
  467                                 ++*lastport;
  468                                 if (*lastport < first || *lastport > last)
  469                                         *lastport = first;
  470                                 lport = htons(*lastport);
  471                         } while (in_pcblookup_local(pcbinfo, laddr, lport,
  472                             wild));
  473                 }
  474         }
  475         if (prison_ip(cred, 0, &laddr.s_addr))
  476                 return (EINVAL);
  477         *laddrp = laddr.s_addr;
  478         *lportp = lport;
  479         return (0);
  480 }
  481 
  482 /*
  483  * Connect from a socket to a specified address.
  484  * Both address and port must be specified in argument sin.
  485  * If don't have a local address for this socket yet,
  486  * then pick one.
  487  */
  488 int
  489 in_pcbconnect(inp, nam, cred)
  490         register struct inpcb *inp;
  491         struct sockaddr *nam;
  492         struct ucred *cred;
  493 {
  494         u_short lport, fport;
  495         in_addr_t laddr, faddr;
  496         int anonport, error;
  497 
  498         INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
  499         INP_LOCK_ASSERT(inp);
  500 
  501         lport = inp->inp_lport;
  502         laddr = inp->inp_laddr.s_addr;
  503         anonport = (lport == 0);
  504         error = in_pcbconnect_setup(inp, nam, &laddr, &lport, &faddr, &fport,
  505             NULL, cred);
  506         if (error)
  507                 return (error);
  508 
  509         /* Do the initial binding of the local address if required. */
  510         if (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0) {
  511                 inp->inp_lport = lport;
  512                 inp->inp_laddr.s_addr = laddr;
  513                 if (in_pcbinshash(inp) != 0) {
  514                         inp->inp_laddr.s_addr = INADDR_ANY;
  515                         inp->inp_lport = 0;
  516                         return (EAGAIN);
  517                 }
  518         }
  519 
  520         /* Commit the remaining changes. */
  521         inp->inp_lport = lport;
  522         inp->inp_laddr.s_addr = laddr;
  523         inp->inp_faddr.s_addr = faddr;
  524         inp->inp_fport = fport;
  525         in_pcbrehash(inp);
  526 #ifdef IPSEC
  527         if (inp->inp_socket->so_type == SOCK_STREAM)
  528                 ipsec_pcbconn(inp->inp_sp);
  529 #endif
  530         if (anonport)
  531                 inp->inp_flags |= INP_ANONPORT;
  532         return (0);
  533 }
  534 
  535 /*
  536  * Set up for a connect from a socket to the specified address.
  537  * On entry, *laddrp and *lportp should contain the current local
  538  * address and port for the PCB; these are updated to the values
  539  * that should be placed in inp_laddr and inp_lport to complete
  540  * the connect.
  541  *
  542  * On success, *faddrp and *fportp will be set to the remote address
  543  * and port. These are not updated in the error case.
  544  *
  545  * If the operation fails because the connection already exists,
  546  * *oinpp will be set to the PCB of that connection so that the
  547  * caller can decide to override it. In all other cases, *oinpp
  548  * is set to NULL.
  549  */
  550 int
  551 in_pcbconnect_setup(inp, nam, laddrp, lportp, faddrp, fportp, oinpp, cred)
  552         register struct inpcb *inp;
  553         struct sockaddr *nam;
  554         in_addr_t *laddrp;
  555         u_short *lportp;
  556         in_addr_t *faddrp;
  557         u_short *fportp;
  558         struct inpcb **oinpp;
  559         struct ucred *cred;
  560 {
  561         struct sockaddr_in *sin = (struct sockaddr_in *)nam;
  562         struct in_ifaddr *ia;
  563         struct sockaddr_in sa;
  564         struct ucred *socred;
  565         struct inpcb *oinp;
  566         struct in_addr laddr, faddr;
  567         u_short lport, fport;
  568         int error;
  569 
  570         INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
  571         INP_LOCK_ASSERT(inp);
  572 
  573         if (oinpp != NULL)
  574                 *oinpp = NULL;
  575         if (nam->sa_len != sizeof (*sin))
  576                 return (EINVAL);
  577         if (sin->sin_family != AF_INET)
  578                 return (EAFNOSUPPORT);
  579         if (sin->sin_port == 0)
  580                 return (EADDRNOTAVAIL);
  581         laddr.s_addr = *laddrp;
  582         lport = *lportp;
  583         faddr = sin->sin_addr;
  584         fport = sin->sin_port;
  585         socred = inp->inp_socket->so_cred;
  586         if (laddr.s_addr == INADDR_ANY && jailed(socred)) {
  587                 bzero(&sa, sizeof(sa));
  588                 sa.sin_addr.s_addr = htonl(prison_getip(socred));
  589                 sa.sin_len = sizeof(sa);
  590                 sa.sin_family = AF_INET;
  591                 error = in_pcbbind_setup(inp, (struct sockaddr *)&sa,
  592                     &laddr.s_addr, &lport, cred);
  593                 if (error)
  594                         return (error);
  595         }
  596         if (!TAILQ_EMPTY(&in_ifaddrhead)) {
  597                 /*
  598                  * If the destination address is INADDR_ANY,
  599                  * use the primary local address.
  600                  * If the supplied address is INADDR_BROADCAST,
  601                  * and the primary interface supports broadcast,
  602                  * choose the broadcast address for that interface.
  603                  */
  604                 if (faddr.s_addr == INADDR_ANY)
  605                         faddr = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr;
  606                 else if (faddr.s_addr == (u_long)INADDR_BROADCAST &&
  607                     (TAILQ_FIRST(&in_ifaddrhead)->ia_ifp->if_flags &
  608                     IFF_BROADCAST))
  609                         faddr = satosin(&TAILQ_FIRST(
  610                             &in_ifaddrhead)->ia_broadaddr)->sin_addr;
  611         }
  612         if (laddr.s_addr == INADDR_ANY) {
  613                 struct route sro;
  614 
  615                 bzero(&sro, sizeof(sro));
  616                 ia = (struct in_ifaddr *)0;
  617                 /*
  618                  * If route is known our src addr is taken from the i/f,
  619                  * else punt.
  620                  */
  621                 if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) {
  622                         /* Find out route to destination */
  623                         sro.ro_dst.sa_family = AF_INET;
  624                         sro.ro_dst.sa_len = sizeof(struct sockaddr_in);
  625                         ((struct sockaddr_in *)&sro.ro_dst)->sin_addr = faddr;
  626                         rtalloc_ign(&sro, RTF_CLONING);
  627                 }
  628                 /*
  629                  * If we found a route, use the address
  630                  * corresponding to the outgoing interface.
  631                  */
  632                 if (sro.ro_rt) {
  633                         ia = ifatoia(sro.ro_rt->rt_ifa);
  634                         RTFREE(sro.ro_rt);
  635                 }
  636                 if (ia == 0) {
  637                         bzero(&sa, sizeof(sa));
  638                         sa.sin_addr = faddr;
  639                         sa.sin_len = sizeof(sa);
  640                         sa.sin_family = AF_INET;
  641 
  642                         ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sa)));
  643                         if (ia == 0)
  644                                 ia = ifatoia(ifa_ifwithnet(sintosa(&sa)));
  645                         if (ia == 0)
  646                                 return (ENETUNREACH);
  647                 }
  648                 /*
  649                  * If the destination address is multicast and an outgoing
  650                  * interface has been set as a multicast option, use the
  651                  * address of that interface as our source address.
  652                  */
  653                 if (IN_MULTICAST(ntohl(faddr.s_addr)) &&
  654                     inp->inp_moptions != NULL) {
  655                         struct ip_moptions *imo;
  656                         struct ifnet *ifp;
  657 
  658                         imo = inp->inp_moptions;
  659                         if (imo->imo_multicast_ifp != NULL) {
  660                                 ifp = imo->imo_multicast_ifp;
  661                                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
  662                                         if (ia->ia_ifp == ifp)
  663                                                 break;
  664                                 if (ia == 0)
  665                                         return (EADDRNOTAVAIL);
  666                         }
  667                 }
  668                 laddr = ia->ia_addr.sin_addr;
  669         }
  670 
  671         oinp = in_pcblookup_hash(inp->inp_pcbinfo, faddr, fport, laddr, lport,
  672             0, NULL);
  673         if (oinp != NULL) {
  674                 if (oinpp != NULL)
  675                         *oinpp = oinp;
  676                 return (EADDRINUSE);
  677         }
  678         if (lport == 0) {
  679                 error = in_pcbbind_setup(inp, NULL, &laddr.s_addr, &lport,
  680                     cred);
  681                 if (error)
  682                         return (error);
  683         }
  684         *laddrp = laddr.s_addr;
  685         *lportp = lport;
  686         *faddrp = faddr.s_addr;
  687         *fportp = fport;
  688         return (0);
  689 }
  690 
  691 void
  692 in_pcbdisconnect(inp)
  693         struct inpcb *inp;
  694 {
  695 
  696         INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
  697         INP_LOCK_ASSERT(inp);
  698 
  699         inp->inp_faddr.s_addr = INADDR_ANY;
  700         inp->inp_fport = 0;
  701         in_pcbrehash(inp);
  702 #ifdef IPSEC
  703         ipsec_pcbdisconn(inp->inp_sp);
  704 #endif
  705         if (inp->inp_socket->so_state & SS_NOFDREF)
  706                 in_pcbdetach(inp);
  707 }
  708 
  709 void
  710 in_pcbdetach(inp)
  711         struct inpcb *inp;
  712 {
  713         struct socket *so = inp->inp_socket;
  714         struct inpcbinfo *ipi = inp->inp_pcbinfo;
  715 
  716         INP_INFO_WLOCK_ASSERT(ipi);
  717         INP_LOCK_ASSERT(inp);
  718 
  719 #if defined(IPSEC) || defined(FAST_IPSEC)
  720         ipsec4_delete_pcbpolicy(inp);
  721 #endif /*IPSEC*/
  722         inp->inp_gencnt = ++ipi->ipi_gencnt;
  723         in_pcbremlists(inp);
  724         if (so) {
  725                 ACCEPT_LOCK();
  726                 SOCK_LOCK(so);
  727                 so->so_pcb = NULL;
  728                 sotryfree(so);
  729         }
  730         if (inp->inp_options)
  731                 (void)m_free(inp->inp_options);
  732         ip_freemoptions(inp->inp_moptions);
  733         inp->inp_vflag = 0;
  734         INP_LOCK_DESTROY(inp);
  735 #ifdef MAC
  736         mac_destroy_inpcb(inp);
  737 #endif
  738         uma_zfree(ipi->ipi_zone, inp);
  739 }
  740 
  741 struct sockaddr *
  742 in_sockaddr(port, addr_p)
  743         in_port_t port;
  744         struct in_addr *addr_p;
  745 {
  746         struct sockaddr_in *sin;
  747 
  748         MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME,
  749                 M_WAITOK | M_ZERO);
  750         sin->sin_family = AF_INET;
  751         sin->sin_len = sizeof(*sin);
  752         sin->sin_addr = *addr_p;
  753         sin->sin_port = port;
  754 
  755         return (struct sockaddr *)sin;
  756 }
  757 
  758 /*
  759  * The wrapper function will pass down the pcbinfo for this function to lock.
  760  * The socket must have a valid
  761  * (i.e., non-nil) PCB, but it should be impossible to get an invalid one
  762  * except through a kernel programming error, so it is acceptable to panic
  763  * (or in this case trap) if the PCB is invalid.  (Actually, we don't trap
  764  * because there actually /is/ a programming error somewhere... XXX)
  765  */
  766 int
  767 in_setsockaddr(so, nam, pcbinfo)
  768         struct socket *so;
  769         struct sockaddr **nam;
  770         struct inpcbinfo *pcbinfo;
  771 {
  772         int s;
  773         register struct inpcb *inp;
  774         struct in_addr addr;
  775         in_port_t port;
  776 
  777         s = splnet();
  778         INP_INFO_RLOCK(pcbinfo);
  779         inp = sotoinpcb(so);
  780         if (!inp) {
  781                 INP_INFO_RUNLOCK(pcbinfo);
  782                 splx(s);
  783                 return ECONNRESET;
  784         }
  785         INP_LOCK(inp);
  786         port = inp->inp_lport;
  787         addr = inp->inp_laddr;
  788         INP_UNLOCK(inp);
  789         INP_INFO_RUNLOCK(pcbinfo);
  790         splx(s);
  791 
  792         *nam = in_sockaddr(port, &addr);
  793         return 0;
  794 }
  795 
  796 /*
  797  * The wrapper function will pass down the pcbinfo for this function to lock.
  798  */
  799 int
  800 in_setpeeraddr(so, nam, pcbinfo)
  801         struct socket *so;
  802         struct sockaddr **nam;
  803         struct inpcbinfo *pcbinfo;
  804 {
  805         int s;
  806         register struct inpcb *inp;
  807         struct in_addr addr;
  808         in_port_t port;
  809 
  810         s = splnet();
  811         INP_INFO_RLOCK(pcbinfo);
  812         inp = sotoinpcb(so);
  813         if (!inp) {
  814                 INP_INFO_RUNLOCK(pcbinfo);
  815                 splx(s);
  816                 return ECONNRESET;
  817         }
  818         INP_LOCK(inp);
  819         port = inp->inp_fport;
  820         addr = inp->inp_faddr;
  821         INP_UNLOCK(inp);
  822         INP_INFO_RUNLOCK(pcbinfo);
  823         splx(s);
  824 
  825         *nam = in_sockaddr(port, &addr);
  826         return 0;
  827 }
  828 
  829 void
  830 in_pcbnotifyall(pcbinfo, faddr, errno, notify)
  831         struct inpcbinfo *pcbinfo;
  832         struct in_addr faddr;
  833         int errno;
  834         struct inpcb *(*notify)(struct inpcb *, int);
  835 {
  836         struct inpcb *inp, *ninp;
  837         struct inpcbhead *head;
  838         int s;
  839 
  840         s = splnet();
  841         INP_INFO_WLOCK(pcbinfo);
  842         head = pcbinfo->listhead;
  843         for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
  844                 INP_LOCK(inp);
  845                 ninp = LIST_NEXT(inp, inp_list);
  846 #ifdef INET6
  847                 if ((inp->inp_vflag & INP_IPV4) == 0) {
  848                         INP_UNLOCK(inp);
  849                         continue;
  850                 }
  851 #endif
  852                 if (inp->inp_faddr.s_addr != faddr.s_addr ||
  853                     inp->inp_socket == NULL) {
  854                         INP_UNLOCK(inp);
  855                         continue;
  856                 }
  857                 if ((*notify)(inp, errno))
  858                         INP_UNLOCK(inp);
  859         }
  860         INP_INFO_WUNLOCK(pcbinfo);
  861         splx(s);
  862 }
  863 
  864 void
  865 in_pcbpurgeif0(pcbinfo, ifp)
  866         struct inpcbinfo *pcbinfo;
  867         struct ifnet *ifp;
  868 {
  869         struct inpcb *inp;
  870         struct ip_moptions *imo;
  871         int i, gap;
  872 
  873         /* why no splnet here? XXX */
  874         INP_INFO_RLOCK(pcbinfo);
  875         LIST_FOREACH(inp, pcbinfo->listhead, inp_list) {
  876                 INP_LOCK(inp);
  877                 imo = inp->inp_moptions;
  878                 if ((inp->inp_vflag & INP_IPV4) &&
  879                     imo != NULL) {
  880                         /*
  881                          * Unselect the outgoing interface if it is being
  882                          * detached.
  883                          */
  884                         if (imo->imo_multicast_ifp == ifp)
  885                                 imo->imo_multicast_ifp = NULL;
  886 
  887                         /*
  888                          * Drop multicast group membership if we joined
  889                          * through the interface being detached.
  890                          */
  891                         for (i = 0, gap = 0; i < imo->imo_num_memberships;
  892                             i++) {
  893                                 if (imo->imo_membership[i]->inm_ifp == ifp) {
  894                                         in_delmulti(imo->imo_membership[i]);
  895                                         gap++;
  896                                 } else if (gap != 0)
  897                                         imo->imo_membership[i - gap] =
  898                                             imo->imo_membership[i];
  899                         }
  900                         imo->imo_num_memberships -= gap;
  901                 }
  902                 INP_UNLOCK(inp);
  903         }
  904         INP_INFO_RUNLOCK(pcbinfo);
  905 }
  906 
  907 /*
  908  * Lookup a PCB based on the local address and port.
  909  */
  910 #define INP_LOOKUP_MAPPED_PCB_COST      3
  911 struct inpcb *
  912 in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
  913         struct inpcbinfo *pcbinfo;
  914         struct in_addr laddr;
  915         u_int lport_arg;
  916         int wild_okay;
  917 {
  918         register struct inpcb *inp;
  919 #ifdef INET6
  920         int matchwild = 3 + INP_LOOKUP_MAPPED_PCB_COST;
  921 #else
  922         int matchwild = 3;
  923 #endif
  924         int wildcard;
  925         u_short lport = lport_arg;
  926 
  927         INP_INFO_WLOCK_ASSERT(pcbinfo);
  928 
  929         if (!wild_okay) {
  930                 struct inpcbhead *head;
  931                 /*
  932                  * Look for an unconnected (wildcard foreign addr) PCB that
  933                  * matches the local address and port we're looking for.
  934                  */
  935                 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
  936                 LIST_FOREACH(inp, head, inp_hash) {
  937 #ifdef INET6
  938                         if ((inp->inp_vflag & INP_IPV4) == 0)
  939                                 continue;
  940 #endif
  941                         if (inp->inp_faddr.s_addr == INADDR_ANY &&
  942                             inp->inp_laddr.s_addr == laddr.s_addr &&
  943                             inp->inp_lport == lport) {
  944                                 /*
  945                                  * Found.
  946                                  */
  947                                 return (inp);
  948                         }
  949                 }
  950                 /*
  951                  * Not found.
  952                  */
  953                 return (NULL);
  954         } else {
  955                 struct inpcbporthead *porthash;
  956                 struct inpcbport *phd;
  957                 struct inpcb *match = NULL;
  958                 /*
  959                  * Best fit PCB lookup.
  960                  *
  961                  * First see if this local port is in use by looking on the
  962                  * port hash list.
  963                  */
  964                 retrylookup:
  965                 porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
  966                     pcbinfo->porthashmask)];
  967                 LIST_FOREACH(phd, porthash, phd_hash) {
  968                         if (phd->phd_port == lport)
  969                                 break;
  970                 }
  971                 if (phd != NULL) {
  972                         /*
  973                          * Port is in use by one or more PCBs. Look for best
  974                          * fit.
  975                          */
  976                         LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
  977                                 wildcard = 0;
  978 #ifdef INET6
  979                                 if ((inp->inp_vflag & INP_IPV4) == 0)
  980                                         continue;
  981                                 /*
  982                                  * We never select the PCB that has
  983                                  * INP_IPV6 flag and is bound to :: if
  984                                  * we have another PCB which is bound
  985                                  * to 0.0.0.0.  If a PCB has the
  986                                  * INP_IPV6 flag, then we set its cost
  987                                  * higher than IPv4 only PCBs.
  988                                  *
  989                                  * Note that the case only happens
  990                                  * when a socket is bound to ::, under
  991                                  * the condition that the use of the
  992                                  * mapped address is allowed.
  993                                  */
  994                                 if ((inp->inp_vflag & INP_IPV6) != 0)
  995                                         wildcard += INP_LOOKUP_MAPPED_PCB_COST;
  996 #endif
  997                                 /*
  998                                  * Clean out old time_wait sockets if they
  999                                  * are clogging up needed local ports.
 1000                                  */
 1001                                 if ((inp->inp_vflag & INP_TIMEWAIT) != 0) {
 1002                                         if (tcp_twrecycleable((struct tcptw *)inp->inp_ppcb)) {
 1003                                                 INP_LOCK(inp);
 1004                                                 tcp_twclose((struct tcptw *)inp->inp_ppcb, 0);
 1005                                                 match = NULL;
 1006                                                 goto retrylookup;
 1007                                         }
 1008                                 }
 1009                                 if (inp->inp_faddr.s_addr != INADDR_ANY)
 1010                                         wildcard++;
 1011                                 if (inp->inp_laddr.s_addr != INADDR_ANY) {
 1012                                         if (laddr.s_addr == INADDR_ANY)
 1013                                                 wildcard++;
 1014                                         else if (inp->inp_laddr.s_addr != laddr.s_addr)
 1015                                                 continue;
 1016                                 } else {
 1017                                         if (laddr.s_addr != INADDR_ANY)
 1018                                                 wildcard++;
 1019                                 }
 1020                                 if (wildcard < matchwild) {
 1021                                         match = inp;
 1022                                         matchwild = wildcard;
 1023                                         if (matchwild == 0) {
 1024                                                 break;
 1025                                         }
 1026                                 }
 1027                         }
 1028                 }
 1029                 return (match);
 1030         }
 1031 }
 1032 #undef INP_LOOKUP_MAPPED_PCB_COST
 1033 
 1034 /*
 1035  * Lookup PCB in hash list.
 1036  */
 1037 struct inpcb *
 1038 in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard,
 1039                   ifp)
 1040         struct inpcbinfo *pcbinfo;
 1041         struct in_addr faddr, laddr;
 1042         u_int fport_arg, lport_arg;
 1043         int wildcard;
 1044         struct ifnet *ifp;
 1045 {
 1046         struct inpcbhead *head;
 1047         register struct inpcb *inp;
 1048         u_short fport = fport_arg, lport = lport_arg;
 1049 
 1050         INP_INFO_RLOCK_ASSERT(pcbinfo);
 1051         /*
 1052          * First look for an exact match.
 1053          */
 1054         head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)];
 1055         LIST_FOREACH(inp, head, inp_hash) {
 1056 #ifdef INET6
 1057                 if ((inp->inp_vflag & INP_IPV4) == 0)
 1058                         continue;
 1059 #endif
 1060                 if (inp->inp_faddr.s_addr == faddr.s_addr &&
 1061                     inp->inp_laddr.s_addr == laddr.s_addr &&
 1062                     inp->inp_fport == fport &&
 1063                     inp->inp_lport == lport) {
 1064                         /*
 1065                          * Found.
 1066                          */
 1067                         return (inp);
 1068                 }
 1069         }
 1070         if (wildcard) {
 1071                 struct inpcb *local_wild = NULL;
 1072 #if defined(INET6)
 1073                 struct inpcb *local_wild_mapped = NULL;
 1074 #endif /* defined(INET6) */
 1075 
 1076                 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
 1077                 LIST_FOREACH(inp, head, inp_hash) {
 1078 #ifdef INET6
 1079                         if ((inp->inp_vflag & INP_IPV4) == 0)
 1080                                 continue;
 1081 #endif
 1082                         if (inp->inp_faddr.s_addr == INADDR_ANY &&
 1083                             inp->inp_lport == lport) {
 1084                                 if (ifp && ifp->if_type == IFT_FAITH &&
 1085                                     (inp->inp_flags & INP_FAITH) == 0)
 1086                                         continue;
 1087                                 if (inp->inp_laddr.s_addr == laddr.s_addr)
 1088                                         return (inp);
 1089                                 else if (inp->inp_laddr.s_addr == INADDR_ANY) {
 1090 #if defined(INET6)
 1091                                         if (INP_CHECK_SOCKAF(inp->inp_socket,
 1092                                                              AF_INET6))
 1093                                                 local_wild_mapped = inp;
 1094                                         else
 1095 #endif /* defined(INET6) */
 1096                                         local_wild = inp;
 1097                                 }
 1098                         }
 1099                 }
 1100 #if defined(INET6)
 1101                 if (local_wild == NULL)
 1102                         return (local_wild_mapped);
 1103 #endif /* defined(INET6) */
 1104                 return (local_wild);
 1105         }
 1106 
 1107         /*
 1108          * Not found.
 1109          */
 1110         return (NULL);
 1111 }
 1112 
 1113 /*
 1114  * Insert PCB onto various hash lists.
 1115  */
 1116 int
 1117 in_pcbinshash(inp)
 1118         struct inpcb *inp;
 1119 {
 1120         struct inpcbhead *pcbhash;
 1121         struct inpcbporthead *pcbporthash;
 1122         struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 1123         struct inpcbport *phd;
 1124         u_int32_t hashkey_faddr;
 1125 
 1126         INP_INFO_WLOCK_ASSERT(pcbinfo);
 1127 #ifdef INET6
 1128         if (inp->inp_vflag & INP_IPV6)
 1129                 hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
 1130         else
 1131 #endif /* INET6 */
 1132         hashkey_faddr = inp->inp_faddr.s_addr;
 1133 
 1134         pcbhash = &pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
 1135                  inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)];
 1136 
 1137         pcbporthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(inp->inp_lport,
 1138             pcbinfo->porthashmask)];
 1139 
 1140         /*
 1141          * Go through port list and look for a head for this lport.
 1142          */
 1143         LIST_FOREACH(phd, pcbporthash, phd_hash) {
 1144                 if (phd->phd_port == inp->inp_lport)
 1145                         break;
 1146         }
 1147         /*
 1148          * If none exists, malloc one and tack it on.
 1149          */
 1150         if (phd == NULL) {
 1151                 MALLOC(phd, struct inpcbport *, sizeof(struct inpcbport), M_PCB, M_NOWAIT);
 1152                 if (phd == NULL) {
 1153                         return (ENOBUFS); /* XXX */
 1154                 }
 1155                 phd->phd_port = inp->inp_lport;
 1156                 LIST_INIT(&phd->phd_pcblist);
 1157                 LIST_INSERT_HEAD(pcbporthash, phd, phd_hash);
 1158         }
 1159         inp->inp_phd = phd;
 1160         LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist);
 1161         LIST_INSERT_HEAD(pcbhash, inp, inp_hash);
 1162         return (0);
 1163 }
 1164 
 1165 /*
 1166  * Move PCB to the proper hash bucket when { faddr, fport } have  been
 1167  * changed. NOTE: This does not handle the case of the lport changing (the
 1168  * hashed port list would have to be updated as well), so the lport must
 1169  * not change after in_pcbinshash() has been called.
 1170  */
 1171 void
 1172 in_pcbrehash(inp)
 1173         struct inpcb *inp;
 1174 {
 1175         struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 1176         struct inpcbhead *head;
 1177         u_int32_t hashkey_faddr;
 1178 
 1179         INP_INFO_WLOCK_ASSERT(pcbinfo);
 1180         INP_LOCK_ASSERT(inp);
 1181 #ifdef INET6
 1182         if (inp->inp_vflag & INP_IPV6)
 1183                 hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
 1184         else
 1185 #endif /* INET6 */
 1186         hashkey_faddr = inp->inp_faddr.s_addr;
 1187 
 1188         head = &pcbinfo->hashbase[INP_PCBHASH(hashkey_faddr,
 1189                 inp->inp_lport, inp->inp_fport, pcbinfo->hashmask)];
 1190 
 1191         LIST_REMOVE(inp, inp_hash);
 1192         LIST_INSERT_HEAD(head, inp, inp_hash);
 1193 }
 1194 
 1195 /*
 1196  * Remove PCB from various lists.
 1197  */
 1198 void
 1199 in_pcbremlists(inp)
 1200         struct inpcb *inp;
 1201 {
 1202         struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 1203 
 1204         INP_INFO_WLOCK_ASSERT(pcbinfo);
 1205         INP_LOCK_ASSERT(inp);
 1206 
 1207         inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
 1208         if (inp->inp_lport) {
 1209                 struct inpcbport *phd = inp->inp_phd;
 1210 
 1211                 LIST_REMOVE(inp, inp_hash);
 1212                 LIST_REMOVE(inp, inp_portlist);
 1213                 if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
 1214                         LIST_REMOVE(phd, phd_hash);
 1215                         free(phd, M_PCB);
 1216                 }
 1217         }
 1218         LIST_REMOVE(inp, inp_list);
 1219         pcbinfo->ipi_count--;
 1220 }
 1221 
 1222 /*
 1223  * A set label operation has occurred at the socket layer, propagate the
 1224  * label change into the in_pcb for the socket.
 1225  */
 1226 void
 1227 in_pcbsosetlabel(so)
 1228         struct socket *so;
 1229 {
 1230 #ifdef MAC
 1231         struct inpcb *inp;
 1232 
 1233         inp = (struct inpcb *)so->so_pcb;
 1234         INP_LOCK(inp);
 1235         SOCK_LOCK(so);
 1236         mac_inpcb_sosetlabel(so, inp);
 1237         SOCK_UNLOCK(so);
 1238         INP_UNLOCK(inp);
 1239 #endif
 1240 }
 1241 
 1242 /*
 1243  * ipport_tick runs once per second, determining if random port
 1244  * allocation should be continued.  If more than ipport_randomcps
 1245  * ports have been allocated in the last second, then we return to
 1246  * sequential port allocation. We return to random allocation only
 1247  * once we drop below ipport_randomcps for at least ipport_randomtime
 1248  * seconds.
 1249  */
 1250 
 1251 void
 1252 ipport_tick(xtp)
 1253         void *xtp;
 1254 {
 1255         if (ipport_tcpallocs > ipport_tcplastcount + ipport_randomcps) {
 1256                 ipport_stoprandom = ipport_randomtime;
 1257         } else {
 1258                 if (ipport_stoprandom > 0)
 1259                         ipport_stoprandom--;
 1260         }
 1261         ipport_tcplastcount = ipport_tcpallocs;
 1262         callout_reset(&ipport_tick_callout, hz, ipport_tick, NULL);
 1263 }

Cache object: 6c1e533e789bb7fdf522721dcdee895b


[ 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.