[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openssl-dev
Subject:    [PATCH] BIO_set_conn_localport - set the local port for remote connections
From:       Jörg_Matysiak <Joerg.Matysiak () web ! de>
Date:       2005-02-08 10:00:45
Message-ID: 42088DCD.1090505 () web ! de
[Download RAW message or body]

Hi,

this patch adds a new macro BIO_set_conn_localport(bio, "hostname:port") 
to be used
with BIO connection streams.

The function binds the client side of the socket to the given host and port
before it tries connecting to the server.

Usage of this function is optional. If it isn't called, a port assigned by
the operating system is used. That's exactly the behaviour of the 
current implementation.

The patch bases on OpenSSL 0.9.7e and has been testen on Windows 2000,
AIX 4.3, SunOS 5.6, SuSE Linux 8.1 and  HP-UX 10.20.


Example code:

 BIO *cbio, *out;
 int len;
 char tmpbuf[1024];

 ERR_load_crypto_strings();
 cbio = BIO_new_connect("localhost:http");

 BIO_set_conn_localport("localhost:4444"); /* use port 4444 on client side */

 out = BIO_new_fp(stdout, BIO_NOCLOSE);
 if(BIO_do_connect(cbio) <= 0) {
        fprintf(stderr, "Error connecting to server\n");
        ERR_print_errors_fp(stderr);
        /* whatever ... */
        }
 BIO_puts(cbio, "GET / HTTP/1.0\n\n");
 for(;;) {
        len = BIO_read(cbio, tmpbuf, 1024);
        if(len <= 0) break;
        BIO_write(out, tmpbuf, len);
 }
 BIO_free(cbio);
 BIO_free(out);



Jörg Matysiak
Software Development Systems Management
CENIT AG Systemhaus

mailto: j.matysiak (at) cenit.de
http://www.cenit-group.com



["openssl.patch" (text/plain)]

diff -ur -x CVS -x '*.exe' -x '*.o' -x '*.bak' -x Configure -x apps -x '*.0' -x '*.s' \
-x Makefile -x lib -x test -x '*.obj' -x opensslconf.h openssl_orig/crypto/bio/bio.h \
                openssl/crypto/bio/bio.h
--- openssl_orig/crypto/bio/bio.h	2004-11-24 11:10:15.000000000 +0100
+++ openssl/crypto/bio/bio.h	2005-02-07 17:08:25.000000000 +0100
@@ -291,6 +291,7 @@
 #define BIO_CONN_S_BEFORE		1
 #define BIO_CONN_S_GET_IP		2
 #define BIO_CONN_S_GET_PORT		3
+#define BIO_CONN_S_BIND_SOCKET 31 /* 31 means 3.1 here (new status is between \
GET_PORT and CREATE_SOCKET) */  #define BIO_CONN_S_CREATE_SOCKET	4
 #define BIO_CONN_S_CONNECT		5
 #define BIO_CONN_S_OK			6
@@ -358,6 +359,8 @@
 #define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port)
 #define BIO_set_conn_ip(b,ip)	  BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip)
 #define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port)
+#define BIO_set_conn_localport(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,4,(char*) name)
+
 #define BIO_get_conn_hostname(b)  BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0)
 #define BIO_get_conn_port(b)      BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)
 #define BIO_get_conn_ip(b) 		 BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)
diff -ur -x CVS -x '*.exe' -x '*.o' -x '*.bak' -x Configure -x apps -x '*.0' -x '*.s' \
-x Makefile -x lib -x test -x '*.obj' -x opensslconf.h \
                openssl_orig/crypto/bio/bss_conn.c openssl/crypto/bio/bss_conn.c
--- openssl_orig/crypto/bio/bss_conn.c	2004-11-24 11:10:15.000000000 +0100
+++ openssl/crypto/bio/bss_conn.c	2005-02-07 17:08:25.000000000 +0100
@@ -87,6 +87,9 @@
 	unsigned char ip[4];
 	unsigned short port;
 
+   char *local_hostname;
+   unsigned short local_port;
+
 	struct sockaddr_in them;
 
 	/* int socket; this will be kept in bio->num so that it is
@@ -219,9 +222,82 @@
 				goto exit_loop;
 				}
 			b->num=ret;
-			c->state=BIO_CONN_S_NBIO;
+			c->state=BIO_CONN_S_BIND_SOCKET;
 			break;
 
+      case BIO_CONN_S_BIND_SOCKET:
+         if (NULL != c->local_hostname)
+         {
+            char *p = c->local_hostname;
+            struct sockaddr_in local_addr;
+            
+
+            /* seach for ':' */
+            for (; (*p != '\0') && (*p != ':') ; p++); /* no body */
+            if (*p == ':')
+            {
+               char *q = p+1;            
+               
+               for(;(*q != '\0') && ('0' <= *q) && (*q <= '9');q++)
+               {
+                  c->local_port=10*(c->local_port) + (*q - '0');
+               }
+            }
+            *p = '\0';
+
+            memset((char *)&local_addr,0,sizeof(local_addr));
+            local_addr.sin_family=AF_INET;
+
+            if (c->local_port > 0)
+            {
+               local_addr.sin_port=htons(c->local_port);
+            }
+            else
+            {
+               local_addr.sin_port=0;
+            }
+            
+            if ((strlen(c->local_hostname) != 0) && (strcmp("*", c->local_hostname) \
!= 0)) +            {
+               unsigned char ip[4];
+
+               if (BIO_get_host_ip(c->local_hostname,&(ip[0])))
+               {
+                  unsigned long l;
+                  l=(unsigned long)
+                     ((unsigned long)ip[0]<<24L)|
+                     ((unsigned long)ip[1]<<16L)|
+                     ((unsigned long)ip[2]<< 8L)|
+                     ((unsigned long)ip[3]);
+                  local_addr.sin_addr.s_addr=htonl(l);
+               }
+            }
+            else
+            {
+               local_addr.sin_addr.s_addr=INADDR_ANY;
+            }
+
+            if (bind(b->num,(struct sockaddr *)&local_addr,sizeof(local_addr)) == \
-1) +            {
+               int err_num=get_last_socket_error();
+               char local_port[10];
+
+               sprintf(local_port, "%d", c->local_port);
+
+               closesocket(b->num);
+               b->num = -1;
+
+               SYSerr(SYS_F_SOCKET,get_last_socket_error());
+               ERR_add_error_data(4,"local_address=",c->local_hostname,
+                                  ":", local_port);
+               
+               BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
+               goto exit_loop;
+            }
+         } /* endif c->local_hostname */
+         c->state=BIO_CONN_S_NBIO;
+      break;
+
 		case BIO_CONN_S_NBIO:
 			if (c->nbio)
 				{
@@ -334,6 +410,8 @@
 	ret->ip[2]=0;
 	ret->ip[3]=0;
 	ret->port=0;
+   ret->local_hostname=NULL;
+   ret->local_port=0;
 	memset((char *)&ret->them,0,sizeof(ret->them));
 	return(ret);
 	}
@@ -538,7 +616,13 @@
 				data->param_port=BUF_strdup(buf);
 				data->port= *(int *)ptr;
 				}
-			}
+         else if (num == 4)
+         {
+            if (data->local_hostname != NULL)
+					OPENSSL_free(data->local_hostname);
+            data->local_hostname=strdup(ptr);
+         }
+		}
 		break;
 	case BIO_C_SET_NBIO:
 		data->nbio=(int)num;


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           majordomo@openssl.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic