diff --git a/src/config/cmdline.c b/src/config/cmdline.c index f4c9a4452..bc4facdd6 100644 --- a/src/config/cmdline.c +++ b/src/config/cmdline.c @@ -777,6 +777,10 @@ union option_info cmdline_options_info[] = { "windows. The ID maps to information that will be used when " "creating the new instance. You don't want to use it.")), + INIT_OPT_STRING("", N_("Use a specific local IP address"), + "bind-address", 0, "", + N_("Use a specific local IP address")), + INIT_OPT_COMMAND("", NULL, "confdir", OPT_HIDDEN, redir_cmd, NULL), INIT_OPT_STRING("", N_("Name of directory with configuration file"), diff --git a/src/network/socket.c b/src/network/socket.c index 3426b6814..14637dd12 100644 --- a/src/network/socket.c +++ b/src/network/socket.c @@ -554,6 +554,8 @@ connect_socket(struct socket *csocket, struct connection_state state) * about such a connection attempt. * XXX: Unify with @local_only handling? --pasky */ int silent_fail = 0; + unsigned char *bind_address = get_cmd_opt_str("bind-address"); + int to_bind = (bind_address && *bind_address); csocket->ops->set_state(csocket, state); @@ -624,6 +626,26 @@ connect_socket(struct socket *csocket, struct connection_state state) close(sock); continue; } + +#ifdef HAVE_INET_PTON + if (to_bind) { + struct sockaddr_in sa; + int res; + + memset(&sa, 0, sizeof sa); + sa.sin_family = AF_INET; + inet_pton(AF_INET, bind_address, &(sa.sin_addr)); + sa.sin_port = htons(0); + res = bind(sock, (struct sockaddr *)(void *)&sa, sizeof sa); + + if (res < 0) { + if (errno && !saved_errno) saved_errno = errno; + close(sock); + continue; + } + } +#endif + csocket->fd = sock; #ifdef CONFIG_IPV6