diff --git a/daemon/main.c b/daemon/main.c index ca55440ef..53567b674 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -188,7 +188,7 @@ static void signals(void) { -static void __find_if_name(char *s, struct ifaddrs *ifas, GQueue *addrs) { +static void __find_if_name(const char *s, struct ifaddrs *ifas, GQueue *addrs) { sockaddr_t *addr; for (struct ifaddrs *ifa = ifas; ifa; ifa = ifa->ifa_next) { @@ -232,7 +232,7 @@ static void __find_if_name(char *s, struct ifaddrs *ifas, GQueue *addrs) { } } -static void __resolve_ifname(char *s, GQueue *addrs) { +static void __resolve_ifname(const char *s, GQueue *addrs) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, @@ -273,87 +273,66 @@ static void __resolve_ifname(char *s, GQueue *addrs) { freeaddrinfo(res); } -static int if_addr_parse(intf_config_q *q, char *s, struct ifaddrs *ifas) { - str name; - char *c; - sockaddr_t *addr, adv; - GQueue addrs = G_QUEUE_INIT; - struct intf_config *ifa; - - while (*s == ' ') - s++; - - /* name */ - c = strpbrk(s, "/="); - if (c) { - char cc = *c; - *c++ = 0; - name = STR(s); - s = c; - if (cc == '=') { - // foo=bar - ifa = g_slice_alloc0(sizeof(*ifa)); - ifa->name = str_dup_str(&name); - ifa->alias = STR_DUP(s); - t_queue_push_tail(q, ifa); - return 0; - } - } - else - name = STR("default"); +static void if_add_alias(intf_config_q *q, const str *name, const char *alias) { + struct intf_config *ifa = g_slice_alloc0(sizeof(*ifa)); + ifa->name = str_dup_str(name); + ifa->alias = STR_DUP(alias); + t_queue_push_tail(q, ifa); +} - /* advertised address */ - c = strchr(s, '!'); - if (c) - *c++ = 0; +static bool if_add(intf_config_q *q, struct ifaddrs *ifas, const str *name, + const char *address, const char *adv_addr, + unsigned int port_min, unsigned int port_max) +{ + GQueue addrs = G_QUEUE_INIT; /* address */ - addr = g_slice_alloc(sizeof(*addr)); - if (!sockaddr_parse_any(addr, s)) { + sockaddr_t *addr = g_slice_alloc(sizeof(*addr)); + if (!sockaddr_parse_any(addr, address)) { if (is_addr_unspecified(addr)) - return -1; + return false; g_queue_push_tail(&addrs, addr); } else { g_slice_free1(sizeof(*addr), addr); // could be an interface name? ilog(LOG_DEBUG, "Could not parse '%s' as network address, checking to see if " - "it's an interface", s); - __find_if_name(s, ifas, &addrs); + "it's an interface", address); + __find_if_name(address, ifas, &addrs); if (!addrs.length) { - ilog(LOG_DEBUG, "'%s' is not an interface, attempting to resolve it as DNS host name", s); - __resolve_ifname(s, &addrs); + ilog(LOG_DEBUG, "'%s' is not an interface, attempting to resolve it as DNS host name", address); + __resolve_ifname(address, &addrs); } } if (!addrs.length) // nothing found - return -1; - - ZERO(adv); - if (c) { - if (sockaddr_parse_any(&adv, c)) { - ilog(LOG_DEBUG, "Could not parse '%s' as an address, attempting DNS lookup", c); - if (sockaddr_getaddrinfo(&adv, c)) { - ilog(LOG_WARN, "DNS lookup for '%s' failed", c); - return -1; + return false; + + sockaddr_t adv = {0}; + if (adv_addr) { + if (sockaddr_parse_any(&adv, adv_addr)) { + ilog(LOG_DEBUG, "Could not parse '%s' as an address, attempting DNS lookup", adv_addr); + if (sockaddr_getaddrinfo(&adv, adv_addr)) { + ilog(LOG_WARN, "DNS lookup for '%s' failed", adv_addr); + return false; } } if (is_addr_unspecified(&adv)) - return -1; + return false; } while ((addr = g_queue_pop_head(&addrs))) { - ifa = g_slice_alloc0(sizeof(*ifa)); - ifa->name = str_dup_str(&name); + struct intf_config *ifa = g_slice_alloc0(sizeof(*ifa)); + ifa->name = str_dup_str(name); ifa->local_address.addr = *addr; ifa->local_address.type = socktype_udp; ifa->advertised_address.addr = adv; if (is_addr_unspecified(&ifa->advertised_address.addr)) ifa->advertised_address.addr = *addr; ifa->advertised_address.type = ifa->local_address.type; - ifa->port_min = rtpe_config.port_min; - ifa->port_max = rtpe_config.port_max; + ifa->port_min = port_min; + ifa->port_max = port_max; // handle "base:suffix" separation for round-robin selection ifa->name_rr_spec = ifa->name; @@ -364,7 +343,38 @@ static int if_addr_parse(intf_config_q *q, char *s, struct ifaddrs *ifas) { g_slice_free1(sizeof(*addr), addr); } - return 0; + return true; +} + +static bool if_addr_parse(intf_config_q *q, char *s, struct ifaddrs *ifas) { + str name; + char *c; + + while (*s == ' ') + s++; + + /* name */ + c = strpbrk(s, "/="); + if (c) { + char cc = *c; + *c++ = 0; + name = STR(s); + s = c; + if (cc == '=') { + // foo=bar + if_add_alias(q, &name, s); + return true; + } + } + else + name = STR("default"); + + /* advertised address */ + c = strchr(s, '!'); + if (c) + *c++ = 0; + + return if_add(q, ifas, &name, s, c, rtpe_config.port_min, rtpe_config.port_max); } @@ -815,8 +825,7 @@ static void options(int *argc, char ***argv, charp_ht templates) { ilog(LOG_WARN, "Failed to retrieve list of network interfaces: %s", strerror(errno)); } for (iter = if_a; *iter; iter++) { - int ret = if_addr_parse(&rtpe_config.interfaces, *iter, ifas); - if (ret) + if (!if_addr_parse(&rtpe_config.interfaces, *iter, ifas)) die("Invalid interface specification: '%s'", *iter); } if (ifas)