[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 int sockerr = WSAGetLastError();
190 return -1;
191 }
192 af = proto_info.iAddressFamily;
193 #else
194 if (getsockname(sd, sa, &salen) == -1)
195 return -1; /* errno is correctly set */
196
197 af = sa->sa_family;
198 memset(sa, 0, salen);
199 #endif
200 } else
201 af = sa->sa_family;
202
203 switch (af) {
204 case AF_INET:
205 proto = IPPROTO_IP;
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;
211 break;
212 #ifdef INET6
213 case AF_INET6:
214 proto = IPPROTO_IPV6;
215 #ifdef IPV6_PORTRANGE
216 portrange = IPV6_PORTRANGE;
217 portlow = IPV6_PORTRANGE_LOW;
218 #endif
219 sin6 = (struct sockaddr_in6 *)sa;
220 salen = sizeof(struct sockaddr_in6);
221 portp = &sin6->sin6_port;
222 break;
223 #endif /* INET6 */
224 default:
225 errno = WSAEPFNOSUPPORT;
226 return (-1);
227 }
228 sa->sa_family = (ADDRESS_FAMILY) af;
229
230 #ifdef IPV6_PORTRANGE
231 if (*portp == 0) {
232 socklen_t oldlen = sizeof(old);
233
234 error = getsockopt(sd, proto, portrange, &old, &oldlen);
235 if (error < 0)
236 return (error);
237
238 error = setsockopt(sd, proto, portrange, &portlow,
239 sizeof(portlow));
240 if (error < 0)
241 return (error);
242 }
243 #endif
244
245 error = bind(sd, sa, salen);
246 if (error) {
247 int err = WSAGetLastError();
248 }
249
250 #ifdef IPV6_PORTRANGE
251 if (*portp == 0) {
252 int saved_errno = errno;
253
254 if (error < 0) {
255 if (setsockopt(sd, proto, portrange, &old,
256 sizeof(old)) < 0)
257 errno = saved_errno;
258 return (error);
259 }
260
261 if (sa != (struct sockaddr *)&myaddr) {
262 /* Hmm, what did the kernel assign? */
263 if (getsockname(sd, sa, &salen) < 0)
264 errno = saved_errno;
265 return (error);
266 }
267 }
268 #endif
269 return (error);
270 }
271 /*
272 #endif
273 */
274 #endif