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.
- 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)
================================
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,
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));
#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.
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)
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)
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.