Temporary pragma to have GCC quiet down about deprecated functions
[openssl.git] / crypto / bio / b_sock.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <errno.h>
61 #include "bio_lcl.h"
62 #if defined(NETWARE_CLIB)
63 # include <sys/ioctl.h>
64 NETDB_DEFINE_CONTEXT
65 #endif
66 #ifndef OPENSSL_NO_SOCK
67 # include <openssl/dso.h>
68 # define SOCKET_PROTOCOL IPPROTO_TCP
69 # ifdef SO_MAXCONN
70 #  define MAX_LISTEN  SO_MAXCONN
71 # elif defined(SOMAXCONN)
72 #  define MAX_LISTEN  SOMAXCONN
73 # else
74 #  define MAX_LISTEN  32
75 # endif
76 # if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
77 static int wsa_init_done = 0;
78 # endif
79
80 /*
81  * WSAAPI specifier is required to make indirect calls to run-time
82  * linked WinSock 2 functions used in this module, to be specific
83  * [get|free]addrinfo and getnameinfo. This is because WinSock uses
84  * uses non-C calling convention, __stdcall vs. __cdecl, on x86
85  * Windows. On non-WinSock platforms WSAAPI needs to be void.
86  */
87 # ifndef WSAAPI
88 #  define WSAAPI
89 # endif
90
91 /*
92  * We are currently using deprecated functions here, and GCC warns
93  * us about them, but since we know, we don't want to hear it.
94  */
95 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
96
97 # if OPENSSL_API_COMPAT < 0x10100000L
98 static int get_ip(const char *str, unsigned char *ip);
99 int BIO_get_host_ip(const char *str, unsigned char *ip)
100 {
101     int i;
102     int err = 1;
103     int locked = 0;
104     struct hostent *he;
105
106     i = get_ip(str, ip);
107     if (i < 0) {
108         BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_INVALID_IP_ADDRESS);
109         goto err;
110     }
111
112     /*
113      * At this point, we have something that is most probably correct in some
114      * way, so let's init the socket.
115      */
116     if (BIO_sock_init() != 1)
117         return 0;               /* don't generate another error code here */
118
119     /*
120      * If the string actually contained an IP address, we need not do
121      * anything more
122      */
123     if (i > 0)
124         return (1);
125
126     /* do a gethostbyname */
127     CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
128     locked = 1;
129     he = BIO_gethostbyname(str);
130     if (he == NULL) {
131         BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_BAD_HOSTNAME_LOOKUP);
132         goto err;
133     }
134
135     if (he->h_addrtype != AF_INET) {
136         BIOerr(BIO_F_BIO_GET_HOST_IP,
137                BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
138         goto err;
139     }
140     for (i = 0; i < 4; i++)
141         ip[i] = he->h_addr_list[0][i];
142     err = 0;
143
144  err:
145     if (locked)
146         CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
147     if (err) {
148         ERR_add_error_data(2, "host=", str);
149         return 0;
150     } else
151         return 1;
152 }
153
154 int BIO_get_port(const char *str, unsigned short *port_ptr)
155 {
156     int i;
157     struct servent *s;
158
159     if (str == NULL) {
160         BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED);
161         return (0);
162     }
163     i = atoi(str);
164     if (i != 0)
165         *port_ptr = (unsigned short)i;
166     else {
167         CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
168         /*
169          * Note: under VMS with SOCKETSHR, it seems like the first parameter
170          * is 'char *', instead of 'const char *'
171          */
172 # ifndef CONST_STRICT
173         s = getservbyname((char *)str, "tcp");
174 # else
175         s = getservbyname(str, "tcp");
176 # endif
177         if (s != NULL)
178             *port_ptr = ntohs((unsigned short)s->s_port);
179         CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
180         if (s == NULL) {
181             if (strcmp(str, "http") == 0)
182                 *port_ptr = 80;
183             else if (strcmp(str, "telnet") == 0)
184                 *port_ptr = 23;
185             else if (strcmp(str, "socks") == 0)
186                 *port_ptr = 1080;
187             else if (strcmp(str, "https") == 0)
188                 *port_ptr = 443;
189             else if (strcmp(str, "ssl") == 0)
190                 *port_ptr = 443;
191             else if (strcmp(str, "ftp") == 0)
192                 *port_ptr = 21;
193             else if (strcmp(str, "gopher") == 0)
194                 *port_ptr = 70;
195             else {
196                 SYSerr(SYS_F_GETSERVBYNAME, get_last_socket_error());
197                 ERR_add_error_data(3, "service='", str, "'");
198                 return (0);
199             }
200         }
201     }
202     return (1);
203 }
204 # endif
205
206 int BIO_sock_error(int sock)
207 {
208     int j, i;
209     union {
210         size_t s;
211         int i;
212     } size;
213
214     /* heuristic way to adapt for platforms that expect 64-bit optlen */
215     size.s = 0, size.i = sizeof(j);
216     /*
217      * Note: under Windows the third parameter is of type (char *) whereas
218      * under other systems it is (void *) if you don't have a cast it will
219      * choke the compiler: if you do have a cast then you can either go for
220      * (char *) or (void *).
221      */
222     i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, (void *)&size);
223     if (i < 0)
224         return (1);
225     else
226         return (j);
227 }
228
229 # if OPENSSL_API_COMPAT < 0x10100000L
230 struct hostent *BIO_gethostbyname(const char *name)
231 {
232     /*
233      * Caching gethostbyname() results forever is wrong, so we have to let
234      * the true gethostbyname() worry about this
235      */
236 # if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__))
237     return gethostbyname((char *)name);
238 # else
239     return gethostbyname(name);
240 # endif
241 }
242 # endif
243
244 int BIO_sock_init(void)
245 {
246 # ifdef OPENSSL_SYS_WINDOWS
247     static struct WSAData wsa_state;
248
249     if (!wsa_init_done) {
250         int err;
251
252         wsa_init_done = 1;
253         memset(&wsa_state, 0, sizeof(wsa_state));
254         /*
255          * Not making wsa_state available to the rest of the code is formally
256          * wrong. But the structures we use are [beleived to be] invariable
257          * among Winsock DLLs, while API availability is [expected to be]
258          * probed at run-time with DSO_global_lookup.
259          */
260         if (WSAStartup(0x0202, &wsa_state) != 0) {
261             err = WSAGetLastError();
262             SYSerr(SYS_F_WSASTARTUP, err);
263             BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP);
264             return (-1);
265         }
266     }
267 # endif                         /* OPENSSL_SYS_WINDOWS */
268 # ifdef WATT32
269     extern int _watt_do_exit;
270     _watt_do_exit = 0;          /* don't make sock_init() call exit() */
271     if (sock_init())
272         return (-1);
273 # endif
274
275 # if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
276     WORD wVerReq;
277     WSADATA wsaData;
278     int err;
279
280     if (!wsa_init_done) {
281         wsa_init_done = 1;
282         wVerReq = MAKEWORD(2, 0);
283         err = WSAStartup(wVerReq, &wsaData);
284         if (err != 0) {
285             SYSerr(SYS_F_WSASTARTUP, err);
286             BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP);
287             return (-1);
288         }
289     }
290 # endif
291
292     return (1);
293 }
294
295 void BIO_sock_cleanup(void)
296 {
297 # ifdef OPENSSL_SYS_WINDOWS
298     if (wsa_init_done) {
299         wsa_init_done = 0;
300         WSACleanup();
301     }
302 # elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
303     if (wsa_init_done) {
304         wsa_init_done = 0;
305         WSACleanup();
306     }
307 # endif
308 }
309
310 # if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000
311
312 int BIO_socket_ioctl(int fd, long type, void *arg)
313 {
314     int i;
315
316 #  ifdef __DJGPP__
317     i = ioctlsocket(fd, type, (char *)arg);
318 #  else
319 #   if defined(OPENSSL_SYS_VMS)
320     /*-
321      * 2011-02-18 SMS.
322      * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
323      * observe that all the consumers pass in an "unsigned long *",
324      * so we arrange a local copy with a short pointer, and use
325      * that, instead.
326      */
327 #    if __INITIAL_POINTER_SIZE == 64
328 #     define ARG arg_32p
329 #     pragma pointer_size save
330 #     pragma pointer_size 32
331     unsigned long arg_32;
332     unsigned long *arg_32p;
333 #     pragma pointer_size restore
334     arg_32p = &arg_32;
335     arg_32 = *((unsigned long *)arg);
336 #    else                       /* __INITIAL_POINTER_SIZE == 64 */
337 #     define ARG arg
338 #    endif                      /* __INITIAL_POINTER_SIZE == 64 [else] */
339 #   else                        /* defined(OPENSSL_SYS_VMS) */
340 #    define ARG arg
341 #   endif                       /* defined(OPENSSL_SYS_VMS) [else] */
342
343     i = ioctlsocket(fd, type, ARG);
344 #  endif                        /* __DJGPP__ */
345     if (i < 0)
346         SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error());
347     return (i);
348 }
349 # endif                         /* __VMS_VER */
350
351 # if OPENSSL_API_COMPAT < 0x10100000L
352 /*
353  * The reason I have implemented this instead of using sscanf is because
354  * Visual C 1.52c gives an unresolved external when linking a DLL :-(
355  */
356 static int get_ip(const char *str, unsigned char ip[4])
357 {
358     unsigned int tmp[4];
359     int num = 0, c, ok = 0;
360
361     tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
362
363     for (;;) {
364         c = *(str++);
365         if ((c >= '0') && (c <= '9')) {
366             ok = 1;
367             tmp[num] = tmp[num] * 10 + c - '0';
368             if (tmp[num] > 255)
369                 return (0);
370         } else if (c == '.') {
371             if (!ok)
372                 return (-1);
373             if (num == 3)
374                 return (0);
375             num++;
376             ok = 0;
377         } else if (c == '\0' && (num == 3) && ok)
378             break;
379         else
380             return (0);
381     }
382     ip[0] = tmp[0];
383     ip[1] = tmp[1];
384     ip[2] = tmp[2];
385     ip[3] = tmp[3];
386     return (1);
387 }
388
389 int BIO_get_accept_socket(char *host, int bind_mode)
390 {
391     int ret = 0;
392     union {
393         struct sockaddr sa;
394         struct sockaddr_in sa_in;
395 # if OPENSSL_USE_IPV6
396         struct sockaddr_in6 sa_in6;
397 # endif
398     } server, client;
399     int s = (int)INVALID_SOCKET, cs, addrlen;
400     unsigned char ip[4];
401     unsigned short port;
402     char *str = NULL, *e;
403     char *h, *p;
404     unsigned long l;
405     int err_num;
406
407     if (BIO_sock_init() != 1)
408         return ((int)INVALID_SOCKET);
409
410     if ((str = OPENSSL_strdup(host)) == NULL)
411         return ((int)INVALID_SOCKET);
412
413     h = p = NULL;
414     h = str;
415     for (e = str; *e; e++) {
416         if (*e == ':') {
417             p = e;
418         } else if (*e == '/') {
419             *e = '\0';
420             break;
421         }
422     }
423     if (p)
424         *p++ = '\0';            /* points at last ':', '::port' is special
425                                  * [see below] */
426     else
427         p = h, h = NULL;
428
429 # ifdef EAI_FAMILY
430     do {
431         static union {
432             void *p;
433             int (WSAAPI *f) (const char *, const char *,
434                              const struct addrinfo *, struct addrinfo **);
435         } p_getaddrinfo = {
436             NULL
437         };
438         static union {
439             void *p;
440             void (WSAAPI *f) (struct addrinfo *);
441         } p_freeaddrinfo = {
442             NULL
443         };
444         struct addrinfo *res, hint;
445
446         if (p_getaddrinfo.p == NULL) {
447             if ((p_getaddrinfo.p = DSO_global_lookup("getaddrinfo")) == NULL
448                 || (p_freeaddrinfo.p =
449                     DSO_global_lookup("freeaddrinfo")) == NULL)
450                 p_getaddrinfo.p = (void *)-1;
451         }
452         if (p_getaddrinfo.p == (void *)-1)
453             break;
454
455         /*
456          * '::port' enforces IPv6 wildcard listener. Some OSes, e.g. Solaris,
457          * default to IPv6 without any hint. Also note that commonly IPv6
458          * wildchard socket can service IPv4 connections just as well...
459          */
460         memset(&hint, 0, sizeof(hint));
461         hint.ai_flags = AI_PASSIVE;
462         if (h) {
463             if (strchr(h, ':')) {
464                 if (h[1] == '\0')
465                     h = NULL;
466 #  if OPENSSL_USE_IPV6
467                 hint.ai_family = AF_INET6;
468 #  else
469                 h = NULL;
470 #  endif
471             } else if (h[0] == '*' && h[1] == '\0') {
472                 hint.ai_family = AF_INET;
473                 h = NULL;
474             }
475         }
476
477         if ((*p_getaddrinfo.f) (h, p, &hint, &res))
478             break;
479
480         addrlen = res->ai_addrlen <= sizeof(server) ?
481             res->ai_addrlen : sizeof(server);
482         memcpy(&server, res->ai_addr, addrlen);
483
484         (*p_freeaddrinfo.f) (res);
485         goto again;
486     } while (0);
487 # endif
488
489     if (!BIO_get_port(p, &port))
490         goto err;
491
492     memset(&server, 0, sizeof(server));
493     server.sa_in.sin_family = AF_INET;
494     server.sa_in.sin_port = htons(port);
495     addrlen = sizeof(server.sa_in);
496
497     if (h == NULL || strcmp(h, "*") == 0)
498         server.sa_in.sin_addr.s_addr = INADDR_ANY;
499     else {
500         if (!BIO_get_host_ip(h, &(ip[0])))
501             goto err;
502         l = (unsigned long)
503             ((unsigned long)ip[0] << 24L) |
504             ((unsigned long)ip[1] << 16L) |
505             ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]);
506         server.sa_in.sin_addr.s_addr = htonl(l);
507     }
508
509  again:
510     s = socket(server.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL);
511     if (s == (int)INVALID_SOCKET) {
512         SYSerr(SYS_F_SOCKET, get_last_socket_error());
513         ERR_add_error_data(3, "port='", host, "'");
514         BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
515         goto err;
516     }
517 # ifdef SO_REUSEADDR
518     if (bind_mode == BIO_BIND_REUSEADDR) {
519         int i = 1;
520
521         ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i));
522         bind_mode = BIO_BIND_NORMAL;
523     }
524 # endif
525     if (bind(s, &server.sa, addrlen) == -1) {
526 # ifdef SO_REUSEADDR
527         err_num = get_last_socket_error();
528         if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
529 #  ifdef OPENSSL_SYS_WINDOWS
530             /*
531              * Some versions of Windows define EADDRINUSE to a dummy value.
532              */
533             (err_num == WSAEADDRINUSE))
534 #  else
535             (err_num == EADDRINUSE))
536 #  endif
537         {
538             client = server;
539             if (h == NULL || strcmp(h, "*") == 0) {
540 #  if OPENSSL_USE_IPV6
541                 if (client.sa.sa_family == AF_INET6) {
542                     memset(&client.sa_in6.sin6_addr, 0,
543                            sizeof(client.sa_in6.sin6_addr));
544                     client.sa_in6.sin6_addr.s6_addr[15] = 1;
545                 } else
546 #  endif
547                 if (client.sa.sa_family == AF_INET) {
548                     client.sa_in.sin_addr.s_addr = htonl(0x7F000001);
549                 } else
550                     goto err;
551             }
552             cs = socket(client.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL);
553             if (cs != (int)INVALID_SOCKET) {
554                 int ii;
555                 ii = connect(cs, &client.sa, addrlen);
556                 closesocket(cs);
557                 if (ii == (int)INVALID_SOCKET) {
558                     bind_mode = BIO_BIND_REUSEADDR;
559                     closesocket(s);
560                     goto again;
561                 }
562                 /* else error */
563             }
564             /* else error */
565         }
566 # endif
567         SYSerr(SYS_F_BIND, err_num);
568         ERR_add_error_data(3, "port='", host, "'");
569         BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_BIND_SOCKET);
570         goto err;
571     }
572     if (listen(s, MAX_LISTEN) == -1) {
573         SYSerr(SYS_F_BIND, get_last_socket_error());
574         ERR_add_error_data(3, "port='", host, "'");
575         BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_LISTEN_SOCKET);
576         goto err;
577     }
578     ret = 1;
579  err:
580     OPENSSL_free(str);
581     if ((ret == 0) && (s != (int)INVALID_SOCKET)) {
582         closesocket(s);
583         s = (int)INVALID_SOCKET;
584     }
585     return (s);
586 }
587
588 int BIO_accept(int sock, char **addr)
589 {
590     int ret = (int)INVALID_SOCKET;
591     unsigned long l;
592     unsigned short port;
593     char *p;
594
595     struct {
596         /*
597          * As for following union. Trouble is that there are platforms
598          * that have socklen_t and there are platforms that don't, on
599          * some platforms socklen_t is int and on some size_t. So what
600          * one can do? One can cook #ifdef spaghetti, which is nothing
601          * but masochistic. Or one can do union between int and size_t.
602          * One naturally does it primarily for 64-bit platforms where
603          * sizeof(int) != sizeof(size_t). But would it work? Note that
604          * if size_t member is initialized to 0, then later int member
605          * assignment naturally does the job on little-endian platforms
606          * regardless accept's expectations! What about big-endians?
607          * If accept expects int*, then it works, and if size_t*, then
608          * length value would appear as unreasonably large. But this
609          * won't prevent it from filling in the address structure. The
610          * trouble of course would be if accept returns more data than
611          * actual buffer can accomodate and overwrite stack... That's
612          * where early OPENSSL_assert comes into picture. Besides, the
613          * only 64-bit big-endian platform found so far that expects
614          * size_t* is HP-UX, where stack grows towards higher address.
615          * <appro>
616          */
617         union {
618             size_t s;
619             int i;
620         } len;
621         union {
622             struct sockaddr sa;
623             struct sockaddr_in sa_in;
624 # if OPENSSL_USE_IPV6
625             struct sockaddr_in6 sa_in6;
626 # endif
627         } from;
628     } sa;
629
630     sa.len.s = 0;
631     sa.len.i = sizeof(sa.from);
632     memset(&sa.from, 0, sizeof(sa.from));
633     ret = accept(sock, &sa.from.sa, (void *)&sa.len);
634     if (sizeof(sa.len.i) != sizeof(sa.len.s) && sa.len.i == 0) {
635         OPENSSL_assert(sa.len.s <= sizeof(sa.from));
636         sa.len.i = (int)sa.len.s;
637         /* use sa.len.i from this point */
638     }
639     if (ret == (int)INVALID_SOCKET) {
640         if (BIO_sock_should_retry(ret))
641             return -2;
642         SYSerr(SYS_F_ACCEPT, get_last_socket_error());
643         BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR);
644         goto end;
645     }
646
647     if (addr == NULL)
648         goto end;
649
650 # ifdef EAI_FAMILY
651     do {
652         char h[NI_MAXHOST], s[NI_MAXSERV];
653         size_t nl;
654         static union {
655             void *p;
656             int (WSAAPI *f) (const struct sockaddr *, size_t /* socklen_t */ ,
657                              char *, size_t, char *, size_t, int);
658         } p_getnameinfo = {
659             NULL
660         };
661         /*
662          * 2nd argument to getnameinfo is specified to be socklen_t.
663          * Unfortunately there is a number of environments where socklen_t is
664          * not defined. As it's passed by value, it's safe to pass it as
665          * size_t... <appro>
666          */
667
668         if (p_getnameinfo.p == NULL) {
669             if ((p_getnameinfo.p = DSO_global_lookup("getnameinfo")) == NULL)
670                 p_getnameinfo.p = (void *)-1;
671         }
672         if (p_getnameinfo.p == (void *)-1)
673             break;
674
675         if ((*p_getnameinfo.f) (&sa.from.sa, sa.len.i, h, sizeof(h), s,
676                                 sizeof(s), NI_NUMERICHOST | NI_NUMERICSERV))
677             break;
678         nl = strlen(h) + strlen(s) + 2;
679         p = *addr;
680         if (p)
681             *p = '\0';
682         p = OPENSSL_realloc(p, nl);
683         if (p == NULL) {
684             BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE);
685             goto end;
686         }
687         *addr = p;
688         BIO_snprintf(*addr, nl, "%s:%s", h, s);
689         goto end;
690     } while (0);
691 # endif
692     if (sa.from.sa.sa_family != AF_INET)
693         goto end;
694     l = ntohl(sa.from.sa_in.sin_addr.s_addr);
695     port = ntohs(sa.from.sa_in.sin_port);
696     if (*addr == NULL) {
697         if ((p = OPENSSL_malloc(24)) == NULL) {
698             BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE);
699             goto end;
700         }
701         *addr = p;
702     }
703     BIO_snprintf(*addr, 24, "%d.%d.%d.%d:%d",
704                  (unsigned char)(l >> 24L) & 0xff,
705                  (unsigned char)(l >> 16L) & 0xff,
706                  (unsigned char)(l >> 8L) & 0xff,
707                  (unsigned char)(l) & 0xff, port);
708  end:
709     return (ret);
710 }
711 # endif
712
713 int BIO_set_tcp_ndelay(int s, int on)
714 {
715     int ret = 0;
716 # if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
717     int opt;
718
719 #  ifdef SOL_TCP
720     opt = SOL_TCP;
721 #  else
722 #   ifdef IPPROTO_TCP
723     opt = IPPROTO_TCP;
724 #   endif
725 #  endif
726
727     ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
728 # endif
729     return (ret == 0);
730 }
731
732 int BIO_socket_nbio(int s, int mode)
733 {
734     int ret = -1;
735     int l;
736
737     l = mode;
738 # ifdef FIONBIO
739     ret = BIO_socket_ioctl(s, FIONBIO, &l);
740 # endif
741     return (ret == 0);
742 }
743
744 int BIO_sock_info(int sock,
745                   enum BIO_sock_info_type type, union BIO_sock_info_u *info)
746 {
747     switch (type) {
748     case BIO_SOCK_INFO_ADDRESS:
749         {
750             socklen_t addr_len;
751             int ret = 0;
752             addr_len = sizeof(*info->addr);
753             ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
754                               &addr_len);
755             if (ret == -1) {
756                 SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error());
757                 BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR);
758                 return 0;
759             }
760             if (addr_len > sizeof(*info->addr)) {
761                 BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
762                 return 0;
763             }
764         }
765         break;
766     default:
767         BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE);
768         return 0;
769     }
770     return 1;
771 }
772
773 #endif