changeset 568:005530560594

Rearrange getaddrstring() etc
author Matt Johnston <matt@ucc.asn.au>
date Tue, 01 Sep 2009 16:38:26 +0000
parents 893a9dd0b9dd
children 6f472dc54da7
files cli-kex.c cli-main.c cli-runopts.c cli-session.c common-session.c dbutil.c dbutil.h debug.h options.h packet.c runopts.h session.h svr-chansession.c svr-main.c svr-runopts.c svr-session.c
diffstat 16 files changed, 141 insertions(+), 139 deletions(-) [+]
line wrap: on
line diff
--- a/cli-kex.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/cli-kex.c	Tue Sep 01 16:38:26 2009 +0000
@@ -304,7 +304,7 @@
 		fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */
 		buf_setpos(line, 0);
 		buf_setlen(line, 0);
-		buf_putbytes(line, ses.remotehost, hostlen);
+		buf_putbytes(line, cli_opts.remotehost, hostlen);
 		buf_putbyte(line, ' ');
 		buf_putbytes(line, algoname, algolen);
 		buf_putbyte(line, ' ');
--- a/cli-main.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/cli-main.c	Tue Sep 01 16:38:26 2009 +0000
@@ -45,8 +45,6 @@
 
 	int sock_in, sock_out;
 	char* error = NULL;
-	char* hostandport;
-	int len;
 
 	_dropbear_exit = cli_dropbear_exit;
 	_dropbear_log = cli_dropbear_log;
@@ -78,14 +76,7 @@
 		dropbear_exit("%s", error);
 	}
 
-	/* Set up the host:port log */
-	len = strlen(cli_opts.remotehost);
-	len += 10; /* 16 bit port and leeway*/
-	hostandport = (char*)m_malloc(len);
-	snprintf(hostandport, len, "%s:%s", 
-			cli_opts.remotehost, cli_opts.remoteport);
-
-	cli_session(sock_in, sock_out, hostandport);
+	cli_session(sock_in, sock_out);
 
 	/* not reached */
 	return -1;
--- a/cli-runopts.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/cli-runopts.c	Tue Sep 01 16:38:26 2009 +0000
@@ -378,15 +378,19 @@
 		}
 	}
 	if (keepalive_arg) {
-		if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) {
+		unsigned int val;
+		if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) {
 			dropbear_exit("Bad keepalive '%s'", keepalive_arg);
 		}
+		opts.keepalive_secs = val;
 	}
 
 	if (idle_timeout_arg) {
-		if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) {
+		unsigned int val;
+		if (m_str_to_uint(idle_timeout_arg, &val) == DROPBEAR_FAILURE) {
 			dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
 		}
+		opts.idle_timeout_secs = val;
 	}
 
 #ifdef ENABLE_CLI_NETCAT
@@ -454,7 +458,7 @@
 		sign_key * key = (sign_key*)iter->item;
 		const size_t size = len - total;
 		int written = snprintf(ret+total, size, "-i %s", key->filename);
-		dropbear_assert(written < size);
+		dropbear_assert((unsigned int)written < size);
 		total += written;
 	}
 
--- a/cli-session.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/cli-session.c	Tue Sep 01 16:38:26 2009 +0000
@@ -82,13 +82,13 @@
 	NULL /* Null termination */
 };
 
