From 3081eeb556bd35abf2cf46f27d6252bb12dbca8e Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Sat, 10 Jul 2021 15:05:03 +0200 Subject: [PATCH] netutils: add netutils_get_ipv6() --- sys/Makefile | 3 ++ sys/Makefile.dep | 4 ++ sys/include/net/utils.h | 52 ++++++++++++++++++++++++++ sys/net/netutils/Makefile | 3 ++ sys/net/netutils/util.c | 78 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 sys/include/net/utils.h create mode 100644 sys/net/netutils/Makefile create mode 100644 sys/net/netutils/util.c diff --git a/sys/Makefile b/sys/Makefile index eade1daea3..50a11546f5 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -113,6 +113,9 @@ endif ifneq (,$(filter netstats_neighbor,$(USEMODULE))) DIRS += net/netstats endif +ifneq (,$(filter netutils,$(USEMODULE))) + DIRS += net/netutils +endif ifneq (,$(filter sema,$(USEMODULE))) DIRS += sema endif diff --git a/sys/Makefile.dep b/sys/Makefile.dep index 9e1bd58772..04598a119b 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -185,6 +185,10 @@ ifneq (,$(filter od_string,$(USEMODULE))) USEMODULE += od endif +ifneq (,$(filter netutils,$(USEMODULE))) + USEMODULE += ipv6_addr +endif + ifneq (,$(filter newlib_gnu_source,$(USEMODULE))) FEATURES_REQUIRED += newlib endif diff --git a/sys/include/net/utils.h b/sys/include/net/utils.h new file mode 100644 index 0000000000..662c3704b0 --- /dev/null +++ b/sys/include/net/utils.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 ML!PA Consulting GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_utils Network helper functions + * @ingroup net + * @brief Common network helper functions + * @{ + * + * @file + * @brief Common network interface API definitions + * + * @author Benjamin Valentin + */ + +#ifndef NET_UTILS_H +#define NET_UTILS_H + +#include +#include + +#include "net/ipv6/addr.h" +#include "net/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Parse an IPv6 address / hostname string. + * If the @ref net_sock_dns module is used, this will + * attempt to resolve hostnames via DNS to IPv6 addresses. + * + * @param[out] addr IPv6 address of the host + * @param[out] netif Interface if address is link-local + * @param[in] hostname IPv6 address string or hostname + * + * @return 0 on success, error otherwise + */ +int netutils_get_ipv6(ipv6_addr_t *addr, netif_t **netif, const char *hostname); + +#ifdef __cplusplus +} +#endif + +#endif /* NET_UTILS_H */ +/** @} */ diff --git a/sys/net/netutils/Makefile b/sys/net/netutils/Makefile new file mode 100644 index 0000000000..dc07bd13e5 --- /dev/null +++ b/sys/net/netutils/Makefile @@ -0,0 +1,3 @@ +MODULE = netutils + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/netutils/util.c b/sys/net/netutils/util.c new file mode 100644 index 0000000000..5fbaaabd1c --- /dev/null +++ b/sys/net/netutils/util.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2021 ML!PA Consulting GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Benjamin Valentin + */ + +#include +#include +#include + +#include "net/utils.h" +#ifdef MODULE_SOCK_DNS +#include "net/af.h" +#include "net/sock/dns.h" +#endif + +/* get the next netif, returns true if there are more */ +static bool _netif_get(netif_t **current_netif) +{ + netif_t *netif = *current_netif; + netif = netif_iter(netif); + + *current_netif = netif; + return netif_iter(netif); +} + +int netutils_get_ipv6(ipv6_addr_t *addr, netif_t **netif, const char *hostname) +{ + *netif = NULL; + + if (hostname == NULL) { + return -EINVAL; + } + +#ifdef MODULE_SOCK_DNS + /* hostname is not an IPv6 address */ + if (strchr(hostname, ':') == NULL) { + int res = sock_dns_query(hostname, addr, AF_INET6); + if (res < 0) { + return res; + } + return 0; + } +#endif + + /* search for interface ID */ + size_t len = strlen(hostname); + char *iface = strchr(hostname, '%'); + if (iface) { + *netif = netif_get_by_id(atoi(iface + 1)); + len -= strlen(iface); + + if (*netif == NULL) { + return -EINVAL; + } + } + /* preliminary select the first interface */ + else if (_netif_get(netif)) { + /* don't take it if there is more than one interface */ + *netif = NULL; + } + + if (ipv6_addr_from_buf(addr, hostname, len) == NULL) { + return -EINVAL; + } + + return 0; +} +/** @} */