diff --git a/src/config/cmdline.c b/src/config/cmdline.c index bc4facdd..3d0db168 100644 --- a/src/config/cmdline.c +++ b/src/config/cmdline.c @@ -781,6 +781,10 @@ union option_info cmdline_options_info[] = { "bind-address", 0, "", N_("Use a specific local IP address")), + INIT_OPT_STRING("", N_("Use a specific local IPv6 address"), + "bind-address-ipv6", 0, "", + N_("Use a specific local IPv6 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 14637dd1..22579553 100644 --- a/src/network/socket.c +++ b/src/network/socket.c @@ -555,7 +555,9 @@ connect_socket(struct socket *csocket, struct connection_state state) * XXX: Unify with @local_only handling? --pasky */ int silent_fail = 0; unsigned char *bind_address = get_cmd_opt_str("bind-address"); + unsigned char *bind_address_ipv6 = get_cmd_opt_str("bind-address-ipv6"); int to_bind = (bind_address && *bind_address); + int to_bind_ipv6 = (bind_address_ipv6 && *bind_address_ipv6); csocket->ops->set_state(csocket, state); @@ -628,7 +630,7 @@ connect_socket(struct socket *csocket, struct connection_state state) } #ifdef HAVE_INET_PTON - if (to_bind) { + if (pf == PF_INET && to_bind) { struct sockaddr_in sa; int res; @@ -638,6 +640,23 @@ connect_socket(struct socket *csocket, struct connection_state state) 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; + } + } +#ifdef CONFIG_IPV6 + if (pf == PF_INET6 && to_bind_ipv6) { + struct sockaddr_in sa; + int res; + + memset(&sa, 0, sizeof sa); + sa.sin_family = AF_INET6; + inet_pton(AF_INET6, bind_address_ipv6, &(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); @@ -645,6 +664,8 @@ connect_socket(struct socket *csocket, struct connection_state state) } } #endif +#endif + csocket->fd = sock;