diff -up openssl-1.0.1h/apps/s_apps.h.ipv6-apps openssl-1.0.1h/apps/s_apps.h --- openssl-1.0.1h/apps/s_apps.h.ipv6-apps 2014-06-05 14:33:38.515668750 +0200 +++ openssl-1.0.1h/apps/s_apps.h 2014-06-05 14:33:38.540669335 +0200 @@ -148,7 +148,7 @@ typedef fd_mask fd_set; #define PORT_STR "4433" #define PROTOCOL "tcp" -int do_server(int port, int type, int *ret, int (*cb) (char *hostname, int s, unsigned char *context), unsigned char *context); +int do_server(char *port, int type, int *ret, int (*cb) (char *hostname, int s, unsigned char *context), unsigned char *context); #ifdef HEADER_X509_H int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); #endif @@ -156,10 +156,9 @@ int MS_CALLBACK verify_callback(int ok, int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key); #endif -int init_client(int *sock, char *server, int port, int type); +int init_client(int *sock, char *server, char *port, int type); int should_retry(int i); -int extract_port(char *str, short *port_ptr); -int extract_host_port(char *str,char **host_ptr,unsigned char *ip,short *p); +int extract_host_port(char *str,char **host_ptr,char **port_ptr); long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret); diff -up openssl-1.0.1h/apps/s_client.c.ipv6-apps openssl-1.0.1h/apps/s_client.c --- openssl-1.0.1h/apps/s_client.c.ipv6-apps 2014-06-05 14:33:38.533669171 +0200 +++ openssl-1.0.1h/apps/s_client.c 2014-06-05 14:33:38.540669335 +0200 @@ -567,7 +567,7 @@ int MAIN(int argc, char **argv) int cbuf_len,cbuf_off; int sbuf_len,sbuf_off; fd_set readfds,writefds; - short port=PORT; + char *port_str = PORT_STR; int full_log=1; char *host=SSL_HOST_NAME; char *cert_file=NULL,*key_file=NULL; @@ -668,13 +668,12 @@ int MAIN(int argc, char **argv) else if (strcmp(*argv,"-port") == 0) { if (--argc < 1) goto bad; - port=atoi(*(++argv)); - if (port == 0) goto bad; + port_str= *(++argv); } else if (strcmp(*argv,"-connect") == 0) { if (--argc < 1) goto bad; - if (!extract_host_port(*(++argv),&host,NULL,&port)) + if (!extract_host_port(*(++argv),&host,&port_str)) goto bad; } else if (strcmp(*argv,"-verify") == 0) @@ -1267,7 +1266,7 @@ bad: re_start: - if (init_client(&s,host,port,socket_type) == 0) + if (init_client(&s,host,port_str,socket_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); diff -up openssl-1.0.1h/apps/s_server.c.ipv6-apps openssl-1.0.1h/apps/s_server.c --- openssl-1.0.1h/apps/s_server.c.ipv6-apps 2014-06-05 14:33:38.533669171 +0200 +++ openssl-1.0.1h/apps/s_server.c 2014-06-05 14:33:38.541669358 +0200 @@ -933,7 +933,7 @@ int MAIN(int argc, char *argv[]) { X509_VERIFY_PARAM *vpm = NULL; int badarg = 0; - short port=PORT; + char *port_str = PORT_STR; char *CApath=NULL,*CAfile=NULL; unsigned char *context = NULL; char *dhfile = NULL; @@ -1004,8 +1004,7 @@ int MAIN(int argc, char *argv[]) (strcmp(*argv,"-accept") == 0)) { if (--argc < 1) goto bad; - if (!extract_port(*(++argv),&port)) - goto bad; + port_str= *(++argv); } else if (strcmp(*argv,"-verify") == 0) { @@ -1892,9 +1891,9 @@ bad: BIO_printf(bio_s_out,"ACCEPT\n"); (void)BIO_flush(bio_s_out); if (www) - do_server(port,socket_type,&accept_socket,www_body, context); + do_server(port_str,socket_type,&accept_socket,www_body, context); else - do_server(port,socket_type,&accept_socket,sv_body, context); + do_server(port_str,socket_type,&accept_socket,sv_body, context); print_stats(bio_s_out,ctx); ret=0; end: diff -up openssl-1.0.1h/apps/s_socket.c.ipv6-apps openssl-1.0.1h/apps/s_socket.c --- openssl-1.0.1h/apps/s_socket.c.ipv6-apps 2014-06-05 11:44:33.000000000 +0200 +++ openssl-1.0.1h/apps/s_socket.c 2014-06-05 14:39:53.226442195 +0200 @@ -102,9 +102,7 @@ static struct hostent *GetHostByName(cha static void ssl_sock_cleanup(void); #endif static int ssl_sock_init(void); -static int init_client_ip(int *sock,unsigned char ip[4], int port, int type); -static int init_server(int *sock, int port, int type); -static int init_server_long(int *sock, int port,char *ip, int type); +static int init_server(int *sock, char *port, int type); static int do_accept(int acc_sock, int *sock, char **host); static int host_ip(char *str, unsigned char ip[4]); @@ -234,57 +232,71 @@ static int ssl_sock_init(void) return(1); } -int init_client(int *sock, char *host, int port, int type) +int init_client(int *sock, char *host, char *port, int type) { - unsigned char ip[4]; - - memset(ip, '\0', sizeof ip); - if (!host_ip(host,&(ip[0]))) - return 0; - return init_client_ip(sock,ip,port,type); - } - -static int init_client_ip(int *sock, unsigned char ip[4], int port, int type) - { - unsigned long addr; - struct sockaddr_in them; - int s,i; + struct addrinfo *res, *res0, hints; + char * failed_call = NULL; + int s; + int e; if (!ssl_sock_init()) return(0); - memset((char *)&them,0,sizeof(them)); - them.sin_family=AF_INET; - them.sin_port=htons((unsigned short)port); - addr=(unsigned long) - ((unsigned long)ip[0]<<24L)| - ((unsigned long)ip[1]<<16L)| - ((unsigned long)ip[2]<< 8L)| - ((unsigned long)ip[3]); - them.sin_addr.s_addr=htonl(addr); - - if (type == SOCK_STREAM) - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); - else /* ( type == SOCK_DGRAM) */ - s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); - - if (s == INVALID_SOCKET) { perror("socket"); return(0); } + memset(&hints, '\0', sizeof(hints)); + hints.ai_socktype = type; + hints.ai_flags = AI_ADDRCONFIG; + + e = getaddrinfo(host, port, &hints, &res); + if (e) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(e)); + if (e == EAI_SYSTEM) + perror("getaddrinfo"); + return (0); + } + res0 = res; + while (res) + { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == INVALID_SOCKET) + { + failed_call = "socket"; + goto nextres; + } #if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) if (type == SOCK_STREAM) { - i=0; - i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); - if (i < 0) { closesocket(s); perror("keepalive"); return(0); } + int i=0; + i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE, + (char *)&i,sizeof(i)); + if (i < 0) { + failed_call = "keepalive"; + goto nextres; + } } #endif - - if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1) - { closesocket(s); perror("connect"); return(0); } + if (connect(s,(struct sockaddr *)res->ai_addr, + res->ai_addrlen) == 0) + { + freeaddrinfo(res0); *sock=s; return(1); } -int do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context) + failed_call = "socket"; +nextres: + if (s != INVALID_SOCKET) + close(s); + res = res->ai_next; + } + freeaddrinfo(res0); + closesocket(s); + + perror(failed_call); + return(0); + } + +int do_server(char *port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context) { int sock; char *name = NULL; @@ -322,33 +334,50 @@ int do_server(int port, int type, int *r } } -static int init_server_long(int *sock, int port, char *ip, int type) +static int init_server(int *sock, char *port, int type) { - int ret=0; - struct sockaddr_in server; - int s= -1; + struct addrinfo *res, *res0 = NULL, hints; + char * failed_call = NULL; + int s = INVALID_SOCKET; + int e; if (!ssl_sock_init()) return(0); - memset((char *)&server,0,sizeof(server)); - server.sin_family=AF_INET; - server.sin_port=htons((unsigned short)port); - if (ip == NULL) - server.sin_addr.s_addr=INADDR_ANY; - else -/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */ -#ifndef BIT_FIELD_LIMITS - memcpy(&server.sin_addr.s_addr,ip,4); -#else - memcpy(&server.sin_addr,ip,4); -#endif + memset(&hints, '\0', sizeof(hints)); + hints.ai_family = AF_INET6; +tryipv4: + hints.ai_socktype = type; + hints.ai_flags = AI_PASSIVE; - if (type == SOCK_STREAM) - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); - else /* type == SOCK_DGRAM */ - s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP); + e = getaddrinfo(NULL, port, &hints, &res); + if (e) + { + if (hints.ai_family == AF_INET) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(e)); + if (e == EAI_SYSTEM) + perror("getaddrinfo"); + return (0); + } + else + res = NULL; + } - if (s == INVALID_SOCKET) goto err; + res0 = res; + while (res) + { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == INVALID_SOCKET) + { + failed_call = "socket"; + goto nextres; + } + if (hints.ai_family == AF_INET6) + { + int j = 0; + setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (void *) &j, sizeof j); + } #if defined SOL_SOCKET && defined SO_REUSEADDR { int j = 1; @@ -356,35 +385,49 @@ static int init_server_long(int *sock, i (void *) &j, sizeof j); } #endif - if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) + + if (bind(s,(struct sockaddr *)res->ai_addr, res->ai_addrlen) == -1) { -#ifndef OPENSSL_SYS_WINDOWS - perror("bind"); -#endif - goto err; + failed_call = "bind"; + goto nextres; } - /* Make it 128 for linux */ - if (type==SOCK_STREAM && listen(s,128) == -1) goto err; - *sock=s; - ret=1; -err: - if ((ret == 0) && (s != -1)) + if (type==SOCK_STREAM && listen(s,128) == -1) { - SHUTDOWN(s); + failed_call = "listen"; + goto nextres; } - return(ret); + + *sock=s; + return(1); + +nextres: + if (s != INVALID_SOCKET) + close(s); + res = res->ai_next; } + if (res0) + freeaddrinfo(res0); -static int init_server(int *sock, int port, int type) + if (s == INVALID_SOCKET) { - return(init_server_long(sock, port, NULL, type)); + if (hints.ai_family == AF_INET6) + { + hints.ai_family = AF_INET; + goto tryipv4; + } + perror("socket"); + return(0); + } + + perror(failed_call); + return(0); } static int do_accept(int acc_sock, int *sock, char **host) { + static struct sockaddr_storage from; + char buffer[NI_MAXHOST]; int ret; - struct hostent *h1,*h2; - static struct sockaddr_in from; int len; /* struct linger ling; */ @@ -424,145 +467,66 @@ redoit: ling.l_onoff=1; ling.l_linger=0; i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling)); - if (i < 0) { perror("linger"); return(0); } + if (i < 0) { closesocket(ret); perror("linger"); return(0); } i=0; i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); - if (i < 0) { perror("keepalive"); return(0); } + if (i < 0) { closesocket(ret); perror("keepalive"); return(0); } */ if (host == NULL) goto end; -#ifndef BIT_FIELD_LIMITS - /* I should use WSAAsyncGetHostByName() under windows */ - h1=gethostbyaddr((char *)&from.sin_addr.s_addr, - sizeof(from.sin_addr.s_addr),AF_INET); -#else - h1=gethostbyaddr((char *)&from.sin_addr, - sizeof(struct in_addr),AF_INET); -#endif - if (h1 == NULL) + + if (getnameinfo((struct sockaddr *)&from, sizeof(from), + buffer, sizeof(buffer), + NULL, 0, 0)) { - BIO_printf(bio_err,"bad gethostbyaddr\n"); + BIO_printf(bio_err,"getnameinfo failed\n"); *host=NULL; /* return(0); */ } else { - if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL) + if ((*host=(char *)OPENSSL_malloc(strlen(buffer)+1)) == NULL) { perror("OPENSSL_malloc"); closesocket(ret); return(0); } - BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1); - - h2=GetHostByName(*host); - if (h2 == NULL) - { - BIO_printf(bio_err,"gethostbyname failure\n"); - closesocket(ret); - return(0); - } - if (h2->h_addrtype != AF_INET) - { - BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); - closesocket(ret); - return(0); - } + strcpy(*host, buffer); } end: *sock=ret; return(1); } -int extract_host_port(char *str, char **host_ptr, unsigned char *ip, - short *port_ptr) +int extract_host_port(char *str, char **host_ptr, + char **port_ptr) { - char *h,*p; + char *h,*p,*x; - h=str; - p=strchr(str,':'); + x=h=str; + if (*h == '[') + { + h++; + p=strchr(h,']'); if (p == NULL) { - BIO_printf(bio_err,"no port defined\n"); + BIO_printf(bio_err,"no ending bracket for IPv6 address\n"); return(0); } *(p++)='\0'; - - if ((ip != NULL) && !host_ip(str,ip)) - goto err; - if (host_ptr != NULL) *host_ptr=h; - - if (!extract_port(p,port_ptr)) - goto err; - return(1); -err: - return(0); + x = p; } - -static int host_ip(char *str, unsigned char ip[4]) - { - unsigned int in[4]; - int i; - - if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4) - { - for (i=0; i<4; i++) - if (in[i] > 255) - { - BIO_printf(bio_err,"invalid IP address\n"); - goto err; - } - ip[0]=in[0]; - ip[1]=in[1]; - ip[2]=in[2]; - ip[3]=in[3]; - } - else - { /* do a gethostbyname */ - struct hostent *he; - - if (!ssl_sock_init()) return(0); - - he=GetHostByName(str); - if (he == NULL) - { - BIO_printf(bio_err,"gethostbyname failure\n"); - goto err; - } - /* cast to short because of win16 winsock definition */ - if ((short)he->h_addrtype != AF_INET) + p=strchr(x,':'); + if (p == NULL) { - BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); - return(0); - } - ip[0]=he->h_addr_list[0][0]; - ip[1]=he->h_addr_list[0][1]; - ip[2]=he->h_addr_list[0][2]; - ip[3]=he->h_addr_list[0][3]; - } - return(1); -err: + BIO_printf(bio_err,"no port defined\n"); return(0); } + *(p++)='\0'; -int extract_port(char *str, short *port_ptr) - { - int i; - struct servent *s; + if (host_ptr != NULL) *host_ptr=h; + if (port_ptr != NULL) *port_ptr=p; - i=atoi(str); - if (i != 0) - *port_ptr=(unsigned short)i; - else - { - s=getservbyname(str,"tcp"); - if (s == NULL) - { - BIO_printf(bio_err,"getservbyname failure for %s\n",str); - return(0); - } - *port_ptr=ntohs((unsigned short)s->s_port); - } return(1); }