summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbeck <>2017-04-30 04:18:58 +0000
committerbeck <>2017-04-30 04:18:58 +0000
commitc24d2cd7917d204ee45c3ba761b4dd27fade46c5 (patch)
treebf86809bcc6cf7fd367721f42ad6a553db17f620 /src
parent453806043c6350970962ebbaa93e03df79df0d3d (diff)
downloadopenbsd-c24d2cd7917d204ee45c3ba761b4dd27fade46c5.tar.gz
openbsd-c24d2cd7917d204ee45c3ba761b4dd27fade46c5.tar.bz2
openbsd-c24d2cd7917d204ee45c3ba761b4dd27fade46c5.zip
Microsoft Windows hates BIO_get_accept_socket in portable. Fix it to
not be awful or have any claims on supporting ipv6 when it does so very badly ok jsing@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/bio/b_sock.c150
1 files changed, 35 insertions, 115 deletions
diff --git a/src/lib/libcrypto/bio/b_sock.c b/src/lib/libcrypto/bio/b_sock.c
index 0cc570b66f..cb5549434f 100644
--- a/src/lib/libcrypto/bio/b_sock.c
+++ b/src/lib/libcrypto/bio/b_sock.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: b_sock.c,v 1.63 2017/01/29 17:49:22 beck Exp $ */ 1/* $OpenBSD: b_sock.c,v 1.64 2017/04/30 04:18:58 beck Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -168,151 +168,71 @@ BIO_socket_ioctl(int fd, long type, void *arg)
168int 168int
169BIO_get_accept_socket(char *host, int bind_mode) 169BIO_get_accept_socket(char *host, int bind_mode)
170{ 170{
171 int ret = 0; 171 struct addrinfo hints = {
172 union { 172 .ai_family = AF_INET,
173 struct sockaddr sa; 173 .ai_socktype = SOCK_STREAM,
174 struct sockaddr_in sa_in; 174 .ai_flags = AI_PASSIVE,
175 struct sockaddr_in6 sa_in6; 175 };
176 } server, client; 176 struct addrinfo *res = NULL;
177 int s = -1, cs, addrlen; 177 char *h, *p, *str = NULL;
178 unsigned char ip[4]; 178 int error, ret = 0, s = -1;
179 unsigned short port;
180 char *str = NULL, *e;
181 char *h, *p;
182 unsigned long l;
183 int err_num;
184 179
185 if (host == NULL || (str = strdup(host)) == NULL) 180 if (host == NULL || (str = strdup(host)) == NULL)
186 return (-1); 181 return (-1);
187 182 p = NULL;
188 h = p = NULL;
189 h = str; 183 h = str;
190 for (e = str; *e; e++) { 184 if ((p = strrchr(str, ':')) == NULL) {
191 if (*e == ':') { 185 BIOerror(BIO_R_NO_PORT_SPECIFIED);
192 p = e; 186 goto err;
193 } else if (*e == '/') {
194 *e = '\0';
195 break;
196 }
197 } 187 }
198 /* points at last ':', '::port' is special [see below] */ 188 *p++ = '\0';
199 if (p) 189 if (*p == '\0') {
200 *p++ = '\0'; 190 BIOerror(BIO_R_NO_PORT_SPECIFIED);
201 else
202 p = h, h = NULL;
203
204 do {
205 struct addrinfo *res, hint;
206
207 /*
208 * '::port' enforces IPv6 wildcard listener. Some OSes,
209 * e.g. Solaris, default to IPv6 without any hint. Also
210 * note that commonly IPv6 wildchard socket can service
211 * IPv4 connections just as well...
212 */
213 memset(&hint, 0, sizeof(hint));
214 hint.ai_flags = AI_PASSIVE;
215 if (h) {
216 if (strchr(h, ':')) {
217 if (h[1] == '\0')
218 h = NULL;
219 hint.ai_family = AF_INET6;
220 } else if (h[0] == '*' && h[1] == '\0') {
221 hint.ai_family = AF_INET;
222 h = NULL;
223 }
224 }
225
226 if (getaddrinfo(h, p, &hint, &res))
227 break;
228
229 addrlen = res->ai_addrlen <= sizeof(server) ?
230 res->ai_addrlen : sizeof(server);
231 memcpy(&server, res->ai_addr, addrlen);
232
233 freeaddrinfo(res);
234 goto again;
235 } while (0);
236
237 if (!BIO_get_port(p, &port))
238 goto err; 191 goto err;
192 }
193 if (*h == '\0' || strcmp(h, "*") == 0)
194 h = NULL;
239 195
240 memset((char *)&server, 0, sizeof(server)); 196 if ((error = getaddrinfo(h, p, &hints, &res)) != 0) {
241 server.sa_in.sin_family = AF_INET; 197 ERR_asprintf_error_data("getaddrinfo: '%s:%s': %s'", h, p,
242 server.sa_in.sin_port = htons(port); 198 gai_strerror(error));
243 addrlen = sizeof(server.sa_in); 199 goto err;
244 200 }
245 if (h == NULL || strcmp(h, "*") == 0) 201 if (h == NULL) {
246 server.sa_in.sin_addr.s_addr = INADDR_ANY; 202 struct sockaddr_in *sin = (struct sockaddr_in *)res->ai_addr;
247 else { 203 sin->sin_addr.s_addr = INADDR_ANY;
248 if (!BIO_get_host_ip(h, &(ip[0])))
249 goto err;
250 l = (unsigned long)((unsigned long)ip[0]<<24L)|
251 ((unsigned long)ip[1]<<16L)|
252 ((unsigned long)ip[2]<< 8L)|
253 ((unsigned long)ip[3]);
254 server.sa_in.sin_addr.s_addr = htonl(l);
255 } 204 }
256 205
257again: 206 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
258 s = socket(server.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
259 if (s == -1) { 207 if (s == -1) {
260 SYSerror(errno); 208 SYSerror(errno);
261 ERR_asprintf_error_data("port='%s'", host); 209 ERR_asprintf_error_data("host='%s'", host);
262 BIOerror(BIO_R_UNABLE_TO_CREATE_SOCKET); 210 BIOerror(BIO_R_UNABLE_TO_CREATE_SOCKET);
263 goto err; 211 goto err;
264 } 212 }
265
266 if (bind_mode == BIO_BIND_REUSEADDR) { 213 if (bind_mode == BIO_BIND_REUSEADDR) {
267 int i = 1; 214 int i = 1;
268 215
269 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); 216 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
270 bind_mode = BIO_BIND_NORMAL; 217 bind_mode = BIO_BIND_NORMAL;
271 } 218 }
272 if (bind(s, &server.sa, addrlen) == -1) { 219 if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
273 err_num = errno; 220 SYSerror(errno);
274 if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && 221 ERR_asprintf_error_data("host='%s'", host);
275 (err_num == EADDRINUSE)) {
276 client = server;
277 if (h == NULL || strcmp(h, "*") == 0) {
278 if (client.sa.sa_family == AF_INET6) {
279 memset(&client.sa_in6.sin6_addr, 0,
280 sizeof(client.sa_in6.sin6_addr));
281 client.sa_in6.sin6_addr.s6_addr[15] = 1;
282 } else if (client.sa.sa_family == AF_INET) {
283 client.sa_in.sin_addr.s_addr =
284 htonl(0x7F000001);
285 } else
286 goto err;
287 }
288 cs = socket(client.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
289 if (cs != -1) {
290 int ii;
291 ii = connect(cs, &client.sa, addrlen);
292 close(cs);
293 if (ii == -1) {
294 bind_mode = BIO_BIND_REUSEADDR;
295 close(s);
296 goto again;
297 }
298 /* else error */
299 }
300 /* else error */
301 }
302 SYSerror(err_num);
303 ERR_asprintf_error_data("port='%s'", host);
304 BIOerror(BIO_R_UNABLE_TO_BIND_SOCKET); 222 BIOerror(BIO_R_UNABLE_TO_BIND_SOCKET);
305 goto err; 223 goto err;
306 } 224 }
307 if (listen(s, SOMAXCONN) == -1) { 225 if (listen(s, SOMAXCONN) == -1) {
308 SYSerror(errno); 226 SYSerror(errno);
309 ERR_asprintf_error_data("port='%s'", host); 227 ERR_asprintf_error_data("host='%s'", host);
310 BIOerror(BIO_R_UNABLE_TO_LISTEN_SOCKET); 228 BIOerror(BIO_R_UNABLE_TO_LISTEN_SOCKET);
311 goto err; 229 goto err;
312 } 230 }
313 ret = 1; 231 ret = 1;
232
314err: 233err:
315 free(str); 234 free(str);
235 freeaddrinfo(res);
316 if ((ret == 0) && (s != -1)) { 236 if ((ret == 0) && (s != -1)) {
317 close(s); 237 close(s);
318 s = -1; 238 s = -1;