socsvn commit: r237821 - in soc2012/exxo: openssl-1.0.1c/crypto/bio regress regress/openssl-1.0.1c

exxo at FreeBSD.org exxo at FreeBSD.org
Sun Jun 17 02:29:07 UTC 2012


Author: exxo
Date: Sun Jun 17 02:29:04 2012
New Revision: 237821
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237821

Log:
  Major rewrite in b_sock.c without breaking the API (however see TODO list), correct buffering issue in regress

Modified:
  soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c
  soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h
  soc2012/exxo/regress/openssl-1.0.1c/Makefile
  soc2012/exxo/regress/regress.in

Modified: soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c
==============================================================================
--- soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c	Sun Jun 17 00:28:57 2012	(r237820)
+++ soc2012/exxo/openssl-1.0.1c/crypto/bio/b_sock.c	Sun Jun 17 02:29:04 2012	(r237821)
@@ -59,6 +59,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <assert.h>
 #define USE_SOCKETS
 #include "cryptlib.h"
 #include <openssl/bio.h>
@@ -84,6 +85,10 @@
 #define MAX_LISTEN  32
 #endif
 
+#ifdef OPENSSL_USE_IPV6
+extern const struct in6_addr in6addr_any;
+#endif
+
 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
 static int wsa_init_done=0;
 #endif
@@ -123,8 +128,12 @@
 	int err = 1;
 	int locked = 0;
 	struct hostent *he;
+	struct addrinfo hint, *res = NULL;
+	char *addr = NULL;
+	int addrlen = 4;
+	int gai_err;
 
-	i=get_ip(str,ip);
+	i=get_ip(str,ip); /* Search for an IPv4 address in in standard dot notation */
 	if (i < 0)
 		{
 		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
@@ -140,29 +149,66 @@
 	   anything more */
 	if (i > 0) return(1);
 
-	/* do a gethostbyname */
-	CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
-	locked = 1;
-	he=BIO_gethostbyname(str);
-	if (he == NULL)
+	memset(&hint,0,sizeof(hint));
+#if OPENSSL_USE_IPV6
+	hint.ai_family=AF_INET6;
+#else
+	hint.ai_family=AF_INET;
+#endif
+	gai_err = BIO_getaddrinfo(str, NULL, &hint, &res);
+	if (gai_err == 0)
 		{
-		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
+		res=NULL;
 		goto err;
 		}
+	else if (gai_err < 0) /* Not supported fallback in gethostbyname */
+		{
+		ERR_get_error(); /* suppress the error generated by BIO_getaddrinfo */
+		/* do a gethostbyname */
+		CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
+		locked = 1;
+		he=BIO_gethostbyname(str);
+		if (he == NULL)
+			{
+			BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
+			goto err;
+			}
 
-	/* cast to short because of win16 winsock definition */
-	if ((short)he->h_addrtype != AF_INET)
+		/* cast to short because of win16 winsock definition */
+		if ((short)he->h_addrtype != AF_INET)
+			{
+			BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
+			goto err;
+			}
+		addr = he->h_addr;
+		addrlen = he->h_length;
+		}
+	else
 		{
-		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
-		goto err;
+		if (res->ai_family == AF_INET)
+			{
+			assert(res->ai_addrlen == sizeof(struct sockaddr_in));
+			addr = (char *) &((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr;
+			addrlen = 4;
+			}
+		else if (res->ai_family == AF_INET6)
+			{
+			assert(res->ai_addrlen == sizeof(struct sockaddr_in6));
+			addr = (char *) &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr.s6_addr;
+			addrlen = 16;
+			}
+		else
+			goto err;
 		}
-	for (i=0; i<4; i++)
-		ip[i]=he->h_addr_list[0][i];
+	for (i=0; i < addrlen; i++)
+		ip[i]=addr[i]; /* Store the address in network byte order */
 	err = 0;
 
  err:
 	if (locked)
 		CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
+	if (res)
+		BIO_freeaddrinfo(res);
 	if (err)
 		{
 		ERR_add_error_data(2,"host=",str);
@@ -498,7 +544,7 @@
 #endif
 				ERR_add_error_data(1, reason);
 				}
-			return (-1);
+			return (0);
 			}
 		return (1);
 		}
@@ -670,122 +716,133 @@
 	return(1);
 	}
 
