From 83539eb7f8268a73c05fe19f5f2a7146b560534d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Fri, 25 Jan 2019 20:20:22 +0100 Subject: [PATCH] lib/utils kr_straddr_split(): tweak meaning, use more Now we don't rewrite the port-splitters in command line by zero bytes. That was confusing the output of some SW showing the command-line of running kresd. --- NEWS | 4 +++ daemon/bindings/net.c | 22 +++++--------- daemon/main.c | 31 ++++++-------------- lib/utils.c | 68 +++++++++++++------------------------------ lib/utils.h | 19 ++++++------ 5 files changed, 52 insertions(+), 92 deletions(-) diff --git a/NEWS b/NEWS index 9af226c36..2dd52d63d 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,10 @@ Improvements - policy module: policy.rpz() will watch the file for changes by default - packaging: lua cqueues added to default dependencies where available +Module API changes +------------------ +- kr_straddr_split() changed API a bit (compiler will catch that) + Knot Resolver 3.2.1 (2019-01-10) ================================ diff --git a/daemon/bindings/net.c b/daemon/bindings/net.c index 82b3beb99..a5622f026 100644 --- a/daemon/bindings/net.c +++ b/daemon/bindings/net.c @@ -373,17 +373,14 @@ static int net_tls_client(lua_State *L) lua_error(L); } - char addr[INET6_ADDRSTRLEN]; - uint16_t port = 0; - if (kr_straddr_split(full_addr, addr, sizeof(addr), &port) != kr_ok()) { + char buf[INET6_ADDRSTRLEN + 1]; + uint16_t port = 853; + const char *addr = kr_straddr_split(full_addr, buf, &port); + if (!addr) { format_error(L, "invalid IP address"); lua_error(L); } - if (port == 0) { - port = 853; - } - if (!pin_exists && !hostname_exists) { int r = tls_client_params_set(&net->tls_client_params, addr, port, NULL, @@ -494,17 +491,14 @@ static int net_tls_client_clear(lua_State *L) const char *full_addr = lua_tostring(L, 1); - char addr[INET6_ADDRSTRLEN]; - uint16_t port = 0; - if (kr_straddr_split(full_addr, addr, sizeof(addr), &port) != kr_ok()) { + char buf[INET6_ADDRSTRLEN + 1]; + uint16_t port = 853; + const char *addr = kr_straddr_split(full_addr, buf, &port); + if (!addr) { format_error(L, "invalid IP address"); lua_error(L); } - if (port == 0) { - port = 853; - } - int r = tls_client_params_clear(&net->tls_client_params, addr, port); if (r != 0) { lua_pushstring(L, kr_strerror(r)); diff --git a/daemon/main.c b/daemon/main.c index c2ebe4915..447de21de 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -337,20 +337,6 @@ end: #pragma GCC diagnostic pop } -/** Split away port from the address. */ -static const char *set_addr(char *addr, int *port) -{ - char *p = strchr(addr, '@'); - if (!p) { - p = strchr(addr, '#'); - } - if (p) { - *port = strtol(p + 1, NULL, 10); - *p = '\0'; - } - - return addr; -} /* * Server operation. @@ -641,20 +627,21 @@ static int bind_fds(struct network *net, fd_array_t *fd_set, bool tls) { return ret; } -static int bind_sockets(struct network *net, addr_array_t *addr_set, bool tls) { +static int bind_sockets(struct network *net, addr_array_t *addr_set, bool tls) { uint32_t flags = tls ? NET_TCP|NET_TLS : NET_UDP|NET_TCP; - int ret = 0; for (size_t i = 0; i < addr_set->len; ++i) { - int port = tls ? KR_DNS_TLS_PORT : KR_DNS_PORT; - const char *addr = set_addr(addr_set->at[i], &port); - ret = network_listen(net, addr, (uint16_t)port, flags); + uint16_t port = tls ? KR_DNS_TLS_PORT : KR_DNS_PORT; + char buf[INET6_ADDRSTRLEN + 1]; + const char *addr = kr_straddr_split(addr_set->at[i], buf, &port); + /* NULL will result into kr_strerror(EINVAL) -> correct. */ + int ret = network_listen(net, addr, (uint16_t)port, flags); if (ret != 0) { - kr_log_error("[system] bind to '%s@%d' %s%s\n", + kr_log_error("[system] bind to '%s@%d' %s%s\n", addr, port, tls ? "(TLS) " : "", kr_strerror(ret)); - break; + return ret; } } - return ret; + return kr_ok(); } int main(int argc, char **argv) diff --git a/lib/utils.c b/lib/utils.c index fe9ab03b5..2625b6191 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -491,55 +491,29 @@ int kr_straddr_subnet(void *dst, const char *addr) return bit_len; } -int kr_straddr_split(const char *addr, char *buf, size_t buflen, uint16_t *port) +const char * kr_straddr_split(const char *addr, char *buf, uint16_t *port) { - const int base = 10; - long p = 0; - size_t addrlen = strlen(addr); - char *p_start = strchr(addr, '@'); - char *p_end; - - if (!p_start) { + assert(addr && buf && port); + /* Find where port number starts. */ + const char *p_start = strchr(addr, '@'); + if (!p_start) p_start = strchr(addr, '#'); - } - - if (p_start) { - if (p_start[1] != '\0'){ - p = strtol(p_start + 1, &p_end, base); - if (*p_end != '\0' || p <= 0 || p > UINT16_MAX) { - return kr_error(EINVAL); - } - } - addrlen = p_start - addr; - } - - /* Check if address is valid. */ - if (addrlen >= INET6_ADDRSTRLEN) { - return kr_error(EINVAL); - } - - char str[INET6_ADDRSTRLEN]; - struct sockaddr_storage ss; - - memcpy(str, addr, addrlen); str[addrlen] = '\0'; - - int family = kr_straddr_family(str); - if (family == kr_error(EINVAL) || !inet_pton(family, str, &ss)) { - return kr_error(EINVAL); - } - - /* Address and port contains valid values, return it to caller */ - if (buf) { - if (addrlen >= buflen) { - return kr_error(ENOSPC); - } - memcpy(buf, addr, addrlen); buf[addrlen] = '\0'; - } - if (port) { - *port = (uint16_t)p; - } - - return kr_ok(); + if (!p_start) /* No port specified -> no need to copy anything. */ + return addr; + if (p_start[1] == '\0') /* Don't accept empty port string. */ + return NULL; + /* Check the port number. */ + char *p_end; + long p = strtol(p_start + 1, &p_end, 10); + if (*p_end != '\0' || p <= 0 || p > UINT16_MAX) + return NULL; + *port = p; + /* We need to copy the address. */ + const size_t addrlen = p_start - addr; + if (addrlen > INET6_ADDRSTRLEN) + return NULL; + memcpy(buf, addr, addrlen); buf[addrlen] = '\0'; + return buf; } int kr_straddr_join(const char *addr, uint16_t port, char *buf, size_t *buflen) diff --git a/lib/utils.h b/lib/utils.h index 21eabac80..9b20afb4e 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -303,16 +303,17 @@ struct sockaddr * kr_straddr_socket(const char *addr, int port); KR_EXPORT int kr_straddr_subnet(void *dst, const char *addr); -/** Splits ip address specified as "addr@port" or "addr#port" into addr and port - * and performs validation. - * @note if #port part isn't present, then port will be set to 0. - * buf and\or port can be set to NULL. - * @return kr_error(EINVAL) - addr part doesn't contains valid ip address or - * #port part is out-of-range (either < 0 either > UINT16_MAX) - * kr_error(ENOSP) - buflen is too small - */ +/** Splits ip address specified as "addr@port" or "addr#port" into addr and port. + * \param addr zero-terminated input + * \param buf buffer in case we need to copy the address; + * length > MIN(strlen(addr), INET6_ADDRSTRLEN + 1) + * \param port[out] written in case it's specified in addr + * \return pointer to address without port (zero-terminated string) + * \note Typically you follow this by kr_straddr_socket(). + */ KR_EXPORT -int kr_straddr_split(const char *addr, char *buf, size_t buflen, uint16_t *port); +const char * kr_straddr_split(const char *addr, char *buf, uint16_t *port); + /** Formats ip address and port in "addr#port" format. * and performs validation. * @note Port always formatted as five-character string with leading zeros. -- 2.47.3