-void cli_session(int sock_in, int sock_out, char* remotehost) {
+void cli_session(int sock_in, int sock_out) {
 
 	seedrandom();
 
 	crypto_init();
 
-	common_session_init(sock_in, sock_out, remotehost);
+	common_session_init(sock_in, sock_out);
 
 	chaninitialise(cli_chantypes);
 
--- a/common-session.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/common-session.c	Tue Sep 01 16:38:26 2009 +0000
@@ -52,12 +52,10 @@
 
 
 /* called only at the start of a session, set up initial state */
-void common_session_init(int sock_in, int sock_out, char* remotehost) {
+void common_session_init(int sock_in, int sock_out) {
 
 	TRACE(("enter session_init"))
 
-	ses.remotehost = remotehost;
-
 	ses.sock_in = sock_in;
 	ses.sock_out = sock_out;
 	ses.maxfd = MAX(sock_in, sock_out);
--- a/dbutil.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/dbutil.c	Tue Sep 01 16:38:26 2009 +0000
@@ -539,14 +539,47 @@
 	execv(usershell, argv);
 }
 
+void get_socket_address(int fd, char **local_host, char **local_port,
+						char **remote_host, char **remote_port, int host_lookup)
+{
+	struct sockaddr_storage addr;
+	socklen_t addrlen;
+	
+	if (local_host || local_port) {
+		addrlen = sizeof(addr);
+		if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
+			dropbear_exit("Failed socket address: %s", strerror(errno));
+		}
+		getaddrstring(&addr, local_host, local_port, host_lookup);		
+	}
+	if (remote_host || remote_port) {
+		addrlen = sizeof(addr);
+		if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
+			dropbear_exit("Failed socket address: %s", strerror(errno));
+		}
+		getaddrstring(&addr, remote_host, remote_port, host_lookup);		
+	}
+}
+
 /* Return a string representation of the socket address passed. The return
  * value is allocated with malloc() */
-unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) {
+void getaddrstring(struct sockaddr_storage* addr, 
+			char **ret_host, char **ret_port,
+			int host_lookup) {
 
-	char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
-	char *retstring = NULL;
+	char host[NI_MAXHOST+1], serv[NI_MAXSERV+1];
+	unsigned int len;
 	int ret;
-	unsigned int len;
+	
+	int flags = NI_NUMERICSERV | NI_NUMERICHOST;
+
+#ifndef DO_HOST_LOOKUP
+	host_lookup = 0;
+#endif
+	
+	if (host_lookup) {
+		flags = NI_NUMERICSERV;
+	}
 
 	len = sizeof(struct sockaddr_storage);
 	/* Some platforms such as Solaris 8 require that len is the length
@@ -564,66 +597,28 @@
 #endif
 #endif
 
-	ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), 
-			sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST);
+	ret = getnameinfo((struct sockaddr*)addr, len, host, sizeof(host)-1, 
+			serv, sizeof(serv)-1, flags);
 
 	if (ret != 0) {
-		/* This is a fairly bad failure - it'll fallback to IP if it
-		 * just can't resolve */
-		dropbear_exit("failed lookup (%d, %d)", ret, errno);
-	}
-
-	if (withport) {
-		len = strlen(hbuf) + 2 + strlen(sbuf);
-		retstring = (char*)m_malloc(len);
-		snprintf(retstring, len, "%s:%s", hbuf, sbuf);
-	} else {
-		retstring = m_strdup(hbuf);
+		if (host_lookup) {
+			/* On some systems (Darwin does it) we get EINTR from getnameinfo
+			 * somehow. Eew. So we'll just return the IP, since that doesn't seem
+			 * to exhibit that behaviour. */
+			getaddrstring(addr, ret_host, ret_port, 0);
+			return;
+		} else {
+			/* if we can't do a numeric lookup, something's gone terribly wrong */
+			dropbear_exit("Failed lookup: %s", gai_strerror(ret));
+		}
 	}
 
-	return retstring;
-}
-
-/* Get the hostname corresponding to the address addr. On failure, the IP
- * address is returned. The return value is allocated with strdup() */
-char* getaddrhostname(struct sockaddr_storage * addr) {
-
-	char hbuf[NI_MAXHOST];
-	char sbuf[NI_MAXSERV];
-	int ret;
-	unsigned int len;
-#ifdef DO_HOST_LOOKUP
-	const int flags = NI_NUMERICSERV;
-#else
-	const int flags = NI_NUMERICHOST | NI_NUMERICSERV;
-#endif
-
-	len = sizeof(struct sockaddr_storage);
-	/* Some platforms such as Solaris 8 require that len is the length
-	 * of the specific structure. */
-#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
-	if (addr->ss_family == AF_INET) {
-		len = sizeof(struct sockaddr_in);
+	if (ret_host) {
+		*ret_host = m_strdup(host);
 	}
-#ifdef AF_INET6
-	if (addr->ss_family == AF_INET6) {
-		len = sizeof(struct sockaddr_in6);
+	if (ret_port) {
+		*ret_port = m_strdup(serv);
 	}
-#endif
-#endif
-
-
-	ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf),
-			sbuf, sizeof(sbuf), flags);
-
-	if (ret != 0) {
-		/* On some systems (Darwin does it) we get EINTR from getnameinfo
-		 * somehow. Eew. So we'll just return the IP, since that doesn't seem
-		 * to exhibit that behaviour. */
-		return getaddrstring(addr, 0);
-	}
-
-	return m_strdup(hbuf);
 }
 
 #ifdef DEBUG_TRACE