-int BIO_get_accept_socket(char *host, int bind_mode)
+static int parse_ip(char *str, char **host, char **port, int *is_inet6)
 	{
-	int ret=0;
-	union {
-		struct sockaddr sa;
-		struct sockaddr_in sa_in;
-#if OPENSSL_USE_IPV6
-		struct sockaddr_in6 sa_in6;
-#endif
-	} server,client;
-	int s=INVALID_SOCKET,cs,addrlen;
-	unsigned char ip[4];
-	unsigned short port;
-	char *str=NULL,*e;
-	char *h,*p;
-	unsigned long l;
-	int err_num;
-
-	if (BIO_sock_init() != 1) return(INVALID_SOCKET);
-
-	if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
-
-	h=p=NULL;
-	h=str;
-	for (e=str; *e; e++)
-		{
-		if (*e == ':')
+	char *tmp;
+	char *h = *host = NULL;
+	char *p = *port = NULL;
+
+	*is_inet6 = 0; 
+	if (*str == '\0')
+		return (0);
+	if (*str == '[' && (tmp = strchr(str + 1, ']')))
+		{  
+		h = str + 1; 
+		*tmp++ = '\0';
+		if (*tmp == ':')
+			p = tmp + 1; 
+		else if (*tmp != '\0')
+			return (0);
+		*is_inet6 = 1; 
+		}  
+	else
+		{  
+		if ((tmp = strchr(str, ':')))
 			{
-			p=e;
+			h = str;
+			*tmp++ = '\0';
+			p = tmp;
 			}
-		else if (*e == '/')
+		else if ((tmp = strchr(str, '/')))
 			{
-			*e='\0';
-			break;
+			if (*(tmp + 1) != '\0')
+			return (0);
+			p = str;
+			*tmp = '\0';
 			}
-		}
-	if (p)	*p++='\0';	/* points at last ':', '::port' is special [see below] */
-	else	p=h,h=NULL;
-
-#ifdef EAI_FAMILY
-	do {
-	static union {	void *p;
-			int (WSAAPI *f)(const char *,const char *,
-				 const struct addrinfo *,
-				 struct addrinfo **);
-			} p_getaddrinfo = {NULL};
-	static union {	void *p;
-			void (WSAAPI *f)(struct addrinfo *);
-			} p_freeaddrinfo = {NULL};
-	struct addrinfo *res,hint;
+		else
+			h = str;
+		}  
+	if (h && (*h == '\0' || !strcmp(h, "*")))
+		h = NULL;
+	if (p && (*p == '\0' || !strcmp(p, "*")))
+		p = NULL;
+	*host = h; 
+	*port = p; 
+	return (1);
+	}
 
-	if (p_getaddrinfo.p==NULL)
-		{
-		if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL ||
-		    (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL)
-			p_getaddrinfo.p=(void*)-1;
-		}
-	if (p_getaddrinfo.p==(void *)-1) break;
+static int fill_addr(union sa_storage *sa, char *host, char *port, int is_inet6)
+	{ 
+	unsigned short p;
+	int sa_len = 0;
+#ifdef OPENSSL_USE_IPV6
+	unsigned char h[16];
+#else
+	unsigned char h[4];
+#endif
 
-	/* '::port' enforces IPv6 wildcard listener. Some OSes,
-	 * e.g. Solaris, default to IPv6 without any hint. Also
-	 * note that commonly IPv6 wildchard socket can service
-	 * IPv4 connections just as well...  */
-	memset(&hint,0,sizeof(hint));
-	hint.ai_flags = AI_PASSIVE;
-	if (h)
-		{
-		if ((e = strchr(h,':')))
+	if (!BIO_get_port(port,&p)) return (0);
+	memset((char *)sa,0,sizeof(*sa));
+	memset(h, 0, sizeof(h));
+	if (is_inet6) /* deal with inet6 format (ie: [host]:port) */
+		{
+#ifdef OPENSSL_USE_IPV6
+		assert(sizeof(*sa) >= sizeof(struct sockaddr_in6));
+		sa->sa_in6.sin6_family = AF_INET6;
+		sa->sa_in6.sin6_port = htons(p);
+		sa_len = sizeof(sa->sa_in6);
+#ifdef SIN6_LEN /* BSD 4.4 */
+		sa->sa_in6.sin6_len = sa_len;
+#endif
+		if (h == NULL)
+			sa->sa_in6.sin6_addr = in6addr_any;
+		else
 			{
-			*e = '\0';
-			if (h[1]=='\0') h=NULL;
-#if OPENSSL_USE_IPV6
-			hint.ai_family = AF_INET6;
+			if (!BIO_get_host_ip(host, h)) return (0);
+			memcpy(&sa->sa_in6.sin6_addr.s6_addr, h, sizeof(h));
+			}
 #else
-			h=NULL;
+		/* inet6 format used without OPENSSL configured properly, thus invalid */
+		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_INVALID_IP_ADDRESS);
+		return (0);
+#endif
+	 	}
+	else /* we must resolve an inet4 address */
+		{
+		assert(sizeof(*sa) >= sizeof(struct sockaddr_in));
+		sa->sa_in.sin_family=AF_INET;
+		sa->sa_in.sin_port=htons(p);
+		sa_len = sizeof(sa->sa_in);
+#if 1
+		/* TODO add a definition at compile time */
+		sa->sa_in.sin_len = sa_len;
 #endif
-			}
-	    	else if (h[0]=='*' && h[1]=='\0')
+		if (h == NULL)
+			sa->sa_in.sin_addr.s_addr=INADDR_ANY;
+		else
 			{
-			hint.ai_family = AF_INET;
-			h=NULL;
+			/* 
+			 * TODO force inet4 listening even with OPENSSL_USE_IPV6
+			 *
+			 * CONF_LOCAL(h)
+			 * CONF_INETONLY(h)
+			 */
+			if (!BIO_get_host_ip(host, h)) return (0);
+			memcpy(&sa->sa_in.sin_addr.s_addr, h, 4); /* always 4 here especially when using inet6 */
 			}
 		}
+	return (sa_len);
+	}
 
