[BACK]Return to s_socket.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/s_socket.c, Revision 1.8

1.8     ! lteo        1: /* $OpenBSD: s_socket.c,v 1.7 2015/07/20 03:22:25 doug Exp $ */
1.1       jsing       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 <sys/socket.h>
                     60:
                     61: #include <netinet/in.h>
                     62:
                     63: #include <errno.h>
                     64: #include <netdb.h>
                     65: #include <stdio.h>
                     66: #include <stdlib.h>
                     67: #include <string.h>
                     68: #include <unistd.h>
                     69:
                     70: #include "apps.h"
                     71:
                     72: #include <openssl/ssl.h>
                     73:
                     74: #include "s_apps.h"
                     75:
                     76: static int init_server(int *sock, int port, int type);
                     77: static int init_server_long(int *sock, int port, char *ip, int type);
                     78: static int do_accept(int acc_sock, int *sock, char **host);
                     79:
                     80: int
                     81: init_client(int *sock, char *host, char *port, int type, int af)
                     82: {
                     83:        struct addrinfo hints, *ai_top, *ai;
1.6       doug       84:        int i, s = -1;
1.1       jsing      85:
                     86:        memset(&hints, '\0', sizeof(hints));
                     87:        hints.ai_family = af;
                     88:        hints.ai_socktype = type;
                     89:
                     90:        if ((i = getaddrinfo(host, port, &hints, &ai_top)) != 0) {
                     91:                BIO_printf(bio_err, "getaddrinfo: %s\n", gai_strerror(i));
                     92:                return (0);
                     93:        }
                     94:        if (ai_top == NULL || ai_top->ai_addr == NULL) {
                     95:                BIO_printf(bio_err, "getaddrinfo returned no addresses\n");
                     96:                if (ai_top != NULL) {
                     97:                        freeaddrinfo(ai_top);
                     98:                }
                     99:                return (0);
                    100:        }
                    101:        for (ai = ai_top; ai != NULL; ai = ai->ai_next) {
                    102:                s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
                    103:                if (s == -1) {
                    104:                        continue;
                    105:                }
                    106:                if (type == SOCK_STREAM) {
                    107:                        i = 0;
                    108:                        i = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
                    109:                            (char *) &i, sizeof(i));
                    110:                        if (i < 0) {
                    111:                                perror("keepalive");
1.5       beck      112:                                goto out;
1.1       jsing     113:                        }
                    114:                }
                    115:                if ((i = connect(s, ai->ai_addr, ai->ai_addrlen)) == 0) {
                    116:                        *sock = s;
                    117:                        freeaddrinfo(ai_top);
                    118:                        return (1);
                    119:                }
                    120:                close(s);
1.6       doug      121:                s = -1;
1.1       jsing     122:        }
                    123:
                    124:        perror("connect");
1.5       beck      125: out:
1.6       doug      126:        if (s != -1)
                    127:                close(s);
1.1       jsing     128:        freeaddrinfo(ai_top);
                    129:        return (0);
                    130: }
                    131:
                    132: int
                    133: do_server(int port, int type, int *ret,
                    134:     int (*cb) (char *hostname, int s, unsigned char *context),
                    135:     unsigned char *context)
                    136: {
                    137:        int sock;
                    138:        char *name = NULL;
                    139:        int accept_socket = 0;
                    140:        int i;
                    141:
                    142:        if (!init_server(&accept_socket, port, type))
                    143:                return (0);
                    144:
                    145:        if (ret != NULL) {
                    146:                *ret = accept_socket;
                    147:                /* return(1); */
                    148:        }
                    149:        for (;;) {
                    150:                if (type == SOCK_STREAM) {
                    151:                        if (do_accept(accept_socket, &sock, &name) == 0) {
                    152:                                shutdown(accept_socket, SHUT_RD);
                    153:                                close(accept_socket);
                    154:                                return (0);
                    155:                        }
                    156:                } else
                    157:                        sock = accept_socket;
                    158:                i = (*cb) (name, sock, context);
                    159:                free(name);
                    160:                if (type == SOCK_STREAM) {
                    161:                        shutdown(sock, SHUT_RDWR);
                    162:                        close(sock);
                    163:                }
                    164:                if (i < 0) {
                    165:                        shutdown(accept_socket, SHUT_RDWR);
                    166:                        close(accept_socket);
                    167:                        return (i);
                    168:                }
                    169:        }
                    170: }
                    171:
                    172: static int
                    173: init_server_long(int *sock, int port, char *ip, int type)
                    174: {
                    175:        int ret = 0;
                    176:        struct sockaddr_in server;
                    177:        int s = -1;
                    178:
                    179:        memset((char *) &server, 0, sizeof(server));
                    180:        server.sin_family = AF_INET;
                    181:        server.sin_port = htons((unsigned short) port);
                    182:        if (ip == NULL)
                    183:                server.sin_addr.s_addr = INADDR_ANY;
                    184:        else
                    185:                memcpy(&server.sin_addr.s_addr, ip, 4);
                    186:
                    187:        if (type == SOCK_STREAM)
1.8     ! lteo      188:                s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1.1       jsing     189:        else                    /* type == SOCK_DGRAM */
                    190:                s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                    191:
                    192:        if (s == -1)
                    193:                goto err;
                    194: #if defined SOL_SOCKET && defined SO_REUSEADDR
                    195:        {
                    196:                int j = 1;
1.7       doug      197:                if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                    198:                    (void *) &j, sizeof j) == -1) {
                    199:                        perror("setsockopt");
                    200:                        goto err;
                    201:                }
