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