From cba809e2933c913fcd088d77957005b55632634d Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 27 May 2019 10:03:45 +0200 Subject: [PATCH] Control socket: respect IP version selection If user requests either -4 or -6 from command-line, the same value is used for the control socket. --- src/control_socket.cpp | 22 +++++++++++++-------- src/control_socket.h | 4 +++- src/hd-rum-translator/hd-rum-translator.cpp | 2 +- src/main.cpp | 4 ++-- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/control_socket.cpp b/src/control_socket.cpp index 9f738dbd5..0001727a2 100644 --- a/src/control_socket.cpp +++ b/src/control_socket.cpp @@ -99,7 +99,7 @@ struct control_state { enum connection_type connection_type; - fd_t socket_fd; + fd_t socket_fd = INVALID_SOCKET; bool started; @@ -152,7 +152,7 @@ static void new_message(struct module *m) { } } -int control_init(int port, int connection_type, struct control_state **state, struct module *root_module) +int control_init(int port, int connection_type, struct control_state **state, struct module *root_module, int force_ip_version) { control_state *s = new control_state(); @@ -173,11 +173,13 @@ int control_init(int port, int connection_type, struct control_state **state, st } if(s->connection_type == SERVER) { - bool ipv6_missing; - s->socket_fd = socket(AF_INET6, SOCK_STREAM, 0); - if (s->socket_fd == INVALID_SOCKET && errno == EAFNOSUPPORT) { // try IPv4 + int ip_version = 6; + if (force_ip_version != 4) { + s->socket_fd = socket(AF_INET6, SOCK_STREAM, 0); + } + if (force_ip_version == 4 || (s->socket_fd == INVALID_SOCKET && errno == EAFNOSUPPORT)) { // try IPv4 + ip_version = 4; s->socket_fd = socket(AF_INET, SOCK_STREAM, 0); - ipv6_missing = true; } if (s->socket_fd == INVALID_SOCKET) { perror("Control socket - socket"); @@ -192,7 +194,7 @@ int control_init(int port, int connection_type, struct control_state **state, st } int ipv6only = 0; - if (!ipv6_missing && setsockopt(s->socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, + if (ip_version == 6 && setsockopt(s->socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)) != 0) { perror("setsockopt IPV6_V6ONLY"); } @@ -202,7 +204,7 @@ int control_init(int port, int connection_type, struct control_state **state, st * using the IPPROTO_IPV6 level socket option IPV6_V6ONLY if required.*/ struct sockaddr_storage s_in; memset(&s_in, 0, sizeof(s_in)); - if(ipv6_missing) { + if (ip_version == 4) { struct sockaddr_in *s_in = (struct sockaddr_in *) &s_in; s_in->sin_family = AF_INET; s_in->sin_addr.s_addr = htonl(INADDR_ANY); @@ -228,6 +230,10 @@ int control_init(int port, int connection_type, struct control_state **state, st } } } else { + if (force_ip_version == 6) { + log_msg(LOG_LEVEL_ERROR, "Control socket: IPv6 unimplemented in client mode!\n"); + return -1; + } s->socket_fd = socket(AF_INET, SOCK_STREAM, 0); assert(s->socket_fd != INVALID_SOCKET); struct addrinfo hints, *res, *res0; diff --git a/src/control_socket.h b/src/control_socket.h index 49762dfd7..3202c761f 100644 --- a/src/control_socket.h +++ b/src/control_socket.h @@ -55,9 +55,11 @@ struct control_state; struct module; /** + * @param[in] force_ip_version IP version to force (4 or 6). Use 0 to + * use default (both 4 and 6 if available) * @retval 0 if success */ -int control_init(int port, int connection_type, struct control_state **state, struct module *root_module); +int control_init(int port, int connection_type, struct control_state **state, struct module *root_module, int force_ip_version); void control_start(struct control_state *state); void control_done(struct control_state *s); void control_report_stats(struct control_state *state, const std::string & stat_line); diff --git a/src/hd-rum-translator/hd-rum-translator.cpp b/src/hd-rum-translator/hd-rum-translator.cpp index de7d5f353..ca4adab31 100644 --- a/src/hd-rum-translator/hd-rum-translator.cpp +++ b/src/hd-rum-translator/hd-rum-translator.cpp @@ -725,7 +725,7 @@ int main(int argc, char **argv) state.replicas.resize(params.host_count); if (params.control_port != -1) { - if(control_init(params.control_port, params.control_connection_type, &state.control_state, &state.mod) != 0) { + if (control_init(params.control_port, params.control_connection_type, &state.control_state, &state.mod, 0) != 0) { fprintf(stderr, "Warning: Unable to create remote control.\n"); return EXIT_FAIL_CONTROL_SOCK; } diff --git a/src/main.cpp b/src/main.cpp index 38b1eba12..73163079e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1076,8 +1076,8 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - if (control_init(control_port, connection_type, &control, &uv.root_module) != 0) { - fprintf(stderr, "Error: Unable to initialize remote control!\n"); + if (control_init(control_port, connection_type, &control, &uv.root_module, force_ip_version) != 0) { + LOG(LOG_LEVEL_FATAL) << "Error: Unable to initialize remote control!\n"; return EXIT_FAIL_CONTROL_SOCK; }