--- a/dbutil.h	Mon Aug 31 15:25:39 2009 +0000
+++ b/dbutil.h	Tue Sep 01 16:38:26 2009 +0000
@@ -46,7 +46,10 @@
 extern int debug_trace;
 #endif
 char * stripcontrol(const char * text);
-unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport);
+void get_socket_address(int fd, char **local_host, char **local_port,
+		char **remote_host, char **remote_port, int host_lookup);
+void getaddrstring(struct sockaddr_storage* addr, 
+		char **ret_host, char **ret_port, int host_lookup);
 int dropbear_listen(const char* address, const char* port,
 		int *socks, unsigned int sockcount, char **errstring, int *maxfd);
 int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
@@ -57,7 +60,6 @@
 #endif
 int connect_remote(const char* remotehost, const char* remoteport,
 		int nonblocking, char ** errstring);
-char* getaddrhostname(struct sockaddr_storage * addr);
 int buf_readfile(buffer* buf, const char* filename);
 int buf_getline(buffer * line, FILE * authfile);
 
--- a/debug.h	Mon Aug 31 15:25:39 2009 +0000
+++ b/debug.h	Tue Sep 01 16:38:26 2009 +0000
@@ -39,7 +39,7 @@
  * Caution: Don't use this in an unfriendly environment (ie unfirewalled),
  * since the printing may not sanitise strings etc. This will add a reasonable
  * amount to your executable size. */
-/*#define DEBUG_TRACE*/
+#define DEBUG_TRACE
 
 /* All functions writing to the cleartext payload buffer call
  * CHECKCLEARTOWRITE() before writing. This is only really useful if you're
--- a/options.h	Mon Aug 31 15:25:39 2009 +0000
+++ b/options.h	Tue Sep 01 16:38:26 2009 +0000
@@ -167,9 +167,9 @@
  * but there's an interface via a PAM module - don't bother using it otherwise.
  * You can't enable both PASSWORD and PAM. */
 
-#define ENABLE_SVR_PASSWORD_AUTH
+/*#define ENABLE_SVR_PASSWORD_AUTH*/
 /* PAM requires ./configure --enable-pam */
-/*#define ENABLE_SVR_PAM_AUTH*/
+#define ENABLE_SVR_PAM_AUTH
 #define ENABLE_SVR_PUBKEY_AUTH
 
 /* Whether to take public key options in 
--- a/packet.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/packet.c	Tue Sep 01 16:38:26 2009 +0000
@@ -157,9 +157,10 @@
 static int read_packet_init() {
 
 	unsigned int maxlen;
-	int len;
-	unsigned char blocksize;
-	unsigned char macsize;
+	int slen;
+	unsigned int len;
+	unsigned int blocksize;
+	unsigned int macsize;
 
 
 	blocksize = ses.keys->recv.algo_crypt->blocksize;
@@ -173,12 +174,12 @@
 	maxlen = blocksize - ses.readbuf->pos;
 			
 	/* read the rest of the packet if possible */
-	len = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
+	slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
 			maxlen);
