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 279