2 * Copyright (c) 2009, Sun Microsystems, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of Sun Microsystems, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
32 * Copyright (c) 1987 by Sun Microsystems, Inc.
34 * Portions Copyright(C) 1996, Jason Downs. All rights reserved.
37 #include <sys/types.h>
38 #include <sys/socket.h>
40 #include <netinet/in.h>
49 #include <reentrant.h>
51 extern pthread_mutex_t port_lock;
54 * Bind a socket to a privileged IP port
59 struct sockaddr_in *sin;
61 return bindresvport_sa(sd, (struct sockaddr *)sin);
68 #define ENDPORT (IPPORT_RESERVED - 1)
69 #define NPORTS (ENDPORT - STARTPORT + 1)
72 bindresvport_sa(sd, sa)
77 struct sockaddr_storage myaddr;
78 struct sockaddr_in *sin;
80 struct sockaddr_in6 *sin6;
83 static u_int16_t port;
84 static short startport = STARTPORT;
87 int endport = ENDPORT;
90 mutex_lock(&port_lock);
91 nports = ENDPORT - startport + 1;
94 salen = sizeof(myaddr);
95 sa = (struct sockaddr *)&myaddr;
97 if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) {
98 mutex_unlock(&port_lock);
99 return -1; /* errno is correctly set */
102 af = myaddr.ss_family;
108 sin = (struct sockaddr_in *)sa;
109 salen = sizeof(struct sockaddr_in);
110 port = ntohs(sin->sin_port);
111 portp = &sin->sin_port;
115 sin6 = (struct sockaddr_in6 *)sa;
116 salen = sizeof(struct sockaddr_in6);
117 port = ntohs(sin6->sin6_port);
118 portp = &sin6->sin6_port;
122 errno = EPFNOSUPPORT;
123 mutex_unlock(&port_lock);
129 port = (getpid() % NPORTS) + STARTPORT;
134 for (i = 0; i < nports; ++i) {
135 *portp = htons(port++);
138 res = bind(sd, sa, salen);
139 if (res >= 0 || errno != EADDRINUSE)
142 if (i == nports && startport != LOWPORT) {
144 endport = STARTPORT - 1;
145 nports = STARTPORT - LOWPORT;
146 port = LOWPORT + port % (STARTPORT - LOWPORT);
149 mutex_unlock(&port_lock);
155 #define IP_PORTRANGE 19
156 #define IP_PORTRANGE_LOW 2
159 * Bind a socket to a privileged IP port
162 bindresvport_sa(sd, sa)
167 struct sockaddr_storage myaddr;
168 struct sockaddr_in *sin;
170 struct sockaddr_in6 *sin6;
172 int proto, portrange, portlow;
177 salen = sizeof(myaddr);
178 sa = (struct sockaddr *)&myaddr;
180 if (getsockname(sd, sa, &salen) == -1)
181 return -1; /* errno is correctly set */
184 memset(sa, 0, salen);
191 portrange = IP_PORTRANGE;
192 portlow = IP_PORTRANGE_LOW;
193 sin = (struct sockaddr_in *)sa;
194 salen = sizeof(struct sockaddr_in);
195 portp = &sin->sin_port;
199 proto = IPPROTO_IPV6;
200 portrange = IPV6_PORTRANGE;
201 portlow = IPV6_PORTRANGE_LOW;
202 sin6 = (struct sockaddr_in6 *)sa;
203 salen = sizeof(struct sockaddr_in6);
204 portp = &sin6->sin6_port;
208 errno = EPFNOSUPPORT;
214 socklen_t oldlen = sizeof(old);
216 error = getsockopt(sd, proto, portrange, &old, &oldlen);
220 error = setsockopt(sd, proto, portrange, &portlow,
226 error = bind(sd, sa, salen);
229 int saved_errno = errno;
232 if (setsockopt(sd, proto, portrange, &old,
238 if (sa != (struct sockaddr *)&myaddr) {
239 /* Hmm, what did the kernel assign? */
240 if (getsockname(sd, sa, &salen) < 0)