1 /* modified from OpenSSH distribution -plb 5/22/2003 */
2
3 /* This file has be modified from the original OpenBSD source */
4
5 /*
6 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
7 * unrestricted use provided that this legend is included on all tape
8 * media and as a part of the software program in whole or part. Users
9 * may copy or modify Sun RPC without charge, but are not authorized
10 * to license or distribute it to anyone else except as part of a product or
11 * program developed by the user.
12 *
13 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
14 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
15 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
16 *
17 * Sun RPC is provided with no support and without any obligation on the
18 * part of Sun Microsystems, Inc. to assist in its use, correction,
19 * modification or enhancement.
20 *
21 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
22 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
23 * OR ANY PART THEREOF.
24 *
25 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
26 * or profits or other special, indirect and consequential damages, even if
27 * Sun has been advised of the possibility of such damages.
28 *
29 * Sun Microsystems, Inc.
30 * 2550 Garcia Avenue
31 * Mountain View, California 94043
32 */
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif /* HAVE_CONFIG_H defined */
37
38 #if defined(LIBC_SCCS) && !defined(lint)
39 static char *rcsid = "$OpenBSD: bindresvport.c,v 1.13 2000/01/26 03:43:21 deraadt Exp $";
40 #endif /* defined(LIBC_SCCS) && !defined(lint) */
41
42 /*
43 * Copyright (c) 1987 by Sun Microsystems, Inc.
44 *
45 * Portions Copyright(C) 1996, Jason Downs. All rights reserved.
46 */
47
48 #ifdef HAVE_WINSOCK_H
49 #include <winsock.h>
50 #include <process.h> /* getpid() */
51 #define HAVE_INCLUDES
52 #endif /* HAVE_WINSOCK_H defined */
53
54 #ifdef HAVE_WINSOCK2_H
55 #include <ws2tcpip.h>
56 #include <process.h> /* getpid() */
57 #define HAVE_INCLUDES
58 #define HAVE_SOCKADDR_IN6
59 #endif /* HAVE_WINSOCK_H defined */
60
61 #ifdef OLD_UCX_INCLUDES
62 #include <types.h>
63 #include <socket.h>
64 #include <in.h>
65 #define HAVE_INCLUDES
66 #endif /* OLD_UCX_INCLUDES defined */
67
68 #ifndef HAVE_INCLUDES
69 #include <sys/types.h>
70 #include <sys/socket.h>
71 #include <netinet/in.h>
72 #endif /* HAVE_INCLUDES not defined */
73
74 #ifdef HAVE_UNISTD_H
75 #include <unistd.h>
76 #endif /* HAVE_UNISTD_H defined */
77
78 #include <errno.h>
79
80 #if !defined(IPPORT_RESERVED) && !defined(__GLIBC__)
81 /*
82 * could be using broken musl libc!
83 * they refuse to identify themselves:
84 * http://wiki.musl-libc.org/wiki/FAQ#Q:_why_is_there_no_MUSL_macro_.3F
85 */
86 #include <netdb.h>
87 #endif
88
89 #include "h.h" /* needed? */
90 #include "str.h" /* bzero() */
91 #include "bindresvport.h"
92
93 #define STARTPORT 600
94 #define ENDPORT (IPPORT_RESERVED - 1)
95 #define NPORTS (ENDPORT - STARTPORT + 1)
96
97 #if !defined(EADDRINUSE) && defined(WSAEADDRINUSE)
98 #define EADDRINUSE WSAEADDRINUSE
99 #endif
100 #if !defined(EPFNOSUPPORT) && defined(WSAEPFNOSUPPORT)
101 #define EPFNOSUPPORT WSAEPFNOSUPPORT
102 #endif
103
104 /*
105 * Bind a socket to a privileged IP port
106 */
107 int
bindresvport_sa(int sd,struct sockaddr * sa)108 bindresvport_sa(int sd, struct sockaddr *sa) {
109 int error, af;
110 struct sockaddr myaddr;
111 unsigned short *portp;
112 unsigned short port;
113 SOCKLEN_T salen;
114 int i;
115
116 if (sa == NULL) {
117 sa = &myaddr;
118 bzero((char *)sa, sizeof(myaddr));
119
120 if (getsockname(sd, sa, &salen) == -1)
121 return -1; /* errno is correctly set */
122
123 af = sa->sa_family;
124 bzero((char *)sa, salen);
125 } else
126 af = sa->sa_family;
127
128 switch (af) {
129 case AF_INET:
130 salen = sizeof(struct sockaddr_in);
131 portp = &((struct sockaddr_in *)sa)->sin_port;
132 break;
133 /* Tru64 4.0 defines AF_INET6, but has nothing else! */
134 #ifdef HAVE_SOCKADDR_IN6
135 case AF_INET6:
136 salen = sizeof(struct sockaddr_in6);
137 portp = &((struct sockaddr_in6 *)sa)->sin6_port;
138 break;
139 #endif /* HAVE_SOCKADDR_IN6 defined */
140 default:
141 errno = EPFNOSUPPORT;
142 return (-1);
143 }
144 sa->sa_family = af;
145
146 port = ntohs(*portp);
147 if (port == 0)
148 port = (getpid() % NPORTS) + STARTPORT;
149
150 /* Avoid warning */
151 error = -1;
152
153 for(i = 0; i < NPORTS; i++) {
154 *portp = htons(port);
155
156 error = bind(sd, sa, salen);
157
158 /* Terminate on success */
159 if (error == 0)
160 break;
161
162 /* Terminate on errors, except "address already in use" */
163 if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL)))
164 break;
165
166 port++;
167 if (port > ENDPORT)
168 port = STARTPORT;
169 }
170
171 return (error);
172 }
173
174 #ifdef NEED_BINDRESVPORT
175 int
bindresvport(int sd,struct sockaddr_in * sin)176 bindresvport(int sd, struct sockaddr_in *sin) {
177 return bindresvport_sa(sd, (struct sockaddr *)sin);
178 }
179 #endif /* NEED_BINDRESVPORT defined */
180