1 1.1 christos /* 2 1.1.1.2 christos * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1.1.2 christos * Licensed under the OpenSSL license (the "License"). You may not use 5 1.1.1.2 christos * this file except in compliance with the License. You can obtain a copy 6 1.1.1.2 christos * in the file LICENSE in the source distribution or at 7 1.1.1.2 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1.1.2 christos /* socket-related functions used by s_client and s_server */ 11 1.1 christos #include <stdio.h> 12 1.1 christos #include <stdlib.h> 13 1.1 christos #include <string.h> 14 1.1 christos #include <errno.h> 15 1.1 christos #include <signal.h> 16 1.1.1.2 christos #include <openssl/opensslconf.h> 17 1.1 christos 18 1.1 christos /* 19 1.1 christos * With IPv6, it looks like Digital has mixed up the proper order of 20 1.1 christos * recursive header file inclusion, resulting in the compiler complaining 21 1.1 christos * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is 22 1.1 christos * needed to have fileno() declared correctly... So let's define u_int 23 1.1 christos */ 24 1.1 christos #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) 25 1.1 christos # define __U_INT 26 1.1 christos typedef unsigned int u_int; 27 1.1 christos #endif 28 1.1 christos 29 1.1 christos #ifndef OPENSSL_NO_SOCK 30 1.1 christos 31 1.1.1.2 christos # include "apps.h" 32 1.1.1.2 christos # include "s_apps.h" 33 1.1.1.2 christos # include "internal/sockets.h" 34 1.1 christos 35 1.1.1.2 christos # include <openssl/bio.h> 36 1.1.1.2 christos # include <openssl/err.h> 37 1.1 christos 38 1.1.1.2 christos /* Keep track of our peer's address for the cookie callback */ 39 1.1.1.2 christos BIO_ADDR *ourpeer = NULL; 40 1.1 christos 41 1.1.1.2 christos /* 42 1.1.1.2 christos * init_client - helper routine to set up socket communication 43 1.1.1.2 christos * @sock: pointer to storage of resulting socket. 44 1.1.1.2 christos * @host: the host name or path (for AF_UNIX) to connect to. 45 1.1.1.2 christos * @port: the port to connect to (ignored for AF_UNIX). 46 1.1.1.2 christos * @bindhost: source host or path (for AF_UNIX). 47 1.1.1.2 christos * @bindport: source port (ignored for AF_UNIX). 48 1.1.1.2 christos * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or 49 1.1.1.2 christos * AF_UNSPEC 50 1.1.1.2 christos * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM 51 1.1.1.2 christos * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any) 52 1.1.1.2 christos * 53 1.1.1.2 christos * This will create a socket and use it to connect to a host:port, or if 54 1.1.1.2 christos * family == AF_UNIX, to the path found in host. 55 1.1.1.2 christos * 56 1.1.1.2 christos * If the host has more than one address, it will try them one by one until 57 1.1.1.2 christos * a successful connection is established. The resulting socket will be 58 1.1.1.2 christos * found in *sock on success, it will be given INVALID_SOCKET otherwise. 59 1.1.1.2 christos * 60 1.1.1.2 christos * Returns 1 on success, 0 on failure. 61 1.1.1.2 christos */ 62 1.1.1.2 christos int init_client(int *sock, const char *host, const char *port, 63 1.1.1.2 christos const char *bindhost, const char *bindport, 64 1.1.1.2 christos int family, int type, int protocol) 65 1.1.1.2 christos { 66 1.1.1.2 christos BIO_ADDRINFO *res = NULL; 67 1.1.1.2 christos BIO_ADDRINFO *bindaddr = NULL; 68 1.1.1.2 christos const BIO_ADDRINFO *ai = NULL; 69 1.1.1.2 christos const BIO_ADDRINFO *bi = NULL; 70 1.1.1.2 christos int found = 0; 71 1.1.1.2 christos int ret; 72 1.1 christos 73 1.1.1.2 christos if (BIO_sock_init() != 1) 74 1.1.1.2 christos return 0; 75 1.1 christos 76 1.1.1.2 christos ret = BIO_lookup_ex(host, port, BIO_LOOKUP_CLIENT, family, type, protocol, 77 1.1.1.2 christos &res); 78 1.1.1.2 christos if (ret == 0) { 79 1.1.1.2 christos ERR_print_errors(bio_err); 80 1.1.1.2 christos return 0; 81 1.1 christos } 82 1.1 christos 83 1.1.1.2 christos if (bindhost != NULL || bindport != NULL) { 84 1.1.1.2 christos ret = BIO_lookup_ex(bindhost, bindport, BIO_LOOKUP_CLIENT, 85 1.1.1.2 christos family, type, protocol, &bindaddr); 86 1.1.1.2 christos if (ret == 0) { 87 1.1.1.2 christos ERR_print_errors (bio_err); 88 1.1.1.2 christos goto out; 89 1.1 christos } 90 1.1 christos } 91 1.1 christos 92 1.1.1.2 christos ret = 0; 93 1.1.1.2 christos for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) { 94 1.1.1.2 christos /* Admittedly, these checks are quite paranoid, we should not get 95 1.1.1.2 christos * anything in the BIO_ADDRINFO chain that we haven't 96 1.1.1.2 christos * asked for. */ 97 1.1.1.2 christos OPENSSL_assert((family == AF_UNSPEC 98 1.1.1.2 christos || family == BIO_ADDRINFO_family(ai)) 99 1.1.1.2 christos && (type == 0 || type == BIO_ADDRINFO_socktype(ai)) 100 1.1.1.2 christos && (protocol == 0 101 1.1.1.2 christos || protocol == BIO_ADDRINFO_protocol(ai))); 102 1.1.1.2 christos 103 1.1.1.2 christos if (bindaddr != NULL) { 104 1.1.1.2 christos for (bi = bindaddr; bi != NULL; bi = BIO_ADDRINFO_next(bi)) { 105 1.1.1.2 christos if (BIO_ADDRINFO_family(bi) == BIO_ADDRINFO_family(ai)) 106 1.1.1.2 christos break; 107 1.1.1.2 christos } 108 1.1.1.2 christos if (bi == NULL) 109 1.1.1.2 christos continue; 110 1.1.1.2 christos ++found; 111 1.1 christos } 112 1.1 christos 113 1.1.1.2 christos *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai), 114 1.1.1.2 christos BIO_ADDRINFO_protocol(ai), 0); 115 1.1.1.2 christos if (*sock == INVALID_SOCKET) { 116 1.1.1.2 christos /* Maybe the kernel doesn't support the socket family, even if 117 1.1.1.2 christos * BIO_lookup() added it in the returned result... 118 1.1.1.2 christos */ 119 1.1.1.2 christos continue; 120 1.1.1.2 christos } 121 1.1 christos 122 1.1.1.2 christos if (bi != NULL) { 123 1.1.1.2 christos if (!BIO_bind(*sock, BIO_ADDRINFO_address(bi), 124 1.1.1.2 christos BIO_SOCK_REUSEADDR)) { 125 1.1.1.2 christos BIO_closesocket(*sock); 126 1.1.1.2 christos *sock = INVALID_SOCKET; 127 1.1.1.2 christos break; 128 1.1.1.2 christos } 129 1.1.1.2 christos } 130 1.1 christos 131 1.1.1.2 christos #ifndef OPENSSL_NO_SCTP 132 1.1.1.2 christos if (protocol == IPPROTO_SCTP) { 133 1.1.1.2 christos /* 134 1.1.1.2 christos * For SCTP we have to set various options on the socket prior to 135 1.1.1.2 christos * connecting. This is done automatically by BIO_new_dgram_sctp(). 136 1.1.1.2 christos * We don't actually need the created BIO though so we free it again 137 1.1.1.2 christos * immediately. 138 1.1.1.2 christos */ 139 1.1.1.2 christos BIO *tmpbio = BIO_new_dgram_sctp(*sock, BIO_NOCLOSE); 140 1.1 christos 141 1.1.1.2 christos if (tmpbio == NULL) { 142 1.1.1.2 christos ERR_print_errors(bio_err); 143 1.1.1.2 christos return 0; 144 1.1 christos } 145 1.1.1.2 christos BIO_free(tmpbio); 146 1.1 christos } 147 1.1.1.2 christos #endif 148 1.1.1.2 christos 149 1.1.1.2 christos if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), 150 1.1.1.2 christos BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) { 151 1.1.1.2 christos BIO_closesocket(*sock); 152 1.1.1.2 christos *sock = INVALID_SOCKET; 153 1.1.1.2 christos continue; 154 1.1.1.2 christos } 155 1.1.1.2 christos 156 1.1.1.2 christos /* Success, don't try any more addresses */ 157 1.1.1.2 christos break; 158 1.1.1.2 christos } 159 1.1.1.2 christos 160 1.1.1.2 christos if (*sock == INVALID_SOCKET) { 161 1.1.1.2 christos if (bindaddr != NULL && !found) { 162 1.1.1.2 christos BIO_printf(bio_err, "Can't bind %saddress for %s%s%s\n", 163 1.1.1.2 christos BIO_ADDRINFO_family(res) == AF_INET6 ? "IPv6 " : 164 1.1.1.2 christos BIO_ADDRINFO_family(res) == AF_INET ? "IPv4 " : 165 1.1.1.2 christos BIO_ADDRINFO_family(res) == AF_UNIX ? "unix " : "", 166 1.1.1.2 christos bindhost != NULL ? bindhost : "", 167 1.1.1.2 christos bindport != NULL ? ":" : "", 168 1.1.1.2 christos bindport != NULL ? bindport : ""); 169 1.1.1.2 christos ERR_clear_error(); 170 1.1.1.2 christos ret = 0; 171 1.1.1.2 christos } 172 1.1.1.2 christos ERR_print_errors(bio_err); 173 1.1.1.2 christos } else { 174 1.1.1.2 christos /* Remove any stale errors from previous connection attempts */ 175 1.1.1.2 christos ERR_clear_error(); 176 1.1.1.2 christos ret = 1; 177 1.1.1.2 christos } 178 1.1.1.2 christos out: 179 1.1.1.2 christos if (bindaddr != NULL) { 180 1.1.1.2 christos BIO_ADDRINFO_free (bindaddr); 181 1.1 christos } 182 1.1.1.2 christos BIO_ADDRINFO_free(res); 183 1.1.1.2 christos return ret; 184 1.1 christos } 185 1.1 christos 186 1.1.1.2 christos /* 187 1.1.1.2 christos * do_server - helper routine to perform a server operation 188 1.1.1.2 christos * @accept_sock: pointer to storage of resulting socket. 189 1.1.1.2 christos * @host: the host name or path (for AF_UNIX) to connect to. 190 1.1.1.2 christos * @port: the port to connect to (ignored for AF_UNIX). 191 1.1.1.2 christos * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or 192 1.1.1.2 christos * AF_UNSPEC 193 1.1.1.2 christos * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM 194 1.1.1.2 christos * @cb: pointer to a function that receives the accepted socket and 195 1.1.1.2 christos * should perform the communication with the connecting client. 196 1.1.1.2 christos * @context: pointer to memory that's passed verbatim to the cb function. 197 1.1.1.2 christos * @naccept: number of times an incoming connect should be accepted. If -1, 198 1.1.1.2 christos * unlimited number. 199 1.1.1.2 christos * 200 1.1.1.2 christos * This will create a socket and use it to listen to a host:port, or if 201 1.1.1.2 christos * family == AF_UNIX, to the path found in host, then start accepting 202 1.1.1.2 christos * incoming connections and run cb on the resulting socket. 203 1.1.1.2 christos * 204 1.1.1.2 christos * 0 on failure, something other on success. 205 1.1.1.2 christos */ 206 1.1.1.2 christos int do_server(int *accept_sock, const char *host, const char *port, 207 1.1.1.2 christos int family, int type, int protocol, do_server_cb cb, 208 1.1.1.2 christos unsigned char *context, int naccept, BIO *bio_s_out) 209 1.1 christos { 210 1.1.1.2 christos int asock = 0; 211 1.1.1.2 christos int sock; 212 1.1.1.2 christos int i; 213 1.1.1.2 christos BIO_ADDRINFO *res = NULL; 214 1.1.1.2 christos const BIO_ADDRINFO *next; 215 1.1.1.2 christos int sock_family, sock_type, sock_protocol, sock_port; 216 1.1.1.2 christos const BIO_ADDR *sock_address; 217 1.1.1.2 christos int sock_family_fallback = AF_UNSPEC; 218 1.1.1.2 christos const BIO_ADDR *sock_address_fallback = NULL; 219 1.1.1.2 christos int sock_options = BIO_SOCK_REUSEADDR; 220 1.1 christos int ret = 0; 221 1.1 christos 222 1.1.1.2 christos if (BIO_sock_init() != 1) 223 1.1.1.2 christos return 0; 224 1.1 christos 225 1.1.1.2 christos if (!BIO_lookup_ex(host, port, BIO_LOOKUP_SERVER, family, type, protocol, 226 1.1.1.2 christos &res)) { 227 1.1.1.2 christos ERR_print_errors(bio_err); 228 1.1.1.2 christos return 0; 229 1.1 christos } 230 1.1 christos 231 1.1.1.2 christos /* Admittedly, these checks are quite paranoid, we should not get 232 1.1.1.2 christos * anything in the BIO_ADDRINFO chain that we haven't asked for */ 233 1.1.1.2 christos OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res)) 234 1.1.1.2 christos && (type == 0 || type == BIO_ADDRINFO_socktype(res)) 235 1.1.1.2 christos && (protocol == 0 || protocol == BIO_ADDRINFO_protocol(res))); 236 1.1.1.2 christos 237 1.1.1.2 christos sock_family = BIO_ADDRINFO_family(res); 238 1.1.1.2 christos sock_type = BIO_ADDRINFO_socktype(res); 239 1.1.1.2 christos sock_protocol = BIO_ADDRINFO_protocol(res); 240 1.1.1.2 christos sock_address = BIO_ADDRINFO_address(res); 241 1.1.1.2 christos next = BIO_ADDRINFO_next(res); 242 1.1.1.2 christos if (sock_family == AF_INET6) 243 1.1.1.2 christos sock_options |= BIO_SOCK_V6_ONLY; 244 1.1.1.2 christos if (next != NULL 245 1.1.1.2 christos && BIO_ADDRINFO_socktype(next) == sock_type 246 1.1.1.2 christos && BIO_ADDRINFO_protocol(next) == sock_protocol) { 247 1.1.1.2 christos if (sock_family == AF_INET 248 1.1.1.2 christos && BIO_ADDRINFO_family(next) == AF_INET6) { 249 1.1.1.2 christos /* In case AF_INET6 is returned but not supported by the 250 1.1.1.2 christos * kernel, retry with the first detected address family */ 251 1.1.1.2 christos sock_family_fallback = sock_family; 252 1.1.1.2 christos sock_address_fallback = sock_address; 253 1.1.1.2 christos sock_family = AF_INET6; 254 1.1.1.2 christos sock_address = BIO_ADDRINFO_address(next); 255 1.1.1.2 christos } else if (sock_family == AF_INET6 256 1.1.1.2 christos && BIO_ADDRINFO_family(next) == AF_INET) { 257 1.1.1.2 christos sock_options &= ~BIO_SOCK_V6_ONLY; 258 1.1 christos } 259 1.1 christos } 260 1.1 christos 261 1.1.1.2 christos asock = BIO_socket(sock_family, sock_type, sock_protocol, 0); 262 1.1.1.2 christos if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) { 263 1.1.1.2 christos asock = BIO_socket(sock_family_fallback, sock_type, sock_protocol, 0); 264 1.1.1.2 christos sock_address = sock_address_fallback; 265 1.1.1.2 christos } 266 1.1.1.2 christos if (asock == INVALID_SOCKET 267 1.1.1.2 christos || !BIO_listen(asock, sock_address, sock_options)) { 268 1.1.1.2 christos BIO_ADDRINFO_free(res); 269 1.1.1.2 christos ERR_print_errors(bio_err); 270 1.1.1.2 christos if (asock != INVALID_SOCKET) 271 1.1.1.2 christos BIO_closesocket(asock); 272 1.1 christos goto end; 273 1.1 christos } 274 1.1 christos 275 1.1.1.2 christos #ifndef OPENSSL_NO_SCTP 276 1.1.1.2 christos if (protocol == IPPROTO_SCTP) { 277 1.1.1.2 christos /* 278 1.1.1.2 christos * For SCTP we have to set various options on the socket prior to 279 1.1.1.2 christos * accepting. This is done automatically by BIO_new_dgram_sctp(). 280 1.1.1.2 christos * We don't actually need the created BIO though so we free it again 281 1.1.1.2 christos * immediately. 282 1.1.1.2 christos */ 283 1.1.1.2 christos BIO *tmpbio = BIO_new_dgram_sctp(asock, BIO_NOCLOSE); 284 1.1.1.2 christos 285 1.1.1.2 christos if (tmpbio == NULL) { 286 1.1.1.2 christos BIO_closesocket(asock); 287 1.1.1.2 christos ERR_print_errors(bio_err); 288 1.1.1.2 christos goto end; 289 1.1.1.2 christos } 290 1.1.1.2 christos BIO_free(tmpbio); 291 1.1.1.2 christos } 292 1.1.1.2 christos #endif 293 1.1 christos 294 1.1.1.2 christos sock_port = BIO_ADDR_rawport(sock_address); 295 1.1 christos 296 1.1.1.2 christos BIO_ADDRINFO_free(res); 297 1.1.1.2 christos res = NULL; 298 1.1 christos 299 1.1.1.2 christos if (sock_port == 0) { 300 1.1.1.2 christos /* dynamically allocated port, report which one */ 301 1.1.1.2 christos union BIO_sock_info_u info; 302 1.1.1.2 christos char *hostname = NULL; 303 1.1.1.2 christos char *service = NULL; 304 1.1.1.2 christos int success = 0; 305 1.1.1.2 christos 306 1.1.1.2 christos if ((info.addr = BIO_ADDR_new()) != NULL 307 1.1.1.2 christos && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info) 308 1.1.1.2 christos && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL 309 1.1.1.2 christos && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL 310 1.1.1.2 christos && BIO_printf(bio_s_out, 311 1.1.1.2 christos strchr(hostname, ':') == NULL 312 1.1.1.2 christos ? /* IPv4 */ "ACCEPT %s:%s\n" 313 1.1.1.2 christos : /* IPv6 */ "ACCEPT [%s]:%s\n", 314 1.1.1.2 christos hostname, service) > 0) 315 1.1.1.2 christos success = 1; 316 1.1.1.2 christos 317 1.1.1.2 christos (void)BIO_flush(bio_s_out); 318 1.1.1.2 christos OPENSSL_free(hostname); 319 1.1.1.2 christos OPENSSL_free(service); 320 1.1.1.2 christos BIO_ADDR_free(info.addr); 321 1.1.1.2 christos if (!success) { 322 1.1.1.2 christos BIO_closesocket(asock); 323 1.1.1.2 christos ERR_print_errors(bio_err); 324 1.1.1.2 christos goto end; 325 1.1 christos } 326 1.1.1.2 christos } else { 327 1.1.1.2 christos (void)BIO_printf(bio_s_out, "ACCEPT\n"); 328 1.1.1.2 christos (void)BIO_flush(bio_s_out); 329 1.1 christos } 330 1.1 christos 331 1.1.1.2 christos if (accept_sock != NULL) 332 1.1.1.2 christos *accept_sock = asock; 333 1.1.1.2 christos for (;;) { 334 1.1.1.2 christos char sink[64]; 335 1.1.1.2 christos struct timeval timeout; 336 1.1.1.2 christos fd_set readfds; 337 1.1 christos 338 1.1.1.2 christos if (type == SOCK_STREAM) { 339 1.1.1.2 christos BIO_ADDR_free(ourpeer); 340 1.1.1.2 christos ourpeer = BIO_ADDR_new(); 341 1.1.1.2 christos if (ourpeer == NULL) { 342 1.1.1.2 christos BIO_closesocket(asock); 343 1.1.1.2 christos ERR_print_errors(bio_err); 344 1.1.1.2 christos goto end; 345 1.1.1.2 christos } 346 1.1.1.2 christos do { 347 1.1.1.2 christos sock = BIO_accept_ex(asock, ourpeer, 0); 348 1.1.1.2 christos } while (sock < 0 && BIO_sock_should_retry(sock)); 349 1.1.1.2 christos if (sock < 0) { 350 1.1.1.2 christos ERR_print_errors(bio_err); 351 1.1.1.2 christos BIO_closesocket(asock); 352 1.1 christos break; 353 1.1.1.2 christos } 354 1.1.1.2 christos BIO_set_tcp_ndelay(sock, 1); 355 1.1.1.2 christos i = (*cb)(sock, type, protocol, context); 356 1.1.1.2 christos 357 1.1.1.2 christos /* 358 1.1.1.2 christos * If we ended with an alert being sent, but still with data in the 359 1.1.1.2 christos * network buffer to be read, then calling BIO_closesocket() will 360 1.1.1.2 christos * result in a TCP-RST being sent. On some platforms (notably 361 1.1.1.2 christos * Windows) then this will result in the peer immediately abandoning 362 1.1.1.2 christos * the connection including any buffered alert data before it has 363 1.1.1.2 christos * had a chance to be read. Shutting down the sending side first, 364 1.1.1.2 christos * and then closing the socket sends TCP-FIN first followed by 365 1.1.1.2 christos * TCP-RST. This seems to allow the peer to read the alert data. 366 1.1.1.2 christos */ 367 1.1.1.2 christos shutdown(sock, 1); /* SHUT_WR */ 368 1.1.1.2 christos /* 369 1.1.1.2 christos * We just said we have nothing else to say, but it doesn't mean 370 1.1.1.2 christos * that the other side has nothing. It's even recommended to 371 1.1.1.2 christos * consume incoming data. [In testing context this ensures that 372 1.1.1.2 christos * alerts are passed on...] 373 1.1.1.2 christos */ 374 1.1.1.2 christos timeout.tv_sec = 0; 375 1.1.1.2 christos timeout.tv_usec = 500000; /* some extreme round-trip */ 376 1.1.1.2 christos do { 377 1.1.1.2 christos FD_ZERO(&readfds); 378 1.1.1.2 christos openssl_fdset(sock, &readfds); 379 1.1.1.2 christos } while (select(sock + 1, &readfds, NULL, NULL, &timeout) > 0 380 1.1.1.2 christos && readsocket(sock, sink, sizeof(sink)) > 0); 381 1.1.1.2 christos 382 1.1.1.2 christos BIO_closesocket(sock); 383 1.1.1.2 christos } else { 384 1.1.1.2 christos i = (*cb)(asock, type, protocol, context); 385 1.1 christos } 386 1.1.1.2 christos 387 1.1.1.2 christos if (naccept != -1) 388 1.1.1.2 christos naccept--; 389 1.1.1.2 christos if (i < 0 || naccept == 0) { 390 1.1.1.2 christos BIO_closesocket(asock); 391 1.1.1.2 christos ret = i; 392 1.1.1.2 christos break; 393 1.1 christos } 394 1.1 christos } 395 1.1.1.2 christos end: 396 1.1.1.2 christos # ifdef AF_UNIX 397 1.1.1.2 christos if (family == AF_UNIX) 398 1.1.1.2 christos unlink(host); 399 1.1.1.2 christos # endif 400 1.1.1.2 christos BIO_ADDR_free(ourpeer); 401 1.1.1.2 christos ourpeer = NULL; 402 1.1.1.2 christos return ret; 403 1.1 christos } 404 1.1 christos 405 1.1.1.2 christos #endif /* OPENSSL_NO_SOCK */ 406