1 /* ==========================================================================
2  * socket.c - Simple Sockets
3  * --------------------------------------------------------------------------
4  * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015  William Ahern
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to permit
11  * persons to whom the Software is furnished to do so, subject to the
12  * following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20  * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23  * USE OR OTHER DEALINGS IN THE SOFTWARE.
24  * ==========================================================================
25  */
26 #if HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include <stddef.h> /* offsetof size_t */
31 #include <limits.h> /* INT_MAX LONG_MAX */
32 #include <stdlib.h> /* malloc(3) free(3) */
33 #include <string.h> /* strdup(3) strlen(3) memset(3) strncpy(3) memcpy(3) strerror(3) */
34 #include <errno.h>  /* EINVAL EAFNOSUPPORT EAGAIN EWOULDBLOCK EINPROGRESS EALREADY ENAMETOOLONG EOPNOTSUPP ENOTSOCK ENOPROTOOPT */
35 #include <signal.h> /* SIGPIPE SIG_BLOCK SIG_SETMASK sigset_t sigprocmask(2) pthread_sigmask(3) sigtimedwait(2) sigpending(2) sigemptyset(3) sigismember(3) sigaddset(3) */
36 #include <assert.h> /* assert(3) */
37 #include <time.h>   /* time(2) */
38 
39 #include <sys/types.h>   /* socklen_t mode_t in_port_t */
40 #include <sys/stat.h>    /* fchmod(2) fstat(2) S_IFSOCK S_ISSOCK */
41 #include <sys/select.h>  /* FD_ZERO FD_SET fd_set select(2) */
42 #include <sys/socket.h>  /* AF_UNIX AF_INET AF_INET6 SO_TYPE SO_NOSIGPIPE MSG_EOR MSG_NOSIGNAL struct sockaddr_storage socket(2) connect(2) bind(2) listen(2) accept(2) getsockname(2) getpeername(2) */
43 #if defined(AF_UNIX)
44 #include <sys/un.h>      /* struct sockaddr_un struct unpcbid */
45 #endif
46 #include <netinet/in.h>  /* IPPROTO_IPV6 IPPROTO_TCP IPV6_V6ONLY struct sockaddr_in struct sockaddr_in6 */
47 #include <netinet/tcp.h> /* TCP_NODELAY TCP_NOPUSH TCP_CORK */
48 #include <arpa/inet.h>   /* inet_ntop(3) inet_pton(3) ntohs(3) htons(3) */
49 #include <netdb.h>       /* struct addrinfo */
50 #include <unistd.h>      /* _POSIX_REALTIME_SIGNALS _POSIX_THREADS close(2) unlink(2) getpeereid(2) */
51 #include <fcntl.h>       /* F_SETFD F_GETFD F_GETFL F_SETFL FD_CLOEXEC O_NONBLOCK O_NOSIGPIPE F_SETNOSIGPIPE F_GETNOSIGPIPE */
52 #include <poll.h>        /* POLLIN POLLOUT */
53 #if defined __sun
54 #include <ucred.h>       /* ucred_t getpeerucred(2) ucred_free(3) */
55 #endif
56 
57 #include <openssl/crypto.h>
58 #include <openssl/ssl.h>
59 #include <openssl/err.h>
60 #include <openssl/bio.h>
61 #include "dns.h"
62 #include "socket.h"
63 
64 
65 /*
66  * V E R S I O N  R O U T I N E S
67  *
68  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
69 
socket_vendor(void)70 const char *socket_vendor(void) {
71 	return SOCKET_VENDOR;
72 } /* socket_vendor() */
73 
74 
socket_v_rel(void)75 int socket_v_rel(void) {
76 	return SOCKET_V_REL;
77 } /* socket_v_rel() */
78 
79 
socket_v_abi(void)80 int socket_v_abi(void) {
81 	return SOCKET_V_ABI;
82 } /* socket_v_abi() */
83 
84 
socket_v_api(void)85 int socket_v_api(void) {
86 	return SOCKET_V_API;
87 } /* socket_v_api() */
88 
89 
90 /*
91  * F E A T U R E  R O U T I N E S
92  *
93  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
94 
95 #if !defined SO_THREAD_SAFE
96 #if (defined _REENTRANT || defined _THREAD_SAFE) && _POSIX_THREADS > 0
97 #define SO_THREAD_SAFE 1
98 #else
99 #define SO_THREAD_SAFE 0
100 #endif
101 #endif
102 
103 #ifdef LIBRESSL_VERSION_NUMBER
104 #define OPENSSL_PREREQ(M, m, p) (0)
105 #define LIBRESSL_PREREQ(M, m, p) \
106 	(LIBRESSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)))
107 #else
108 #define OPENSSL_PREREQ(M, m, p) \
109 	(OPENSSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)))
110 #define LIBRESSL_PREREQ(M, m, p) (0)
111 #endif
112 
113 #ifndef HAVE_BIO_CTRL_SET_CONNECTED_2ARY
114 #define HAVE_BIO_CTRL_SET_CONNECTED_2ARY OPENSSL_PREREQ(1,1,0)
115 #endif
116 
117 #ifndef HAVE_BIO_SET_INIT
118 #define HAVE_BIO_SET_INIT (OPENSSL_PREREQ(1,1,0) || LIBRESSL_PREREQ(2,7,0))
119 #endif
120 
121 #ifndef HAVE_BIO_SET_SHUTDOWN
122 #define HAVE_BIO_SET_SHUTDOWN (OPENSSL_PREREQ(1,1,0) || LIBRESSL_PREREQ(2,7,0))
123 #endif
124 
125 #ifndef HAVE_BIO_SET_DATA
126 #define HAVE_BIO_SET_DATA (OPENSSL_PREREQ(1,1,0) || LIBRESSL_PREREQ(2,7,0))
127 #endif
128 
129 #ifndef HAVE_BIO_GET_DATA
130 #define HAVE_BIO_GET_DATA (OPENSSL_PREREQ(1,1,0) || LIBRESSL_PREREQ(2,7,0))
131 #endif
132 
133 #ifndef HAVE_BIO_UP_REF
134 #define HAVE_BIO_UP_REF (OPENSSL_PREREQ(1,1,0) || LIBRESSL_PREREQ(2,7,0))
135 #endif
136 
137 #ifndef HAVE_SSL_IS_SERVER
138 #define HAVE_SSL_IS_SERVER OPENSSL_PREREQ(1,1,0)
139 #endif
140 
141 #ifndef HAVE_SSL_UP_REF
142 #define HAVE_SSL_UP_REF (OPENSSL_PREREQ(1,1,0) || LIBRESSL_PREREQ(2,7,0))
143 #endif
144 
145 
146 /*
147  * C O M P A T  R O U T I N E S
148  *
149  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
150 
151 #if !HAVE_BIO_CTRL_SET_CONNECTED_2ARY
152 #undef BIO_ctrl_set_connected
153 #define BIO_ctrl_set_connected(b, peer) (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, 0, (char *)peer)
154 #endif
155 
156 #if !HAVE_BIO_SET_INIT
157 #define BIO_set_init(bio, val) ((void)((bio)->init = (val)))
158 #endif
159 
160 #if !HAVE_BIO_SET_SHUTDOWN
161 #define BIO_set_shutdown(bio, val) ((void)((bio)->shutdown = (val)))
162 #endif
163 
164 #if !HAVE_BIO_SET_DATA
165 #define BIO_set_data(bio, val) ((void)((bio)->ptr = (val)))
166 #endif
167 
168 #if !HAVE_BIO_GET_DATA
169 #define BIO_get_data(bio) ((bio)->ptr)
170 #endif
171 
172 #if !HAVE_BIO_UP_REF
173 #define BIO_up_ref(bio) CRYPTO_add(&(bio)->references, 1, CRYPTO_LOCK_BIO)
174 #endif
175 
176 #if !HAVE_SSL_IS_SERVER
177 #undef SSL_is_server
178 #define SSL_is_server(ssl) compat_SSL_is_server(ssl)
179 
compat_SSL_is_server(SSL * ssl)180 static _Bool compat_SSL_is_server(SSL *ssl) {
181 #if LIBRESSL_PREREQ(2,5,1)
182 	/*
183 	 * NOTE: LibreSSL 2.5.1 made the SSL structure partially opaque
184 	 * without providing the SSL_is_server accessor.
185 	 * See libressl mailing list thread '[PATCH] add SSL_is_server'
186 	 * https://marc.info/?t=149253819800003
187 	 */
188 	return ssl->server != NULL;
189 #else
190 	const SSL_METHOD *method = SSL_get_ssl_method(ssl);
191 
192 	/*
193 	 * NOTE: SSLv23_server_method()->ssl_connect should be a reference to
194 	 * OpenSSL's internal ssl_undefined_function().
195 	 *
196 	 * Server methods such as TLSv1_2_server_method(), etc. should have
197 	 * their .ssl_connect method set to this value.
198 	 *
199 	 * WARNING: SSL_is_server in OpenSSL 1.1 defaults to server mode
200 	 * when both connect and accept methods are present (e.g. as
201 	 * returned by SSLv23_method()), whereas we always defaulted to
202 	 * client mode. We keep our old logic to avoid breaking any existing
203 	 * code that relies on our behavior. Such code will break when
204 	 * moving to OpenSSL 1.1, but it would be even more surprising if
205 	 * their code broke when the only change was a minor version of
206 	 * something using this library.
207 	 */
208 	if (!method->ssl_connect || method->ssl_connect == SSLv23_server_method()->ssl_connect)
209 		return 1;
210 
211 	return 0;
212 #endif
213 } /* compat_SSL_is_server() */
214 #endif
215 
216 #if !HAVE_SSL_UP_REF
217 #define SSL_up_ref(...) compat_SSL_up_ref(__VA_ARGS__)
218 
compat_SSL_up_ref(SSL * ssl)219 static int compat_SSL_up_ref(SSL *ssl) {
220 	/* our caller should already have had a proper reference */
221 	if (CRYPTO_add(&ssl->references, 1, CRYPTO_LOCK_SSL) < 2)
222 		return 0; /* fail */
223 
224 	return 1;
225 } /* compat_SSL_up_ref() */
226 #endif
227 
228 
229 /*
230  * D E B U G  R O U T I N E S
231  *
232  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
233 
234 int socket_debug;
235 
236 
237 enum so_trace {
238 	SO_T_CONNECT,
239 	SO_T_STARTTLS,
240 	SO_T_READ,
241 	SO_T_WRITE,
242 }; /* enum so_trace */
243 
244 
245 static void so_trace(enum so_trace, int, const struct addrinfo *, ...);
246 
247 
248 #if !defined(SOCKET_DEBUG)
249 #define SOCKET_DEBUG 0
250 #endif
251 
252 #if SOCKET_DEBUG
253 
254 #include <stdio.h>
255 #include <stdarg.h>
256 
257 #include <ctype.h>
258 
259 
260 #undef SOCKET_DEBUG
261 #define SOCKET_DEBUG socket_debug
262 
263 
264 #if !defined(SAY)
265 #define SAY_(fmt, ...) fprintf(stderr, fmt "%s", __FILE__, __LINE__, __func__, __VA_ARGS__);
266 #define SAY(...) SAY_("@@ %s:%d:%s: " __VA_ARGS__, "\n");
267 #endif
268 
269 #if !defined(HAI)
270 #define HAI SAY_("@@ %s:%d:%s", "\n");
271 #endif
272 
273 
so_dump(const unsigned char * src,size_t len,FILE * fp)274 static void so_dump(const unsigned char *src, size_t len, FILE *fp) {
275 	static const unsigned char hex[] = "0123456789abcdef";
276 	static const unsigned char tmp[] = "                                                            |                |\n";
277 	unsigned char ln[sizeof tmp];
278 	const unsigned char *p, *pe;
279 	unsigned char *h, *g;
280 	unsigned i, n;
281 
282 	p  = src;
283 	pe = p + len;
284 
285 	while (p < pe) {
286 		memcpy(ln, tmp, sizeof ln);
287 
288 		h = &ln[2];
289 		g = &ln[61];
290 
291 		n = p - src;
292 		h[0] = hex[0x0f & (n >> 20)];
293 		h[1] = hex[0x0f & (n >> 16)];
294 		h[2] = hex[0x0f & (n >> 12)];
295 		h[3] = hex[0x0f & (n >> 8)];
296 		h[4] = hex[0x0f & (n >> 4)];
297 		h[5] = hex[0x0f & (n >> 0)];
298 		h += 8;
299 
300 		for (n = 0; n < 2; n++) {
301 			for (i = 0; i < 8 && pe - p > 0; i++, p++) {
302 				h[0] = hex[0x0f & (*p >> 4)];
303 				h[1] = hex[0x0f & (*p >> 0)];
304 				h += 3;
305 
306 				*g++ = (isgraph(*p))? *p : '.';
307 			}
308 
309 			h++;
310 		}
311 
312 		fputs((char *)ln, fp);
313 	}
314 } /* so_dump() */
315 
316 
so_trace(enum so_trace event,int fd,const struct addrinfo * host,...)317 static void so_trace(enum so_trace event, int fd, const struct addrinfo *host, ...) {
318 	struct sockaddr_storage saddr = {0};
319 	socklen_t saddr_len = sizeof saddr;
320 	char addr[64], who[256];
321 	in_port_t port;
322 	va_list ap;
323 	SSL *ctx;
324 	const void *data;
325 	size_t count;
326 	const char *fmt;
327 	int error;
328 
329 	if (!socket_debug)
330 		return;
331 
332 	if (host) {
333 		sa_ntop(addr, sizeof addr, host->ai_addr, NULL, &error);
334 		port = *sa_port(host->ai_addr, SA_PORT_NONE, NULL);
335 
336 		if (host->ai_canonname)
337 			snprintf(who, sizeof who, "%.96s/[%s]:%hu", host->ai_canonname, addr, ntohs(port));
338 		else
339 			snprintf(who, sizeof who, "[%s]:%hu", addr, ntohs(port));
340 	} else if (fd != -1 && 0 == getpeername(fd, (struct sockaddr *)&saddr, &saddr_len)) {
341 		sa_ntop(addr, saddr_len, &saddr, NULL, &error);
342 		port = *sa_port(&saddr, SA_PORT_NONE, NULL);
343 
344 		snprintf(who, sizeof who, "[%s]:%hu", addr, ntohs(port));
345 	} else
346 		dns_strlcpy(who, "[unknown]", sizeof who);
347 
348 	va_start(ap, host);
349 
350 	flockfile(stderr);
351 
352 	switch (event) {
353 	case SO_T_CONNECT:
354 		fmt = va_arg(ap, char *);
355 
356 		fprintf(stderr, "connect(%s): ", who);
357 		vfprintf(stderr, fmt, ap);
358 		fputc('\n', stderr);
359 
360 		break;
361 	case SO_T_STARTTLS:
362 		ctx = va_arg(ap, SSL *);
363 		fmt = va_arg(ap, char *);
364 
365 		(void)ctx; /* unused for now */
366 		fprintf(stderr, "starttls(%s): ", who);
367 		vfprintf(stderr, fmt, ap);
368 		fputc('\n', stderr);
369 
370 		break;
371 	case SO_T_READ:
372 		data  = va_arg(ap, void *);
373 		count = va_arg(ap, size_t);
374 		fmt   = va_arg(ap, char *);
375 
376 		fprintf(stderr, "read(%s): ", who);
377 		vfprintf(stderr, fmt, ap);
378 		fputc('\n', stderr);
379 
380 		so_dump(data, count, stderr);
381 
382 		break;
383 	case SO_T_WRITE:
384 		data  = va_arg(ap, void *);
385 		count = va_arg(ap, size_t);
386 		fmt   = va_arg(ap, char *);
387 
388 		fprintf(stderr, "write(%s): ", who);
389 		vfprintf(stderr, fmt, ap);
390 		fputc('\n', stderr);
391 
392 		so_dump(data, count, stderr);
393 
394 		break;
395 	} /* switch(event) */
396 
397 	funlockfile(stderr);
398 
399 	va_end(ap);
400 } /* so_trace() */
401 
402 
so_initdebug(void)403 static void so_initdebug(void) {
404 	const char *debug;
405 
406 	if ((debug = getenv("SOCKET_DEBUG")) || (debug = getenv("SO_DEBUG"))) {
407 		switch (*debug) {
408 		case 'Y': case 'y':
409 		case 'T': case 't':
410 		case '1':
411 			socket_debug = 1;
412 
413 			break;
414 		case 'N': case 'n':
415 		case 'F': case 'f':
416 		case '0':
417 			socket_debug = 0;
418 
419 			break;
420 		} /* switch() */
421 	}
422 } /* so_initdebug() */
423 
424 
425 #else
426 
427 #define so_trace(...) (void)0
428 
429 #define so_initdebug() (void)0
430 
431 #endif /* SOCKET_DEBUG */
432 
433 
434 /*
435  * M A C R O  R O U T I N E S
436  *
437  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
438 
439 #ifndef countof
440 #define countof(a) (sizeof (a) / sizeof *(a))
441 #endif
442 
443 #ifndef endof
444 #define endof(a) (&(a)[countof(a)])
445 #endif
446 
447 
448 /*
449  * E R R O R  R O U T I N E S
450  *
451  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
452 
453 #if _WIN32
454 
455 #define SO_EINTR	WSAEINTR
456 #define SO_EINPROGRESS	WSAEINPROGRESS
457 #define SO_EISCONN	WSAEISCONN
458 #define SO_EWOULDBLOCK	WSAEWOULDBLOCK
459 #define SO_EALREADY	WSAEALREADY
460 #define SO_EAGAIN	WSAEWOULDBLOCK
461 #define SO_ENOTCONN	WSAENOTCONN
462 #define SO_ECONNABORTED WSAECONNABORTED
463 
464 #define so_syerr()	((int)GetLastError())
465 #define so_soerr()	((int)WSAGetLastError())
466 
467 #else
468 
469 #define SO_EINTR	EINTR
470 #define SO_EINPROGRESS	EINPROGRESS
471 #define SO_EISCONN	EISCONN
472 #define SO_EWOULDBLOCK	EWOULDBLOCK
473 #define SO_EALREADY	EALREADY
474 #define SO_EAGAIN	EAGAIN
475 #define SO_ENOTCONN	ENOTCONN
476 #define SO_ECONNABORTED ECONNABORTED
477 
478 #define so_syerr()	errno
479 #define so_soerr()	errno
480 
481 #endif
482 
483 
so_strerror(int error)484 const char *so_strerror(int error) {
485 	static const char *errlist[] = {
486 		[SO_EOPENSSL - SO_ERRNO0] = "TLS/SSL error",
487 		[SO_EX509INT - SO_ERRNO0] = "X.509 certificate lookup interrupt",
488 		[SO_ENOTVRFD - SO_ERRNO0] = "Absent or unverified peer certificate",
489 		[SO_ECLOSURE - SO_ERRNO0] = "Peers elected to shutdown secure transport",
490 		[SO_ENOHOST - SO_ERRNO0]  = "No host address available to complete operation",
491 	};
492 
493 	if (error >= 0)
494 		return strerror(error);
495 
496 	if (error == SO_EOPENSSL) {
497 #if SO_THREAD_SAFE && (!defined __NetBSD__ || __NetBSD_Version__ > 600000000)
498 		static __thread char sslstr[256];
499 #else
500 		static char sslstr[256];
501 #endif
502 		unsigned long code = ERR_peek_last_error();
503 
504 		if (!code)
505 			return "Unknown TLS/SSL error";
506 
507 		ERR_error_string_n(code, sslstr, sizeof sslstr);
508 
509 		return sslstr;
510 	} else {
511 		int index = error - SO_ERRNO0;
512 
513 		if (index >= 0 && index < (int)countof(errlist) && errlist[index])
514 			return errlist[index];
515 		else
516 			return "Unknown socket error";
517 	}
518 } /* so_strerror() */
519 
520 
521 /*
522  * Translate SSL_get_error(3) errors into something sensible.
523  */
ssl_error(SSL * ctx,int rval,short * events)524 static int ssl_error(SSL *ctx, int rval, short *events) {
525 	unsigned long code;
526 
527 	switch (SSL_get_error(ctx, rval)) {
528 	case SSL_ERROR_ZERO_RETURN:
529 		return SO_ECLOSURE;
530 	case SSL_ERROR_WANT_READ:
531 		*events |= POLLIN;
532 
533 		return SO_EAGAIN;
534 	case SSL_ERROR_WANT_WRITE:
535 		*events |= POLLOUT;
536 
537 		return SO_EAGAIN;
538 	case SSL_ERROR_WANT_CONNECT:
539 		*events |= POLLOUT;
540 
541 		return SO_EAGAIN;
542 	case SSL_ERROR_WANT_ACCEPT:
543 		*events |= POLLIN;
544 
545 		return SO_EAGAIN;
546 	case SSL_ERROR_WANT_X509_LOOKUP:
547 		return SO_EX509INT;
548 	case SSL_ERROR_SYSCALL:
549 		if ((code = ERR_peek_last_error()))
550 			return SO_EOPENSSL;
551 		else if (rval == 0)
552 			return ECONNRESET;
553 		else if (rval == -1 && so_soerr() && so_soerr() != SO_EAGAIN)
554 			return so_soerr();
555 		else
556 			return SO_EOPENSSL;
557 	case SSL_ERROR_SSL:
558 		/* FALL THROUGH */
559 	default:
560 		return SO_EOPENSSL;
561 	} /* switch(SSL_get_error()) */
562 } /* ssl_error() */
563 
564 
565 /*
566  * A D D R E S S  R O U T I N E S
567  *
568  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
569 
sa_ntop(char * dst,size_t lim,const void * src,const char * def,int * _error)570 char *sa_ntop(char *dst, size_t lim, const void *src, const char *def, int *_error) {
571 	union sockaddr_any *any = (void *)src;
572 	const char *unspec = "0.0.0.0";
573 	char text[SA_ADDRSTRLEN];
574 	int error;
575 
576 	switch (*sa_family(&any->sa)) {
577 	case AF_INET:
578 		unspec = "0.0.0.0";
579 
580 		if (!inet_ntop(AF_INET, &any->sin.sin_addr, text, sizeof text))
581 			goto syerr;
582 
583 		break;
584 	case AF_INET6:
585 		unspec = "::";
586 
587 		if (!inet_ntop(AF_INET6, &any->sin6.sin6_addr, text, sizeof text))
588 			goto syerr;
589 
590 		break;
591 #if SA_UNIX
592 	case AF_UNIX:
593 		unspec = "/nonexistent";
594 
595 		memset(text, 0, sizeof text);
596 		memcpy(text, any->sun.sun_path, SO_MIN(sizeof text - 1, sizeof any->sun.sun_path));
597 
598 		break;
599 #endif
600 	default:
601 		error = EAFNOSUPPORT;
602 
603 		goto error;
604 	} /* switch() */
605 
606 	if (dns_strlcpy(dst, text, lim) >= lim) {
607 		error = ENOSPC;
608 
609 		goto error;
610 	}
611 
612 	return dst;
613 syerr:
614 	error = so_syerr();
615 error:
616 	if (_error)
617 		*_error = error;
618 
619 	/*
620 	 * NOTE: Always write something in case caller ignores errors, such
621 	 * as when caller is using the sa_ntoa() macro.
622 	 */
623 	dns_strlcpy(dst, (def)? def : unspec, lim);
624 
625 	return (char *)def;
626 } /* sa_ntop() */
627 
628 
sa_pton(void * dst,size_t lim,const char * src,const void * def,int * _error)629 void *sa_pton(void *dst, size_t lim, const char *src, const void *def, int *_error) {
630 	union sockaddr_any family[] = { { { .sa_family = AF_INET } }, { { .sa_family = AF_INET6 } } }, *fp;
631 	int error;
632 
633 	memset(dst, 0, lim);
634 
635 	for (fp = family; fp < endof(family); fp++) {
636 		switch (inet_pton(*sa_family(fp), src, sa_addr(fp, NULL, NULL))) {
637 		case -1:
638 			goto syerr;
639 		case 1:
640 			if (lim < sa_len(fp)) {
641 				error = ENOSPC;
642 
643 				goto error;
644 			}
645 
646 			memcpy(dst, fp, sa_len(fp));
647 
648 			return dst;
649 		}
650 	}
651 
652 	error = EAFNOSUPPORT;
653 
654 	goto error;
655 syerr:
656 	error = so_syerr();
657 error:
658 	if (_error)
659 		*_error = error;
660 
661 	return (void *)def;
662 } /* sa_pton() */
663 
664 
665 /*
666  * U T I L I T I Y  R O U T I N E S
667  *
668  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
669 
sa_egress(void * lcl,size_t lim,sockaddr_arg_t rmt,int * _error)670 void *sa_egress(void *lcl, size_t lim, sockaddr_arg_t rmt, int *_error) {
671 	static struct { sa_family_t pf; int fd;} udp4 = { PF_INET, -1 }, udp6 = { PF_INET6, -1 }, *udp;
672 	struct sockaddr_storage ss;
673 	int error;
674 
675 	switch (*sa_family(rmt)) {
676 	case AF_INET:
677 		udp = &udp4;
678 
679 		break;
680 	case AF_INET6:
681 		udp = &udp6;
682 
683 		break;
684 	default:
685 		error = EINVAL;
686 
687 		goto error;
688 	}
689 
690 	if (udp->fd == -1) {
691 #if defined SOCK_CLOEXEC
692 		if (-1 == (udp->fd = socket(udp->pf, SOCK_DGRAM|SOCK_CLOEXEC, 0)))
693 			goto syerr;
694 #else
695 		if (-1 == (udp->fd = socket(udp->pf, SOCK_DGRAM, 0)))
696 			goto syerr;
697 #endif
698 
699 		if ((error = so_cloexec(udp->fd, 1))) {
700 			so_closesocket(&udp->fd, NULL);
701 
702 			goto error;
703 		}
704 	}
705 
706 	assert(sizeof ss >= sa_len(rmt));
707 	memcpy(&ss, sockaddr_ref(rmt).sa, sa_len(rmt));
708 
709 	if (!*sa_port(&ss, SA_PORT_NONE, NULL))
710 		*sa_port(&ss, SA_PORT_NONE, NULL) = htons(6970);
711 
712 	if (0 != connect(udp->fd, (struct sockaddr *)&ss, sa_len(&ss)))
713 		goto syerr;
714 
715 	memset(&ss, 0, sizeof ss);
716 
717 	if (0 != getsockname(udp->fd, (struct sockaddr *)&ss, &(socklen_t){ sizeof ss }))
718 		goto syerr;
719 
720 	if (lim < sa_len(&ss)) {
721 		error = ENOSPC;
722 
723 		goto error;
724 	}
725 
726 	memcpy(lcl, &ss, sa_len(&ss));
727 
728 	return lcl;
729 syerr:
730 	error = so_syerr();
731 error:
732 	if (_error)
733 		*_error = error;
734 
735 	return memset(lcl, 0, lim);
736 } /* sa_egress() */
737 
738 
so_ffamily(int fd,int * family)739 static so_error_t so_ffamily(int fd, int *family) {
740 	struct sockaddr_storage ss;
741 
742 	if (0 != getsockname(fd, (struct sockaddr *)&ss, &(socklen_t){ sizeof ss }))
743 		return errno;
744 
745 	*family = ss.ss_family;
746 
747 	return 0;
748 } /* so_ffamily() */
749 
750 
so_ftype(int fd,mode_t * mode,int * domain,int * type,int * protocol)751 static so_error_t so_ftype(int fd, mode_t *mode, int *domain, int *type, int *protocol) {
752 	struct stat st;
753 	int error;
754 
755 	if (0 != fstat(fd, &st))
756 		return errno;
757 
758 	*mode = S_IFMT & st.st_mode;
759 
760 	if (!S_ISSOCK(*mode))
761 		return 0;
762 
763 #if defined SO_DOMAIN
764 	if (0 != getsockopt(fd, SOL_SOCKET, SO_DOMAIN, domain, &(socklen_t){ sizeof *domain })) {
765 		if (errno != ENOPROTOOPT)
766 			return errno;
767 
768 		if ((error = so_ffamily(fd, domain)))
769 			return error;
770 	}
771 #else
772 	if ((error = so_ffamily(fd, domain)))
773 		return error;
774 #endif
775 
776 	if (0 != getsockopt(fd, SOL_SOCKET, SO_TYPE, type, &(socklen_t){ sizeof *type }))
777 		return errno;
778 
779 #if defined SO_PROTOCOL
780 	if (0 != getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, protocol, &(socklen_t){ sizeof *protocol })) {
781 		if (errno != ENOPROTOOPT)
782 			return errno;
783 	}
784 #else
785 	(void)protocol;
786 #endif
787 
788 	return 0;
789 } /* so_ftype() */
790 
791 
792 static int so_opts2flags(const struct so_options *, int *);
793 static int so_type2mask(mode_t, int, int, int);
794 
so_socket(int domain,int type,const struct so_options * opts,int * _error)795 int so_socket(int domain, int type, const struct so_options *opts, int *_error) {
796 	int error, fd, flags, mask, need;
797 
798 #if defined SOCK_CLOEXEC
799 	if (-1 == (fd = socket(domain, type|SOCK_CLOEXEC, 0)))
800 		goto syerr;
801 #else
802 	if (-1 == (fd = socket(domain, type, 0)))
803 		goto syerr;
804 #endif
805 
806 	flags = so_opts2flags(opts, &mask);
807 	mask &= so_type2mask(S_IFSOCK, domain, type, 0);
808 	need = ~(SO_F_NODELAY|SO_F_NOPUSH|SO_F_NOSIGPIPE|SO_F_OOBINLINE);
809 
810 	if ((error = so_setfl(fd, flags, mask, need)))
811 		goto error;
812 
813 	return fd;
814 syerr:
815 	error = so_syerr();
816 
817 	goto error;
818 error:
819 	*_error = error;
820 
821 	so_closesocket(&fd, opts);
822 
823 	return -1;
824 } /* so_socket() */
825 
826 
827 #define so_bind(...) SO_EXTENSION so_bind(__VA_ARGS__)
828 
829 int (so_bind)(int fd, sockaddr_arg_t arg, const struct so_options *opts) {
830 #if SA_UNIX
831 	if (*sa_family(arg) == AF_UNIX) {
832 		char *path = strncpy((char [sizeof sockaddr_ref(arg).sun->sun_path + 1]){ 0 }, sockaddr_ref(arg).sun->sun_path, sizeof sockaddr_ref(arg).sun->sun_path);
833 		_Bool nochmod = 0;
834 		int error;
835 
836 		if (opts->sun_unlink && *path)
837 			(void)unlink(path);
838 
839 		if (opts->sun_mode) {
840 			if (0 == fchmod(fd, (opts->sun_mode & 0777)))
841 				nochmod = 1;
842 			else if (errno != EINVAL) /* BSDs return EINVAL */
843 				return errno;
844 		}
845 
846 		if (opts->sun_mask) {
847 			mode_t omask = umask(opts->sun_mask & 0777);
848 			error = (0 == bind(fd, sockaddr_ref(arg).sa, sa_len(arg)))? 0 : errno;
849 			umask(omask);
850 		} else {
851 			error = (0 == bind(fd, sockaddr_ref(arg).sa, sa_len(arg)))? 0 : errno;
852 		}
853 
854 		if (error)
855 			return error;
856 
857 		if (opts->sun_mode && !nochmod && *path) {
858 			if (0 != chmod(path, (opts->sun_mode & 0777)))
859 				return errno;
860 		}
861 
862 		return 0;
863 	}
864 #endif
865 
866 	if (0 != bind(fd, sockaddr_ref(arg).sa, sa_len(arg)))
867 		return so_soerr();
868 
869 	return 0;
870 } /* so_bind() */
871 
872 
so_closesocket(int * fd,const struct so_options * opts)873 void so_closesocket(int *fd, const struct so_options *opts) {
874 	if (opts && opts->fd_close.cb)
875 		opts->fd_close.cb(fd, opts->fd_close.arg);
876 
877 	if (*fd != -1) {
878 #if _WIN32
879 		closesocket(*fd);
880 #else
881 		close(*fd);
882 #endif
883 
884 		*fd = -1;
885 	}
886 } /* so_closesocket() */
887 
888 
so_cloexec(int fd,_Bool cloexec)889 int so_cloexec(int fd, _Bool cloexec) {
890 #if _WIN32
891 	return 0;
892 #else
893 	if (-1 == fcntl(fd, F_SETFD, cloexec))
894 		return so_syerr();
895 
896 	return 0;
897 #endif
898 } /* so_cloexec() */
899 
900 
so_nonblock(int fd,_Bool nonblock)901 int so_nonblock(int fd, _Bool nonblock) {
902 	int flags, mask = (nonblock)? ~0 : (~O_NONBLOCK);
903 
904 	if (-1 == (flags = fcntl(fd, F_GETFL))
905 	||  -1 == fcntl(fd, F_SETFL, mask & (flags | O_NONBLOCK)))
906 		return so_syerr();
907 
908 	return 0;
909 } /* so_nonblock() */
910 
911 
so_getboolopt(int fd,int lvl,int opt)912 static _Bool so_getboolopt(int fd, int lvl, int opt) {
913 	int val;
914 
915 	if (0 != getsockopt(fd, lvl, opt, &val, &(socklen_t){ sizeof val }))
916 		return 0;
917 
918 	return !!val;
919 } /* so_getboolopt() */
920 
921 
so_setboolopt(int fd,int lvl,int opt,_Bool enable)922 static int so_setboolopt(int fd, int lvl, int opt, _Bool enable) {
923 	if (0 != setsockopt(fd, lvl, opt, &(int){ enable }, sizeof (int))) {
924 		switch (errno) {
925 		case ENOTSOCK:
926 			/* FALL THROUGH */
927 		case ENOPROTOOPT:
928 			return EOPNOTSUPP;
929 		default:
930 			return errno;
931 		}
932 	}
933 
934 	return 0;
935 } /* so_setboolopt() */
936 
937 
so_reuseaddr(int fd,_Bool reuseaddr)938 int so_reuseaddr(int fd, _Bool reuseaddr) {
939 	return so_setboolopt(fd, SOL_SOCKET, SO_REUSEADDR, reuseaddr);
940 } /* so_reuseaddr() */
941 
942 
so_reuseport(int fd,_Bool reuseport)943 int so_reuseport(int fd, _Bool reuseport) {
944 	int error;
945 #if defined SO_REUSEPORT
946 	error = so_setboolopt(fd, SOL_SOCKET, SO_REUSEPORT, reuseport);
947 #else
948 	(void)fd;
949 	error = EOPNOTSUPP;
950 #endif
951 	if (error == EOPNOTSUPP && !reuseport)
952 		error = 0; /* already disabled */
953 
954 	return error;
955 } /* so_reuseport() */
956 
957 
so_broadcast(int fd,_Bool broadcast)958 int so_broadcast(int fd, _Bool broadcast) {
959 	return so_setboolopt(fd, SOL_SOCKET, SO_BROADCAST, broadcast);
960 } /* so_broadcast() */
961 
962 
so_nodelay(int fd,_Bool nodelay)963 int so_nodelay(int fd, _Bool nodelay) {
964 	return so_setboolopt(fd, IPPROTO_TCP, TCP_NODELAY, nodelay);
965 } /* so_nodelay() */
966 
967 
968 #ifndef TCP_NOPUSH
969 #ifdef TCP_CORK
970 #define TCP_NOPUSH TCP_CORK
971 #endif
972 #endif
973 
so_nopush(int fd,_Bool nopush)974 int so_nopush(int fd, _Bool nopush) {
975 #ifdef TCP_NOPUSH
976 	return so_setboolopt(fd, IPPROTO_TCP, TCP_NOPUSH, nopush);
977 #else
978 	return EOPNOTSUPP;
979 #endif
980 } /* so_nopush() */
981 
982 
so_nosigpipe(int fd,_Bool nosigpipe)983 int so_nosigpipe(int fd, _Bool nosigpipe) {
984 #if defined O_NOSIGPIPE
985 	int flags, mask = (nosigpipe)? ~0 : (~O_NOSIGPIPE);
986 
987 	if (-1 == (flags = fcntl(fd, F_GETFL))
988 	||  -1 == fcntl(fd, F_SETFL, mask & (flags | O_NOSIGPIPE)))
989 		return errno;
990 
991 	return 0;
992 #elif defined F_SETNOSIGPIPE
993 	if (0 != fcntl(fd, F_SETNOSIGPIPE, nosigpipe))
994 		return errno;
995 
996 	return 0;
997 #elif defined SO_NOSIGPIPE
998 	return so_setboolopt(fd, SOL_SOCKET, SO_NOSIGPIPE, nosigpipe);
999 #else
1000 	(void)fd;
1001 	(void)nosigpipe;
1002 
1003 	return EOPNOTSUPP;
1004 #endif
1005 } /* so_nosigpipe() */
1006 
1007 
so_v6only(int fd,_Bool v6only)1008 int so_v6only(int fd, _Bool v6only) {
1009 	/*
1010 	 * NOTE: OS X will return EINVAL if socket already connected.
1011 	 * Haven't checked other systems. Should we should suppress this
1012 	 * error?
1013 	 */
1014 	return so_setboolopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, v6only);
1015 } /* so_v6only() */
1016 
1017 
so_oobinline(int fd,_Bool oobinline)1018 int so_oobinline(int fd, _Bool oobinline) {
1019 	return so_setboolopt(fd, SOL_SOCKET, SO_OOBINLINE, oobinline);
1020 } /* so_oobinline() */
1021 
1022 
1023 #define NO_OFFSET ((size_t)-1)
1024 #define optoffset(m) offsetof(struct so_options, m)
1025 
1026 static const struct flops {
1027 	int flag;
1028 	int (*set)(int, _Bool);
1029 	size_t offset;
1030 } fltable[] = {
1031 	{ SO_F_CLOEXEC,   &so_cloexec,   optoffset(fd_cloexec),    },
1032 	{ SO_F_NONBLOCK,  &so_nonblock,  optoffset(fd_nonblock),   },
1033 	{ SO_F_REUSEADDR, &so_reuseaddr, optoffset(sin_reuseaddr), },
1034 	{ SO_F_REUSEPORT, &so_reuseport, optoffset(sin_reuseport), },
1035 	{ SO_F_BROADCAST, &so_broadcast, optoffset(sin_broadcast), },
1036 	{ SO_F_NODELAY,   &so_nodelay,   optoffset(sin_nodelay),   },
1037 	{ SO_F_NOPUSH,    &so_nopush,    optoffset(sin_nopush),    },
1038 	{ SO_F_NOSIGPIPE, &so_nosigpipe, optoffset(fd_nosigpipe),  },
1039 	{ SO_F_V6ONLY,    &so_v6only,    NO_OFFSET,                },
1040 	{ SO_F_OOBINLINE, &so_oobinline, optoffset(sin_oobinline), },
1041 };
1042 
1043 
so_opts2flags(const struct so_options * opts,int * mask)1044 static int so_opts2flags(const struct so_options *opts, int *mask) {
1045 	const struct flops *f;
1046 	int flags = 0;
1047 
1048 	*mask = 0;
1049 
1050 	for (f = fltable; f < endof(fltable); f++) {
1051 		if (f->offset == NO_OFFSET)
1052 			continue;
1053 
1054 		flags |= (*(_Bool *)((char *)opts + f->offset))? f->flag : 0;
1055 		*mask |= f->flag;
1056 	}
1057 
1058 	switch (opts->sin_v6only) {
1059 	case SO_V6ONLY_DEFAULT:
1060 		break;
1061 	case SO_V6ONLY_ENABLE:
1062 		flags |= SO_F_V6ONLY;
1063 		*mask |= SO_F_V6ONLY;
1064 		break;
1065 	case SO_V6ONLY_DISABLE:
1066 		*mask |= SO_F_V6ONLY;
1067 		break;
1068 	}
1069 
1070 	return flags;
1071 } /* so_opts2flags() */
1072 
1073 
so_type2mask(mode_t mode,int family,int type,int protocol)1074 static int so_type2mask(mode_t mode, int family, int type, int protocol) {
1075 	int mask = SO_F_CLOEXEC|SO_F_NONBLOCK|SO_F_NOSIGPIPE;
1076 
1077 	if (S_ISSOCK(mode)) {
1078 		mask |= SO_F_REUSEADDR|SO_F_REUSEPORT|SO_F_OOBINLINE;
1079 
1080 		if (!protocol) {
1081 			if (family == AF_INET || family == AF_INET6) {
1082 				protocol = (type == SOCK_STREAM)? IPPROTO_TCP : IPPROTO_UDP;
1083 			}
1084 		}
1085 
1086 		if (family == AF_INET6) {
1087 			mask |= SO_F_V6ONLY;
1088 		}
1089 
1090 		if (type == SOCK_DGRAM) {
1091 			mask |= SO_F_BROADCAST;
1092 		}
1093 
1094 		if (protocol == IPPROTO_TCP) {
1095 			mask |= SO_F_NODELAY|SO_F_NOPUSH;
1096 		}
1097 	}
1098 
1099 	return mask;
1100 } /* so_type2mask() */
1101 
1102 
so_getfl(int fd,int which)1103 int so_getfl(int fd, int which) {
1104 	int flags = 0, getfl = 0, getfd;
1105 
1106 	if ((which & SO_F_CLOEXEC) && -1 != (getfd = fcntl(fd, F_GETFD))) {
1107 		if (getfd & FD_CLOEXEC)
1108 			flags |= SO_F_CLOEXEC;
1109 	}
1110 
1111 	if ((which & SO_F_NONBLOCK) && -1 != (getfl = fcntl(fd, F_GETFL))) {
1112 		if (getfl & O_NONBLOCK)
1113 			flags |= SO_F_NONBLOCK;
1114 	}
1115 
1116 	if ((which & SO_F_REUSEADDR) && so_getboolopt(fd, SOL_SOCKET, SO_REUSEADDR))
1117 		flags |= SO_F_REUSEADDR;
1118 
1119 #if defined SO_REUSEPORT
1120 	if ((which & SO_F_REUSEPORT) && so_getboolopt(fd, SOL_SOCKET, SO_REUSEPORT))
1121 		flags |= SO_F_REUSEPORT;
1122 #endif
1123 
1124 	if ((which & SO_F_BROADCAST) && so_getboolopt(fd, SOL_SOCKET, SO_BROADCAST))
1125 		flags |= SO_F_BROADCAST;
1126 
1127 	if ((which & SO_F_NODELAY) && so_getboolopt(fd, IPPROTO_TCP, TCP_NODELAY))
1128 		flags |= SO_F_NODELAY;
1129 
1130 #if defined TCP_NOPUSH
1131 	if ((which & SO_F_NOPUSH) && so_getboolopt(fd, IPPROTO_TCP, TCP_NOPUSH))
1132 		flags |= SO_F_NOPUSH;
1133 #endif
1134 
1135 #if defined O_NOSIGPIPE || defined F_GETNOSIGPIPE || defined SO_NOSIGPIPE
1136 	if ((which & SO_F_NOSIGPIPE)) {
1137 #if defined O_NOSIGPIPE
1138 		if (getfl) {
1139 			if (getfl != -1 && (getfl & O_NOSIGPIPE))
1140 				flags |= SO_F_NOSIGPIPE;
1141 		} else if (-1 != (getfl = fcntl(fd, F_GETFL))) {
1142 			if (getfl & O_NOSIGPIPE)
1143 				flags |= SO_F_NOSIGPIPE;
1144 		}
1145 #elif defined F_GETNOSIGPIPE
1146 		int nosigpipe;
1147 
1148 		if (-1 != (nosigpipe = fcntl(fd, F_GETNOSIGPIPE))) {
1149 			if (nosigpipe)
1150 				flags |= SO_F_NOSIGPIPE;
1151 		}
1152 #else
1153 		if (so_getboolopt(fd, SOL_SOCKET, SO_NOSIGPIPE))
1154 			flags |= SO_F_NOSIGPIPE;
1155 #endif
1156 	}
1157 #endif
1158 
1159 	if ((which & SO_F_V6ONLY) && so_getboolopt(fd, IPPROTO_IPV6, IPV6_V6ONLY))
1160 		flags |= SO_F_V6ONLY;
1161 
1162 	if ((which & SO_F_OOBINLINE) && so_getboolopt(fd, SOL_SOCKET, SO_OOBINLINE))
1163 		flags |= SO_F_OOBINLINE;
1164 
1165 	return flags;
1166 } /* so_getfl() */
1167 
1168 
so_rstfl(int fd,int * oflags,int flags,int mask,int require)1169 int so_rstfl(int fd, int *oflags, int flags, int mask, int require) {
1170 	const struct flops *f;
1171 	int error;
1172 
1173 	for (f = fltable; f < endof(fltable); f++) {
1174 		if (!(f->flag & mask))
1175 			continue;
1176 
1177 		if ((error = f->set(fd, !!(f->flag & flags)))) {
1178 			if ((f->flag & require) || error != EOPNOTSUPP)
1179 				return error;
1180 
1181 			*oflags &= ~f->flag;
1182 		} else {
1183 			*oflags &= ~f->flag;
1184 			*oflags |= (f->flag & flags);
1185 		}
1186 	}
1187 
1188 	return 0;
1189 } /* so_rstfl() */
1190 
1191 
so_setfl(int fd,int flags,int mask,int require)1192 int so_setfl(int fd, int flags, int mask, int require) {
1193 	return so_rstfl(fd, &(int){ 0 }, flags, mask, require);
1194 } /* so_setfl() */
1195 
1196 
1197 int (so_addfl)(int fd, int flags, int require) {
1198 	return so_rstfl(fd, &(int){ 0 }, flags, flags, require);
1199 } /* so_addfl() */
1200 
1201 
1202 int (so_delfl)(int fd, int flags, int require) {
1203 	return so_rstfl(fd, &(int){ 0 }, ~flags, flags, require);
1204 } /* so_delfl() */
1205 
1206 
x509_discard(X509 ** cert)1207 static void x509_discard(X509 **cert) {
1208 	if (*cert)
1209 		X509_free(*cert);
1210 	*cert = 0;
1211 } /* x509_discard() */
1212 
1213 
ssl_discard(SSL ** ctx)1214 static void ssl_discard(SSL **ctx) {
1215 	if (*ctx)
1216 		SSL_free(*ctx);
1217 	*ctx = 0;
1218 } /* ssl_discard() */
1219 
1220 
thr_sigmask(int how,const sigset_t * set,sigset_t * oset)1221 static int thr_sigmask(int how, const sigset_t *set, sigset_t *oset) {
1222 #if SO_THREAD_SAFE
1223 	return pthread_sigmask(how, set, oset);
1224 #else
1225 	return (0 == sigprocmask(how, set, oset))? 0 : errno;
1226 #endif
1227 } /* thr_sigmask() */
1228 
1229 
math_addull(unsigned long long * x,unsigned long long a,unsigned long long b)1230 static int math_addull(unsigned long long *x, unsigned long long a, unsigned long long b) {
1231 	if (~a < b) {
1232 		*x = ~0ULL;
1233 
1234 		return EOVERFLOW;
1235 	} else {
1236 		*x = a + b;
1237 
1238 		return 0;
1239 	}
1240 } /* math_addull() */
1241 
1242 
st_update(struct st_log * log,size_t len,const struct so_options * opts)1243 static void st_update(struct st_log *log, size_t len, const struct so_options *opts) {
1244 	math_addull(&log->count, log->count, len);
1245 
1246 	if (opts->st_time)
1247 		time(&log->time);
1248 } /* st_update() */
1249 
1250 
1251 /*
1252  * S O C K E T  R O U T I N E S
1253  *
1254  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1255 
1256 /*
1257  * NOTE: We give SO_S_SHUTWR higher precedence because on some systems
1258  * shutdown(SHUT_RD) will fail if EOF has already been sent by the peer. A
1259  * mitigation was already committed to address this issue (see so_shutrd_),
1260  * but it never made it downstream. This makes merging easier and is
1261  * otherwise sensible on its own terms.
1262  */
1263 enum so_state {
1264 	SO_S_INIT     = 1<<0,
1265 	SO_S_GETADDR  = 1<<1,
1266 	SO_S_SOCKET   = 1<<2,
1267 	SO_S_BIND     = 1<<3,
1268 	SO_S_LISTEN   = 1<<4,
1269 	SO_S_CONNECT  = 1<<5,
1270 	SO_S_STARTTLS = 1<<6,
1271 	SO_S_SETREAD  = 1<<7,
1272 	SO_S_SETWRITE = 1<<8,
1273 	SO_S_RSTLOWAT = 1<<9,
1274 	SO_S_SHUTWR   = 1<<10, /* see NOTE above */
1275 	SO_S_SHUTRD   = 1<<11,
1276 
1277 	SO_S_END,
1278 	SO_S_ALL = ((SO_S_END - 1) << 1) - 1
1279 }; /* enum so_state */
1280 
1281 
1282 struct socket {
1283 	struct so_options opts;
1284 	struct dns_addrinfo *res;
1285 
1286 	int fd;
1287 
1288 	mode_t mode;  /* file mode */
1289 	int domain;   /* socket domain (address family) */
1290 	int type;     /* socket type */
1291 	int protocol; /* socket protocol */
1292 	int flags;    /* descriptor flags */
1293 
1294 	struct so_stat st;
1295 
1296 	struct {
1297 		_Bool rd;
1298 		_Bool wr;
1299 	} shut;
1300 
1301 	struct addrinfo *host;
1302 
1303 	short events;
1304 
1305 	int done, todo;
1306 
1307 	int lerror;
1308 
1309 	int olowat;
1310 
1311 	struct {
1312 		SSL *ctx;
1313 		int error;
1314 		int state;
1315 		_Bool accept;
1316 		_Bool vrfd;
1317 	} ssl;
1318 
1319 	struct {
1320 		BIO *ctx;
1321 //		BIO *ctrl; /* proxy unknown DTLS BIO_ctrl commands */
1322 		int error;
1323 
1324 		struct {
1325 			void *data;
1326 			unsigned char *p, *pe;
1327 		} ahead;
1328 	} bio;
1329 
1330 	struct {
1331 		int ncalls;
1332 		sigset_t pending;
1333 		sigset_t blocked;
1334 	} pipeign;
1335 
1336 	struct {
1337 		pid_t pid;
1338 		uid_t uid;
1339 		gid_t gid;
1340 	} cred;
1341 }; /* struct socket */
1342 
1343 
so_needign(struct socket * so,_Bool rdonly)1344 static _Bool so_needign(struct socket *so, _Bool rdonly) {
1345 	if (!so->opts.fd_nosigpipe || (so->flags & SO_F_NOSIGPIPE))
1346 		return 0;
1347 	if (so->ssl.ctx && !so->bio.ctx)
1348 		return 1;
1349 	if (rdonly)
1350 		return 0;
1351 #if defined MSG_NOSIGNAL
1352 	if (S_ISSOCK(so->mode))
1353 		return 0;
1354 #endif
1355 	return 1;
1356 } /* so_needign() */
1357 
1358 
so_pipeign(struct socket * so,_Bool rdonly)1359 static int so_pipeign(struct socket *so, _Bool rdonly) {
1360 	if (!so_needign(so, rdonly))
1361 		return 0;
1362 
1363 #if _POSIX_REALTIME_SIGNALS > 0
1364 	if (so->pipeign.ncalls++ > 0)
1365 		return 0;
1366 
1367 	sigemptyset(&so->pipeign.pending);
1368 	sigpending(&so->pipeign.pending);
1369 
1370 	if (sigismember(&so->pipeign.pending, SIGPIPE))
1371 		return 0;
1372 
1373 	sigset_t piped;
1374 	sigemptyset(&piped);
1375 	sigaddset(&piped, SIGPIPE);
1376 	sigemptyset(&so->pipeign.blocked);
1377 
1378 	return thr_sigmask(SIG_BLOCK, &piped, &so->pipeign.blocked);
1379 #else
1380 	return EOPNOTSUPP;
1381 #endif
1382 } /* so_pipeign() */
1383 
1384 
so_pipeok(struct socket * so,_Bool rdonly)1385 static int so_pipeok(struct socket *so, _Bool rdonly) {
1386 	if (!so_needign(so, rdonly))
1387 		return 0;
1388 
1389 #if _POSIX_REALTIME_SIGNALS > 0
1390 	assert(so->pipeign.ncalls > 0);
1391 
1392 	if (--so->pipeign.ncalls)
1393 		return 0;
1394 
1395 	if (sigismember(&so->pipeign.pending, SIGPIPE))
1396 		return 0;
1397 
1398 	sigset_t piped;
1399 	sigemptyset(&piped);
1400 	sigaddset(&piped, SIGPIPE);
1401 
1402 	while (-1 == sigtimedwait(&piped, NULL, &(struct timespec){ 0, 0 }) && errno == EINTR)
1403 		;;
1404 
1405 	return thr_sigmask(SIG_SETMASK, &so->pipeign.blocked, NULL);
1406 #else
1407 	return EOPNOTSUPP;
1408 #endif
1409 } /* so_pipeok() */
1410 
1411 
so_getaddr_(struct socket * so)1412 static int so_getaddr_(struct socket *so) {
1413 	int error;
1414 
1415 	if (!so->res)
1416 		return SO_ENOHOST;
1417 
1418 	so->events = 0;
1419 
1420 	free(so->host);
1421 	so->host = 0;
1422 
1423 	if ((error = dns_ai_nextent(&so->host, so->res)))
1424 		goto error;
1425 
1426 	return 0;
1427 error:
1428 	switch (error) {
1429 #if SO_EWOULDBLOCK != SO_EAGAIN
1430 	case SO_EWOULDBLOCK:
1431 		/* FALL THROUGH */
1432 #endif
1433 	case SO_EAGAIN:
1434 		so->events = dns_ai_events(so->res);
1435 
1436 		break;
1437 	} /* switch() */
1438 
1439 	return error;
1440 } /* so_getaddr_() */
1441 
1442 
so_socket_(struct socket * so)1443 static int so_socket_(struct socket *so) {
1444 	int error;
1445 
1446 	if (!so->host)
1447 		return SO_ENOHOST;
1448 
1449 	so_closesocket(&so->fd, &so->opts);
1450 
1451 	if (-1 == (so->fd = so_socket(so->host->ai_family, so->host->ai_socktype, &so->opts, &error)))
1452 		return error;
1453 
1454 	if ((error = so_ftype(so->fd, &so->mode, &so->domain, &so->type, &so->protocol)))
1455 		return error;
1456 
1457 	so->flags = so_getfl(so->fd, ~0);
1458 
1459 	return 0;
1460 } /* so_socket_() */
1461 
1462 
so_bind_(struct socket * so)1463 static int so_bind_(struct socket *so) {
1464 	struct sockaddr *saddr;
1465 
1466 	if (so->todo & SO_S_LISTEN) {
1467 		if (!so->host)
1468 			return SO_ENOHOST;
1469 
1470 		saddr = so->host->ai_addr;
1471 	} else if (so->opts.sa_bind) {
1472 		saddr = (struct sockaddr *)so->opts.sa_bind;
1473 	} else {
1474 		return 0;
1475 	}
1476 
1477 	return so_bind(so->fd, saddr, &so->opts);
1478 } /* so_bind_() */
1479 
1480 
so_listen_(struct socket * so)1481 static int so_listen_(struct socket *so) {
1482 	if (!S_ISSOCK(so->mode) || (so->type != SOCK_STREAM && so->type != SOCK_SEQPACKET))
1483 		return 0;
1484 
1485 	return (0 == listen(so->fd, SOMAXCONN))? 0 : so_soerr();
1486 } /* so_listen_() */
1487 
1488 
so_connect_(struct socket * so)1489 static int so_connect_(struct socket *so) {
1490 	int error;
1491 
1492 	so->events &= ~POLLOUT;
1493 
1494 retry:
1495 	if (!so->host) {
1496 		error = SO_ENOHOST;
1497 		goto error;
1498 	}
1499 
1500 	if (0 != connect(so->fd, so->host->ai_addr, so->host->ai_addrlen)) {
1501 		error = so_soerr();
1502 		goto error;
1503 	}
1504 
1505 ready:
1506 	so_trace(SO_T_CONNECT, so->fd, so->host, "ready");
1507 
1508 	return 0;
1509 error:
1510 	switch (error) {
1511 	case SO_EISCONN:
1512 		goto ready;
1513 	case SO_EINTR:
1514 		goto retry;
1515 	case SO_EINPROGRESS:
1516 		/* FALL THROUGH */
1517 	case SO_EALREADY:
1518 		/* FALL THROUGH */
1519 #if SO_EWOULDBLOCK != SO_EAGAIN
1520 	case SO_EWOULDBLOCK
1521 		/* FALL THROUGH */
1522 #endif
1523 		so->events |= POLLOUT;
1524 
1525 		return SO_EAGAIN;
1526 	default:
1527 		so_trace(SO_T_CONNECT, so->fd, so->host, "%s", so_strerror(error));
1528 
1529 		return error;
1530 	} /* switch() */
1531 } /* so_connect_() */
1532 
1533 
1534 static BIO *so_newbio(struct socket *, int *);
1535 
so_starttls_(struct socket * so)1536 static int so_starttls_(struct socket *so) {
1537 	X509 *peer;
1538 	int rval, error;
1539 
1540 	if (so->ssl.error)
1541 		return so->ssl.error;
1542 
1543 	so_pipeign(so, 0);
1544 
1545 	ERR_clear_error();
1546 
1547 	switch (so->ssl.state) {
1548 	case 0: {
1549 		/*
1550 		 * NOTE: For SOCK_DGRAM continue using OpenSSL's BIO until
1551 		 * we have time to reverse engineer the semantics necessary
1552 		 * for DTLS.
1553 		 */
1554 		if (S_ISSOCK(so->mode) && so->type == SOCK_DGRAM) {
1555 			struct sockaddr_storage peer;
1556 			BIO *bio;
1557 
1558 			memset(&peer, 0, sizeof peer);
1559 
1560 			if (0 != getpeername(so->fd, (struct sockaddr *)&peer, &(socklen_t){ sizeof peer })) {
1561 				error = errno;
1562 				goto error;
1563 			}
1564 
1565 			if (!(bio = BIO_new_dgram(so->fd, BIO_NOCLOSE))) {
1566 				error = SO_EOPENSSL;
1567 				goto error;
1568 			}
1569 
1570 			BIO_ctrl_set_connected(bio, &peer);
1571 
1572 			SSL_set_bio(so->ssl.ctx, bio, bio);
1573 			SSL_set_read_ahead(so->ssl.ctx, 1);
1574 		} else {
1575 			BIO *bio;
1576 
1577 			if (!(bio = so_newbio(so, &error)))
1578 				goto error;
1579 
1580 			SSL_set_bio(so->ssl.ctx, bio, bio);
1581 		}
1582 
1583 		if (so->ssl.accept) {
1584 			SSL_set_accept_state(so->ssl.ctx);
1585 		} else {
1586 			SSL_set_connect_state(so->ssl.ctx);
1587 		}
1588 
1589 		so->ssl.state++;
1590 	}
1591 	/* FALL THROUGH */
1592 	case 1:
1593 		rval = SSL_do_handshake(so->ssl.ctx);
1594 
1595 		if (rval > 0) {
1596 			/* SUCCESS (continue to next state) */
1597 			;;
1598 		} else {
1599 			/* ERROR (either need I/O or a plain error) or SHUTDOWN */
1600 			so->events &= ~(POLLIN|POLLOUT);
1601 
1602 			error = ssl_error(so->ssl.ctx, rval, &so->events);
1603 
1604 			goto error;
1605 		} /* (rval) */
1606 
1607 		so->ssl.state++;
1608 		/* FALL THROUGH */
1609 	case 2:
1610 		/*
1611 		 * NOTE: Must call SSL_get_peer_certificate() first, which
1612 		 * processes the certificate. SSL_get_verify_result() merely
1613 		 * returns the result of this processing.
1614 		 */
1615 		peer = SSL_get_peer_certificate(so->ssl.ctx);
1616 		so->ssl.vrfd = (peer && SSL_get_verify_result(so->ssl.ctx) == X509_V_OK);
1617 		x509_discard(&peer);
1618 
1619 		so->ssl.state++;
1620 		/* FALL THROUGH */
1621 	case 3:
1622 		if (so->opts.tls_verify && !so->ssl.vrfd) {
1623 			error = SO_ENOTVRFD;
1624 
1625 			goto error;
1626 		}
1627 
1628 		so->ssl.state++;
1629 		/* FALL THROUGH */
1630 	case 4:
1631 		break;
1632 	} /* switch(so->ssl.state) */
1633 
1634 #if SOCKET_DEBUG
1635 	if (SOCKET_DEBUG) {
1636 		const SSL_CIPHER *cipher = SSL_get_current_cipher(so->ssl.ctx);
1637 
1638 		so_trace(SO_T_STARTTLS, so->fd, so->host, so->ssl.ctx,
1639 			"%s-%s", SSL_get_version(so->ssl.ctx), SSL_CIPHER_get_name(cipher));
1640 	}
1641 #endif
1642 
1643 	so_pipeok(so, 0);
1644 
1645 	return 0;
1646 error:
1647 	if (error != SO_EAGAIN)
1648 		so_trace(SO_T_STARTTLS, so->fd, so->host, so->ssl.ctx, "%s", so_strerror(error));
1649 
1650 	so_pipeok(so, 0);
1651 
1652 	return error;
1653 } /* so_starttls_() */
1654 
1655 
so_rstlowat_(struct socket * so)1656 static int so_rstlowat_(struct socket *so) {
1657 	if (0 != setsockopt(so->fd, SOL_SOCKET, SO_RCVLOWAT, &so->olowat, sizeof so->olowat))
1658 		return so_soerr();
1659 
1660 	return 0;
1661 } /* so_rstlowat_() */
1662 
1663 
so_shutwr_(struct socket * so)1664 static int so_shutwr_(struct socket *so) {
1665 	if (so->fd != -1 && 0 != shutdown(so->fd, SHUT_WR))
1666 		return so_soerr();
1667 
1668 	so->shut.wr = 1;
1669 	so->st.sent.eof = 1;
1670 
1671 	return 0;
1672 } /* so_shutwr_() */
1673 
1674 
so_isconn(int fd)1675 static _Bool so_isconn(int fd) {
1676 		struct sockaddr sa;
1677 		socklen_t slen = sizeof sa;
1678 
1679 		return 0 == getpeername(fd, &sa, &slen) || so_soerr() != SO_ENOTCONN;
1680 } /* so_isconn() */
1681 
so_shutrd_(struct socket * so)1682 static int so_shutrd_(struct socket *so) {
1683 	if (so->fd != -1 && 0 != shutdown(so->fd, SHUT_RD)) {
1684 		/*
1685 		 * NOTE: OS X will fail with ENOTCONN if the requested
1686 		 * SHUT_RD or SHUT_WR flag is already set, including if the
1687 		 * SHUT_RD flag is set from the peer sending eof. Other OSs
1688 		 * just treat this as a noop and return successfully.
1689 		 */
1690 		if (so_soerr() != SO_ENOTCONN)
1691 			return so_soerr();
1692 		else if (!so_isconn(so->fd))
1693 			return SO_ENOTCONN;
1694 	}
1695 
1696 	so->shut.rd = 1;
1697 
1698 	return 0;
1699 } /* so_shutrd_() */
1700 
1701 
so_state(const struct socket * so)1702 static inline int so_state(const struct socket *so) {
1703 	if (so->todo & ~so->done) {
1704 		int i = 1;
1705 
1706 		while (i < SO_S_END && !(i & (so->todo & ~so->done)))
1707 			i <<= 1;
1708 
1709 		return (i < SO_S_END)? i : 0;
1710 	} else
1711 		return 0;
1712 } /* so_state() */
1713 
1714 
so_exec(struct socket * so)1715 static int so_exec(struct socket *so) {
1716 	int state, error_, error = 0;
1717 
1718 exec:
1719 
1720 	switch (state = so_state(so)) {
1721 	case SO_S_INIT:
1722 		break;
1723 	case SO_S_GETADDR:
1724 		switch ((error_ = so_getaddr_(so))) {
1725 		case 0:
1726 			break;
1727 		case ENOENT:
1728 			/* NOTE: Return the last error if possible. */
1729 			if (error)
1730 				error_ = error;
1731 			else if (so->lerror)
1732 				error_ = so->lerror;
1733 
1734 			/* FALL THROUGH */
1735 		default:
1736 			error = error_;
1737 
1738 			goto error;
1739 		}
1740 
1741 		so->done |= state;
1742 
1743 		goto exec;
1744 	case SO_S_SOCKET:
1745 		if ((error = so_socket_(so)))
1746 			goto retry;
1747 
1748 		so->done |= state;
1749 
1750 		goto exec;
1751 	case SO_S_BIND:
1752 		if ((error = so_bind_(so)))
1753 			goto retry;
1754 
1755 		so->done |= state;
1756 
1757 		goto exec;
1758 	case SO_S_LISTEN:
1759 		if ((error = so_listen_(so)))
1760 			return error;
1761 
1762 		so->done |= state;
1763 
1764 		goto exec;
1765 	case SO_S_CONNECT:
1766 		if ((error = so_connect_(so))) {
1767 			switch (error) {
1768 			case SO_EAGAIN:
1769 				goto error;
1770 			default:
1771 				goto retry;
1772 			} /* switch() */
1773 		}
1774 
1775 		so->done |= state;
1776 
1777 		goto exec;
1778 	case SO_S_STARTTLS:
1779 		if ((error = so_starttls_(so)))
1780 			goto error;
1781 
1782 		so->done |= state;
1783 
1784 		goto exec;
1785 	case SO_S_SETREAD:
1786 		so->events |= POLLIN;
1787 		so->done   |= state;
1788 
1789 		goto exec;
1790 	case SO_S_SETWRITE:
1791 		so->events |= POLLOUT;
1792 		so->done   |= state;
1793 
1794 		goto exec;
1795 	case SO_S_RSTLOWAT:
1796 		if ((error = so_rstlowat_(so)))
1797 			goto error;
1798 
1799 		so->todo &= ~state;
1800 
1801 		goto exec;
1802 	case SO_S_SHUTWR:
1803 		if ((error = so_shutwr_(so)))
1804 			goto error;
1805 
1806 		so->done |= state;
1807 
1808 		goto exec;
1809 	case SO_S_SHUTRD:
1810 		if ((error = so_shutrd_(so)))
1811 			goto error;
1812 
1813 		so->done |= state;
1814 
1815 		goto exec;
1816 	} /* so_exec() */
1817 
1818 	return 0;
1819 retry:
1820 	/*
1821 	 * Jump back to the SO_S_GETADDR iterator if enabled. Otherwise,
1822 	 * this is a terminal error.
1823 	 */
1824 	if (so->todo & SO_S_GETADDR) {
1825 		so->done = 0;
1826 		so->lerror = error;
1827 
1828 		goto exec;
1829 	}
1830 
1831 	/* FALL THROUGH */
1832 error:
1833 	return error;
1834 } /* so_exec() */
1835 
1836 
so_make(const struct so_options * opts,int * error)1837 static struct socket *so_make(const struct so_options *opts, int *error) {
1838 	static const struct socket so_initializer = {
1839 		.fd = -1,
1840 		.domain = PF_UNSPEC,
1841 		.cred = { (pid_t)-1, (uid_t)-1, (gid_t)-1, }
1842 	};
1843 	struct socket *so;
1844 	size_t len;
1845 
1846 	if (!(so = malloc(sizeof *so)))
1847 		goto syerr;
1848 
1849 	*so = so_initializer;
1850 	so->opts = *opts;
1851 
1852 	if (opts->sa_bind) {
1853 		if (!(len = sa_len((void *)opts->sa_bind))) {
1854 			*error = EAFNOSUPPORT;
1855 			goto error;
1856 		}
1857 
1858 		if (!(so->opts.sa_bind = malloc(len)))
1859 			goto syerr;
1860 
1861 		memcpy((void *)so->opts.sa_bind, opts->sa_bind, len);
1862 	}
1863 
1864 	if (opts->tls_sendname && opts->tls_sendname != SO_OPTS_TLS_HOSTNAME) {
1865 		if (!(so->opts.tls_sendname = strdup(opts->tls_sendname)))
1866 			goto syerr;
1867 	}
1868 
1869 	return so;
1870 syerr:
1871 	*error = so_syerr();
1872 error:
1873 	if (so) {
1874 		if (so->opts.tls_sendname != opts->tls_sendname)
1875 			free((void *)so->opts.tls_sendname);
1876 
1877 		if (so->opts.sa_bind != opts->sa_bind)
1878 			free((void *)so->opts.sa_bind);
1879 
1880 		free(so);
1881 	}
1882 
1883 	return NULL;
1884 } /* so_make() */
1885 
1886 
1887 static void so_resetssl(struct socket *);
1888 
so_destroy(struct socket * so)1889 static int so_destroy(struct socket *so) {
1890 	so_resetssl(so);
1891 
1892 	dns_ai_close(so->res);
1893 	so->res = NULL;
1894 
1895 	free(so->host);
1896 	so->host = NULL;
1897 
1898 	so_closesocket(&so->fd, &so->opts);
1899 
1900 	so->events = 0;
1901 
1902 	if (so->opts.tls_sendname && so->opts.tls_sendname != SO_OPTS_TLS_HOSTNAME) {
1903 		free((void *)so->opts.tls_sendname);
1904 		so->opts.tls_sendname = NULL;
1905 	}
1906 
1907 	free((void *)so->opts.sa_bind);
1908 	so->opts.sa_bind = NULL;
1909 
1910 	return 0;
1911 } /* so_destroy() */
1912 
1913 
sa_isnumeric(const char * host)1914 static _Bool sa_isnumeric(const char *host) {
1915 	union sockaddr_any ip;
1916 
1917 	return !!sa_pton(&ip, sizeof ip, host, NULL, NULL);
1918 } /* sa_isnumeric() */
1919 
1920 
1921 struct socket *(so_open)(const char *host, const char *port, int qtype, int domain, int type, const struct so_options *opts, int *error_) {
1922 	_Bool isnumeric = sa_isnumeric(host);
1923 	struct dns_resolver *res = NULL;
1924 	struct addrinfo hints;
1925 	struct socket *so;
1926 	int error;
1927 
1928 	if (!(so = so_make(opts, &error)))
1929 		goto error;
1930 
1931 	/*
1932 	 * Copy host name as TLS server host name.
1933 	 *
1934 	 * NOTE: All the TLS RFCs (from RFC 3546 to RFC 6066)
1935 	 * declare
1936 	 *
1937 	 *      Literal IPv4 and IPv6 addresses are not permitted in
1938 	 *      "HostName".
1939 	 *
1940 	 * If the caller wants to send the IP address as the TLS
1941 	 * server host name, they can set .tls_hostname explicitly.
1942 	 */
1943 	if (so->opts.tls_sendname == SO_OPTS_TLS_HOSTNAME && !isnumeric) {
1944 		if (!(so->opts.tls_sendname = strdup(host)))
1945 			goto syerr;
1946 	}
1947 
1948 	memset(&hints, 0, sizeof hints);
1949 
1950 	hints.ai_flags    = AI_CANONNAME;
1951 	hints.ai_family   = domain;
1952 	hints.ai_socktype = type;
1953 
1954 	if (isnumeric) {
1955 		hints.ai_flags |= AI_NUMERICHOST;
1956 	} else {
1957 		struct dns_options *opts = dns_opts();
1958 
1959 		opts->closefd.arg = so->opts.fd_close.arg;
1960 		opts->closefd.cb = so->opts.fd_close.cb;
1961 
1962 		if (!(res = dns_res_stub(opts, &error)))
1963 			goto error;
1964 	}
1965 
1966 	if (!(so->res = dns_ai_open(host, port, qtype, &hints, res, &error)))
1967 		goto error;
1968 
1969 	so->todo = SO_S_GETADDR | SO_S_SOCKET | SO_S_BIND;
1970 
1971 	dns_res_close(res);
1972 
1973 	return so;
1974 syerr:
1975 	error = so_syerr();
1976 error:
1977 	dns_res_close(res);
1978 
1979 	so_close(so);
1980 
1981 	*error_ = error;
1982 
1983 	return 0;
1984 } /* so_open() */
1985 
1986 
so_dial(const struct sockaddr * sa,int type,const struct so_options * opts,int * error_)1987 struct socket *so_dial(const struct sockaddr *sa, int type, const struct so_options *opts, int *error_) {
1988 	struct { struct addrinfo ai; struct sockaddr_storage ss; } *host;
1989 	struct socket *so;
1990 	int error;
1991 
1992 	if (!(so = so_make(opts, &error)))
1993 		goto error;
1994 
1995 	if (!(host = malloc(sizeof *host)))
1996 		goto syerr;
1997 
1998 	memset(&host->ai, 0, sizeof host->ai);
1999 	memcpy(&host->ss, sa, SO_MIN(af_len(sa->sa_family), sizeof host->ss));
2000 
2001 	so->host = &host->ai;
2002 	so->host->ai_family = sa->sa_family;
2003 	so->host->ai_socktype = type;
2004 	so->host->ai_protocol = 0;
2005 	so->host->ai_addrlen = af_len(sa->sa_family);
2006 	so->host->ai_addr = (struct sockaddr *)&host->ss;
2007 
2008 	so->todo = SO_S_SOCKET | SO_S_BIND;
2009 
2010 	return so;
2011 syerr:
2012 	error = so_syerr();
2013 error:
2014 	so_close(so);
2015 
2016 	*error_ = error;
2017 
2018 	return 0;
2019 } /* so_dial() */
2020 
2021 
so_fdopen(int fd,const struct so_options * opts,int * error_)2022 struct socket *so_fdopen(int fd, const struct so_options *opts, int *error_) {
2023 	struct socket *so;
2024 	int flags, mask, need, error;
2025 
2026 	if (!(so = so_make(opts, &error)))
2027 		goto error;
2028 
2029 	if ((error = so_ftype(fd, &so->mode, &so->domain, &so->type, &so->protocol)))
2030 		goto error;
2031 
2032 	flags = so_opts2flags(opts, &mask);
2033 	mask &= so_type2mask(so->mode, so->domain, so->type, so->protocol);
2034 	need = ~(SO_F_NODELAY|SO_F_NOPUSH|SO_F_NOSIGPIPE|SO_F_OOBINLINE);
2035 
2036 	if ((error = so_rstfl(fd, &so->flags, flags, mask, need)))
2037 		goto error;
2038 
2039 	so->fd = fd;
2040 
2041 	return so;
2042 error:
2043 	so_close(so);
2044 
2045 	*error_ = error;
2046 
2047 	return 0;
2048 } /* so_fdopen() */
2049 
2050 
so_close(struct socket * so)2051 int so_close(struct socket *so) {
2052 	if (!so)
2053 		return EINVAL;
2054 
2055 	so_destroy(so);
2056 
2057 	free(so);
2058 
2059 	return 0;
2060 } /* so_close() */
2061 
2062 
so_family(struct socket * so,int * error_)2063 int so_family(struct socket *so, int *error_) {
2064 	struct sockaddr_storage saddr;
2065 	socklen_t slen = sizeof saddr;
2066 	int error;
2067 
2068 	if ((error = so_localaddr(so, (void *)&saddr, &slen)))
2069 		{ *error_ = error; return AF_UNSPEC; }
2070 
2071 	return *sa_family(&saddr);
2072 } /* so_family() */
2073 
2074 
so_localaddr(struct socket * so,void * saddr,socklen_t * slen)2075 int so_localaddr(struct socket *so, void *saddr, socklen_t *slen) {
2076 	int error;
2077 
2078 	if ((so_state(so) < SO_S_STARTTLS) && (error = so_exec(so)))
2079 		return error;
2080 
2081 	if (0 != getsockname(so->fd, saddr, slen))
2082 		return errno;
2083 
2084 	return 0;
2085 } /* so_localaddr() */
2086 
2087 
so_remoteaddr(struct socket * so,void * saddr,socklen_t * slen)2088 int so_remoteaddr(struct socket *so, void *saddr, socklen_t *slen) {
2089 	int error;
2090 
2091 	if ((so_state(so) < SO_S_STARTTLS) && (error = so_exec(so)))
2092 		return error;
2093 
2094 	if (0 != getpeername(so->fd, saddr, slen))
2095 		return errno;
2096 
2097 	return 0;
2098 } /* so_remoteaddr() */
2099 
2100 
so_connect(struct socket * so)2101 int so_connect(struct socket *so) {
2102 	if (so->done & SO_S_CONNECT)
2103 		return 0;
2104 
2105 	so->todo |= SO_S_CONNECT;
2106 
2107 	return so_exec(so);
2108 } /* so_connect() */
2109 
2110 
so_listen(struct socket * so)2111 int so_listen(struct socket *so) {
2112 	if (so->done & SO_S_LISTEN)
2113 		return 0;
2114 
2115 	so->todo |= SO_S_LISTEN;
2116 
2117 	return so_exec(so);
2118 } /* so_listen() */
2119 
2120 
so_accept(struct socket * so,struct sockaddr * saddr,socklen_t * slen,int * error_)2121 int so_accept(struct socket *so, struct sockaddr *saddr, socklen_t *slen, int *error_) {
2122 	int fd = -1, error;
2123 
2124 	if ((error = so_listen(so)))
2125 		goto error;
2126 
2127 	if ((error = so_exec(so)))
2128 		goto error;
2129 
2130 	so->events = POLLIN;
2131 
2132 retry:
2133 #if HAVE_ACCEPT4 && defined SOCK_CLOEXEC
2134 	if (-1 == (fd = accept4(so->fd, saddr, slen, SOCK_CLOEXEC)))
2135 		goto soerr;
2136 #elif HAVE_PACCEPT && defined SOCK_CLOEXEC
2137 	if (-1 == (fd = paccept(so->fd, saddr, slen, NULL, SOCK_CLOEXEC)))
2138 		goto soerr;
2139 #else
2140 	if (-1 == (fd = accept(so->fd, saddr, slen)))
2141 		goto soerr;
2142 
2143 	if ((error = so_cloexec(fd, 1)))
2144 		goto error;
2145 #endif
2146 
2147 	return fd;
2148 soerr:
2149 	switch ((error = so_soerr())) {
2150 	case SO_EINTR:
2151 		goto retry;
2152 #if SO_EWOULDBLOCK != SO_EAGAIN
2153 	case SO_EWOULDBLOCK:
2154 		error = SO_EAGAIN;
2155 
2156 		break;
2157 #endif
2158 	case SO_ECONNABORTED:
2159 		error = SO_EAGAIN;
2160 
2161 		break;
2162 	}
2163 error:
2164 	*error_ = error;
2165 
2166 	so_closesocket(&fd, NULL);
2167 
2168 	return -1;
2169 } /* so_accept() */
2170 
2171 
so_resetssl(struct socket * so)2172 static void so_resetssl(struct socket *so) {
2173 	ssl_discard(&so->ssl.ctx);
2174 	so->ssl.state  = 0;
2175 	so->ssl.error  = 0;
2176 	so->ssl.accept = 0;
2177 	so->ssl.vrfd   = 0;
2178 
2179 	if (so->bio.ctx) {
2180 		BIO_free(so->bio.ctx);
2181 		so->bio.ctx = NULL;
2182 	}
2183 
2184 	free(so->bio.ahead.data);
2185 	so->bio.ahead.data = NULL;
2186 	so->bio.ahead.p = NULL;
2187 	so->bio.ahead.pe = NULL;
2188 } /* so_resetssl() */
2189 
so_starttls(struct socket * so,const struct so_starttls * cfg)2190 int so_starttls(struct socket *so, const struct so_starttls *cfg) {
2191 	SSL_CTX *ctx, *tmp = NULL;
2192 	SSL *ssl = NULL;
2193 	const SSL_METHOD *method;
2194 	int error;
2195 
2196 	if (so->done & SO_S_STARTTLS)
2197 		return 0;
2198 
2199 	if (so->todo & SO_S_STARTTLS)
2200 		goto check;
2201 
2202 	cfg = (cfg)? cfg : &(struct so_starttls){ 0 };
2203 
2204 	so_resetssl(so);
2205 
2206 	/*
2207 	 * NOTE: Commit to the SO_S_STARTTLS state at this point, no matter
2208 	 * whether we can allocate the proper objects, so any errors will
2209 	 * persist. so_starttls_() immediately returns if so->ssl.error is
2210 	 * set. See NOTE at error label below.
2211 	 */
2212 	so->todo |= SO_S_STARTTLS;
2213 
2214 	if (cfg->pushback.iov_len > 0) {
2215 		if (!(so->bio.ahead.data = malloc(cfg->pushback.iov_len))) {
2216 			error = errno;
2217 			goto error;
2218 		}
2219 
2220 		memcpy(so->bio.ahead.data, cfg->pushback.iov_base, cfg->pushback.iov_len);
2221 		so->bio.ahead.p = so->bio.ahead.data;
2222 		so->bio.ahead.pe = so->bio.ahead.p + cfg->pushback.iov_len;
2223 	}
2224 
2225 	ERR_clear_error();
2226 
2227 	if ((ssl = cfg->instance)) {
2228 		SSL_up_ref(ssl);
2229 	} else {
2230 		if (!(ctx = cfg->context)) {
2231 			if (!(method = cfg->method)) {
2232 				if (so_isbool(cfg->accept)) {
2233 					method = SSLv23_method();
2234 				} else {
2235 					method = SSLv23_client_method();
2236 				}
2237 			}
2238 
2239 			if (!(ctx = tmp = SSL_CTX_new((SSL_METHOD *)method)))
2240 				goto eossl;
2241 		}
2242 
2243 		if (!(ssl = SSL_new(ctx)))
2244 			goto eossl;
2245 	}
2246 
2247 	if (so_isbool(cfg->accept)) {
2248 		so->ssl.accept = so_tobool(cfg->accept);
2249 	} else {
2250 		/* NB: see WARNING at compat_SSL_is_server() */
2251 		so->ssl.accept = SSL_is_server(ssl);
2252 	}
2253 
2254 	if (!so->ssl.accept && so->opts.tls_sendname && so->opts.tls_sendname != SO_OPTS_TLS_HOSTNAME) {
2255 		if (!SSL_set_tlsext_host_name(ssl, so->opts.tls_sendname))
2256 			goto eossl;
2257 	}
2258 
2259 	SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
2260 	SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
2261 
2262 	so->ssl.ctx = ssl;
2263 	ssl = NULL;
2264 
2265 	if (tmp)
2266 		SSL_CTX_free(tmp);
2267 
2268 check:
2269 	return so_exec(so);
2270 eossl:
2271 	error = SO_EOPENSSL;
2272 error:
2273 	/*
2274 	 * NOTE: Store any error in so->ssl.error because callers expect to
2275 	 * call-and-forget this routine, similar to so_connect() and
2276 	 * so_listen(), but we still need to replay the error.
2277 	 */
2278 	so->ssl.error = error;
2279 
2280 	if (ssl)
2281 		SSL_free(ssl);
2282 
2283 	if (tmp)
2284 		SSL_CTX_free(tmp);
2285 
2286 	return so->ssl.error;
2287 } /* so_starttls() */
2288 
2289 
so_checktls(struct socket * so)2290 SSL *so_checktls(struct socket *so) {
2291 	return so->ssl.ctx;
2292 } /* so_checktls() */
2293 
2294 
so_shutdown(struct socket * so,int how)2295 int so_shutdown(struct socket *so, int how) {
2296 	switch (how) {
2297 	case SHUT_RD:
2298 		so->todo |= SO_S_SHUTRD;
2299 
2300 		break;
2301 	case SHUT_WR:
2302 		so->todo |= SO_S_SHUTWR;
2303 
2304 		break;
2305 	case SHUT_RDWR:
2306 		so->todo |= SO_S_SHUTRD|SO_S_SHUTWR;
2307 
2308 		break;
2309 	} /* switch (how) */
2310 
2311 	return so_exec(so);
2312 } /* so_shutdown() */
2313 
2314 
so_sysread(struct socket * so,void * dst,size_t lim,int * error)2315 static size_t so_sysread(struct socket *so, void *dst, size_t lim, int *error) {
2316 	long len;
2317 
2318 retry:
2319 #if _WIN32
2320 	len = recv(so->fd, dst, SO_MIN(lim, LONG_MAX), 0);
2321 #else
2322 	len = read(so->fd, dst, SO_MIN(lim, LONG_MAX));
2323 #endif
2324 
2325 	if (len == -1)
2326 		goto error;
2327 	if (len == 0)
2328 		goto epipe;
2329 
2330 	return len;
2331 epipe:
2332 	*error = EPIPE;
2333 	so->st.rcvd.eof = 1;
2334 
2335 	return 0;
2336 error:
2337 	*error = so_soerr();
2338 
2339 	switch (*error) {
2340 	case SO_EINTR:
2341 		goto retry;
2342 #if SO_EWOULDBLOCK != SO_EAGAIN
2343 	case SO_EWOULDBLOCK:
2344 		*error = SO_EAGAIN;
2345 		/* FALL THROUGH */
2346 #endif
2347 	case SO_EAGAIN:
2348 		so->events |= POLLIN;
2349 		break;
2350 	} /* switch() */
2351 
2352 	return 0;
2353 } /* so_sysread() */
2354 
so_syswrite(struct socket * so,const void * src,size_t len,int * error)2355 static size_t so_syswrite(struct socket *so, const void *src, size_t len, int *error) {
2356 	long count;
2357 	int flags = 0;
2358 
2359 	if (so->st.sent.eof) {
2360 		*error = EPIPE;
2361 		return 0;
2362 	}
2363 
2364 //	so_pipeign(so, 0);
2365 
2366 #if _WIN32
2367 #else
2368 	if (S_ISSOCK(so->mode)) {
2369 		#if defined(MSG_NOSIGNAL)
2370 		if (so->opts.fd_nosigpipe)
2371 			flags |= MSG_NOSIGNAL;
2372 		#endif
2373 		if (so->type == SOCK_SEQPACKET)
2374 			flags |= MSG_EOR;
2375 	}
2376 #endif
2377 retry:
2378 #if _WIN32
2379 	if (1) {
2380 #else
2381 	if (S_ISSOCK(so->mode)) {
2382 #endif
2383 		count = send(so->fd, src, SO_MIN(len, LONG_MAX), flags);
2384 	} else {
2385 		count = write(so->fd, src, SO_MIN(len, LONG_MAX));
2386 	}
2387 
2388 	if (count == -1)
2389 		goto error;
2390 
2391 //	so_pipeok(so, 0);
2392 
2393 	return count;
2394 error:
2395 	*error = so_soerr();
2396 
2397 	switch (*error) {
2398 	case EPIPE:
2399 		so->st.sent.eof = 1;
2400 		break;
2401 	case SO_EINTR:
2402 		goto retry;
2403 #if SO_EWOULDBLOCK != SO_EAGAIN
2404 	case SO_EWOULDBLOCK:
2405 		*error = SO_EAGAIN;
2406 		/* FALL THROUGH */
2407 #endif
2408 	case SO_EAGAIN:
2409 		so->events |= POLLOUT;
2410 		break;
2411 	} /* switch() */
2412 
2413 //	so_pipeok(so, 0);
2414 
2415 	return 0;
2416 } /* so_syswrite() */
2417 
2418 
2419 static _Bool bio_nonfatal(int error) {
2420 	switch (error) {
2421 	case SO_EAGAIN:
2422 	case SO_EALREADY:
2423 	case SO_EINPROGRESS:
2424 	case SO_EINTR:
2425 	case SO_ENOTCONN: /* FIXME (bss_sock.c has this but is it correct?) */
2426 		return 1;
2427 	default:
2428 		return 0;
2429 	}
2430 } /* bio_nonfatal() */
2431 
2432 static int bio_read(BIO *bio, char *dst, int lim) {
2433 	struct socket *so = BIO_get_data(bio);
2434 	size_t count;
2435 
2436 	assert(so);
2437 	assert(lim >= 0);
2438 
2439 	BIO_clear_retry_flags(bio);
2440 	so->bio.error = 0;
2441 
2442 	if (so->bio.ahead.p < so->bio.ahead.pe) {
2443 		count = SO_MIN(so->bio.ahead.pe - so->bio.ahead.p, lim);
2444 		memcpy(dst, so->bio.ahead.p, count);
2445 		so->bio.ahead.p += count;
2446 
2447 		return count;
2448 	}
2449 
2450 	if ((count = so_sysread(so, dst, lim, &so->bio.error)))
2451 		return (int)count;
2452 
2453 	if (bio_nonfatal(so->bio.error))
2454 		BIO_set_retry_read(bio);
2455 
2456 	/* see note about SSL_ERROR_SYSCALL at bio_write */
2457 	errno = so->bio.error;
2458 
2459 	return (so->bio.error == EPIPE)? 0 : -1;
2460 } /* bio_read() */
2461 
2462 static int bio_write(BIO *bio, const char *src, int len) {
2463 	struct socket *so = BIO_get_data(bio);
2464 	size_t count;
2465 
2466 	assert(so);
2467 	assert(len >= 0);
2468 
2469 	BIO_clear_retry_flags(bio);
2470 	so->bio.error = 0;
2471 
2472 	if ((count = so_syswrite(so, src, len, &so->bio.error)))
2473 		return (int)count;
2474 
2475 	if (bio_nonfatal(so->bio.error))
2476 		BIO_set_retry_write(bio);
2477 
2478 	/*
2479 	 * SSL_get_error will return SSL_ERROR_SYSCALL, expecting errno to
2480 	 * be set.
2481 	 */
2482 	errno = so->bio.error;
2483 
2484 	return -1;
2485 } /* bio_write() */
2486 
2487 static int bio_puts(BIO *bio, const char *src) {
2488 	size_t len = strlen(src);
2489 
2490 	return bio_write(bio, src, (int)SO_MIN(len, INT_MAX));
2491 } /* bio_puts() */
2492 
2493 static long bio_ctrl(BIO *bio, int cmd, long udata_i, void *udata_p) {
2494 	(void)bio;
2495 	(void)udata_i;
2496 
2497 	switch (cmd) {
2498 	case BIO_CTRL_DUP: {
2499 		/*
2500 		 * We'll permit duping, just like all the other BIOs do by
2501 		 * default and so we don't inadvertently break something.
2502 		 * But we won't copy our state because our memory management
2503 		 * assumes 1:1 mapping between BIO and socket objects. And
2504 		 * just to be safe, zero the state members. BIO_dup_chain,
2505 		 * for example, has a hack to always copy .init and .num.
2506 		 */
2507 		BIO *udata = udata_p;
2508 		BIO_set_init(udata, 0);
2509 		BIO_set_data(udata, NULL);
2510 
2511 		return 1;
2512 	}
2513 	case BIO_CTRL_FLUSH:
2514 		return 1;
2515 	default:
2516 		/*
2517 		 * BIO_ctrl manual page says
2518 		 *
2519 		 * 	Source/sink BIOs return an 0 if they do not
2520 		 * 	recognize the BIO_ctrl() operation.
2521 		 */
2522 		return 0;
2523 	} /* switch() */
2524 } /* bio_ctrl() */
2525 
2526 static int bio_create(BIO *bio) {
2527 	BIO_set_init(bio, 0);
2528 	BIO_set_shutdown(bio, 0);
2529 	BIO_set_data(bio, NULL);
2530 
2531 	return 1;
2532 } /* bio_create() */
2533 
2534 static int bio_destroy(BIO *bio) {
2535 	BIO_set_init(bio, 0);
2536 	BIO_set_shutdown(bio, 0);
2537 	BIO_set_data(bio, NULL);
2538 
2539 	return 1;
2540 } /* bio_destroy() */
2541 
2542 #if !OPENSSL_PREREQ(1,1,0)
2543 static BIO_METHOD bio_methods = {
2544 	BIO_TYPE_SOURCE_SINK,
2545 	"struct socket*",
2546 	bio_write,
2547 	bio_read,
2548 	bio_puts,
2549 	NULL,
2550 	bio_ctrl,
2551 	bio_create,
2552 	bio_destroy,
2553 	NULL,
2554 };
2555 
2556 static BIO_METHOD *so_get_bio_methods() {
2557 	return &bio_methods;
2558 } /* so_get_bio_methods() */
2559 #else
2560 static BIO_METHOD *bio_methods = NULL;
2561 
2562 static CRYPTO_ONCE bio_methods_init_once = CRYPTO_ONCE_STATIC_INIT;
2563 
2564 static void bio_methods_init(void) {
2565 	int type = BIO_get_new_index();
2566 	if (type == -1)
2567 		return;
2568 
2569 	bio_methods = BIO_meth_new(type|BIO_TYPE_SOURCE_SINK, "struct socket*");
2570 	if (bio_methods == NULL)
2571 		return;
2572 
2573 	BIO_meth_set_write(bio_methods, bio_write);
2574 	BIO_meth_set_read(bio_methods, bio_read);
2575 	BIO_meth_set_puts(bio_methods, bio_puts);
2576 	BIO_meth_set_ctrl(bio_methods, bio_ctrl);
2577 	BIO_meth_set_create(bio_methods, bio_create);
2578 	BIO_meth_set_destroy(bio_methods, bio_destroy);
2579 } /* bio_methods_init() */
2580 
2581 static BIO_METHOD *so_get_bio_methods() {
2582 	if (bio_methods == NULL) {
2583 		CRYPTO_THREAD_run_once(&bio_methods_init_once, bio_methods_init);
2584 	}
2585 	return bio_methods;
2586 } /* so_get_bio_methods() */
2587 #endif
2588 
2589 static BIO *so_newbio(struct socket *so, int *error) {
2590 	BIO *bio;
2591 	BIO_METHOD *bio_methods = so_get_bio_methods();
2592 
2593 	if (bio_methods == NULL || !(bio = BIO_new(bio_methods))) {
2594 		*error = SO_EOPENSSL;
2595 		return NULL;
2596 	}
2597 
2598 	BIO_set_init(bio, 1);
2599 	BIO_set_data(bio, so);
2600 
2601 	/*
2602 	 * NOTE: Applications can acquire a reference to our BIO via the SSL
2603 	 * state object. The lifetime of the BIO could last longer than the
2604 	 * lifetime of our socket object, so we must keep our own reference
2605 	 * and zero any pointer to ourselves here and from so_destroy.
2606 	 */
2607 	if (so->bio.ctx) {
2608 		BIO_set_init(so->bio.ctx, 0);
2609 		BIO_set_data(so->bio.ctx, NULL);
2610 		BIO_free(so->bio.ctx);
2611 	}
2612 
2613 	BIO_up_ref(bio);
2614 	so->bio.ctx = bio;
2615 
2616 	return bio;
2617 } /* so_newbio() */
2618 
2619 
2620 size_t so_read(struct socket *so, void *dst, size_t lim, int *error_) {
2621 	size_t len;
2622 	int error;
2623 
2624 	so_pipeign(so, 1);
2625 
2626 	so->todo |= SO_S_SETREAD;
2627 
2628 	if ((error = so_exec(so)))
2629 		goto error;
2630 
2631 	if (so->fd == -1) {
2632 		error = ENOTCONN;
2633 		goto error;
2634 	}
2635 
2636 	so->events &= ~POLLIN;
2637 retry:
2638 	if (so->ssl.ctx) {
2639 		int n;
2640 
2641 		ERR_clear_error();
2642 
2643 		if ((n = SSL_read(so->ssl.ctx, dst, SO_MIN(lim, INT_MAX))) < 0) {
2644 			if (SO_EINTR == (error = ssl_error(so->ssl.ctx, n, &so->events)))
2645 				goto retry;
2646 			goto error;
2647 		} else if (n == 0) {
2648 			error = EPIPE; /* FIXME: differentiate clean from unclean shutdown? */
2649 			so->st.rcvd.eof = 1;
2650 			goto error;
2651 		}
2652 
2653 		len = n;
2654 	} else {
2655 		if (!(len = so_sysread(so, dst, lim, &error)))
2656 			goto error;
2657 	}
2658 
2659 	so_trace(SO_T_READ, so->fd, so->host, dst, (size_t)len, "rcvd %zu bytes", (size_t)len);
2660 	st_update(&so->st.rcvd, len, &so->opts);
2661 
2662 	so_pipeok(so, 1);
2663 
2664 	return len;
2665 error:
2666 	*error_ = error;
2667 
2668 	if (error != SO_EAGAIN)
2669 		so_trace(SO_T_READ, so->fd, so->host, (void *)0, (size_t)0, "%s", so_strerror(error));
2670 
2671 	so_pipeok(so, 1);
2672 
2673 	return 0;
2674 } /* so_read() */
2675 
2676 
2677 size_t so_write(struct socket *so, const void *src, size_t len, int *error_) {
2678 	size_t count;
2679 	int error;
2680 
2681 	so_pipeign(so, 0);
2682 
2683 	so->todo |= SO_S_SETWRITE;
2684 
2685 	if ((error = so_exec(so)))
2686 		goto error;
2687 
2688 	if (so->fd == -1) {
2689 		error = ENOTCONN;
2690 		goto error;
2691 	}
2692 
2693 	so->events &= ~POLLOUT;
2694 retry:
2695 	if (so->ssl.ctx) {
2696 		if (len > 0) {
2697 			int n;
2698 
2699 			ERR_clear_error();
2700 
2701 			if ((n = SSL_write(so->ssl.ctx, src, SO_MIN(len, INT_MAX))) < 0) {
2702 				if (SO_EINTR == (error = ssl_error(so->ssl.ctx, n, &so->events)))
2703 					goto retry;
2704 				goto error;
2705 			} else if (n == 0) {
2706 				error = EPIPE; /* FIXME: differentiate clean from unclean shutdown? */
2707 				so->st.sent.eof = 1;
2708 				goto error;
2709 			}
2710 
2711 			count = n;
2712 		} else {
2713 			count = 0;
2714 		}
2715 	} else {
2716 		if (!(count = so_syswrite(so, src, len, &error)))
2717 			goto error;
2718 	}
2719 
2720 	so_trace(SO_T_WRITE, so->fd, so->host, src, (size_t)count, "sent %zu bytes", (size_t)count);
2721 	st_update(&so->st.sent, count, &so->opts);
2722 
2723 	so_pipeok(so, 0);
2724 
2725 	return count;
2726 error:
2727 	*error_ = error;
2728 
2729 	if (error != SO_EAGAIN)
2730 		so_trace(SO_T_WRITE, so->fd, so->host, (void *)0, (size_t)0, "%s", so_strerror(error));
2731 
2732 	so_pipeok(so, 0);
2733 
2734 	return 0;
2735 } /* so_write() */
2736 
2737 
2738 size_t so_peek(struct socket *so, void *dst, size_t lim, int flags, int *_error) {
2739 	int rstlowat = so->todo & SO_S_RSTLOWAT;
2740 	long count;
2741 	int lowat, error;
2742 
2743 	so->todo &= ~SO_S_RSTLOWAT;
2744 
2745 	error = so_exec(so);
2746 
2747 	so->todo |= rstlowat;
2748 
2749 	if (error)
2750 		goto error;
2751 
2752 	if (flags & SO_F_PEEKALL)
2753 		so->events &= ~POLLIN;
2754 retry:
2755 	count = recv(so->fd, dst, lim, MSG_PEEK);
2756 
2757 	if (count == -1)
2758 		goto soerr;
2759 
2760 	if ((size_t)count == lim || !(flags & SO_F_PEEKALL))
2761 		return count;
2762 pollin:
2763 	if (!(so->todo & SO_S_RSTLOWAT)) {
2764 		if (0 != getsockopt(so->fd, SOL_SOCKET, SO_RCVLOWAT, &so->olowat, &(socklen_t){ sizeof so->olowat }))
2765 			goto soerr;
2766 
2767 		if (lim > INT_MAX) {
2768 			error = EOVERFLOW;
2769 
2770 			goto error;
2771 		}
2772 
2773 		lowat = (int)lim;
2774 
2775 		if (0 != setsockopt(so->fd, SOL_SOCKET, SO_RCVLOWAT, &lowat, sizeof lowat))
2776 			goto soerr;
2777 
2778 		so->todo |= SO_S_RSTLOWAT;
2779 	}
2780 
2781 	so->events |= POLLIN;
2782 
2783 	*_error = SO_EAGAIN;
2784 
2785 	return 0;
2786 soerr:
2787 	error = so_soerr();
2788 
2789 	switch (error) {
2790 	case SO_EINTR:
2791 		goto retry;
2792 #if SO_EWOULDBLOCK != SO_EAGAIN
2793 	case SO_EWOULDBLOCK:
2794 		/* FALL THROUGH */
2795 #endif
2796 	case SO_EAGAIN:
2797 		if (flags & SO_F_PEEKALL)
2798 			goto pollin;
2799 
2800 		break;
2801 	} /* switch() */
2802 error:
2803 	*_error = error;
2804 
2805 	return 0;
2806 } /* so_peek() */
2807 
2808 
2809 int so_sendmsg(struct socket *so, const struct msghdr *msg, int flags) {
2810 	ssize_t count;
2811 	int error;
2812 
2813 	so_pipeign(so, 0);
2814 
2815 	so->todo |= SO_S_SETWRITE;
2816 
2817 	if ((error = so_exec(so)))
2818 		goto error;
2819 
2820 	so->events &= ~POLLOUT;
2821 
2822 #if defined MSG_NOSIGNAL
2823 	if (so->opts.fd_nosigpipe)
2824 		flags |= MSG_NOSIGNAL;
2825 #endif
2826 
2827 retry:
2828 	if (-1 == (count = sendmsg(so->fd, msg, flags)))
2829 		goto syerr;
2830 
2831 	st_update(&so->st.sent, count, &so->opts);
2832 
2833 	so_pipeok(so, 0);
2834 
2835 	return 0;
2836 syerr:
2837 	error = errno;
2838 error:
2839 	switch (error) {
2840 	case SO_EINTR:
2841 		goto retry;
2842 #if SO_EWOULDBLOCK != SO_EAGAIN
2843 	case SO_EWOULDBLOCK:
2844 		/* FALL THROUGH */
2845 #endif
2846 	case SO_EAGAIN:
2847 		so->events |= POLLOUT;
2848 
2849 		break;
2850 	} /* switch() */
2851 
2852 	so_pipeok(so, 0);
2853 
2854 	return error;
2855 } /* so_sendmsg() */
2856 
2857 
2858 int so_recvmsg(struct socket *so, struct msghdr *msg, int flags) {
2859 	ssize_t count;
2860 	int error;
2861 
2862 	so_pipeign(so, 1);
2863 
2864 	so->todo |= SO_S_SETREAD;
2865 
2866 	if ((error = so_exec(so)))
2867 		goto error;
2868 
2869 	so->events &= ~POLLIN;
2870 retry:
2871 	if (-1 == (count = recvmsg(so->fd, msg, flags))) {
2872 		goto syerr;
2873 	} else if (!count) {
2874 		so->st.rcvd.eof = 1;
2875 		error = EPIPE;
2876 		goto error;
2877 	}
2878 
2879 	st_update(&so->st.rcvd, count, &so->opts);
2880 
2881 	/* RE .msg_iovlen type
2882 	 *
2883 	 * 	- Linux    : size_t
2884 	 * 	- OS X     : int
2885 	 * 	- OpenBSD  : unsigned int
2886 	 * 	- Solaris  : int
2887 	 * 	- FreeBSD  : int
2888 	 * 	- NetBSD   : int
2889 	 * 	- RFC 2292 : size_t
2890 	 */
2891 	for (size_t i = 0; i < (size_t)msg->msg_iovlen; i++) {
2892 		if ((size_t)count < msg->msg_iov[i].iov_len) {
2893 			msg->msg_iov[i].iov_len = count;
2894 
2895 			break;
2896 		} else {
2897 			count -= (ssize_t)msg->msg_iov[i].iov_len;
2898 		}
2899 	}
2900 
2901 	so_pipeok(so, 1);
2902 
2903 	return 0;
2904 syerr:
2905 	error = errno;
2906 error:
2907 	switch (error) {
2908 	case SO_EINTR:
2909 		goto retry;
2910 #if SO_EWOULDBLOCK != SO_EAGAIN
2911 	case SO_EWOULDBLOCK:
2912 		/* FALL THROUGH */
2913 #endif
2914 	case SO_EAGAIN:
2915 		so->events |= POLLIN;
2916 
2917 		break;
2918 	} /* switch() */
2919 
2920 	so_pipeok(so, 1);
2921 
2922 	return error;
2923 } /* so_recvmsg() */
2924 
2925 
2926 const struct so_stat *so_stat(struct socket *so) {
2927 	return &so->st;
2928 } /* so_stat() */
2929 
2930 
2931 void so_clear(struct socket *so) {
2932 	so->todo   &= ~(SO_S_SETREAD|SO_S_SETWRITE);
2933 	so->events = 0;
2934 } /* so_clear() */
2935 
2936 
2937 int so_events(struct socket *so) {
2938 	short events;
2939 
2940 	switch (so->opts.fd_events) {
2941 	case SO_LIBEVENT:
2942 		events = SO_POLL2EV(so->events);
2943 
2944 		break;
2945 	default:
2946 		/* FALL THROUGH */
2947 	case SO_SYSPOLL:
2948 		events = so->events;
2949 
2950 		break;
2951 	} /* switch (.fd_events) */
2952 
2953 	return events;
2954 } /* so_events() */
2955 
2956 
2957 int so_pollfd(struct socket *so) {
2958 	switch (so_state(so)) {
2959 	case SO_S_GETADDR:
2960 		return dns_ai_pollfd(so->res);
2961 	default:
2962 		return so->fd;
2963 	} /* switch() */
2964 } /* so_pollfd() */
2965 
2966 
2967 int so_poll(struct socket *so, int timeout) {
2968 	int nfds;
2969 
2970 #if 1
2971 	struct pollfd pfd = { .fd = so_pollfd(so), .events = so->events, };
2972 
2973 	if (!pfd.events)
2974 		return 0;
2975 
2976 	if (timeout != -1)
2977 		timeout *= 1000;
2978 
2979 	nfds = poll(&pfd, 1, timeout);
2980 #else
2981 	fd_set rfds, wfds;
2982 	int set, fd;
2983 
2984 	FD_ZERO(&rfds);
2985 	FD_ZERO(&wfds);
2986 
2987 	if (!(set = so->events))
2988 		return 0;
2989 
2990 	fd = so_pollfd(so);
2991 
2992 	if ((set & POLLIN) && fd < FD_SETSIZE)
2993 		FD_SET(fd, &rfds);
2994 
2995 	if ((set & POLLOUT) && fd < FD_SETSIZE)
2996 		FD_SET(fd, &wfds);
2997 
2998 	nfds = select(fd + 1, &rfds, &wfds, 0, (timeout >= 0)? &(struct timeval){ timeout, 0 } : 0);
2999 #endif
3000 
3001 	switch (nfds) {
3002 	case -1:
3003 		return errno;
3004 	case 0:
3005 		return ETIMEDOUT;
3006 	default:
3007 		return 0;
3008 	}
3009 } /* so_poll() */
3010 
3011 
3012 int so_peerfd(struct socket *so) {
3013 	return so->fd;
3014 } /* so_peerfd() */
3015 
3016 
3017 int so_uncork(struct socket *so) {
3018 	return so_nopush(so->fd, 0);
3019 } /* so_uncork() */
3020 
3021 
3022 static int so_loadcred(struct socket *so) {
3023 	if (so->cred.uid != (uid_t)-1)
3024 		return 0;
3025 
3026 #if defined SO_PEERCRED
3027 #if defined __OpenBSD__
3028 	struct sockpeercred uc;
3029 #else
3030 	struct ucred uc;
3031 #endif
3032 
3033 	if (0 != getsockopt(so->fd, SOL_SOCKET, SO_PEERCRED, &uc, &(socklen_t){ sizeof uc }))
3034 		return errno;
3035 
3036 	so->cred.pid = uc.pid;
3037 	so->cred.uid = uc.uid;
3038 	so->cred.gid = uc.gid;
3039 
3040 	return 0;
3041 #elif defined LOCAL_PEEREID
3042 	struct unpcbid unp = { -1, -1, -1 };
3043 
3044 	if (0 != getsockopt(so->fd, 0, LOCAL_PEEREID, &unp, &(socklen_t){ sizeof unp }))
3045 		return errno;
3046 
3047 	so->cred.pid = unp.unp_pid;
3048 	so->cred.uid = unp.unp_euid;
3049 	so->cred.gid = unp.unp_egid;
3050 
3051 	return 0;
3052 #elif defined __sun
3053 	ucred_t *uc = NULL;
3054 
3055 	if (0 != getpeerucred(so->fd, &uc))
3056 		return errno;
3057 
3058 	so->cred.pid = ucred_getpid(uc);
3059 	so->cred.uid = ucred_geteuid(uc);
3060 	so->cred.gid = ucred_getegid(uc);
3061 
3062 	ucred_free(uc);
3063 
3064 	return 0;
3065 #else
3066 	if (0 != getpeereid(so->fd, &so->cred.uid, &so->cred.gid))
3067 		return errno;
3068 
3069 	return 0;
3070 #endif
3071 } /* so_loadcred() */
3072 
3073 
3074 int so_peereid(struct socket *so, uid_t *uid, gid_t *gid) {
3075 	int error;
3076 
3077 	if ((error = so_loadcred(so)))
3078 		return error;
3079 
3080 	if (so->cred.uid == (uid_t)-1)
3081 		return EOPNOTSUPP;
3082 
3083 	if (uid)
3084 		*uid = so->cred.uid;
3085 	if (gid)
3086 		*gid = so->cred.gid;
3087 
3088 	return 0;
3089 } /* so_peereid() */
3090 
3091 
3092 int so_peerpid(struct socket *so, pid_t *pid) {
3093 	int error;
3094 
3095 	if ((error = so_loadcred(so)))
3096 		return error;
3097 
3098 	if (so->cred.pid == (pid_t)-1)
3099 		return EOPNOTSUPP;
3100 
3101 	if (pid)
3102 		*pid = so->cred.pid;
3103 
3104 	return 0;
3105 } /* so_peerpid() */
3106 
3107 
3108 /*
3109  * L I B R A R Y  R O U T I N E S
3110  *
3111  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3112 
3113 void socket_init(void) __attribute__((constructor, used));
3114 
3115 void socket_init(void) {
3116 	SSL_load_error_strings();
3117 	SSL_library_init();
3118 
3119 	so_initdebug();
3120 } /* socket_init() */
3121 
3122 
3123 
3124 #if SOCKET_MAIN
3125 
3126 #include <stdarg.h>
3127 #include <stdio.h>
3128 #include <stdlib.h>
3129 
3130 #include <string.h>
3131 
3132 #include <unistd.h>
3133 
3134 #include <err.h>
3135 
3136 #include <regex.h>
3137 
3138 #include "fifo.h"
3139 
3140 
3141 struct {
3142 	char arg0[64];
3143 
3144 	struct {
3145 		char scheme[32];
3146 		char authority[128];
3147 		char host[128];
3148 		char port[32];
3149 		char path[128];
3150 		char query[64];
3151 		char fragment[32];
3152 	} url;
3153 } MAIN = {
3154 	.url = {
3155 		.scheme = "http",
3156 		.host   = "google.com",
3157 		.port   = "80",
3158 		.path   = "/",
3159 	},
3160 };
3161 
3162 
3163 static void panic(const char *fmt, ...) {
3164 	va_list ap;
3165 
3166 	va_start(ap, fmt);
3167 
3168 #if _WIN32
3169 	vfprintf(stderr, fmt, ap);
3170 
3171 	exit(EXIT_FAILURE);
3172 #else
3173 	verrx(EXIT_FAILURE, fmt, ap);
3174 #endif
3175 } /* panic() */
3176 
3177 #define panic_(fn, ln, fmt, ...)	\
3178 	panic(fmt "%0s", (fn), (ln), __VA_ARGS__)
3179 #define panic(...)			\
3180 	panic_(__func__, __LINE__, "(%s:%d) " __VA_ARGS__, "")
3181 
3182 
3183 void parseurl(const char *url) {
3184 	static const char *expr = "^(([^:/?#]+):)?(//(([^/@]*@)?([^/?#:]*)(:([[:digit:]]*))?))?([^?#]*)(\\?([^#]*))?(#(.*))?";
3185 	regex_t re;
3186 	regmatch_t match[16];
3187 	char errstr[128];
3188 	int error;
3189 	struct { const char *name; char *dst; size_t lim; } part[16] = {
3190 		[2]  = { "scheme:   ", MAIN.url.scheme,    sizeof MAIN.url.scheme },
3191 		[4]  = { "authority:", MAIN.url.authority, sizeof MAIN.url.authority },
3192 		[6]  = { "host:     ", MAIN.url.host,      sizeof MAIN.url.host },
3193 		[8]  = { "port:     ", MAIN.url.port,      sizeof MAIN.url.port },
3194 		[9]  = { "path:     ", MAIN.url.path,      sizeof MAIN.url.path },
3195 		[11] = { "query:    ", MAIN.url.query,     sizeof MAIN.url.query },
3196 		[13] = { "fragment: ", MAIN.url.fragment,  sizeof MAIN.url.fragment },
3197 	};
3198 
3199 	if ((error = regcomp(&re, expr, REG_EXTENDED)))
3200 		goto error;
3201 
3202 	if ((error = regexec(&re, url, countof(match), match, 0)))
3203 		goto error;
3204 
3205 	for (size_t i = 0; i < countof(match); i++) {
3206 		if (match[i].rm_so == -1)
3207 			continue;
3208 
3209 		if (part[i].dst) {
3210 			snprintf(part[i].dst, part[i].lim, "%.*s", (int)(match[i].rm_eo - match[i].rm_so), &url[match[i].rm_so]);
3211 //			SAY("%s %s", part[i].name, part[i].dst);
3212 		} else {
3213 //			SAY("[%d]:       %.*s", i, (int)(match[i].rm_eo - match[i].rm_so), &url[match[i].rm_so]);
3214 			;;
3215 		}
3216 	}
3217 
3218 	regfree(&re);
3219 
3220 	return;
3221 error:
3222 	regerror(error, &re, errstr, sizeof errstr);
3223 	regfree(&re);
3224 
3225 	panic("%s", errstr);
3226 } /* parseurl() */
3227 
3228 
3229 int httpget(const char *url) {
3230 	const struct so_stat *st;
3231 	struct socket *so;
3232 	struct fifo *req;
3233 	struct iovec iov;
3234 	long n;
3235 	int lc, error;
3236 
3237 	parseurl(url);
3238 
3239 	if (!(so = so_open(MAIN.url.host, MAIN.url.port, DNS_T_A, PF_INET, SOCK_STREAM, so_opts(), &error)))
3240 		errx(EXIT_FAILURE, "so_open: %s", so_strerror(error));
3241 
3242 	so_connect(so);
3243 
3244 	if (!strcasecmp("https", MAIN.url.scheme)) {
3245 		SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
3246 
3247 #if 0 /* example code if waiting for SSL negotiation */
3248 		while ((error = so_starttls(so, ctx))) {
3249 			if (error != SO_EAGAIN || (error = so_poll(so, 3)))
3250 				errx(EXIT_FAILURE, "so_starttls: %s", so_strerror(error));
3251 		}
3252 #else
3253 		so_starttls(so, &(struct so_starttls){ .context = ctx });
3254 #endif
3255 	}
3256 
3257 	req = fifo_new(1024);
3258 
3259 	fifo_puts(req, "GET ");
3260 	fifo_puts(req, MAIN.url.path);
3261 	fifo_puts(req, " HTTP/1.0\r\n");
3262 	fifo_puts(req, "Host: ");
3263 	fifo_puts(req, MAIN.url.host);
3264 	fifo_putc(req, ':');
3265 	fifo_puts(req, MAIN.url.port);
3266 	fifo_puts(req, "\r\n\r\n");
3267 
3268 	while (fifo_rvec(req, &iov)) {
3269 		if (!(n = so_write(so, iov.iov_base, iov.iov_len, &error))) {
3270 			switch (error) {
3271 			case SO_EAGAIN:
3272 				so_poll(so, 1);
3273 
3274 				break;
3275 			default:
3276 				errx(EXIT_FAILURE, "so_write: %s", so_strerror(error));
3277 			}
3278 		} else {
3279 			fifo_discard(req, n);
3280 		}
3281 	}
3282 
3283 //	so_shutdown(so, SHUT_WR); /* send EOF (but some servers don't like this) */
3284 
3285 	lc = 0;
3286 
3287 	do {
3288 		char res[512];
3289 
3290 		while (0 == (n = so_read(so, res, sizeof res, &error)) && error != EPIPE) {
3291 			switch (error) {
3292 			case SO_EAGAIN:
3293 				so_poll(so, 1);
3294 
3295 				continue;
3296 			default:
3297 				errx(EXIT_FAILURE, "so_read: %s", so_strerror(error));
3298 			}
3299 		}
3300 
3301 		if (n > 0) {
3302 			fwrite(res, 1, n, stdout);
3303 			lc = res[n-1];
3304 		}
3305 	} while (n);
3306 
3307 	if (isatty(STDOUT_FILENO) && isatty(STDERR_FILENO)) {
3308 		if (lc != '\n')
3309 			fputc('\n', stdout);
3310 
3311 		fflush(stdout);
3312 
3313 		fputs("--\n", stderr);
3314 	}
3315 
3316 	st = so_stat(so);
3317 
3318 	fprintf(stderr, "sent: %llu bytes\n", st->sent.count);
3319 	fprintf(stderr, "rcvd: %llu bytes\n", st->rcvd.count);
3320 
3321 	so_close(so);
3322 
3323 	return 0;
3324 } /* httpget() */
3325 
3326 
3327 int echo(void) {
3328 	struct socket *srv0, *srv, *cli;
3329 	struct fifo out, in;
3330 	char obuf[512], ibuf[512];
3331 	size_t olen, len;
3332 	struct iovec iov;
3333 	int fd, error;
3334 
3335 	if (!(srv0 = so_open("127.0.0.1", "54321", DNS_T_A, PF_INET, SOCK_STREAM, so_opts(), &error)))
3336 		panic("so_open: %s", so_strerror(error));
3337 
3338 	if (!(cli = so_open("127.0.0.1", "54321", DNS_T_A, PF_UNSPEC, SOCK_STREAM, so_opts(), &error)))
3339 		panic("so_open: %s", so_strerror(error));
3340 
3341 	so_listen(srv0);
3342 
3343 	while (-1 == (fd = so_accept(srv0, 0, 0, &error))) {
3344 		if (error != SO_EAGAIN)
3345 			panic("so_accept: %s", so_strerror(error));
3346 
3347 		if ((error = so_connect(cli)) && error != SO_EAGAIN)
3348 			panic("so_connect: %s", so_strerror(error));
3349 
3350 		so_poll(cli, 1);
3351 	}
3352 
3353 	if (!(srv = so_fdopen(fd, so_opts(), &error)))
3354 		panic("so_fdopen: %s", so_strerror(error));
3355 
3356 	while ((olen = fread(obuf, 1, sizeof obuf, stdin))) {
3357 		fifo_from(&out, obuf, olen);
3358 		fifo_init(&in, ibuf, sizeof ibuf);
3359 
3360 		while (fifo_rlen(&in) < olen) {
3361 			if (fifo_rvec(&out, &iov)) {
3362 				so_poll(cli, 1);
3363 
3364 				if (!(len = so_write(cli, iov.iov_base, iov.iov_len, &error)) && error != SO_EAGAIN)
3365 					panic("so_write: %s", so_strerror(error));
3366 				else
3367 					fifo_discard(&out, len);
3368 			}
3369 
3370 			so_poll(srv, 1);
3371 
3372 			fifo_wvec(&in, &iov);
3373 
3374 			if (!(len = so_read(srv, iov.iov_base, iov.iov_len, &error)) && error != SO_EAGAIN && error != EPIPE)
3375 				panic("so_read: %s", so_strerror(error));
3376 			else
3377 				fifo_update(&in, +len);
3378 		}
3379 
3380 		while (fifo_rvec(&in, &iov))
3381 			fifo_discard(&in, fwrite(iov.iov_base, 1, iov.iov_len, stdout));
3382 	}
3383 
3384 	so_close(srv0);
3385 	so_close(srv);
3386 	so_close(cli);
3387 
3388 	return 0;
3389 } /* echo() */
3390 
3391 
3392 #define USAGE \
3393 	"%s [-h] echo | egress ADDR [PORT] | print ADDR [PORT] | get URI\n" \
3394 	"  -v  be verbose--trace input/output\n" \
3395 	"  -V  print version information\n" \
3396 	"  -h  print usage information\n" \
3397 	"\n" \
3398 	"Report bugs to william@25thandClement.com\n"
3399 
3400 int main(int argc, char **argv) {
3401 	extern int optind;
3402 	int opt;
3403 
3404 	dns_strlcpy(MAIN.arg0, (strrchr(argv[0], '/')? strrchr(argv[0], '/') + 1 : argv[0]), sizeof MAIN.arg0);
3405 
3406 	while (-1 != (opt = getopt(argc, argv, "vVh"))) {
3407 		switch (opt) {
3408 		case 'v':
3409 #if !defined(so_trace) /* macro expanding to void statement if no debug support */
3410 			socket_debug++;
3411 #else
3412 			fprintf(stderr, "%s: not compiled with tracing support\n", MAIN.arg0);
3413 #endif
3414 
3415 			break;
3416 		case 'V':
3417 			printf("%s (socket.c) %.8X\n", MAIN.arg0, socket_v_rel());
3418 			printf("vendor  %s\n", socket_vendor());
3419 			printf("release %.8X\n", socket_v_rel());
3420 			printf("abi     %.8X\n", socket_v_abi());
3421 			printf("api     %.8X\n", socket_v_api());
3422 			printf("dns     %.8X\n", dns_v_rel());
3423 			printf("ssl     %s\n", OPENSSL_VERSION_TEXT);
3424 
3425 			return 0;
3426 		case 'h':
3427 			/* FALL THROUGH */
3428 usage:		default:
3429 			fprintf(stderr, USAGE, MAIN.arg0);
3430 
3431 			return (opt == 'h')? 0: EXIT_FAILURE;
3432 		} /* switch() */
3433 	} /* while () */
3434 
3435 	argc -= optind;
3436 	argv += optind;
3437 
3438 	socket_init();
3439 
3440 	if (!argc) {
3441 		goto usage;
3442 	} else if (!strcmp(*argv, "echo")) {
3443 		return echo();
3444 	} else if (!strcmp(*argv, "egress") && argv[1]) {
3445 		struct sockaddr *saddr;
3446 		struct sockaddr_storage egress;
3447 		int error;
3448 
3449 		if (AF_UNSPEC == *sa_family(saddr = sa_aton(argv[1]))) {
3450 			struct dns_resolver *res;
3451 			struct dns_packet *ans;
3452 			struct dns_rr rr;
3453 			union dns_any rd;
3454 			char addr[SA_ADDRSTRLEN];
3455 
3456 			if (!(res = dns_res_stub(dns_opts(), &error)))
3457 				panic("dns_res_stub: %s", so_strerror(error));
3458 
3459 			if (!(ans = dns_res_query(res, argv[1], DNS_T_A, DNS_C_IN, 1, &error)))
3460 				panic("dns_res_query: %s", so_strerror(error));
3461 
3462 			dns_res_close(res);
3463 
3464 			if (!dns_rr_grep(&rr, 1, dns_rr_i_new(ans, .section = DNS_S_AN, .type = DNS_T_A), ans, &error))
3465 				panic("%s: no A record", argv[1]);
3466 
3467 			if ((error = dns_any_parse(&rd, &rr, ans)))
3468 				panic("%s: %s", argv[1], so_strerror(error));
3469 
3470 			dns_any_print(addr, sizeof addr, &rd, rr.type);
3471 
3472 			free(ans);
3473 
3474 			saddr = sa_aton(addr);
3475 
3476 			if (AF_UNSPEC == sa_family(saddr))
3477 				goto usage;
3478 		}
3479 
3480 		if (argc > 2) {
3481 			*sa_port(saddr, SA_PORT_NONE, NULL) = htons(atoi(argv[2]));
3482 
3483 			printf("[%s]:%hu => %s\n", sa_ntoa(saddr), ntohs(*sa_port(saddr, SA_PORT_NONE, NULL)), sa_ntoa(sa_egress(&egress, sizeof egress, saddr, 0)));
3484 		} else
3485 			printf("%s => %s\n", sa_ntoa(saddr), sa_ntoa(sa_egress(&egress, sizeof egress, saddr, 0)));
3486 	} else if (!strcmp(*argv, "print") && argv[1]) {
3487 		struct sockaddr *saddr = sa_aton(argv[1]);
3488 
3489 		if (AF_UNSPEC == sa_family(saddr))
3490 			goto usage;
3491 
3492 		if (argc > 2) {
3493 			*sa_port(saddr, SA_PORT_NONE, NULL) = htons(atoi(argv[2]));
3494 
3495 			printf("[%s]:%hu\n", sa_ntoa(saddr), ntohs(*sa_port(saddr, SA_PORT_NONE, NULL)));
3496 		} else {
3497 			*sa_port(saddr, SA_PORT_NONE, NULL) = htons(6970);
3498 
3499 			printf("%s\n", sa_ntoa(saddr));
3500 		}
3501 	} else if (!strcmp(*argv, "get") && argv[1]) {
3502 		return httpget(argv[1]);
3503 	} else
3504 		goto usage;
3505 
3506 	return 0;
3507 } /* main() */
3508 
3509 #endif
3510