changeset 63:dcc43965928f

- A nice cleaner structure for tcp (acceptor) forwarding. - still a checkpoint-ish commit - sorted out listening on localhost only
author Matt Johnston <matt@ucc.asn.au>
date Wed, 11 Aug 2004 17:26:47 +0000
parents 20563735e8b5
children efb5e0b335cf
files cli-tcpfwd.c dbutil.c listener.c listener.h svr-main.c svr-tcpfwd.c tcp-accept.c tcp-accept.h tcp-connect.c
diffstat 9 files changed, 77 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/cli-tcpfwd.c	Tue Aug 10 17:09:52 2004 +0000
+++ b/cli-tcpfwd.c	Wed Aug 11 17:26:47 2004 +0000
@@ -12,22 +12,26 @@
 	NULL
 };
 
+void setup_localtcp() {
 
+	qv
 
+}
 
-static int cli_localtcp(char* port) {
+static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
+		unsigned int remoteport) {
 
 	struct TCPListener* tcpinfo = NULL;
 
 	tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*));
-	tcpinfo->addr = NULL;
-	tcpinfo->port = port;
+	tcpinfo->sendaddr = remoteaddr;
+	tcpinfo->sendport = remoteport;
+	tcpinfo->listenport = listenport;
 	tcpinfo->chantype = &cli_chan_tcplocal;
 
 	ret = listen_tcpfwd(tcpinfo);
 
 	if (ret == DROPBEAR_FAILURE) {
-		DROPBEAR_LOG(LOG_WARNING, "Failed to listen on port %s", port);
 		m_free(tcpinfo);
 	}
 	return ret;
--- a/dbutil.c	Tue Aug 10 17:09:52 2004 +0000
+++ b/dbutil.c	Wed Aug 11 17:26:47 2004 +0000
@@ -114,10 +114,8 @@
 #endif /* DEBUG_TRACE */
 
 /* Listen on address:port. Unless address is NULL, in which case listen on
- * everything (ie 0.0.0.0, or ::1 - note that this is IPv? agnostic. Linux is
- * broken with respect to listening to v6 or v4, so the addresses you get when
- * people connect will be wrong. It doesn't break things, just looks quite
- * ugly. Returns the number of sockets bound on success, or -1 on failure. On
+ * everything. If called with address == "", we'll listen on localhost/loopback.
+ * Returns the number of sockets bound on success, or -1 on failure. On
  * failure, if errstring wasn't NULL, it'll be a newly malloced error
  * string.*/
 int dropbear_listen(const char* address, const char* port,
@@ -135,7 +133,14 @@
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
 	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_flags = AI_PASSIVE;
+
+	if (address && address[0] == '\0') {
+		TRACE(("dropbear_listen: local loopback"));
+		address = NULL;
+	} else {
+		TRACE(("dropbear_listen: not local loopback"));
+		hints.ai_flags = AI_PASSIVE;
+	}
 	err = getaddrinfo(address, port, &hints, &res0);
 
 	if (err) {
--- a/listener.c	Tue Aug 10 17:09:52 2004 +0000
+++ b/listener.c	Wed Aug 11 17:26:47 2004 +0000
@@ -42,7 +42,7 @@
 			for (j = 0; j < listener->nsocks; j++) {
 				sock = listener->socks[j];
 				if (FD_ISSET(sock, readfds)) {
-					listener->accepter(listener, sock);
+					listener->acceptor(listener, sock);
 				}
 			}
 		}
@@ -50,11 +50,11 @@
 }
 
 
