summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2004-08-11 17:26:47 +0000
committerMatt Johnston <matt@ucc.asn.au>2004-08-11 17:26:47 +0000
commit09d419bc31dc598240ed03cdf9168d7d0ae6a98f (patch)
treedffe7a4d63c88753c9763cbbe584d3d95d1a95f2
parent97858f3dcef78891ed7befc02d073c3dd4d9be18 (diff)
downloaddropbear-09d419bc31dc598240ed03cdf9168d7d0ae6a98f.tar.gz
- A nice cleaner structure for tcp (acceptor) forwarding.
- still a checkpoint-ish commit - sorted out listening on localhost only
-rw-r--r--cli-tcpfwd.c12
-rw-r--r--dbutil.c15
-rw-r--r--listener.c8
-rw-r--r--listener.h4
-rw-r--r--svr-main.c5
-rw-r--r--svr-tcpfwd.c19
-rw-r--r--tcp-accept.c43
-rw-r--r--tcp-accept.h18
-rw-r--r--tcp-connect.c2
9 files changed, 77 insertions, 49 deletions
diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c
index 3dc6e20..955ffab 100644
--- a/cli-tcpfwd.c
+++ b/cli-tcpfwd.c
@@ -12,22 +12,26 @@ static const struct ChanType cli_chan_tcplocal = {
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;
diff --git a/dbutil.c b/dbutil.c
index a377da2..72d25e7 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -114,10 +114,8 @@ void dropbear_trace(const char* format, ...) {
#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 @@ int dropbear_listen(const char* address, const char* port,
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) {
diff --git a/listener.c b/listener.c
index 3022bd5..9424c6a 100644
--- a/listener.c
+++ b/listener.c
@@ -42,7 +42,7 @@ void handle_listeners(fd_set * readfds) {
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 @@ void handle_listeners(fd_set * readfds) {
}
-/* 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 @@ struct Listener* new_listener(int socks[], unsigned int nsocks,
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;
diff --git a/listener.h b/listener.h
index c634ead..11f9dc4 100644
--- a/listener.h
+++ b/listener.h
@@ -11,7 +11,7 @@ struct Listener {
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 @@ void set_listener_fds(fd_set * readfds);
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,
diff --git a/svr-main.c b/svr-main.c
index 6a49626..503d781 100644
--- a/svr-main.c
+++ b/svr-main.c
@@ -188,7 +188,8 @@ int main(int argc, char ** argv)
/* 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 void sigintterm_handler(int fish) {
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;
diff --git a/svr-tcpfwd.c b/svr-tcpfwd.c
index 499ee46..46c7129 100644
--- a/svr-tcpfwd.c
+++ b/svr-tcpfwd.c
@@ -104,9 +104,9 @@ static int matchtcp(void* typedata1, void* typedata2) {
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 @@ static int svr_cancelremotetcp() {
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 @@ static int svr_remotetcpreq() {
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 @@ static int svr_remotetcpreq() {
}
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"));
diff --git a/tcp-accept.c b/tcp-accept.c
index 1fb80dd..8f8b5c0 100644
--- a/tcp-accept.c
+++ b/tcp-accept.c
@@ -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 @@ static void accept_tcp(struct Listener *listener, int sock) {
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 accept_tcp(struct Listener *listener, int sock) {
}
}
-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);
diff --git a/tcp-accept.h b/tcp-accept.h
index 96ddb76..8c795dc 100644
--- a/tcp-accept.h
+++ b/tcp-accept.h
@@ -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;
};
diff --git a/tcp-connect.c b/tcp-connect.c
index 00dbd8a..d24f32d 100644
--- a/tcp-connect.c
+++ b/tcp-connect.c
@@ -15,7 +15,7 @@ int newtcpdirect(struct Channel * channel) {
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;