From 63bdd615653e5c7cf5430cd7b0ece013bf622b51 Mon Sep 17 00:00:00 2001 From: Lucian Balaceanu Date: Fri, 21 Jul 2017 17:00:07 +0200 Subject: [PATCH] on startup, also accept hostname:port params for endpoints --- daemon/main.c | 24 ++++++++++---------- daemon/socket.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ daemon/socket.h | 15 +++++++++++-- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/daemon/main.c b/daemon/main.c index d08ae44e8..d4c738c48 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -225,7 +225,7 @@ static int redis_ep_parse(endpoint_t *ep, int *db, char **auth, const char *auth if (l < 0) return -1; *db = l; - if (endpoint_parse_any_full(ep, str)) + if (endpoint_parse_any_getaddrinfo_full(ep, str)) return -1; return 0; } @@ -260,10 +260,10 @@ static void options(int *argc, char ***argv) { { "interface", 'i', 0, G_OPTION_ARG_STRING_ARRAY,&if_a, "Local interface for RTP", "[NAME/]IP[!IP]"}, { "subscribe-keyspace", 'k', 0, G_OPTION_ARG_STRING_ARRAY,&ks_a, "Subscription keyspace list", "INT INT ..."}, { "listen-tcp", 'l', 0, G_OPTION_ARG_STRING, &listenps, "TCP port to listen on", "[IP:]PORT" }, - { "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP46:]PORT" }, - { "listen-ng", 'n', 0, G_OPTION_ARG_STRING, &listenngs, "UDP port to listen on, NG protocol", "[IP46:]PORT" }, - { "listen-cli", 'c', 0, G_OPTION_ARG_STRING, &listencli, "UDP port to listen on, CLI", "[IP46:]PORT" }, - { "graphite", 'g', 0, G_OPTION_ARG_STRING, &graphitep, "Address of the graphite server", "IP46:PORT" }, + { "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP46|HOSTNAME:]PORT" }, + { "listen-ng", 'n', 0, G_OPTION_ARG_STRING, &listenngs, "UDP port to listen on, NG protocol", "[IP46|HOSTNAME:]PORT" }, + { "listen-cli", 'c', 0, G_OPTION_ARG_STRING, &listencli, "UDP port to listen on, CLI", "[IP46|HOSTNAME:]PORT" }, + { "graphite", 'g', 0, G_OPTION_ARG_STRING, &graphitep, "Address of the graphite server", "IP46|HOSTNAME:PORT" }, { "graphite-interval", 'G', 0, G_OPTION_ARG_INT, &graphite_interval, "Graphite send interval in seconds", "INT" }, { "graphite-prefix",0, 0, G_OPTION_ARG_STRING, &graphite_prefix_s, "Prefix for graphite line", "STRING"}, { "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "Default TOS value to set on streams", "INT" }, @@ -286,7 +286,7 @@ static void options(int *argc, char ***argv) { { "sip-source", 0, 0, G_OPTION_ARG_NONE, &sip_source, "Use SIP source address by default", NULL }, { "dtls-passive", 0, 0, G_OPTION_ARG_NONE, &dtls_passive_def,"Always prefer DTLS passive role", NULL }, { "max-sessions", 0, 0, G_OPTION_ARG_INT, &max_sessions, "Limit of maximum number of sessions", "INT" }, - { "homer", 0, 0, G_OPTION_ARG_STRING, &homerp, "Address of Homer server for RTCP stats","IP46:PORT"}, + { "homer", 0, 0, G_OPTION_ARG_STRING, &homerp, "Address of Homer server for RTCP stats","IP46|HOSTNAME:PORT"}, { "homer-protocol",0,0,G_OPTION_ARG_STRING, &homerproto, "Transport protocol for Homer (default udp)", "udp|tcp" }, { "homer-id", 0, 0, G_OPTION_ARG_STRING, &homer_id, "'Capture ID' to use within the HEP protocol", "INT" }, { "recording-dir", 0, 0, G_OPTION_ARG_STRING, &spooldir, "Directory for storing pcap and metadata files", "FILE" }, @@ -328,23 +328,23 @@ static void options(int *argc, char ***argv) { } if (listenps) { - if (endpoint_parse_any(&tcp_listen_ep, listenps)) + if (endpoint_parse_any_getaddrinfo(&tcp_listen_ep, listenps)) die("Invalid IP or port (--listen-tcp)"); } if (listenudps) { - if (endpoint_parse_any(&udp_listen_ep, listenudps)) + if (endpoint_parse_any_getaddrinfo(&udp_listen_ep, listenudps)) die("Invalid IP or port (--listen-udp)"); } if (listenngs) { - if (endpoint_parse_any(&ng_listen_ep, listenngs)) + if (endpoint_parse_any_getaddrinfo(&ng_listen_ep, listenngs)) die("Invalid IP or port (--listen-ng)"); } - if (listencli) {if (endpoint_parse_any(&cli_listen_ep, listencli)) + if (listencli) {if (endpoint_parse_any_getaddrinfo(&cli_listen_ep, listencli)) die("Invalid IP or port (--listen-cli)"); } - if (graphitep) {if (endpoint_parse_any_full(&graphite_ep, graphitep)) + if (graphitep) {if (endpoint_parse_any_getaddrinfo_full(&graphite_ep, graphitep)) die("Invalid IP or port (--graphite)"); } @@ -352,7 +352,7 @@ static void options(int *argc, char ***argv) { set_prefix(graphite_prefix_s); if (homerp) { - if (endpoint_parse_any_full(&homer_ep, homerp)) + if (endpoint_parse_any_getaddrinfo_full(&homer_ep, homerp)) die("Invalid IP or port (--homer)"); } if (homerproto) { diff --git a/daemon/socket.c b/daemon/socket.c index 924f58095..00f731c49 100644 --- a/daemon/socket.c +++ b/daemon/socket.c @@ -2,9 +2,11 @@ #include #include #include +#include #include #include #include +#include #include "str.h" #include "media_socket.h" #include "xt_RTPENGINE.h" @@ -535,6 +537,62 @@ int endpoint_parse_any(endpoint_t *d, const char *s) { return -1; } +int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s) { + unsigned int len; + const char *ep; + char buf[64]; + void *addr; + struct addrinfo hints, *res; + int status; + + ep = strrchr(s, ':'); + if (!ep) { + if (strchr(s, '.')) + return -1; + /* just a port number */ + d->port = atoi(s); + ZERO(d->address); + d->address.family = __get_socket_family_enum(SF_IP4); + return 0; + } + len = ep - s; + if (len >= sizeof(buf)) + return -1; + d->port = atoi(ep+1); + if (d->port > 0xffff) + return -1; + + /* original s was [IPv6]:port */ + if ((len > 2) && (s[0] == '[') && (s[len - 1] == ']')) { + sprintf(buf, "%.*s", len - 2, s + 1); + } else { + sprintf(buf, "%.*s", len, s); + } + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + + if ((status = getaddrinfo(buf, NULL, &hints, &res)) != 0) { + __C_DBG("getaddrinfo failed for %s, status is \"%s\"\n", s, gai_strerror(status)); + return -1; + } + + if (res->ai_family == AF_INET) { // IPv4 + struct sockaddr_in *ipv4 = (struct sockaddr_in *) res->ai_addr; + addr = &(ipv4->sin_addr); + memcpy(&d->address.u, addr, sizeof(struct in_addr)); + d->address.family = &__socket_families[SF_IP4]; + } else { // IPv6 + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) res->ai_addr; + addr = &(ipv6->sin6_addr); + memcpy(&d->address.u, addr, sizeof(struct in6_addr)); + d->address.family = &__socket_families[SF_IP6]; + } + + freeaddrinfo(res); + return 0; +} + static int __socket(socket_t *r, int type, sockfamily_t *fam) { ZERO(*r); r->family = fam; diff --git a/daemon/socket.h b/daemon/socket.h index 5694eed66..424e529c5 100644 --- a/daemon/socket.h +++ b/daemon/socket.h @@ -204,7 +204,8 @@ sockfamily_t *__get_socket_family_enum(enum socket_families); 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 optional +int endpoint_parse_any(endpoint_t *, const char *); // address (ip) optional +int endpoint_parse_any_getaddrinfo(endpoint_t *d, const char *s); // address (ip or hostname) optional void kernel2endpoint(endpoint_t *ep, const struct re_address *ra); unsigned int sockaddr_hash(const sockaddr_t *); @@ -228,7 +229,7 @@ INLINE int endpoint_parse_port_any(endpoint_t *e, const char *p, unsigned int po e->port = port; return sockaddr_parse_any(&e->address, p); } -// address required +// address (ip) required INLINE int endpoint_parse_any_full(endpoint_t *d, const char *s) { int ret; ret = endpoint_parse_any(d, s); @@ -238,6 +239,16 @@ INLINE int endpoint_parse_any_full(endpoint_t *d, const char *s) { return -1; return 0; } +// address (ip or hostname) required +INLINE int endpoint_parse_any_getaddrinfo_full(endpoint_t *d, const char *s) { + int ret; + ret = endpoint_parse_any_getaddrinfo(d, s); + if (ret) + return ret; + if (is_addr_unspecified(&d->address)) + return -1; + return 0; +} INLINE int ipv46_any_convert(endpoint_t *ep) { if (ep->address.family->af != AF_INET) return 0;