(root)/
glibc-2.38/
inet/
bindresvport.c
       1  /*
       2   * Copyright (c) 2010, Oracle America, Inc.
       3   *
       4   * Redistribution and use in source and binary forms, with or without
       5   * modification, are permitted provided that the following conditions are
       6   * met:
       7   *
       8   *     * Redistributions of source code must retain the above copyright
       9   *       notice, this list of conditions and the following disclaimer.
      10   *     * Redistributions in binary form must reproduce the above
      11   *       copyright notice, this list of conditions and the following
      12   *       disclaimer in the documentation and/or other materials
      13   *       provided with the distribution.
      14   *     * Neither the name of the "Oracle America, Inc." nor the names of its
      15   *       contributors may be used to endorse or promote products derived
      16   *       from this software without specific prior written permission.
      17   *
      18   *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19   *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20   *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      21   *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      22   *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      23   *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      24   *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
      25   *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      26   *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      27   *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      28   *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      29   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30   */
      31  
      32  #include <errno.h>
      33  #include <unistd.h>
      34  #include <string.h>
      35  #include <sys/types.h>
      36  #include <sys/socket.h>
      37  #include <netinet/in.h>
      38  #include <libc-lock.h>
      39  
      40  /*
      41   * Locks the static variables in this file.
      42   */
      43  __libc_lock_define_initialized (static, lock);
      44  
      45  /*
      46   * Bind a socket to a privileged IP port
      47   */
      48  int
      49  bindresvport (int sd, struct sockaddr_in *sin)
      50  {
      51    static short port;
      52    struct sockaddr_in myaddr;
      53    int i;
      54  
      55  #define STARTPORT 600
      56  #define LOWPORT 512
      57  #define ENDPORT (IPPORT_RESERVED - 1)
      58  #define NPORTS	(ENDPORT - STARTPORT + 1)
      59    static short startport = STARTPORT;
      60  
      61    if (sin == (struct sockaddr_in *) 0)
      62      {
      63        sin = &myaddr;
      64        memset (sin, 0, sizeof (*sin));
      65        sin->sin_family = AF_INET;
      66      }
      67    else if (sin->sin_family != AF_INET)
      68      {
      69        __set_errno (EAFNOSUPPORT);
      70        return -1;
      71      }
      72  
      73    if (port == 0)
      74      {
      75        port = (__getpid () % NPORTS) + STARTPORT;
      76      }
      77  
      78    /* Initialize to make gcc happy.  */
      79    int res = -1;
      80  
      81    int nports = ENDPORT - startport + 1;
      82    int endport = ENDPORT;
      83  
      84    __libc_lock_lock (lock);
      85  
      86   again:
      87    for (i = 0; i < nports; ++i)
      88      {
      89        sin->sin_port = htons (port++);
      90        if (port > endport)
      91  	port = startport;
      92        res = __bind (sd, sin, sizeof (struct sockaddr_in));
      93        if (res >= 0 || errno != EADDRINUSE)
      94  	break;
      95      }
      96  
      97    if (i == nports && startport != LOWPORT)
      98      {
      99        startport = LOWPORT;
     100        endport = STARTPORT - 1;
     101        nports = STARTPORT - LOWPORT;
     102        port = LOWPORT + port % (STARTPORT - LOWPORT);
     103        goto again;
     104      }
     105  
     106    __libc_lock_unlock (lock);
     107  
     108    return res;
     109  }
     110  libc_hidden_def (bindresvport)