-/* accepter(int fd, void* typedata) is a function to accept connections, 
+/* acceptor(int fd, void* typedata) is a function to accept connections, 
  * cleanup(void* typedata) happens when cleaning up */
 struct Listener* new_listener(int socks[], unsigned int nsocks,
 		int type, void* typedata, 
-		void (*accepter)(struct Listener*, int sock), 
+		void (*acceptor)(struct Listener* listener, int sock), 
 		void (*cleanup)(struct Listener*)) {
 
 	unsigned int i, j;
@@ -99,7 +99,7 @@
 	newlisten->typedata = typedata;
 	newlisten->nsocks = nsocks;
 	memcpy(newlisten->socks, socks, nsocks * sizeof(int));
-	newlisten->accepter = accepter;
+	newlisten->acceptor = acceptor;
 	newlisten->cleanup = cleanup;
 
 	ses.listeners[i] = newlisten;
--- a/listener.h	Tue Aug 10 17:09:52 2004 +0000
+++ b/listener.h	Wed Aug 11 17:26:47 2004 +0000
@@ -11,7 +11,7 @@
 
 	int index; /* index in the array of listeners */
 
-	void (*accepter)(struct Listener*, int sock);
+	void (*acceptor)(struct Listener*, int sock);
 	void (*cleanup)(struct Listener*);
 
 	int type; /* CHANNEL_ID_X11, CHANNEL_ID_AGENT, 
@@ -28,7 +28,7 @@
 
 struct Listener* new_listener(int socks[], unsigned int nsocks, 
 		int type, void* typedata, 
-		void (*accepter)(struct Listener*, int sock), 
+		void (*acceptor)(struct Listener* listener, int sock), 
 		void (*cleanup)(struct Listener*));
 
 struct Listener * get_listener(int type, void* typedata,
--- a/svr-main.c	Tue Aug 10 17:09:52 2004 +0000
+++ b/svr-main.c	Wed Aug 11 17:26:47 2004 +0000
@@ -188,7 +188,8 @@
 
 			/* child connection XXX - ip6 stuff here */
 			remoteaddrlen = sizeof(remoteaddr);
-			childsock = accept(listensocks[i], &remoteaddr, &remoteaddrlen);
+			childsock = accept(listensocks[i], 
+					(struct sockaddr*)&remoteaddr, &remoteaddrlen);
 
 			if (childsock < 0) {
 				/* accept failed */
@@ -295,7 +296,7 @@
 static int listensockets(int *sock, int sockcount, int *maxfd) {
 	
 	unsigned int i;
-	char portstring[6];
+	char portstring[NI_MAXSERV];
 	char* errstring = NULL;
 	unsigned int sockpos = 0;
 	int nsock;
--- a/svr-tcpfwd.c	Tue Aug 10 17:09:52 2004 +0000
+++ b/svr-tcpfwd.c	Wed Aug 11 17:26:47 2004 +0000
@@ -104,9 +104,9 @@
 	const struct TCPListener *info1 = (struct TCPListener*)typedata1;
 	const struct TCPListener *info2 = (struct TCPListener*)typedata2;
 
-	return (info1->port == info2->port)
+	return (info1->sendport == info2->sendport)
 			&& (info1->chantype == info2->chantype)
-			&& (strcmp(info1->addr, info2->addr) == 0);
+			&& (strcmp(info1->sendaddr, info2->sendaddr) == 0);
 }
 
 static int svr_cancelremotetcp() {
@@ -128,8 +128,8 @@
 
 	port = buf_getint(ses.payload);
 
-	tcpinfo.addr = bindaddr;
-	tcpinfo.port = port;
+	tcpinfo.sendaddr = bindaddr;
+	tcpinfo.sendport = port;
 	listener = get_listener(CHANNEL_ID_TCPFORWARDED, &tcpinfo, matchtcp);
 	if (listener) {
 		remove_listener( listener );
@@ -152,6 +152,7 @@
 
 	TRACE(("enter remotetcpreq"));
 
+	/* NOTE: at this stage, we ignore bindaddr. see below and listen_tcpfwd */
 	bindaddr = buf_getstring(ses.payload, &addrlen);
 	if (addrlen > MAX_IP_LEN) {
 		TRACE(("addr len too long: %d", addrlen));
@@ -176,18 +177,20 @@
 	}
 
 	tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
-	tcpinfo->addr = bindaddr;
-	tcpinfo->port = port;
-	tcpinfo->localport = -1;
+	tcpinfo->sendaddr = bindaddr;
+	TRACE(("sendport = %d", port));
+	tcpinfo->sendport = port;
 	tcpinfo->chantype = &svr_chan_tcpremote;
 
+	/* Note: bindaddr is actually ignored by listen_tcpfwd, since
+	 * we only want to bind to localhost */
 	ret = listen_tcpfwd(tcpinfo);
 
 out:
 	if (ret == DROPBEAR_FAILURE) {
 		/* we only free it if a listener wasn't created, since the listener
 		 * has to remember it if it's to be cancelled */
-		m_free(tcpinfo->addr);
+		m_free(tcpinfo->sendaddr);
 		m_free(tcpinfo);
 	}
 	TRACE(("leave remotetcpreq"));
--- a/tcp-accept.c	Tue Aug 10 17:09:52 2004 +0000
+++ b/tcp-accept.c	Wed Aug 11 17:26:47 2004 +0000
@@ -10,7 +10,16 @@
 
 #ifndef DISABLE_TCP_ACCEPT
 
-static void accept_tcp(struct Listener *listener, int sock) {
+
+static void cleanup_tcp(struct Listener *listener) {
+
+	struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata);
+
+	m_free(tcpinfo->sendaddr);
+	m_free(tcpinfo);
+}
+
+static void tcp_acceptor(struct Listener *listener, int sock) {
 
 	int fd;
 	struct sockaddr_storage addr;
@@ -33,10 +42,12 @@
 
 	if (send_msg_channel_open_init(fd, tcpinfo->chantype) == DROPBEAR_SUCCESS) {
 
-		buf_putstring(ses.writepayload, tcpinfo->addr, strlen(tcpinfo->addr));
-		buf_putint(ses.writepayload, tcpinfo->port);
+		buf_putstring(ses.writepayload, tcpinfo->sendaddr, 
+				strlen(tcpinfo->sendaddr));
+		buf_putint(ses.writepayload, tcpinfo->sendport);
 		buf_putstring(ses.writepayload, ipstring, strlen(ipstring));
 		buf_putint(ses.writepayload, atol(portstring));
+
 		encrypt_packet();
 
 	} else {
@@ -45,35 +56,33 @@
 	}
 }
 
-static void cleanup_tcp(struct Listener *listener) {
-
-	struct TCPListener *tcpinfo = (struct TCPListener*)(listener->typedata);
-
-	m_free(tcpinfo->addr);
-	m_free(tcpinfo);
-}
-
-
 int listen_tcpfwd(struct TCPListener* tcpinfo) {
 
-	char portstring[6]; /* "65535\0" */
+	char portstring[NI_MAXSERV];
 	int socks[DROPBEAR_MAX_SOCKS];
 	struct Listener *listener = NULL;
 	int nsocks;
+	char* errstring = NULL;
 
 	TRACE(("enter listen_tcpfwd"));
 
 	/* first we try to bind, so don't need to do so much cleanup on failure */
-	snprintf(portstring, sizeof(portstring), "%d", tcpinfo->port);
-	nsocks = dropbear_listen(tcpinfo->addr, portstring, socks, 
-			DROPBEAR_MAX_SOCKS, NULL, &ses.maxfd);
+	snprintf(portstring, sizeof(portstring), "%d", tcpinfo->sendport);
+
+	/* XXX Note: we're just listening on localhost, no matter what they tell
+	 * us. If someone wants to make it listen otherways, then change
+	 * the "" argument. but that requires UI changes too */
+	nsocks = dropbear_listen("", portstring, socks, 
+			DROPBEAR_MAX_SOCKS, &errstring, &ses.maxfd);
 	if (nsocks < 0) {
+		dropbear_log(LOG_INFO, "TCP forward failed: %s", errstring);
+		m_free(errstring);
 		TRACE(("leave listen_tcpfwd: dropbear_listen failed"));
 		return DROPBEAR_FAILURE;
 	}
 
 	listener = new_listener(socks, nsocks, CHANNEL_ID_TCPFORWARDED, tcpinfo, 
-			accept_tcp, cleanup_tcp);
+			tcp_acceptor, cleanup_tcp);
 
 	if (listener == NULL) {
 		m_free(tcpinfo);
--- a/tcp-accept.h	Tue Aug 10 17:09:52 2004 +0000
+++ b/tcp-accept.h	Wed Aug 11 17:26:47 2004 +0000
@@ -3,12 +3,18 @@
 
 struct TCPListener {
 
-	/* Local ones */
-	unsigned char *localaddr; /* Can be NULL */
-	unsigned int localport;
-	/* Remote ones: */
-	unsigned char *remoteaddr;
-	unsigned int remoteport;
+	/* sendaddr/sendport are what we send in the channel init request. For a 
+	 * forwarded-tcpip request, it's the addr/port we were binding to.
+	 * For a direct-tcpip request, it's the addr/port we want the other
+	 * end to connect to */
+	
+	unsigned char *sendaddr;
+	unsigned int sendport;
+
+	/* This is for direct-tcpip (ie the client listening), and specifies the
+	 * port to listen on. Is unspecified for the server */
+	unsigned int listenport;
+
 	const struct ChanType *chantype;
 
 };
--- a/tcp-connect.c	Tue Aug 10 17:09:52 2004 +0000
+++ b/tcp-connect.c	Wed Aug 11 17:26:47 2004 +0000
@@ -15,7 +15,7 @@
 	unsigned int destport;
 	unsigned char* orighost = NULL;
 	unsigned int origport;
-	char portstring[6];
+	char portstring[NI_MAXSERV];
 	int sock;
 	int len;
 	int ret = DROPBEAR_FAILURE;