Dear openssl-devs,

I am a network engineer and I am interested in networking and security.

For a VPN peer-to-peer project, we need a UDP socket that could contact multiple peers and multiple peers can contact this socket. To add security, we have thinking about DTLS, but the user API is based like TCP thus one server and one client. I made some basics functions that could multiplex remote peers on a single DTLS socket (which can act either server or client). All of this works good for IPv4.

When I wanted to test IPv6, it did not work so I investigate OpenSSL code to known why. I found in crypto/bio/bss_dgram.c that "bio_dgram_data_st" store the network address as "struct sockaddr" which is too short to store IPv6 address.

Thus I have done a patch that correct this (based on the CVS). So now BIO_dgram_set_peer() and others works correctly when using IPv6 address :) .

Regards.

--
Sebastien Vincent
Network and Protocol Team, University of Strasbourg, France
Index: crypto/bio/bss_dgram.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/bio/bss_dgram.c,v
retrieving revision 1.5
diff -u -r1.5 bss_dgram.c
--- crypto/bio/bss_dgram.c	3 Jan 2008 22:43:01 -0000	1.5
+++ crypto/bio/bss_dgram.c	22 Jul 2008 13:49:47 -0000
@@ -100,7 +100,7 @@
 
 typedef struct bio_dgram_data_st
 	{
-	struct sockaddr peer;
+	struct sockaddr_storage peer;
 	unsigned int connected;
 	unsigned int _errno;
 	unsigned int mtu;
@@ -171,7 +171,7 @@
 	int ret=0;
 	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
 
-	struct sockaddr peer;
+	struct sockaddr_storage peer;
 	int peerlen = sizeof(peer);
 
 	if (out != NULL)
@@ -183,7 +183,7 @@
 		 * but this is not universal. Cast to (void *) to avoid
 		 * compiler warnings.
 		 */
-		ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen);
+		ret=recvfrom(b->num,out,outl,0,(struct sockaddr*)&peer,(void *)&peerlen);
 
 		if ( ! data->connected  && ret > 0)
 			BIO_ctrl(b, BIO_CTRL_DGRAM_CONNECT, 0, &peer);
@@ -205,15 +205,16 @@
 	{
 	int ret;
 	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
+  char buf[64];
 	clear_socket_error();
 
     if ( data->connected )
         ret=writesocket(b->num,in,inl);
     else
 #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
-        ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer));
+        ret=sendto(b->num, (char *)in, inl, 0, &data->peer, data->peer.ss_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
 #else
-        ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer));
+        ret=sendto(b->num, in, inl, 0, (struct sockaddr*)&data->peer, data->peer.ss_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
 #endif
 
 	BIO_clear_retry_flags(b);
@@ -289,12 +290,12 @@
 	case BIO_CTRL_DGRAM_CONNECT:
 		to = (struct sockaddr *)ptr;
 #if 0
-		if (connect(b->num, to, sizeof(struct sockaddr)) < 0)
+		if (connect(b->num, to, sizeof(struct sockaddr_storage)) < 0)
 			{ perror("connect"); ret = 0; }
 		else
 			{
 #endif
-			memcpy(&(data->peer),to, sizeof(struct sockaddr));
+			memcpy(&(data->peer),to, to->sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
 #if 0
 			}
 #endif
@@ -332,18 +333,18 @@
 		if ( to != NULL)
 			{
 			data->connected = 1;
-			memcpy(&(data->peer),to, sizeof(struct sockaddr));
+			memcpy(&(data->peer),to, to->sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
 			}
 		else
 			{
 			data->connected = 0;
-			memset(&(data->peer), 0x00, sizeof(struct sockaddr));
+			memset(&(data->peer), 0x00, sizeof(struct sockaddr_storage));
 			}
 		break;
     case BIO_CTRL_DGRAM_SET_PEER:
         to = (struct sockaddr *) ptr;
 
-        memcpy(&(data->peer), to, sizeof(struct sockaddr));
+        memcpy(&(data->peer), to, to->sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
         break;
 #if defined(SO_RCVTIMEO)
 	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:

Reply via email to