From 12f23b311c189caf54b20df1a53b148205a283a9 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 10 Jan 2022 08:29:05 -0500 Subject: [PATCH] TT#157801 shift handling of v4/v6 addresses Handling of dual stack v4/v6 was previously done by the individual listener objects for INADDR_ANY listening addresses. If listening on INADDR_ANY was requested, then each listener would create two instances, one for IPv4 and one for IPv6. This works fine for INADDR_ANY but fails for listening on host names that resolve to multiple addresses, such as `localhost`. Solve this by relieving the listener objects from handling this and instead handle it in the code setting up the listeners. If a host name resolves to multiple addresses, then set up multiple listeners (up to two supported currently). This allows us to listen on `localhost` by default and have both 127.0.0.1 and ::1 active. INADDR_ANY is handled specially by also setting up :: in that case. Change-Id: I2a1e1d7090d7d23863c7a9bb1e89b85ad2ea44f4 --- daemon/cli.c | 65 +++++++++++-------- daemon/control_ng.c | 44 +++---------- daemon/control_tcp.c | 40 ++++-------- daemon/control_udp.c | 7 +- daemon/main.c | 145 +++++++++++++++++++++++++++++------------- include/cli.h | 2 +- include/control_ng.h | 7 +- include/control_udp.h | 2 +- include/main.h | 13 ++-- lib/socket.c | 56 +++++++++++----- lib/socket.h | 11 +++- t/test-stats.c | 1 + t/test-transcode.c | 1 + 13 files changed, 227 insertions(+), 167 deletions(-) diff --git a/daemon/cli.c b/daemon/cli.c index 509b73cb6..dcf6e8d37 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -315,11 +315,22 @@ static void cli_incoming_params_start(str *instr, struct cli_writer *cw) { "recording-format = %s\niptables-chain = %s\n", initial_rtpe_config.b2b_url, initial_rtpe_config.redis_auth, initial_rtpe_config.redis_write_auth, initial_rtpe_config.spooldir, initial_rtpe_config.rec_method, initial_rtpe_config.rec_format, initial_rtpe_config.iptables_chain); - cw->cw_printf(cw,"listen-tcp = %s:%d\nlisten-udp = %s:%d\nlisten-ng = %s:%d\nlisten-cli = %s:%d\n", - sockaddr_print_buf(&initial_rtpe_config.tcp_listen_ep.address), initial_rtpe_config.tcp_listen_ep.port, - sockaddr_print_buf(&initial_rtpe_config.udp_listen_ep.address), initial_rtpe_config.udp_listen_ep.port, - sockaddr_print_buf(&initial_rtpe_config.ng_listen_ep.address), initial_rtpe_config.ng_listen_ep.port, - sockaddr_print_buf(&initial_rtpe_config.cli_listen_ep.address), initial_rtpe_config.cli_listen_ep.port); + cw->cw_printf(cw, "listen-tcp = %s\n", + endpoint_print_buf(&initial_rtpe_config.tcp_listen_ep[0])); + cw->cw_printf(cw, "listen-tcp = %s\n", + endpoint_print_buf(&initial_rtpe_config.tcp_listen_ep[1])); + cw->cw_printf(cw, "listen-udp = %s\n", + endpoint_print_buf(&initial_rtpe_config.udp_listen_ep[0])); + cw->cw_printf(cw, "listen-udp = %s\n", + endpoint_print_buf(&initial_rtpe_config.udp_listen_ep[1])); + cw->cw_printf(cw, "listen-ng = %s\n", + endpoint_print_buf(&initial_rtpe_config.ng_listen_ep[0])); + cw->cw_printf(cw, "listen-ng = %s\n", + endpoint_print_buf(&initial_rtpe_config.ng_listen_ep[1])); + cw->cw_printf(cw, "listen-cli = %s\n", + endpoint_print_buf(&initial_rtpe_config.cli_listen_ep[0])); + cw->cw_printf(cw, "listen-cli = %s\n", + endpoint_print_buf(&initial_rtpe_config.cli_listen_ep[1])); } static void cli_incoming_params_current(str *instr, struct cli_writer *cw) { @@ -367,11 +378,22 @@ static void cli_incoming_params_current(str *instr, struct cli_writer *cw) { "recording-format = %s\niptables-chain = %s\n", rtpe_config.b2b_url, rtpe_config.redis_auth, rtpe_config.redis_write_auth, rtpe_config.spooldir, rtpe_config.rec_method, rtpe_config.rec_format, rtpe_config.iptables_chain); - cw->cw_printf(cw,"listen-tcp = %s:%d\nlisten-udp = %s:%d\nlisten-ng = %s:%d\nlisten-cli = %s:%d\n", - sockaddr_print_buf(&rtpe_config.tcp_listen_ep.address), rtpe_config.tcp_listen_ep.port, - sockaddr_print_buf(&rtpe_config.udp_listen_ep.address), rtpe_config.udp_listen_ep.port, - sockaddr_print_buf(&rtpe_config.ng_listen_ep.address), rtpe_config.ng_listen_ep.port, - sockaddr_print_buf(&rtpe_config.cli_listen_ep.address), rtpe_config.cli_listen_ep.port); + cw->cw_printf(cw, "listen-tcp = %s\n", + endpoint_print_buf(&rtpe_config.tcp_listen_ep[0])); + cw->cw_printf(cw, "listen-tcp = %s\n", + endpoint_print_buf(&rtpe_config.tcp_listen_ep[1])); + cw->cw_printf(cw, "listen-udp = %s\n", + endpoint_print_buf(&rtpe_config.udp_listen_ep[0])); + cw->cw_printf(cw, "listen-udp = %s\n", + endpoint_print_buf(&rtpe_config.udp_listen_ep[1])); + cw->cw_printf(cw, "listen-ng = %s\n", + endpoint_print_buf(&rtpe_config.ng_listen_ep[0])); + cw->cw_printf(cw, "listen-ng = %s\n", + endpoint_print_buf(&rtpe_config.ng_listen_ep[1])); + cw->cw_printf(cw, "listen-cli = %s\n", + endpoint_print_buf(&rtpe_config.cli_listen_ep[0])); + cw->cw_printf(cw, "listen-cli = %s\n", + endpoint_print_buf(&rtpe_config.cli_listen_ep[1])); } #define int_diff_print(struct_member, option_string) \ @@ -1217,8 +1239,7 @@ void cli_handle(str *instr, struct cli_writer *cw) { static void cli_free(void *p) { struct cli *c = p; - streambuf_listener_shutdown(&c->listeners[0]); - streambuf_listener_shutdown(&c->listeners[1]); + streambuf_listener_shutdown(&c->listener); } struct cli *cli_new(struct poller *p, endpoint_t *ep) { @@ -1229,7 +1250,7 @@ struct cli *cli_new(struct poller *p, endpoint_t *ep) { c = obj_alloc0("cli", sizeof(*c), cli_free); - if (streambuf_listener_init(&c->listeners[0], p, ep, + if (streambuf_listener_init(&c->listener, p, ep, cli_incoming, cli_stream_readable, NULL, NULL, @@ -1238,17 +1259,6 @@ struct cli *cli_new(struct poller *p, endpoint_t *ep) { ilogs(control, LOG_ERR, "Failed to open TCP control port: %s", strerror(errno)); goto fail; } - if (ipv46_any_convert(ep)) { - if (streambuf_listener_init(&c->listeners[1], p, ep, - cli_incoming, cli_stream_readable, - NULL, - NULL, - &c->obj)) - { - ilogs(control, LOG_ERR, "Failed to open TCP control port: %s", strerror(errno)); - goto fail; - } - } c->poller = p; @@ -1656,7 +1666,6 @@ static void cli_incoming_list_controltos(str *instr, struct cli_writer *cw) { static void cli_incoming_set_controltos(str *instr, struct cli_writer *cw) { long tos; char *endptr; - int i; if (str_shift(instr, 1)) { cw->cw_printf(cw, "%s\n", "More parameters required."); @@ -1674,9 +1683,9 @@ static void cli_incoming_set_controltos(str *instr, struct cli_writer *cw) { rtpe_config.control_tos = tos; rwlock_unlock_w(&rtpe_config.config_lock); - for (i=0; i < G_N_ELEMENTS(rtpe_control_ng->udp_listeners); i++) { - if (rtpe_control_ng->udp_listeners[i].fd != -1) { - set_tos(&rtpe_control_ng->udp_listeners[i],tos); + for (int i = 0; i < G_N_ELEMENTS(rtpe_control_ng); i++) { + if (rtpe_control_ng[i]->udp_listener.fd != -1) { + set_tos(&rtpe_control_ng[i]->udp_listener, tos); } } diff --git a/daemon/control_ng.c b/daemon/control_ng.c index 8604d235e..f30252abc 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -26,7 +26,6 @@ mutex_t rtpe_cngs_lock; mutex_t tcp_connections_lock; GHashTable *rtpe_cngs_hash; GHashTable *tcp_connections_hash; -struct control_ng *rtpe_control_ng; static struct cookie_cache ng_cookie_cache; const char magic_load_limit_strings[__LOAD_LIMIT_MAX][64] = { @@ -516,12 +515,9 @@ void control_ng_free(void *p) { g_hash_table_destroy(rtpe_cngs_hash); rtpe_cngs_hash = NULL; } - poller_del_item(c->poller, c->udp_listeners[0].fd); - poller_del_item(c->poller, c->udp_listeners[1].fd); - close_socket(&c->udp_listeners[0]); - close_socket(&c->udp_listeners[1]); - streambuf_listener_shutdown(&c->tcp_listeners[0]); - streambuf_listener_shutdown(&c->tcp_listeners[1]); + poller_del_item(c->poller, c->udp_listener.fd); + close_socket(&c->udp_listener); + streambuf_listener_shutdown(&c->tcp_listener); if (tcp_connections_hash) g_hash_table_destroy(tcp_connections_hash); } @@ -534,20 +530,13 @@ struct control_ng *control_ng_new(struct poller *p, endpoint_t *ep, unsigned cha c = obj_alloc0("control_ng", sizeof(*c), control_ng_free); - c->udp_listeners[0].fd = -1; - c->udp_listeners[1].fd = -1; + c->udp_listener.fd = -1; c->poller = p; - if (udp_listener_init(&c->udp_listeners[0], p, ep, control_ng_incoming, &c->obj)) + if (udp_listener_init(&c->udp_listener, p, ep, control_ng_incoming, &c->obj)) goto fail2; if (tos) - set_tos(&c->udp_listeners[0],tos); - if (ipv46_any_convert(ep)) { - if (udp_listener_init(&c->udp_listeners[1], p, ep, control_ng_incoming, &c->obj)) - goto fail2; - if (tos) - set_tos(&c->udp_listeners[1],tos); - } + set_tos(&c->udp_listener, tos); return c; fail2: @@ -555,19 +544,16 @@ fail2: return NULL; } -struct control_ng *control_ng_tcp_new(struct poller *p, endpoint_t *ep, struct control_ng *ctrl_ng) { +struct control_ng *control_ng_tcp_new(struct poller *p, endpoint_t *ep) { if (!p) return NULL; - if (!ctrl_ng) { - ctrl_ng = obj_alloc0("control_ng", sizeof(*ctrl_ng), NULL); - ctrl_ng->udp_listeners[0].fd = -1; - ctrl_ng->udp_listeners[1].fd = -1; - } + struct control_ng * ctrl_ng = obj_alloc0("control_ng", sizeof(*ctrl_ng), NULL); + ctrl_ng->udp_listener.fd = -1; ctrl_ng->poller = p; - if (streambuf_listener_init(&ctrl_ng->tcp_listeners[0], p, ep, + if (streambuf_listener_init(&ctrl_ng->tcp_listener, p, ep, control_incoming, control_stream_readable, control_closed, NULL, @@ -575,16 +561,6 @@ struct control_ng *control_ng_tcp_new(struct poller *p, endpoint_t *ep, struct c ilog(LOG_ERR, "Failed to open TCP control port: %s", strerror(errno)); goto fail; } - if (ipv46_any_convert(ep)) { - if (streambuf_listener_init(&ctrl_ng->tcp_listeners[1], p, ep, - control_incoming, control_stream_readable, - control_closed, - NULL, - &ctrl_ng->obj)) { - ilog(LOG_ERR, "Failed to open TCP control port: %s", strerror(errno)); - goto fail; - } - } tcp_connections_hash = g_hash_table_new(g_str_hash, g_str_equal); mutex_init(&tcp_connections_lock); diff --git a/daemon/control_tcp.c b/daemon/control_tcp.c index b59a723fa..f7513d1eb 100644 --- a/daemon/control_tcp.c +++ b/daemon/control_tcp.c @@ -26,7 +26,7 @@ struct control_tcp { struct obj obj; - struct streambuf_listener listeners[2]; + struct streambuf_listener listener; pcre *parse_re; pcre_extra *parse_ree; @@ -44,22 +44,20 @@ static void control_stream_closed(struct streambuf_stream *s) { static void control_list(struct control_tcp *c, struct streambuf_stream *s) { - for (int i = 0; i < G_N_ELEMENTS(c->listeners); i++) { - if (!c->listeners[i].listener.family || !c->listeners[i].poller) - continue; // not used + if (!c->listener.listener.family || !c->listener.poller) + return; - mutex_lock(&c->listeners[i].lock); + mutex_lock(&c->listener.lock); - GList *streams = g_hash_table_get_values(c->listeners[i].streams); - for (GList *l = streams; l; l = l->next) { - struct streambuf_stream *cl = l->data; - streambuf_printf(s->outbuf, "%s\n", cl->addr); - } + GList *streams = g_hash_table_get_values(c->listener.streams); + for (GList *l = streams; l; l = l->next) { + struct streambuf_stream *cl = l->data; + streambuf_printf(s->outbuf, "%s\n", cl->addr); + } - mutex_unlock(&c->listeners[i].lock); + mutex_unlock(&c->listener.lock); - g_list_free(streams); - } + g_list_free(streams); streambuf_printf(s->outbuf, "End.\n"); } @@ -156,8 +154,7 @@ static void control_incoming(struct streambuf_stream *s) { static void control_tcp_free(void *p) { struct control_tcp *c = p; - streambuf_listener_shutdown(&c->listeners[0]); - streambuf_listener_shutdown(&c->listeners[1]); + streambuf_listener_shutdown(&c->listener); pcre_free(c->parse_re); pcre_free_study(c->parse_ree); } @@ -172,7 +169,7 @@ struct control_tcp *control_tcp_new(struct poller *p, endpoint_t *ep) { c = obj_alloc0("control", sizeof(*c), control_tcp_free); - if (streambuf_listener_init(&c->listeners[0], p, ep, + if (streambuf_listener_init(&c->listener, p, ep, control_incoming, control_stream_readable, control_stream_closed, control_stream_timer, @@ -181,17 +178,6 @@ struct control_tcp *control_tcp_new(struct poller *p, endpoint_t *ep) { ilogs(control, LOG_ERR, "Failed to open TCP control port: %s", strerror(errno)); goto fail; } - if (ipv46_any_convert(ep)) { - if (streambuf_listener_init(&c->listeners[1], p, ep, - control_incoming, control_stream_readable, - control_stream_closed, - control_stream_timer, - &c->obj)) - { - ilogs(control, LOG_ERR, "Failed to open TCP control port: %s", strerror(errno)); - goto fail; - } - } c->parse_re = pcre_compile( /* reqtype callid streams ip fromdom fromtype todom totype agent info |reqtype callid info | reqtype */ diff --git a/daemon/control_udp.c b/daemon/control_udp.c index f5a66aa29..e4e33c16c 100644 --- a/daemon/control_udp.c +++ b/daemon/control_udp.c @@ -138,8 +138,7 @@ void control_udp_free(void *p) { pcre_free_study(u->parse_ree); pcre_free(u->parse_re); pcre_free(u->fallback_re); - close_socket(&u->udp_listeners[0]); - close_socket(&u->udp_listeners[1]); + close_socket(&u->udp_listener); cookie_cache_cleanup(&u->cookie_cache); } @@ -174,9 +173,7 @@ struct control_udp *control_udp_new(struct poller *p, endpoint_t *ep) { cookie_cache_init(&c->cookie_cache); - if (udp_listener_init(&c->udp_listeners[0], p, ep, control_udp_incoming, &c->obj)) - goto fail2; - if (ipv46_any_convert(ep) && udp_listener_init(&c->udp_listeners[1], p, ep, control_udp_incoming, &c->obj)) + if (udp_listener_init(&c->udp_listener, p, ep, control_udp_incoming, &c->obj)) goto fail2; return c; diff --git a/daemon/main.c b/daemon/main.c index 6d60b52b4..dec6f8a93 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -62,9 +62,12 @@ struct poller *rtpe_poller; struct poller_map *rtpe_poller_map; struct rtpengine_config initial_rtpe_config; -static struct control_tcp *rtpe_tcp; -static struct control_udp *rtpe_udp; -static struct cli *rtpe_cli; +static struct control_tcp *rtpe_tcp[2]; +static struct control_udp *rtpe_udp[2]; +static struct cli *rtpe_cli[2]; + +struct control_ng *rtpe_control_ng[2]; +struct control_ng *rtpe_control_ng_tcp[2]; struct rtpengine_config rtpe_config = { // non-zero defaults @@ -631,24 +634,27 @@ static void options(int *argc, char ***argv) { } if (listenps) { - if (endpoint_parse_any_getaddrinfo(&rtpe_config.tcp_listen_ep, listenps)) + if (endpoint_parse_any_getaddrinfo_alt(&rtpe_config.tcp_listen_ep[0], &rtpe_config.tcp_listen_ep[1], listenps)) die("Invalid IP or port '%s' (--listen-tcp)", listenps); } if (listenudps) { - if (endpoint_parse_any_getaddrinfo(&rtpe_config.udp_listen_ep, listenudps)) + if (endpoint_parse_any_getaddrinfo_alt(&rtpe_config.udp_listen_ep[0], &rtpe_config.udp_listen_ep[1], listenudps)) die("Invalid IP or port '%s' (--listen-udp)", listenudps); } if (listenngs) { - if (endpoint_parse_any_getaddrinfo(&rtpe_config.ng_listen_ep, listenngs)) + if (endpoint_parse_any_getaddrinfo_alt(&rtpe_config.ng_listen_ep[0], &rtpe_config.ng_listen_ep[1], listenngs)) die("Invalid IP or port '%s' (--listen-ng)", listenngs); } if (listenngtcps) { - if (endpoint_parse_any_getaddrinfo(&rtpe_config.ng_tcp_listen_ep, listenngtcps)) + if (endpoint_parse_any_getaddrinfo_alt(&rtpe_config.ng_tcp_listen_ep[0], &rtpe_config.ng_tcp_listen_ep[1], + listenngtcps)) die("Invalid IP or port '%s' (--listen-tcp-ng)", listenngtcps); } - if (listencli) {if (endpoint_parse_any_getaddrinfo(&rtpe_config.cli_listen_ep, listencli)) - die("Invalid IP or port '%s' (--listen-cli)", listencli); + if (listencli) { + if (endpoint_parse_any_getaddrinfo_alt(&rtpe_config.cli_listen_ep[0], &rtpe_config.cli_listen_ep[1], + listencli)) + die("Invalid IP or port '%s' (--listen-cli)", listencli); } if (graphitep) {if (endpoint_parse_any_getaddrinfo_full(&rtpe_config.graphite_ep, graphitep)) @@ -902,11 +908,11 @@ void fill_initial_rtpe_cfg(struct rtpengine_config* ini_rtpe_cfg) { memcpy(&ini_rtpe_cfg->common.log_levels, &rtpe_config.common.log_levels, sizeof(ini_rtpe_cfg->common.log_levels)); ini_rtpe_cfg->graphite_ep = rtpe_config.graphite_ep; - ini_rtpe_cfg->tcp_listen_ep = rtpe_config.tcp_listen_ep; - ini_rtpe_cfg->udp_listen_ep = rtpe_config.udp_listen_ep; - ini_rtpe_cfg->ng_listen_ep = rtpe_config.ng_listen_ep; - ini_rtpe_cfg->ng_tcp_listen_ep = rtpe_config.ng_tcp_listen_ep; - ini_rtpe_cfg->cli_listen_ep = rtpe_config.cli_listen_ep; + memcpy(ini_rtpe_cfg->tcp_listen_ep, rtpe_config.tcp_listen_ep, sizeof(ini_rtpe_cfg->tcp_listen_ep)); + memcpy(ini_rtpe_cfg->udp_listen_ep, rtpe_config.udp_listen_ep, sizeof(ini_rtpe_cfg->udp_listen_ep)); + memcpy(ini_rtpe_cfg->ng_listen_ep, rtpe_config.ng_listen_ep, sizeof(ini_rtpe_cfg->ng_listen_ep)); + memcpy(ini_rtpe_cfg->ng_tcp_listen_ep, rtpe_config.ng_tcp_listen_ep, sizeof(ini_rtpe_cfg->ng_tcp_listen_ep)); + memcpy(ini_rtpe_cfg->cli_listen_ep, rtpe_config.cli_listen_ep, sizeof(ini_rtpe_cfg->cli_listen_ep)); ini_rtpe_cfg->redis_ep = rtpe_config.redis_ep; ini_rtpe_cfg->redis_write_ep = rtpe_config.redis_write_ep; ini_rtpe_cfg->homer_ep = rtpe_config.homer_ep; @@ -1073,41 +1079,84 @@ no_kernel: if (rtpe_config.redis_num_threads < 1) rtpe_config.redis_num_threads = num_cpu_cores(REDIS_RESTORE_NUM_THREADS); - rtpe_tcp = NULL; - if (rtpe_config.tcp_listen_ep.port) { - rtpe_tcp = control_tcp_new(rtpe_poller, &rtpe_config.tcp_listen_ep); - if (!rtpe_tcp) - die("Failed to open TCP control connection port"); + if (rtpe_config.tcp_listen_ep[0].port) { + rtpe_tcp[0] = control_tcp_new(rtpe_poller, &rtpe_config.tcp_listen_ep[0]); + if (!rtpe_tcp[0]) + die("Failed to open TCP control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.tcp_listen_ep[0]), + strerror(errno)); + if (rtpe_config.tcp_listen_ep[1].port) { + rtpe_tcp[1] = control_tcp_new(rtpe_poller, &rtpe_config.tcp_listen_ep[1]); + if (!rtpe_tcp[1]) + die("Failed to open TCP control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.tcp_listen_ep[1]), + strerror(errno)); + } } - rtpe_udp = NULL; - if (rtpe_config.udp_listen_ep.port) { - interfaces_exclude_port(rtpe_config.udp_listen_ep.port); - rtpe_udp = control_udp_new(rtpe_poller, &rtpe_config.udp_listen_ep); - if (!rtpe_udp) - die("Failed to open UDP control connection port"); + if (rtpe_config.udp_listen_ep[0].port) { + interfaces_exclude_port(rtpe_config.udp_listen_ep[0].port); + rtpe_udp[0] = control_udp_new(rtpe_poller, &rtpe_config.udp_listen_ep[0]); + if (!rtpe_udp[0]) + die("Failed to open UDP control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.udp_listen_ep[0]), + strerror(errno)); + if (rtpe_config.udp_listen_ep[1].port) { + rtpe_udp[1] = control_udp_new(rtpe_poller, &rtpe_config.udp_listen_ep[1]); + if (!rtpe_udp[1]) + die("Failed to open UDP control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.udp_listen_ep[1]), + strerror(errno)); + } } - rtpe_control_ng = NULL; - if (rtpe_config.ng_listen_ep.port) { - interfaces_exclude_port(rtpe_config.ng_listen_ep.port); - rtpe_control_ng = control_ng_new(rtpe_poller, &rtpe_config.ng_listen_ep, rtpe_config.control_tos); - if (!rtpe_control_ng) - die("Failed to open UDP control connection port"); + if (rtpe_config.ng_listen_ep[0].port) { + interfaces_exclude_port(rtpe_config.ng_listen_ep[0].port); + rtpe_control_ng[0] = control_ng_new(rtpe_poller, &rtpe_config.ng_listen_ep[0], + rtpe_config.control_tos); + if (!rtpe_control_ng[0]) + die("Failed to open UDP NG control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.ng_listen_ep[0]), + strerror(errno)); + if (rtpe_config.ng_listen_ep[1].port) { + rtpe_control_ng[1] = control_ng_new(rtpe_poller, &rtpe_config.ng_listen_ep[1], + rtpe_config.control_tos); + if (!rtpe_control_ng[1]) + die("Failed to open UDP NG control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.ng_listen_ep[1]), + strerror(errno)); + } } - if (rtpe_config.ng_tcp_listen_ep.port) { - rtpe_control_ng = control_ng_tcp_new(rtpe_poller, &rtpe_config.ng_tcp_listen_ep, rtpe_control_ng); - if (!rtpe_control_ng) - die("Failed to open TCP control connection port"); + if (rtpe_config.ng_tcp_listen_ep[0].port) { + rtpe_control_ng_tcp[0] = control_ng_tcp_new(rtpe_poller, &rtpe_config.ng_tcp_listen_ep[0]); + if (!rtpe_control_ng_tcp[0]) + die("Failed to open TCP NG control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.ng_tcp_listen_ep[0]), + strerror(errno)); + if (rtpe_config.ng_tcp_listen_ep[1].port) { + rtpe_control_ng_tcp[1] = control_ng_tcp_new(rtpe_poller, &rtpe_config.ng_tcp_listen_ep[1]); + if (!rtpe_control_ng_tcp[1]) + die("Failed to open TCP NG control connection port (%s): %s", + endpoint_print_buf(&rtpe_config.ng_tcp_listen_ep[1]), + strerror(errno)); + } } - rtpe_cli = NULL; - if (rtpe_config.cli_listen_ep.port) { - interfaces_exclude_port(rtpe_config.cli_listen_ep.port); - rtpe_cli = cli_new(rtpe_poller, &rtpe_config.cli_listen_ep); - if (!rtpe_cli) - die("Failed to open UDP CLI connection port"); + if (rtpe_config.cli_listen_ep[0].port) { + interfaces_exclude_port(rtpe_config.cli_listen_ep[0].port); + rtpe_cli[0] = cli_new(rtpe_poller, &rtpe_config.cli_listen_ep[0]); + if (!rtpe_cli[0]) + die("Failed to open CLI connection port (%s): %s", + endpoint_print_buf(&rtpe_config.cli_listen_ep[0]), + strerror(errno)); + if (rtpe_config.cli_listen_ep[1].port) { + rtpe_cli[1] = cli_new(rtpe_poller, &rtpe_config.cli_listen_ep[1]); + if (!rtpe_cli[1]) + die("Failed to open CLI connection port (%s): %s", + endpoint_print_buf(&rtpe_config.cli_listen_ep[1]), + strerror(errno)); + } } if (!is_addr_unspecified(&rtpe_config.redis_write_ep.address)) { @@ -1311,10 +1360,16 @@ int main(int argc, char **argv) { log_free(); janus_free(); - obj_release(rtpe_cli); - obj_release(rtpe_udp); - obj_release(rtpe_tcp); - obj_release(rtpe_control_ng); + obj_release(rtpe_cli[0]); + obj_release(rtpe_cli[1]); + obj_release(rtpe_udp[0]); + obj_release(rtpe_udp[1]); + obj_release(rtpe_tcp[0]); + obj_release(rtpe_tcp[1]); + obj_release(rtpe_control_ng[0]); + obj_release(rtpe_control_ng[1]); + obj_release(rtpe_control_ng_tcp[0]); + obj_release(rtpe_control_ng_tcp[1]); poller_free(&rtpe_poller); poller_map_free(&rtpe_poller_map); interfaces_free(); diff --git a/include/cli.h b/include/cli.h index d2b6dc7d0..1cff5bdec 100644 --- a/include/cli.h +++ b/include/cli.h @@ -10,7 +10,7 @@ struct cli { struct poller *poller; - struct streambuf_listener listeners[2]; + struct streambuf_listener listener; }; struct cli_writer; diff --git a/include/control_ng.h b/include/control_ng.h index dd22774e2..01549cc89 100644 --- a/include/control_ng.h +++ b/include/control_ng.h @@ -53,8 +53,8 @@ struct control_ng_stats { struct control_ng { struct obj obj; - socket_t udp_listeners[2]; - struct streambuf_listener tcp_listeners[2]; + socket_t udp_listener; + struct streambuf_listener tcp_listener; struct poller *poller; }; @@ -69,7 +69,7 @@ extern const char *ng_command_strings[NGC_COUNT]; extern const char *ng_command_strings_short[NGC_COUNT]; struct control_ng *control_ng_new(struct poller *, endpoint_t *, unsigned char); -struct control_ng *control_ng_tcp_new(struct poller *, endpoint_t *, struct control_ng *); +struct control_ng *control_ng_tcp_new(struct poller *, endpoint_t *); void notify_ng_tcp_clients(str *); void control_ng_init(void); void control_ng_cleanup(void); @@ -83,7 +83,6 @@ INLINE void ng_buffer_release(struct ng_buffer *ngbuf) { extern mutex_t rtpe_cngs_lock; extern GHashTable *rtpe_cngs_hash; -extern struct control_ng *rtpe_control_ng; enum load_limit_reasons { LOAD_LIMIT_NONE = -1, diff --git a/include/control_udp.h b/include/control_udp.h index 420b9fb62..c5a2170c3 100644 --- a/include/control_udp.h +++ b/include/control_udp.h @@ -48,7 +48,7 @@ struct control_udp { struct obj obj; struct cookie_cache cookie_cache; - socket_t udp_listeners[2]; + socket_t udp_listener; pcre *parse_re; pcre_extra *parse_ree; diff --git a/include/main.h b/include/main.h index 62bc10c3f..1976b1358 100644 --- a/include/main.h +++ b/include/main.h @@ -51,11 +51,11 @@ struct rtpengine_config { int graphite_interval; int redis_num_threads; GQueue interfaces; - endpoint_t tcp_listen_ep; - endpoint_t udp_listen_ep; - endpoint_t ng_listen_ep; - endpoint_t ng_tcp_listen_ep; - endpoint_t cli_listen_ep; + endpoint_t tcp_listen_ep[2]; + endpoint_t udp_listen_ep[2]; + endpoint_t ng_listen_ep[2]; + endpoint_t ng_tcp_listen_ep[2]; + endpoint_t cli_listen_ep[2]; endpoint_t redis_ep; endpoint_t redis_write_ep; endpoint_t homer_ep; @@ -161,6 +161,9 @@ extern struct poller_map *rtpe_poller_map; extern struct rtpengine_config rtpe_config; extern struct rtpengine_config initial_rtpe_config; +extern struct control_ng *rtpe_control_ng[2]; +extern struct control_ng *rtpe_control_ng_tcp[2]; + #endif diff --git a/lib/socket.c b/lib/socket.c index 25bae9786..5465b6a92 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -576,38 +576,52 @@ int endpoint_parse_any(endpoint_t *d, const char *s) { return -1; } -int sockaddr_getaddrinfo(sockaddr_t *a, const char *s) { +static int socket_addrinfo_convert(sockaddr_t *a, struct addrinfo *res) { + if (res->ai_family == AF_INET) { // IPv4 + struct sockaddr_in *ipv4 = (struct sockaddr_in *) res->ai_addr; + a->u.ipv4 = ipv4->sin_addr; + a->family = &__socket_families[SF_IP4]; + } + else if (res->ai_family == AF_INET6) { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) res->ai_addr; + a->u.ipv6 = ipv6->sin6_addr; + a->family = &__socket_families[SF_IP6]; + } + else + return -1; + return 0; +} +int sockaddr_getaddrinfo_alt(sockaddr_t *a, sockaddr_t *a2, const char *s) { struct addrinfo hints, *res; int status; int ret; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_socktype = SOCK_DGRAM; if ((status = getaddrinfo(s, NULL, &hints, &res)) != 0) { __C_DBG("getaddrinfo failed for %s, status is \"%s\"\n", s, gai_strerror(status)); return -1; } - ret = 0; - if (res->ai_family == AF_INET) { // IPv4 - struct sockaddr_in *ipv4 = (struct sockaddr_in *) res->ai_addr; - a->u.ipv4 = ipv4->sin_addr; - a->family = &__socket_families[SF_IP4]; - } - else if (res->ai_family == AF_INET6) { - struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) res->ai_addr; - a->u.ipv6 = ipv6->sin6_addr; - a->family = &__socket_families[SF_IP6]; + ret = socket_addrinfo_convert(a, res); + + if (a2) { + if (ret == 0 && res->ai_next) { + struct addrinfo *next = res->ai_next; + ret = socket_addrinfo_convert(a2, next); + } + else + ZERO(*a2); } - else - ret = -1; freeaddrinfo(res); return ret; } -int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s) { +int endpoint_parse_any_getaddrinfo_alt(endpoint_t *d, endpoint_t *d2, const char *s) { unsigned int len; const char *ep; char buf[64]; @@ -620,6 +634,11 @@ int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s) { d->port = atoi(s); ZERO(d->address); d->address.family = __get_socket_family_enum(SF_IP4); + if (d2) { + ZERO(*d2); + *d2 = *d; + ipv46_any_convert(d2); + } return 0; } len = ep - s; @@ -636,9 +655,16 @@ int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s) { sprintf(buf, "%.*s", len, s); } - if (sockaddr_getaddrinfo(&d->address, buf)) + if (sockaddr_getaddrinfo_alt(&d->address, d2 ? &d2->address : NULL, buf)) return -1; + if (d2) { + if (d2->address.family) + d2->port = d->port; + else + ZERO(*d2); + } + return 0; } diff --git a/lib/socket.h b/lib/socket.h index 26952d625..c27a62df5 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -218,8 +218,9 @@ int sockaddr_parse_any(sockaddr_t *dst, const char *src); int sockaddr_parse_any_str(sockaddr_t *dst, const str *src); int sockaddr_parse_str(sockaddr_t *dst, sockfamily_t *fam, const str *src); int endpoint_parse_any(endpoint_t *, const char *); // address (ip) optional -int sockaddr_getaddrinfo(sockaddr_t *a, const char *s); -int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s); // address (ip or hostname) optional +int sockaddr_getaddrinfo_alt(sockaddr_t *a, sockaddr_t *a2, const char *s); +int endpoint_parse_any_getaddrinfo_alt(endpoint_t *d, endpoint_t *d2, const char *s); // address (ip or hostname) optional +INLINE int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s); void endpoint_parse_sockaddr_storage(endpoint_t *, struct sockaddr_storage *); void kernel2endpoint(endpoint_t *ep, const struct re_address *ra); @@ -264,6 +265,12 @@ INLINE int endpoint_parse_any_getaddrinfo_full(endpoint_t *d, const char *s) { return -1; return 0; } +INLINE int sockaddr_getaddrinfo(sockaddr_t *a, const char *s) { + return sockaddr_getaddrinfo_alt(a, NULL, s); +} +INLINE int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s) { + return endpoint_parse_any_getaddrinfo_alt(d, NULL, s); +} INLINE int ipv46_any_convert(endpoint_t *ep) { if (ep->address.family->af != AF_INET) return 0; diff --git a/t/test-stats.c b/t/test-stats.c index 1adb5baf3..75af8f8ed 100644 --- a/t/test-stats.c +++ b/t/test-stats.c @@ -17,6 +17,7 @@ struct rtpengine_config initial_rtpe_config; struct poller *rtpe_poller; struct poller_map *rtpe_poller_map; GString *dtmf_logs; +struct control_ng *rtpe_control_ng[2]; static void __assert_g_string_eq(GString *a, const char *b, unsigned int line) { if (strcmp(a->str, b) == 0) { diff --git a/t/test-transcode.c b/t/test-transcode.c index 30ca206f9..28c8942fe 100644 --- a/t/test-transcode.c +++ b/t/test-transcode.c @@ -13,6 +13,7 @@ struct rtpengine_config initial_rtpe_config; struct poller *rtpe_poller; struct poller_map *rtpe_poller_map; GString *dtmf_logs; +struct control_ng *rtpe_control_ng[2]; static str *sdup(char *s) { str r;