-	if (len == 0) {
+	if (slen == 0) {
 		ses.remoteclosed();
 	}
-	if (len < 0) {
+	if (slen < 0) {
 		if (errno == EINTR) {
 			TRACE(("leave read_packet_init: EINTR"))
 			return DROPBEAR_FAILURE;
@@ -186,9 +187,9 @@
 		dropbear_exit("error reading: %s", strerror(errno));
 	}
 
-	buf_incrwritepos(ses.readbuf, len);
+	buf_incrwritepos(ses.readbuf, slen);
 
-	if ((unsigned int)len != maxlen) {
+	if ((unsigned int)slen != maxlen) {
 		/* don't have enough bytes to determine length, get next time */
 		return DROPBEAR_FAILURE;
 	}
--- a/runopts.h	Mon Aug 31 15:25:39 2009 +0000
+++ b/runopts.h	Tue Sep 01 16:38:26 2009 +0000
@@ -37,8 +37,8 @@
 	int listen_fwd_all;
 #endif
 	unsigned int recv_window;
-	unsigned int keepalive_secs;
-	unsigned int idle_timeout_secs;
+	time_t keepalive_secs;
+	time_t idle_timeout_secs;
 
 } runopts;
 
--- a/session.h	Mon Aug 31 15:25:39 2009 +0000
+++ b/session.h	Tue Sep 01 16:38:26 2009 +0000
@@ -41,7 +41,7 @@
 extern int sessinitdone; /* Is set to 0 somewhere */
 extern int exitflag;
 
-void common_session_init(int sock_in, int sock_out, char* remotehost);
+void common_session_init(int sock_in, int sock_out);
 void session_loop(void(*loophandler)());
 void common_session_cleanup();
 void session_identification();
@@ -51,12 +51,12 @@
 void fill_passwd(const char* username);
 
 /* Server */
-void svr_session(int sock, int childpipe, char *remotehost, char *addrstring);
+void svr_session(int sock, int childpipe);
 void svr_dropbear_exit(int exitcode, const char* format, va_list param);
 void svr_dropbear_log(int priority, const char* format, va_list param);
 
 /* Client */
-void cli_session(int sock_in, int sock_out, char *remotehost);
+void cli_session(int sock_in, int sock_out);
 void cli_session_cleanup();
 void cleantext(unsigned char* dirtytext);
 
@@ -110,8 +110,6 @@
 	int sock_in;
 	int sock_out;
 
-	unsigned char *remotehost; /* the peer hostname */
-
 	unsigned char *remoteident;
 
 	int maxfd; /* the maximum file descriptor to check with select() */
--- a/svr-chansession.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/svr-chansession.c	Tue Sep 01 16:38:26 2009 +0000
@@ -250,6 +250,17 @@
 
 }
 
+static struct logininfo* 
+chansess_login_alloc(struct ChanSess *chansess) {
+	char *remotehost;
+	struct logininfo * li;
+	get_socket_address(ses.sock_in, NULL, NULL, &remotehost, NULL, 1);
+	li = login_alloc_entry(chansess->pid, ses.authstate.username,
+			remotehost, chansess->tty);
+	m_free(remotehost);	
+	return li;
+}
+
 /* clean a session channel */
 static void closechansess(struct Channel *channel) {
 
@@ -273,8 +284,7 @@
 
 	if (chansess->tty) {
 		/* write the utmp/wtmp login record */
-		li = login_alloc_entry(chansess->pid, ses.authstate.username,
-				ses.remotehost, chansess->tty);
+		li = chansess_login_alloc(chansess);
 		login_logout(li);
 		login_free_entry(li);
 
@@ -578,7 +588,6 @@
 		int iscmd, int issubsys) {
 
 	unsigned int cmdlen;
-	int is_forced;
 	int ret;
 
 	TRACE(("enter sessioncommand"))
@@ -628,6 +637,8 @@
 	}
 #endif
 
+	// XXX set SSH_CONNECTION string here, since about to close socket...
+
 	if (chansess->term == NULL) {
 		/* no pty */
 		ret = noptycommand(channel, chansess);
@@ -737,8 +748,7 @@
 
 		/* write the utmp/wtmp login record - must be after changing the
 		 * terminal used for stdout with the dup2 above */
-		li= login_alloc_entry(getpid(), ses.authstate.username,
-				ses.remotehost, chansess->tty);
+		li = chansess_login_alloc(chansess);
 		login_login(li);
 		login_free_entry(li);
 
@@ -886,6 +896,8 @@
 		addnewvar("SSH_TTY", chansess->tty);
 	}
 	
+	
+	
 #ifdef ENABLE_SVR_PUBKEY_OPTIONS
 	if (ses.authstate.pubkey_options &&
 			ses.authstate.pubkey_options->original_command) {
--- a/svr-main.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/svr-main.c	Tue Sep 01 16:38:26 2009 +0000
@@ -77,22 +77,16 @@
 
 #ifdef INETD_MODE
 static void main_inetd() {
-
-	struct sockaddr_storage remoteaddr;
-	socklen_t remoteaddrlen;
-	char * addrstring = NULL;
+	char *host, *port = NULL;
 
 	/* Set up handlers, syslog, seed random */
 	commonsetup();
 
-	remoteaddrlen = sizeof(remoteaddr);
-	if (getpeername(0, (struct sockaddr*)&remoteaddr, &remoteaddrlen) < 0) {
-		dropbear_exit("Unable to getpeername: %s", strerror(errno));
-	}
-
 	/* In case our inetd was lax in logging source addresses */
-	addrstring = getaddrstring(&remoteaddr, 1);
-	dropbear_log(LOG_INFO, "Child connection from %s", addrstring);
+	get_socket_address(0, NULL, NULL, &host, &port, 0);
+	dropbear_log(LOG_INFO, "Child connection from %s:%s", host, port);
+	m_free(host);
+	m_free(port);
 
 	/* Don't check the return value - it may just fail since inetd has
 	 * already done setsid() after forking (xinetd on Darwin appears to do
@@ -102,7 +96,7 @@
 	/* Start service program 
 	 * -1 is a dummy childpipe, just something we can close() without 
 	 * mattering. */
-	svr_session(0, -1, getaddrhostname(&remoteaddr), addrstring);
+	svr_session(0, -1);
 
 	/* notreached */
 }
@@ -218,14 +212,13 @@
 
 		/* handle each socket which has something to say */
 		for (i = 0; i < listensockcount; i++) {
-
-			struct sockaddr_storage remoteaddr;
-			socklen_t remoteaddrlen = 0;
 			size_t num_unauthed_for_addr = 0;
 			size_t num_unauthed_total = 0;
-			char * remote_addr_str = NULL;
+			char *remote_host = NULL, *remote_port = NULL;
 			pid_t fork_ret = 0;
 			size_t conn_idx = 0;
+			struct sockaddr_storage remoteaddr;
+			socklen_t remoteaddrlen;
 
 			if (!FD_ISSET(listensocks[i], &fds)) 
 				continue;
@@ -240,14 +233,14 @@
 			}
 
 			/* Limit the number of unauthenticated connections per IP */
-			remote_addr_str = getaddrstring(&remoteaddr, 0);
+			getaddrstring(&remoteaddr, &remote_host, NULL, 0);
 
 			num_unauthed_for_addr = 0;
 			num_unauthed_total = 0;
 			for (j = 0; j < MAX_UNAUTH_CLIENTS; j++) {
 				if (childpipes[j] >= 0) {
 					num_unauthed_total++;
-					if (strcmp(remote_addr_str, preauth_addrs[j]) == 0) {
+					if (strcmp(remote_host, preauth_addrs[j]) == 0) {
 						num_unauthed_for_addr++;
 					}
 				} else {
@@ -280,21 +273,21 @@
 				/* parent */
 				childpipes[conn_idx] = childpipe[0];
 				m_close(childpipe[1]);
-				preauth_addrs[conn_idx] = remote_addr_str;
-				remote_addr_str = NULL;
+				preauth_addrs[conn_idx] = remote_host;
+				remote_host = NULL;
 
 			} else {
 
 				/* child */
-				char * addrstring = NULL;
 #ifdef DEBUG_FORKGPROF
 				extern void _start(void), etext(void);
 				monstartup((u_long)&_start, (u_long)&etext);
 #endif /* DEBUG_FORKGPROF */
 
-				m_free(remote_addr_str);
-				addrstring = getaddrstring(&remoteaddr, 1);
-				dropbear_log(LOG_INFO, "Child connection from %s", addrstring);
+				getaddrstring(&remoteaddr, NULL, &remote_port, 0);
+				dropbear_log(LOG_INFO, "Child connection from %s:%s", remote_host, remote_port);
+				m_free(remote_host);
+				m_free(remote_port);
 
 #ifndef DEBUG_NOFORK
 				if (setsid() < 0) {
@@ -310,9 +303,7 @@
 				m_close(childpipe[0]);
 
 				/* start the session */
-				svr_session(childsock, childpipe[1], 
-								getaddrhostname(&remoteaddr),
-								addrstring);
+				svr_session(childsock, childpipe[1]);
 				/* don't return */
 				dropbear_assert(0);
 			}
@@ -320,8 +311,8 @@
 out:
 			/* This section is important for the parent too */
 			m_close(childsock);
-			if (remote_addr_str) {
-				m_free(remote_addr_str);
+			if (remote_host) {
+				m_free(remote_host);
 			}
 		}
 	} /* for(;;) loop */
--- a/svr-runopts.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/svr-runopts.c	Tue Sep 01 16:38:26 2009 +0000
@@ -296,15 +296,19 @@
 	}
 	
 	if (keepalive_arg) {
-		if (m_str_to_uint(keepalive_arg, &opts.keepalive_secs) == DROPBEAR_FAILURE) {
+		unsigned int val;
+		if (m_str_to_uint(keepalive_arg, &val) == DROPBEAR_FAILURE) {
 			dropbear_exit("Bad keepalive '%s'", keepalive_arg);
 		}
+		opts.keepalive_secs = val;
 	}
 
 	if (idle_timeout_arg) {
-		if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) {
+		unsigned int val;
+		if (m_str_to_uint(idle_timeout_arg, &val) == DROPBEAR_FAILURE) {
 			dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
 		}
+		opts.idle_timeout_secs = val;
 	}
 }
 
--- a/svr-session.c	Mon Aug 31 15:25:39 2009 +0000
+++ b/svr-session.c	Tue Sep 01 16:38:26 2009 +0000
@@ -74,27 +74,33 @@
 	NULL /* Null termination is mandatory. */
 };
 
-void svr_session(int sock, int childpipe, 
-		char* remotehost, char *addrstring) {
-
+void svr_session(int sock, int childpipe) {
+	char *host, *port;
+	size_t len;
     reseedrandom();
 
 	crypto_init();
-	common_session_init(sock, sock, remotehost);
+	common_session_init(sock, sock);
 
 	/* Initialise server specific parts of the session */
 	svr_ses.childpipe = childpipe;
-	svr_ses.addrstring = addrstring;
 #ifdef __uClinux__
 	svr_ses.server_pid = getpid();
 #endif
-	svr_ses.addrstring = addrstring;
 	svr_authinitialise();
 	chaninitialise(svr_chantypes);
 	svr_chansessinitialise();
 
 	ses.connect_time = time(NULL);
 
+	/* for logging the remote address */
+	get_socket_address(ses.sock_in, NULL, NULL, &host, &port, 0);
+	len = strlen(host) + strlen(port) + 2;
+	svr_ses.addrstring = m_malloc(len);
+	snprintf(svr_ses.addrstring, len, "%s:%s", host, port);
+	m_free(host);
+	m_free(port);
+
 	/* set up messages etc */
 	ses.remoteclosed = svr_remoteclosed;