-	if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break;
-
-	addrlen = res->ai_addrlen<=sizeof(server) ?
-			res->ai_addrlen :
-			sizeof(server);
-	memcpy(&server, res->ai_addr, addrlen);
-
-	(*p_freeaddrinfo.f)(res);
-	goto again;
-	} while (0);
-#endif
-
-	if (!BIO_get_port(p,&port)) goto err;
-
-	memset((char *)&server,0,sizeof(server));
-	server.sa_in.sin_family=AF_INET;
-	server.sa_in.sin_port=htons(port);
-	addrlen = sizeof(server.sa_in);
+int BIO_get_accept_socket(char *host, int bind_mode)
+	{
+	union sa_storage server,client;
+	int s=INVALID_SOCKET,cs,addrlen;
+	char *str=NULL;
+	char *h,*p;
+	int err_num;
+	int is_inet6 = 0;
+	int ret = 0;
 
-	if (h == NULL || strcmp(h,"*") == 0)
-		server.sa_in.sin_addr.s_addr=INADDR_ANY;
-	else
+	if (BIO_sock_init() != 1) return(INVALID_SOCKET);
+	if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
+	if (parse_ip(str, &h, &p, &is_inet6) != 1)
 		{
-                if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
-		l=(unsigned long)
-			((unsigned long)ip[0]<<24L)|
-			((unsigned long)ip[1]<<16L)|
-			((unsigned long)ip[2]<< 8L)|
-			((unsigned long)ip[3]);
-		server.sa_in.sin_addr.s_addr=htonl(l);
+		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_INVALID_IP_ADDRESS);
+		goto err;
 		}
