[LIBTIRPC]
[reactos.git] / reactos / dll / win32 / libtirpc / src / bindresvport.c
1 /*
2 * Copyright (c) 2009, Sun Microsystems, Inc.
3 * 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 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.
15 *
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.
27 */
28
29 //#include <sys/cdefs.h>
30
31 /*
32 * Copyright (c) 1987 by Sun Microsystems, Inc.
33 *
34 * Portions Copyright(C) 1996, Jason Downs. All rights reserved.
35 */
36
37 #include <wintirpc.h>
38 #include <sys/types.h>
39 //#include <sys/socket.h>
40
41 //#include <netinet/in.h>
42
43 #include <errno.h>
44 #include <string.h>
45 //#include <unistd.h>
46
47 #include <rpc/rpc.h>
48
49 /*
50 * Bind a socket to a privileged IP port
51 */
52 int
53 bindresvport(sd, sin)
54 SOCKET sd;
55 struct sockaddr_in *sin;
56 {
57 return bindresvport_sa(sd, (struct sockaddr *)sin);
58 }
59
60 #ifdef __linux__
61
62 #define STARTPORT 600
63 #define LOWPORT 512
64 #define ENDPORT (IPPORT_RESERVED - 1)
65 #define NPORTS (ENDPORT - STARTPORT + 1)
66
67 int
68 bindresvport_sa(sd, sa)
69 int sd;
70 struct sockaddr *sa;
71 {
72 int res, af;
73 struct sockaddr_storage myaddr;
74 struct sockaddr_in *sin;
75 #ifdef INET6
76 struct sockaddr_in6 *sin6;
77 #endif
78 u_int16_t *portp;
79 static u_int16_t port;
80 static short startport = STARTPORT;
81 socklen_t salen;
82 int nports = ENDPORT - startport + 1;
83 int endport = ENDPORT;
84 int i;
85
86 if (sa == NULL) {
87 salen = sizeof(myaddr);
88 sa = (struct sockaddr *)&myaddr;
89
90 if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1)
91 return -1; /* errno is correctly set */
92
93 af = myaddr.ss_family;
94 } else
95 af = sa->sa_family;
96
97 switch (af) {
98 case AF_INET:
99 sin = (struct sockaddr_in *)sa;
100 salen = sizeof(struct sockaddr_in);
101 port = ntohs(sin->sin_port);
102 portp = &sin->sin_port;
103 break;
104 #ifdef INET6
105 case AF_INET6:
106 sin6 = (struct sockaddr_in6 *)sa;
107 salen = sizeof(struct sockaddr_in6);
108 port = ntohs(sin6->sin6_port);
109 portp = &sin6->sin6_port;
110 break;
111 #endif
112 default:
113 errno = EPFNOSUPPORT;
114 return (-1);
115 }
116 sa->sa_family = af;
117
118 if (port == 0) {
119 port = (getpid() % NPORTS) + STARTPORT;
120 }
121 res = -1;
122 errno = EADDRINUSE;
123 again:
124 for (i = 0; i < nports; ++i) {
125 *portp = htons(port++);
126 if (port > endport)
127 port = startport;
128 res = bind(sd, sa, salen);
129 if (res >= 0 || errno != EADDRINUSE)
130 break;
131 }
132 if (i == nports && startport != LOWPORT) {
133 startport = LOWPORT;
134 endport = STARTPORT - 1;
135 nports = STARTPORT - LOWPORT;
136 port = LOWPORT + port % (STARTPORT - LOWPORT);
137 goto again;
138 }
139 return (res);
140 }
141
142 #else
143 /*----------------------
144 #if defined(_WIN32)
145
146 int
147 bindresvport_sa(SOCKET sd, struct sockaddr *sa)
148 {
149 fprintf(stderr, "Do-nothing bindresvport_sa!\n");
150 return 0;
151 }
152 #else
153 -------------------------*/
154 #define IP_PORTRANGE 19
155 #define IP_PORTRANGE_LOW 2
156
157 /*
158 * Bind a socket to a privileged IP port
159 */
160 int
161 bindresvport_sa(sd, sa)
162 SOCKET sd;
163 struct sockaddr *sa;
164 {
165 #ifdef IPV6_PORTRANGE
166 int old;
167 #endif
168 int error, af;
169 struct sockaddr_storage myaddr;
170 struct sockaddr_in *sin;
171 #ifdef INET6
172 struct sockaddr_in6 *sin6;
173 #endif
174 int proto, portrange, portlow;
175 u_int16_t *portp;
176 socklen_t salen;
177 #ifdef _WIN32
178 WSAPROTOCOL_INFO proto_info;
179 int proto_info_size = sizeof(proto_info);
180 #endif
181
182 if (sa == NULL) {
183 salen = sizeof(myaddr);
184 sa = (struct sockaddr *)&myaddr;
185
186 #ifdef _WIN32
187 memset(sa, 0, salen);
188 if (error = getsockopt(sd, SOL_SOCKET, SO_PROTOCOL_INFO, (char *)&proto_info, &proto_info_size) == SOCKET_ERROR) {
189 #ifndef __REACTOS__
190 int sockerr = WSAGetLastError();
191 #endif
192 return -1;
193 }
194 af = proto_info.iAddressFamily;
195 #else
196 if (getsockname(sd, sa, &salen) == -1)
197 return -1; /* errno is correctly set */
198
199 af = sa->sa_family;
200 memset(sa, 0, salen);
201 #endif
202 } else
203 af = sa->sa_family;
204
205 switch (af) {
206 case AF_INET:
207 proto = IPPROTO_IP;
208 portrange = IP_PORTRANGE;
209 portlow = IP_PORTRANGE_LOW;
210 sin = (struct sockaddr_in *)sa;
211 salen = sizeof(struct sockaddr_in);
212 portp = &sin->sin_port;
213 break;
214 #ifdef INET6
215 case AF_INET6:
216 proto = IPPROTO_IPV6;
217 #ifdef IPV6_PORTRANGE
218 portrange = IPV6_PORTRANGE;
219 portlow = IPV6_PORTRANGE_LOW;
220 #endif
221 sin6 = (struct sockaddr_in6 *)sa;
222 salen = sizeof(struct sockaddr_in6);
223 portp = &sin6->sin6_port;
224 break;
225 #endif /* INET6 */
226 default:
227 errno = WSAEPFNOSUPPORT;
228 return (-1);
229 }
230 sa->sa_family = (ADDRESS_FAMILY) af;
231
232 #ifdef IPV6_PORTRANGE
233 if (*portp == 0) {
234 socklen_t oldlen = sizeof(old);
235
236 error = getsockopt(sd, proto, portrange, &old, &oldlen);
237 if (error < 0)
238 return (error);
239
240 error = setsockopt(sd, proto, portrange, &portlow,
241 sizeof(portlow));
242 if (error < 0)
243 return (error);
244 }
245 #endif
246
247 error = bind(sd, sa, salen);
248 if (error) {
249 #ifndef __REACTOS__
250 int err = WSAGetLastError();
251 #endif
252 }
253
254 #ifdef IPV6_PORTRANGE
255 if (*portp == 0) {
256 int saved_errno = errno;
257
258 if (error < 0) {
259 if (setsockopt(sd, proto, portrange, &old,
260 sizeof(old)) < 0)
261 errno = saved_errno;
262 return (error);
263 }
264
265 if (sa != (struct sockaddr *)&myaddr) {
266 /* Hmm, what did the kernel assign? */
267 if (getsockname(sd, sa, &salen) < 0)
268 errno = saved_errno;
269 return (error);
270 }
271 }
272 #endif
273 return (error);
274 }
275 /*
276 #endif
277 */
278 #endif