Hi,
This diff changes the s_client and s_server apps to use getaddrinfo
for address parsing rather than manual IPv4 parsing and gethostbyname.
This allows specification of port by name:
openssl s_client -connect bugzilla.mindrot.org:https
But the main point is to support IPv6. You can now specify an IPv6
address explicitly (using '/' as a port separator to avoid ambiguity)
or use DNS names with IPv6 A records listed. s_client gets new -4 and
-6 options to force the issue when a host resolves to both IPv4 and
IPv6 addresses.
diff is against 0.9.8j, it has been in OpenBSD for a couple of years
now.
-d
Index: apps/s_apps.h
===================================================================
RCS file: /cvs/src/lib/libssl/src/apps/s_apps.h,v
retrieving revision 1.1.1.4
retrieving revision 1.8
diff -u -p -r1.1.1.4 -r1.8
--- apps/s_apps.h 6 Sep 2008 12:15:38 -0000 1.1.1.4
+++ apps/s_apps.h 6 Sep 2008 12:20:16 -0000 1.8
@@ -156,10 +156,10 @@ 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 af);
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,unsigned char *ip,char **p);
long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp,
int argi, long argl, long ret);
Index: apps/s_client.c
===================================================================
RCS file: /cvs/src/lib/libssl/src/apps/s_client.c,v
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.8 s_client.c
--- apps/s_client.c 9 Jan 2009 12:13:49 -0000 1.1.1.8
+++ apps/s_client.c 30 Jan 2009 03:45:08 -0000
@@ -109,6 +109,8 @@
*
*/
+#include <sys/types.h>
+#include <netinet/in.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -192,6 +194,8 @@ static void sc_usage(void)
{
BIO_printf(bio_err,"usage: s_client args\n");
BIO_printf(bio_err,"\n");
+ BIO_printf(bio_err," -4 - Force IPv4\n");
+ BIO_printf(bio_err," -6 - Force IPv6\n");
BIO_printf(bio_err," -host host - use -connect instead\n");
BIO_printf(bio_err," -port port - use -connect instead\n");
BIO_printf(bio_err," -connect host:port - who to connect to (default is
%s:%s)\n",SSL_HOST_NAME,PORT_STR);
@@ -289,12 +293,12 @@ int MAIN(int argc, char **argv)
int off=0;
SSL *con=NULL,*con2=NULL;
X509_STORE *store = NULL;
- int s,k,width,state=0;
+ int s,k,width,state=0, af=AF_UNSPEC;
char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL;
int cbuf_len,cbuf_off;
int sbuf_len,sbuf_off;
fd_set readfds,writefds;
- short port=PORT;
+ char *port=PORT_STR;
int full_log=1;
char *host=SSL_HOST_NAME;
char *cert_file=NULL,*key_file=NULL;
@@ -391,8 +395,8 @@ 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= *(++argv);
+ if (port == NULL || *port == '\0') goto bad;
}
else if (strcmp(*argv,"-connect") == 0)
{
@@ -578,6 +582,8 @@ int MAIN(int argc, char **argv)
if (--argc < 1) goto bad;
inrand= *(++argv);
}
+ else if (strcmp(*argv,"-4") == 0) { af = AF_INET;}
+ else if (strcmp(*argv,"-6") == 0) { af = AF_INET6;}
#ifndef OPENSSL_NO_TLSEXT
else if (strcmp(*argv,"-servername") == 0)
{
@@ -795,7 +801,7 @@ bad:
re_start:
- if (init_client(&s,host,port,sock_type) == 0)
+ if (init_client(&s,host,port,sock_type,af) == 0)
{
BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error());
SHUTDOWN(s);
Index: apps/s_socket.c
===================================================================
RCS file: /cvs/src/lib/libssl/src/apps/s_socket.c,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 s_socket.c
--- apps/s_socket.c 6 Sep 2008 12:15:39 -0000 1.1.1.6
+++ apps/s_socket.c 30 Jan 2009 03:45:08 -0000
@@ -96,11 +96,9 @@ 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 do_accept(int acc_sock, int *sock, char **host);
-static int host_ip(char *str, unsigned char ip[4]);
#ifdef OPENSSL_SYS_WIN16
#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
@@ -228,44 +226,33 @@ 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, int af)
{
- unsigned char ip[4];
- short p=0;
-
- if (!host_ip(host,&(ip[0])))
- {
- return(0);
- }
- if (p != 0) port=p;
- 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 hints, *ai_top, *ai;
+ int i, s;
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);
+ memset(&hints, '\0', sizeof(hints));
+ hints.ai_family = af;
+ hints.ai_socktype = type;
- 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); }
+ if ((i = getaddrinfo(host, port, &hints, &ai_top)) != 0)
+ {
+ BIO_printf(bio_err,"getaddrinfo: %s\n", gai_strerror(i));
+ return (0);
+ }
+ if (ai_top == NULL || ai_top->ai_addr == NULL)
+ {
+ BIO_printf(bio_err,"getaddrinfo returned no addresses\n");
+ if (ai_top != NULL) { freeaddrinfo(ai_top); }
+ return (0);
+ }
+ for (ai = ai_top; ai != NULL; ai = ai->ai_next)
+ {
+ s=socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s == INVALID_SOCKET) { continue; }
#ifndef OPENSSL_SYS_MPE
if (type == SOCK_STREAM)
{
@@ -274,11 +261,16 @@ static int init_client_ip(int *sock, uns
if (i < 0) { perror("keepalive"); return(0); }
}
#endif
+ if ((i = connect(s, ai->ai_addr, ai->ai_addrlen)) == 0)
+ { *sock=s; freeaddrinfo(ai_top); return (1); }
- if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1)
- { close(s); perror("connect"); return(0); }
- *sock=s;
- return(1);
+ close(s);
+ }
+
+ perror("connect");
+ close(s);
+ freeaddrinfo(ai_top);
+ return(0);
}
int do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s,
unsigned char *context), unsigned char *context)
@@ -470,12 +462,13 @@ end:
}
int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
- short *port_ptr)
+ char **port_ptr)
{
char *h,*p;
h=str;
- p=strchr(str,':');
+ p=strrchr(str,'/'); /* IPv6 host/port */
+ if (p == NULL) { p=strrchr(str,':'); }
if (p == NULL)
{
BIO_printf(bio_err,"no port defined\n");
@@ -483,58 +476,11 @@ int extract_host_port(char *str, char **
}
*(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);
- }
-
-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);
+ if (port_ptr != NULL && p != NULL && *p != '\0')
+ *port_ptr = p;
- 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)
- {
- 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:
return(0);
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]