-
+	if ((addrlen = fill_addr(&server, h, p, is_inet6)) == 0) goto err; /* Errors have been already generated */
 again:
 	s=socket(server.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
 	if (s == INVALID_SOCKET)
@@ -820,7 +877,7 @@
 #endif
 			{
 			client = server;
-			if (h == NULL || strcmp(h,"*") == 0)
+			if (h == NULL)
 				{
 #if OPENSSL_USE_IPV6
 				if (client.sa.sa_family == AF_INET6)

Modified: soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h
==============================================================================
--- soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h	Sun Jun 17 00:28:57 2012	(r237820)
+++ soc2012/exxo/openssl-1.0.1c/crypto/bio/bio.h	Sun Jun 17 02:29:04 2012	(r237821)
@@ -76,8 +76,12 @@
 # endif
 #endif
 
-/* under which condition ? */
+/* TODO
+ * Under which condition ?
+ */
 #include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 
 #ifdef  __cplusplus
 extern "C" {
@@ -720,9 +724,40 @@
  */
 
 #ifndef EAI_FAMILY
-struct addrinfo {  /* dummy interface */ };
+
+struct addrinfo /* fake interface */
+	{ 
+	int ai_flags;
+	int ai_family;
+	int ai_socktype;
+	int ai_protocol;
+	int ai_addrlen;
+	char* ai_canonname;
+	struct sockaddr *ai_addr;
+	struct addrinfo *ai_next;
+	};
+
+/* dummy definitions */
+#define	AI_PASSIVE	0
+#define	AI_CANONNAME	0
+#define	AI_NUMERICHOST	0
+#define	AI_NUMERICSERV	0
+#define	AI_ALL		0
+#define	AI_V4MAPPED_CFG	0
+#define	AI_ADDRCONFIG	0
+#define	AI_V4MAPPED	0
+
 #endif
 
+union sa_storage
+	{
+	struct sockaddr sa;
+	struct sockaddr_in sa_in;
+#if OPENSSL_USE_IPV6
+	struct sockaddr_in6 sa_in6;
+#endif
+	};
+
 int BIO_getaddrinfo(const char *hostname, const char *servname,
 		    const struct addrinfo *hints, struct addrinfo **res);
 void BIO_freeaddrinfo(struct addrinfo *ai);

Modified: soc2012/exxo/regress/openssl-1.0.1c/Makefile
==============================================================================
--- soc2012/exxo/regress/openssl-1.0.1c/Makefile	Sun Jun 17 00:28:57 2012	(r237820)
+++ soc2012/exxo/regress/openssl-1.0.1c/Makefile	Sun Jun 17 02:29:04 2012	(r237821)
@@ -1,6 +1,7 @@
 REGRESS_TARGETS	= rg1 rg2 rg3
 
 OPENSSL		= ${.CURDIR}/../../openssl-1.0.1c
+OPENSSL_FLAGS	+= -g -DOPENSSL_USE_IPV6
 LIB_CRYPTO	= $(OPENSSL)/libcrypto.a
 
 MAKE		?= make
@@ -8,7 +9,7 @@
 .PHONY: all clean openssl openssl-fconfig openssl-clean regress
 .MAIN: all
 
-OPENSSL_CONFIGURE = cd $(OPENSSL) && ./config -g
+OPENSSL_CONFIGURE = cd $(OPENSSL) && ./config $(OPENSSL_FLAGS)
 
 depend $(LIB_CRYPTO): .SILENT
 	if ! [ -e $(OPENSSL)/Makefile.bak ]; then \

Modified: soc2012/exxo/regress/regress.in
==============================================================================
--- soc2012/exxo/regress/regress.in	Sun Jun 17 00:28:57 2012	(r237820)
+++ soc2012/exxo/regress/regress.in	Sun Jun 17 02:29:04 2012	(r237821)
@@ -72,7 +72,9 @@
 
 _startest_()
 {
-	${BINDIR}/${BASENAME} > "${LOGDIR}/${BASENAME}-err.log" 2>&1 &
+	local args=""
+
+	stdbuf -o L ${BINDIR}/${BASENAME} "${args}" > "${LOGDIR}/${BASENAME}-err.log" 2>&1 &
 	PID=$!
 }
 


More information about the svn-soc-all mailing list