bindresvport.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. #include <errno.h>
  32. #include <unistd.h>
  33. #include <string.h>
  34. #include <sys/types.h>
  35. #include <sys/socket.h>
  36. #include <netinet/in.h>
  37. #include <libc-lock.h>
  38. /*
  39. * Locks the static variables in this file.
  40. */
  41. __libc_lock_define_initialized (static, lock);
  42. /*
  43. * Bind a socket to a privileged IP port
  44. */
  45. int
  46. bindresvport (int sd, struct sockaddr_in *sin)
  47. {
  48. static short port;
  49. struct sockaddr_in myaddr;
  50. int i;
  51. #define STARTPORT 600
  52. #define LOWPORT 512
  53. #define ENDPORT (IPPORT_RESERVED - 1)
  54. #define NPORTS (ENDPORT - STARTPORT + 1)
  55. static short startport = STARTPORT;
  56. if (sin == (struct sockaddr_in *) 0)
  57. {
  58. sin = &myaddr;
  59. memset (sin, 0, sizeof (*sin));
  60. sin->sin_family = AF_INET;
  61. }
  62. else if (sin->sin_family != AF_INET)
  63. {
  64. __set_errno (EAFNOSUPPORT);
  65. return -1;
  66. }
  67. if (port == 0)
  68. {
  69. port = (__getpid () % NPORTS) + STARTPORT;
  70. }
  71. /* Initialize to make gcc happy. */
  72. int res = -1;
  73. int nports = ENDPORT - startport + 1;
  74. int endport = ENDPORT;
  75. __libc_lock_lock (lock);
  76. again:
  77. for (i = 0; i < nports; ++i)
  78. {
  79. sin->sin_port = htons (port++);
  80. if (port > endport)
  81. port = startport;
  82. res = __bind (sd, sin, sizeof (struct sockaddr_in));
  83. if (res >= 0 || errno != EADDRINUSE)
  84. break;
  85. }
  86. if (i == nports && startport != LOWPORT)
  87. {
  88. startport = LOWPORT;
  89. endport = STARTPORT - 1;
  90. nports = STARTPORT - LOWPORT;
  91. port = LOWPORT + port % (STARTPORT - LOWPORT);
  92. goto again;
  93. }
  94. __libc_lock_unlock (lock);
  95. return res;
  96. }
  97. libc_hidden_def (bindresvport)