# HG changeset patch # User houseofkodai # Date 1493607375 -19800 # Node ID f7a53832501da35f6c53fdd4c341908635616082 # Parent ad637c9e0f6fb4e311b0dcfb9e8b673860f6b165 cli_bind_address_connect * replaces -b dummy option in dbclient to be similar with openssh -b option * useful in multi-wan connections diff -r ad637c9e0f6f -r f7a53832501d cli-main.c --- a/cli-main.c Thu Jan 25 19:51:41 2018 +0530 +++ b/cli-main.c Mon May 01 08:26:15 2017 +0530 @@ -66,8 +66,8 @@ } #endif - TRACE(("user='%s' host='%s' port='%s'", cli_opts.username, - cli_opts.remotehost, cli_opts.remoteport)) + TRACE(("user='%s' host='%s' port='%s' bind_address='%s'", cli_opts.username, + cli_opts.remotehost, cli_opts.remoteport, cli_opts.bind_address)) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { dropbear_exit("signal() error"); @@ -86,7 +86,7 @@ } else #endif { - progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, cli_connected, &ses); + progress = connect_remote(cli_opts.remotehost, cli_opts.remoteport, cli_connected, &ses, cli_opts.bind_address); sock_in = sock_out = -1; } diff -r ad637c9e0f6f -r f7a53832501d cli-runopts.c --- a/cli-runopts.c Thu Jan 25 19:51:41 2018 +0530 +++ b/cli-runopts.c Mon May 01 08:26:15 2017 +0530 @@ -92,6 +92,7 @@ "-c Specify preferred ciphers ('-c help' to list options)\n" "-m Specify preferred MACs for packet verification (or '-m help')\n" #endif + "-b bind_address\n" "-V Version\n" #if DEBUG_TRACE "-v verbose (compiled with DEBUG_TRACE)\n" @@ -125,7 +126,6 @@ OPT_OTHER } opt; unsigned int cmdlen; - char* dummy = NULL; /* Not used for anything real */ char* recv_window_arg = NULL; char* keepalive_arg = NULL; @@ -166,6 +166,7 @@ #if DROPBEAR_CLI_PROXYCMD cli_opts.proxycmd = NULL; #endif + cli_opts.bind_address = NULL; #ifndef DISABLE_ZLIB opts.compress_mode = DROPBEAR_COMPRESS_ON; #endif @@ -314,8 +315,8 @@ exit(EXIT_SUCCESS); break; case 'b': - next = &dummy; - /* FALLTHROUGH */ + next = &cli_opts.bind_address; + break; default: fprintf(stderr, "WARNING: Ignoring unknown option -%c\n", c); diff -r ad637c9e0f6f -r f7a53832501d cli-tcpfwd.c --- a/cli-tcpfwd.c Thu Jan 25 19:51:41 2018 +0530 +++ b/cli-tcpfwd.c Mon May 01 08:26:15 2017 +0530 @@ -274,7 +274,7 @@ } snprintf(portstring, sizeof(portstring), "%u", fwd->connectport); - channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel); + channel->conn_pending = connect_remote(fwd->connectaddr, portstring, channel_connect_done, channel, NULL); channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE; diff -r ad637c9e0f6f -r f7a53832501d netio.c --- a/netio.c Thu Jan 25 19:51:41 2018 +0530 +++ b/netio.c Mon May 01 08:26:15 2017 +0530 @@ -19,6 +19,7 @@ int sock; char* errstring; + struct addrinfo *bind_addrinfo; }; /* Deallocate a progress connection. Removes from the pending list if iter!=NULL. @@ -30,6 +31,7 @@ m_free(c->remotehost); m_free(c->remoteport); m_free(c->errstring); + if (c->bind_addrinfo) freeaddrinfo(c->bind_addrinfo); m_free(c); if (iter) { @@ -66,6 +68,17 @@ continue; } + if (c->bind_addrinfo) { + if (bind(c->sock, c->bind_addrinfo->ai_addr, c->bind_addrinfo->ai_addrlen) < 0) { + /* failure */ + m_free(c->errstring); + c->errstring = m_strdup(strerror(errno)); + close(c->sock); + c->sock = -1; + continue; + } + } + ses.maxfd = MAX(ses.maxfd, c->sock); set_sock_nodelay(c->sock); setnonblocking(c->sock); @@ -130,7 +143,7 @@ /* Connect via TCP to a host. */ struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport, - connect_callback cb, void* cb_data) + connect_callback cb, void* cb_data, char* bind_address) { struct dropbear_progress_connection *c = NULL; int err; @@ -142,6 +155,7 @@ c->sock = -1; c->cb = cb; c->cb_data = cb_data; + c->bind_addrinfo = NULL; list_append(&ses.conn_pending, c); @@ -160,6 +174,22 @@ } else { c->res_iter = c->res; } + + if (NULL != bind_address) { + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + err = getaddrinfo(bind_address, NULL, &hints, &c->bind_addrinfo); + if (err) { + int len; + len = 100 + strlen(gai_strerror(err)); + c->errstring = (char*)m_malloc(len); + snprintf(c->errstring, len, "Error resolving '%s'. %s", + bind_address, gai_strerror(err)); + TRACE(("Error resolving: %s", gai_strerror(err))) + c->res_iter = NULL; + } + } return c; } diff -r ad637c9e0f6f -r f7a53832501d netio.h --- a/netio.h Thu Jan 25 19:51:41 2018 +0530 +++ b/netio.h Mon May 01 08:26:15 2017 +0530 @@ -30,7 +30,7 @@ /* Always returns a progress connection, if it fails it will call the callback at a later point */ struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport, - connect_callback cb, void *cb_data); + connect_callback cb, void *cb_data, char* bind_address); /* Sets up for select() */ void set_connect_fds(fd_set *writefd); diff -r ad637c9e0f6f -r f7a53832501d runopts.h --- a/runopts.h Thu Jan 25 19:51:41 2018 +0530 +++ b/runopts.h Mon May 01 08:26:15 2017 +0530 @@ -167,6 +167,7 @@ #if DROPBEAR_CLI_PROXYCMD char *proxycmd; #endif + char *bind_address; } cli_runopts; extern cli_runopts cli_opts; diff -r ad637c9e0f6f -r f7a53832501d svr-tcpfwd.c --- a/svr-tcpfwd.c Thu Jan 25 19:51:41 2018 +0530 +++ b/svr-tcpfwd.c Mon May 01 08:26:15 2017 +0530 @@ -285,7 +285,7 @@ } snprintf(portstring, sizeof(portstring), "%u", destport); - channel->conn_pending = connect_remote(desthost, portstring, channel_connect_done, channel); + channel->conn_pending = connect_remote(desthost, portstring, channel_connect_done, channel, NULL); channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;