1--- a/apps/s_apps.h
2+++ b/apps/s_apps.h
3@@ -151,7 +151,7 @@ typedef fd_mask fd_set;
4 #define PORT_STR        "4433"
5 #define PROTOCOL        "tcp"
6
7-int do_server(int port, int type, int *ret,
8+int do_server(char *port, int type, int *ret,
9               int (*cb) (char *hostname, int s, int stype,
10                          unsigned char *context), unsigned char *context,
11               int naccept);
12@@ -167,11 +167,10 @@ int ssl_print_point_formats(BIO *out, SSL *s);
13 int ssl_print_curves(BIO *out, SSL *s, int noshared);
14 #endif
15 int ssl_print_tmp_key(BIO *out, SSL *s);
16-int init_client(int *sock, char *server, int port, int type);
17+int init_client(int *sock, char *server, char *port, int type);
18 int should_retry(int i);
19 int extract_port(char *str, short *port_ptr);
20-int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
21-                      short *p);
22+int extract_host_port(char *str, char **host_ptr, char **port_ptr);
23
24 long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp,
25                                    int argi, long argl, long ret);
26
27--- a/apps/s_client.c
28+++ b/apps/s_client.c
29@@ -678,7 +678,7 @@ int MAIN(int argc, char **argv)
30     int cbuf_len, cbuf_off;
31     int sbuf_len, sbuf_off;
32     fd_set readfds, writefds;
33-    short port = PORT;
34+    char *port_str = PORT_STR;
35     char *http_proxy_str = NULL, *connect_str = NULL;
36     int full_log = 1;
37     char *host = SSL_HOST_NAME;
38@@ -803,9 +803,7 @@ int MAIN(int argc, char **argv)
39         } else if (strcmp(*argv, "-port") == 0) {
40             if (--argc < 1)
41                 goto bad;
42-            port = atoi(*(++argv));
43-            if (port == 0)
44-                goto bad;
45+	    port_str = *(++argv);
46         } else if (strcmp(*argv, "-connect") == 0) {
47             if (--argc < 1)
48                 goto bad;
49@@ -1156,10 +1154,10 @@ int MAIN(int argc, char **argv)
50     }
51
52     if (http_proxy_str) {
53-		if (!extract_host_port(http_proxy_str, &host, NULL, &port))
54+		if (!extract_host_port(http_proxy_str, &host, &port_str))
55 			goto bad;
56 	} else if (connect_str) {
57-        if (!extract_host_port(connect_str, &host, NULL, &port))
58+	if (!extract_host_port(connect_str, &host, &port_str))
59             goto bad;
60     }
61
62@@ -1456,7 +1454,7 @@ int MAIN(int argc, char **argv)
63
64  re_start:
65
66-    if (init_client(&s, host, port, socket_type) == 0) {
67+    if (init_client(&s, host, port_str, socket_type) == 0) {
68         BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
69         SHUTDOWN(s);
70         goto end;
71
72--- a/apps/s_server.c
73+++ b/apps/s_server.c
74@@ -1093,7 +1093,7 @@ int MAIN(int argc, char *argv[])
75 {
76     X509_VERIFY_PARAM *vpm = NULL;
77     int badarg = 0;
78-    short port = PORT;
79+    char *port_str = PORT_STR;
80     char *CApath = NULL, *CAfile = NULL;
81     char *chCApath = NULL, *chCAfile = NULL;
82     char *vfyCApath = NULL, *vfyCAfile = NULL;
83@@ -1180,7 +1180,8 @@ int MAIN(int argc, char *argv[])
84         if ((strcmp(*argv, "-port") == 0) || (strcmp(*argv, "-accept") == 0)) {
85             if (--argc < 1)
86                 goto bad;
87-            if (!extract_port(*(++argv), &port))
88+            port_str = *(++argv);
89+            if (port_str == NULL || *port_str == '\0')
90                 goto bad;
91         } else if (strcmp(*argv, "-naccept") == 0) {
92             if (--argc < 1)
93@@ -2056,13 +2057,13 @@ int MAIN(int argc, char *argv[])
94     BIO_printf(bio_s_out, "ACCEPT\n");
95     (void)BIO_flush(bio_s_out);
96     if (rev)
97-        do_server(port, socket_type, &accept_socket, rev_body, context,
98+        do_server(port_str, socket_type, &accept_socket, rev_body, context,
99                   naccept);
100     else if (www)
101-        do_server(port, socket_type, &accept_socket, www_body, context,
102+        do_server(port_str, socket_type, &accept_socket, www_body, context,
103                   naccept);
104     else
105-        do_server(port, socket_type, &accept_socket, sv_body, context,
106+        do_server(port_str, socket_type, &accept_socket, sv_body, context,
107                   naccept);
108     print_stats(bio_s_out, ctx);
109     ret = 0;
110
111--- a/apps/s_socket.c
112+++ b/apps/s_socket.c
113@@ -106,9 +106,7 @@ static struct hostent *GetHostByName(char *name);
114 static void ssl_sock_cleanup(void);
115 # endif
116 static int ssl_sock_init(void);
117-static int init_client_ip(int *sock, unsigned char ip[4], int port, int type);
118-static int init_server(int *sock, int port, int type);
119-static int init_server_long(int *sock, int port, char *ip, int type);
120+static int init_server(int *sock, char *port, int type);
121 static int do_accept(int acc_sock, int *sock, char **host);
122 static int host_ip(char *str, unsigned char ip[4]);
123
124@@ -231,65 +229,66 @@ static int ssl_sock_init(void)
125     return (1);
126 }
127
128-int init_client(int *sock, char *host, int port, int type)
129+int init_client(int *sock, char *host, char *port, int type)
130 {
131-    unsigned char ip[4];
132-
133-    memset(ip, '\0', sizeof ip);
134-    if (!host_ip(host, &(ip[0])))
135-        return 0;
136-    return init_client_ip(sock, ip, port, type);
137-}
138-
139-static int init_client_ip(int *sock, unsigned char ip[4], int port, int type)
140-{
141-    unsigned long addr;
142-    struct sockaddr_in them;
143-    int s, i;
144+    struct addrinfo *res, *res0, hints;
145+    char *failed_call = NULL;
146+    int s;
147+    int e;
148
149     if (!ssl_sock_init())
150         return (0);
151
152-    memset((char *)&them, 0, sizeof(them));
153-    them.sin_family = AF_INET;
154-    them.sin_port = htons((unsigned short)port);
155-    addr = (unsigned long)
156-        ((unsigned long)ip[0] << 24L) |
157-        ((unsigned long)ip[1] << 16L) |
158-        ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]);
159-    them.sin_addr.s_addr = htonl(addr);
160-
161-    if (type == SOCK_STREAM)
162-        s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
163-    else                        /* ( type == SOCK_DGRAM) */
164-        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
165+    memset(&hints, '\0', sizeof(hints));
166+    hints.ai_socktype = type;
167+    hints.ai_flags = AI_ADDRCONFIG;
168
169-    if (s == INVALID_SOCKET) {
170-        perror("socket");
171+    e = getaddrinfo(host, port, &hints, &res);
172+    if (e) {
173+        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(e));
174+        if (e == EAI_SYSTEM)
175+            perror("getaddrinfo");
176         return (0);
177     }
178+
179+    res0 = res;
180+    while (res) {
181+        s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
182+        if (s == INVALID_SOCKET) {
183+            failed_call = "socket";
184+            goto nextres;
185+        }
186 # if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
187-    if (type == SOCK_STREAM) {
188-        i = 0;
189-        i = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof(i));
190-        if (i < 0) {
191-            closesocket(s);
192-            perror("keepalive");
193-            return (0);
194+        if (type == SOCK_STREAM) {
195+            int i = 0;
196+            i = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
197+                           (char *)&i, sizeof(i));
198+            if (i < 0) {
199+                failed_call = "keepalive";
200+                goto nextres;
201+            }
202         }
203-    }
204 # endif
205+        if (connect(s, (struct sockaddr *)res->ai_addr, res->ai_addrlen) == 0) {
206+            freeaddrinfo(res0);
207+            *sock = s;
208+            return (1);
209+        }
210
211-    if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1) {
212-        closesocket(s);
213-        perror("connect");
214-        return (0);
215+        failed_call = "socket";
216+ nextres:
217+        if (s != INVALID_SOCKET)
218+            close(s);
219+        res = res->ai_next;
220     }
221-    *sock = s;
222-    return (1);
223+    freeaddrinfo(res0);
224+    closesocket(s);
225+
226+    perror(failed_call);
227+    return (0);
228 }
229
230-int do_server(int port, int type, int *ret,
231+int do_server(char *port, int type, int *ret,
232               int (*cb) (char *hostname, int s, int stype,
233                          unsigned char *context), unsigned char *context,
234               int naccept)
235@@ -328,69 +327,89 @@ int do_server(int port, int type, int *ret,
236     }
237 }
238
239-static int init_server_long(int *sock, int port, char *ip, int type)
240+static int init_server(int *sock, char *port, int type)
241 {
242-    int ret = 0;
243-    struct sockaddr_in server;
244-    int s = -1;
245+    struct addrinfo *res, *res0 = NULL, hints;
246+    char *failed_call = NULL;
247+    int s = INVALID_SOCKET;
248+    int e;
249
250     if (!ssl_sock_init())
251         return (0);
252
253-    memset((char *)&server, 0, sizeof(server));
254-    server.sin_family = AF_INET;
255-    server.sin_port = htons((unsigned short)port);
256-    if (ip == NULL)
257-        server.sin_addr.s_addr = INADDR_ANY;
258-    else
259-/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
260-# ifndef BIT_FIELD_LIMITS
261-        memcpy(&server.sin_addr.s_addr, ip, 4);
262-# else
263-        memcpy(&server.sin_addr, ip, 4);
264-# endif
265-
266-    if (type == SOCK_STREAM)
267-        s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
268-    else                        /* type == SOCK_DGRAM */
269-        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
270+    memset(&hints, '\0', sizeof(hints));
271+    hints.ai_family = AF_INET6;
272+ tryipv4:
273+    hints.ai_socktype = type;
274+    hints.ai_flags = AI_PASSIVE;
275+
276+    e = getaddrinfo(NULL, port, &hints, &res);
277+    if (e) {
278+        if (hints.ai_family == AF_INET) {
279+            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(e));
280+            if (e == EAI_SYSTEM)
281+                perror("getaddrinfo");
282+            return (0);
283+        } else
284+            res = NULL;
285+    }
286
287-    if (s == INVALID_SOCKET)
288-        goto err;
289+    res0 = res;
290+    while (res) {
291+        s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
292+        if (s == INVALID_SOCKET) {
293+            failed_call = "socket";
294+            goto nextres;
295+        }
296+        if (hints.ai_family == AF_INET6) {
297+            int j = 0;
298+            setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&j, sizeof j);
299+        }
300 # if defined SOL_SOCKET && defined SO_REUSEADDR
301-    {
302-        int j = 1;
303-        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&j, sizeof j);
304-    }
305-# endif
306-    if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) {
307-# ifndef OPENSSL_SYS_WINDOWS
308-        perror("bind");
309+        {
310+            int j = 1;
311+            setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&j, sizeof j);
312+        }
313 # endif
314-        goto err;
315+
316+        if (bind(s, (struct sockaddr *)res->ai_addr, res->ai_addrlen) == -1) {
317+            failed_call = "bind";
318+            goto nextres;
319+        }
320+        if (type == SOCK_STREAM && listen(s, 128) == -1) {
321+            failed_call = "listen";
322+            goto nextres;
323+        }
324+
325+        *sock = s;
326+        return (1);
327+
328+ nextres:
329+        if (s != INVALID_SOCKET)
330+            close(s);
331+        res = res->ai_next;
332     }
333-    /* Make it 128 for linux */
334-    if (type == SOCK_STREAM && listen(s, 128) == -1)
335-        goto err;
336-    *sock = s;
337-    ret = 1;
338- err:
339-    if ((ret == 0) && (s != -1)) {
340-        SHUTDOWN(s);
341+    if (res0)
342+        freeaddrinfo(res0);
343+
344+    if (s == INVALID_SOCKET) {
345+        if (hints.ai_family == AF_INET6) {
346+            hints.ai_family = AF_INET;
347+            goto tryipv4;
348+        }
349+        perror("socket");
350+        return (0);
351     }
352-    return (ret);
353-}
354
355-static int init_server(int *sock, int port, int type)
356-{
357-    return (init_server_long(sock, port, NULL, type));
358+    perror(failed_call);
359+    return (0);
360 }
361
362 static int do_accept(int acc_sock, int *sock, char **host)
363 {
364+    static struct sockaddr_storage from;
365+    char buffer[NI_MAXHOST];
366     int ret;
367-    struct hostent *h1, *h2;
368-    static struct sockaddr_in from;
369     int len;
370 /*      struct linger ling; */
371
372@@ -432,134 +451,60 @@ static int do_accept(int acc_sock, int *sock, char **host)
373     ling.l_onoff=1;
374     ling.l_linger=0;
375     i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
376-    if (i < 0) { perror("linger"); return(0); }
377+    if (i < 0) { closesocket(ret); perror("linger"); return(0); }
378     i=0;
379     i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
380-    if (i < 0) { perror("keepalive"); return(0); }
381+    if (i < 0) { closesocket(ret); perror("keepalive"); return(0); }
382 */
383
384     if (host == NULL)
385         goto end;
386-# ifndef BIT_FIELD_LIMITS
387-    /* I should use WSAAsyncGetHostByName() under windows */
388-    h1 = gethostbyaddr((char *)&from.sin_addr.s_addr,
389-                       sizeof(from.sin_addr.s_addr), AF_INET);
390-# else
391-    h1 = gethostbyaddr((char *)&from.sin_addr,
392-                       sizeof(struct in_addr), AF_INET);
393-# endif
394-    if (h1 == NULL) {
395-        BIO_printf(bio_err, "bad gethostbyaddr\n");
396+
397+    if (getnameinfo((struct sockaddr *)&from, sizeof(from),
398+                    buffer, sizeof(buffer), NULL, 0, 0)) {
399+        BIO_printf(bio_err, "getnameinfo failed\n");
400         *host = NULL;
401         /* return(0); */
402     } else {
403-        if ((*host = (char *)OPENSSL_malloc(strlen(h1->h_name) + 1)) == NULL) {
404+        if ((*host = (char *)OPENSSL_malloc(strlen(buffer) + 1)) == NULL) {
405             perror("OPENSSL_malloc");
406             closesocket(ret);
407             return (0);
408         }
409-        BUF_strlcpy(*host, h1->h_name, strlen(h1->h_name) + 1);
410-
411-        h2 = GetHostByName(*host);
412-        if (h2 == NULL) {
413-            BIO_printf(bio_err, "gethostbyname failure\n");
414-            closesocket(ret);
415-            return (0);
416-        }
417-        if (h2->h_addrtype != AF_INET) {
418-            BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n");
419-            closesocket(ret);
420-            return (0);
421-        }
422+        strcpy(*host, buffer);
423     }
424  end:
425     *sock = ret;
426     return (1);
427 }
428
429-int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
430-                      short *port_ptr)
431+int extract_host_port(char *str, char **host_ptr, char **port_ptr)
432 {
433-    char *h, *p;
434-
435-    h = str;
436-    p = strchr(str, ':');
437+    char *h, *p, *x;
438+
439+    x = h = str;
440+    if (*h == '[') {
441+        h++;
442+        p = strchr(h, ']');
443+        if (p == NULL) {
444+            BIO_printf(bio_err, "no ending bracket for IPv6 address\n");
445+            return (0);
446+        }
447+        *(p++) = '\0';
448+        x = p;
449+    }
450+    p = strchr(x, ':');
451     if (p == NULL) {
452         BIO_printf(bio_err, "no port defined\n");
453         return (0);
454     }
455     *(p++) = '\0';
456
457-    if ((ip != NULL) && !host_ip(str, ip))
458-        goto err;
459     if (host_ptr != NULL)
460         *host_ptr = h;
461+    if (port_ptr != NULL)
462+        *port_ptr = p;
463
464-    if (!extract_port(p, port_ptr))
465-        goto err;
466-    return (1);
467- err:
468-    return (0);
469-}
470-
471-static int host_ip(char *str, unsigned char ip[4])
472-{
473-    unsigned int in[4];
474-    int i;
475-
476-    if (sscanf(str, "%u.%u.%u.%u", &(in[0]), &(in[1]), &(in[2]), &(in[3])) ==
477-        4) {
478-        for (i = 0; i < 4; i++)
479-            if (in[i] > 255) {
480-                BIO_printf(bio_err, "invalid IP address\n");
481-                goto err;
482-            }
483-        ip[0] = in[0];
484-        ip[1] = in[1];
485-        ip[2] = in[2];
486-        ip[3] = in[3];
487-    } else {                    /* do a gethostbyname */
488-        struct hostent *he;
489-
490-        if (!ssl_sock_init())
491-            return (0);
492-
493-        he = GetHostByName(str);
494-        if (he == NULL) {
495-            BIO_printf(bio_err, "gethostbyname failure\n");
496-            goto err;
497-        }
498-        /* cast to short because of win16 winsock definition */
499-        if ((short)he->h_addrtype != AF_INET) {
500-            BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n");
501-            return (0);
502-        }
503-        ip[0] = he->h_addr_list[0][0];
504-        ip[1] = he->h_addr_list[0][1];
505-        ip[2] = he->h_addr_list[0][2];
506-        ip[3] = he->h_addr_list[0][3];
507-    }
508-    return (1);
509- err:
510-    return (0);
511-}
512-
513-int extract_port(char *str, short *port_ptr)
514-{
515-    int i;
516-    struct servent *s;
517-
518-    i = atoi(str);
519-    if (i != 0)
520-        *port_ptr = (unsigned short)i;
521-    else {
522-        s = getservbyname(str, "tcp");
523-        if (s == NULL) {
524-            BIO_printf(bio_err, "getservbyname failure for %s\n", str);
525-            return (0);
526-        }
527-        *port_ptr = ntohs((unsigned short)s->s_port);
528-    }
529     return (1);
530 }
531
532