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