1.1       jsing     202:        }
                    203: #endif
                    204:        if (bind(s, (struct sockaddr *) & server, sizeof(server)) == -1) {
                    205:                perror("bind");
                    206:                goto err;
                    207:        }
                    208:        /* Make it 128 for linux */
                    209:        if (type == SOCK_STREAM && listen(s, 128) == -1)
                    210:                goto err;
                    211:        *sock = s;
                    212:        ret = 1;
                    213: err:
                    214:        if ((ret == 0) && (s != -1)) {
                    215:                shutdown(s, SHUT_RD);
                    216:                close(s);
                    217:        }
                    218:        return (ret);
                    219: }
                    220:
                    221: static int
                    222: init_server(int *sock, int port, int type)
                    223: {
                    224:        return (init_server_long(sock, port, NULL, type));
                    225: }
                    226:
                    227: static int
                    228: do_accept(int acc_sock, int *sock, char **host)
                    229: {
                    230:        int ret;
                    231:        struct hostent *h1, *h2;
                    232:        static struct sockaddr_in from;
                    233:        socklen_t len;
                    234: /*     struct linger ling; */
                    235:
                    236: redoit:
                    237:
                    238:        memset((char *) &from, 0, sizeof(from));
                    239:        len = sizeof(from);
                    240:        ret = accept(acc_sock, (struct sockaddr *) & from, &len);
                    241:        if (ret == -1) {
                    242:                if (errno == EINTR) {
                    243:                        /* check_timeout(); */
                    244:                        goto redoit;
                    245:                }
                    246:                fprintf(stderr, "errno=%d ", errno);
                    247:                perror("accept");
                    248:                return (0);
                    249:        }
                    250: /*
                    251:        ling.l_onoff=1;
                    252:        ling.l_linger=0;
                    253:        i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
                    254:        if (i < 0) { perror("linger"); return(0); }
                    255:        i=0;
                    256:        i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
                    257:        if (i < 0) { perror("keepalive"); return(0); }
                    258: */
                    259:
                    260:        if (host == NULL)
                    261:                goto end;
                    262:        h1 = gethostbyaddr((char *) &from.sin_addr.s_addr,
                    263:            sizeof(from.sin_addr.s_addr), AF_INET);
                    264:        if (h1 == NULL) {
                    265:                BIO_printf(bio_err, "bad gethostbyaddr\n");
                    266:                *host = NULL;
                    267:                /* return(0); */
                    268:        } else {
                    269:                if ((*host = strdup(h1->h_name)) == NULL) {
                    270:                        perror("strdup");
                    271:                        close(ret);
                    272:                        return (0);
                    273:                }
                    274:
                    275:                h2 = gethostbyname(*host);
                    276:                if (h2 == NULL) {
                    277:                        BIO_printf(bio_err, "gethostbyname failure\n");
                    278:                        close(ret);
                    279:                        return (0);
                    280:                }
                    281:                if (h2->h_addrtype != AF_INET) {
                    282:                        BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n");
                    283:                        close(ret);
                    284:                        return (0);
                    285:                }
                    286:        }
                    287:
                    288: end:
                    289:        *sock = ret;
                    290:        return (1);
                    291: }
                    292:
                    293: int
                    294: extract_host_port(char *str, char **host_ptr, unsigned char *ip,
                    295:     char **port_ptr)
                    296: {
                    297:        char *h, *p;
                    298:
                    299:        h = str;
                    300:        p = strrchr(str, '/');  /* IPv6 host/port */
                    301:        if (p == NULL) {
                    302:                p = strrchr(str, ':');
                    303:        }
                    304:        if (p == NULL) {
                    305:                BIO_printf(bio_err, "no port defined\n");
                    306:                return (0);
                    307:        }
                    308:        *(p++) = '\0';
                    309:
                    310:        if (host_ptr != NULL)
                    311:                *host_ptr = h;
                    312:
                    313:        if (port_ptr != NULL && p != NULL && *p != '\0')
                    314:                *port_ptr = p;
                    315:
                    316:        return (1);
                    317: }
                    318:
                    319: int
                    320: extract_port(char *str, short *port_ptr)
                    321: {
                    322:        int i;
                    323:        const char *errstr;
                    324:        struct servent *s;
                    325:
                    326:        i = strtonum(str, 1, 65535, &errstr);
                    327:        if (!errstr) {
                    328:                *port_ptr = (unsigned short) i;
                    329:        } else {
                    330:                s = getservbyname(str, "tcp");
                    331:                if (s == NULL) {
                    332:                        BIO_printf(bio_err, "getservbyname failure for %s\n", str);
                    333:                        return (0);
                    334:                }
                    335:                *port_ptr = ntohs((unsigned short) s->s_port);
                    336:        }
                    337:        return (1);
                    338: }