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.
38 #include <sys/types.h>
39 //#include <sys/socket.h>
41 //#include <netinet/in.h>
50 * Bind a socket to a privileged IP port
55 struct sockaddr_in
*sin
;
57 return bindresvport_sa(sd
, (struct sockaddr
*)sin
);
64 #define ENDPORT (IPPORT_RESERVED - 1)
65 #define NPORTS (ENDPORT - STARTPORT + 1)
68 bindresvport_sa(sd
, sa
)
73 struct sockaddr_storage myaddr
;
74 struct sockaddr_in
*sin
;
76 struct sockaddr_in6
*sin6
;
79 static u_int16_t port
;
80 static short startport
= STARTPORT
;
82 int nports
= ENDPORT
- startport
+ 1;
83 int endport
= ENDPORT
;
87 salen
= sizeof(myaddr
);
88 sa
= (struct sockaddr
*)&myaddr
;
90 if (getsockname(sd
, (struct sockaddr
*)&myaddr
, &salen
) == -1)
91 return -1; /* errno is correctly set */
93 af
= myaddr
.ss_family
;
99 sin
= (struct sockaddr_in
*)sa
;
100 salen
= sizeof(struct sockaddr_in
);
101 port
= ntohs(sin
->sin_port
);
102 portp
= &sin
->sin_port
;
106 sin6
= (struct sockaddr_in6
*)sa
;
107 salen
= sizeof(struct sockaddr_in6
);
108 port
= ntohs(sin6
->sin6_port
);
109 portp
= &sin6
->sin6_port
;
113 errno
= EPFNOSUPPORT
;
119 port
= (getpid() % NPORTS
) + STARTPORT
;
124 for (i
= 0; i
< nports
; ++i
) {
125 *portp
= htons(port
++);
128 res
= bind(sd
, sa
, salen
);
129 if (res
>= 0 || errno
!= EADDRINUSE
)
132 if (i
== nports
&& startport
!= LOWPORT
) {
134 endport
= STARTPORT
- 1;
135 nports
= STARTPORT
- LOWPORT
;
136 port
= LOWPORT
+ port
% (STARTPORT
- LOWPORT
);
143 /*----------------------
147 bindresvport_sa(SOCKET sd, struct sockaddr *sa)
149 fprintf(stderr, "Do-nothing bindresvport_sa!\n");
153 -------------------------*/
154 #define IP_PORTRANGE 19
155 #define IP_PORTRANGE_LOW 2
158 * Bind a socket to a privileged IP port
161 bindresvport_sa(sd
, sa
)
165 #ifdef IPV6_PORTRANGE
169 struct sockaddr_storage myaddr
;
170 struct sockaddr_in
*sin
;
172 struct sockaddr_in6
*sin6
;
174 int proto
, portrange
, portlow
;
178 WSAPROTOCOL_INFO proto_info
;
179 int proto_info_size
= sizeof(proto_info
);
183 salen
= sizeof(myaddr
);
184 sa
= (struct sockaddr
*)&myaddr
;
187 memset(sa
, 0, salen
);
188 if (error
= getsockopt(sd
, SOL_SOCKET
, SO_PROTOCOL_INFO
, (char *)&proto_info
, &proto_info_size
) == SOCKET_ERROR
) {
189 int sockerr
= WSAGetLastError();
192 af
= proto_info
.iAddressFamily
;
194 if (getsockname(sd
, sa
, &salen
) == -1)
195 return -1; /* errno is correctly set */
198 memset(sa
, 0, salen
);
206 portrange
= IP_PORTRANGE
;
207 portlow
= IP_PORTRANGE_LOW
;
208 sin
= (struct sockaddr_in
*)sa
;
209 salen
= sizeof(struct sockaddr_in
);
210 portp
= &sin
->sin_port
;
214 proto
= IPPROTO_IPV6
;
215 #ifdef IPV6_PORTRANGE
216 portrange
= IPV6_PORTRANGE
;
217 portlow
= IPV6_PORTRANGE_LOW
;
219 sin6
= (struct sockaddr_in6
*)sa
;
220 salen
= sizeof(struct sockaddr_in6
);
221 portp
= &sin6
->sin6_port
;
225 errno
= WSAEPFNOSUPPORT
;
228 sa
->sa_family
= (ADDRESS_FAMILY
) af
;
230 #ifdef IPV6_PORTRANGE
232 socklen_t oldlen
= sizeof(old
);
234 error
= getsockopt(sd
, proto
, portrange
, &old
, &oldlen
);
238 error
= setsockopt(sd
, proto
, portrange
, &portlow
,
245 error
= bind(sd
, sa
, salen
);
247 int err
= WSAGetLastError();
250 #ifdef IPV6_PORTRANGE
252 int saved_errno
= errno
;
255 if (setsockopt(sd
, proto
, portrange
, &old
,
261 if (sa
!= (struct sockaddr
*)&myaddr
) {
262 /* Hmm, what did the kernel assign? */
263 if (getsockname(sd
, sa
, &salen
) < 0)