diff --git a/include/net/sntp.h b/include/net/sntp.h index da950b561b2a6..eeaaf81949781 100644 --- a/include/net/sntp.h +++ b/include/net/sntp.h @@ -82,6 +82,22 @@ int sntp_query(struct sntp_ctx *ctx, u32_t timeout, */ void sntp_close(struct sntp_ctx *ctx); +/** + * @brief Convenience function to query SNTP in one-shot fashion + * + * Convenience wrapper which calls getaddrinfo(), sntp_init(), + * sntp_query(), and sntp_close(). + * + * @param server Address of server in format addr[:port] + * @param timeout Query timeout + * @param time Timestamp including integer and fractional seconds since + * 1 Jan 1970 (output). + * + * @return 0 if ok, <0 if error (-ETIMEDOUT if timeout). + */ +int sntp_simple(const char *server, u32_t timeout, + struct sntp_time *time); + /** * @} */ diff --git a/include/net/socket.h b/include/net/socket.h index 1cebc8073645b..34ba0245bf7c5 100644 --- a/include/net/socket.h +++ b/include/net/socket.h @@ -498,6 +498,13 @@ const char *zsock_gai_strerror(int errcode); /** zsock_getnameinfo(): Dummy option for compatibility */ #define NI_DGRAM 16 +/* POSIX extensions */ + +/** zsock_getnameinfo(): Max supported hostname length */ +#ifndef NI_MAXHOST +#define NI_MAXHOST 64 +#endif + /** * @brief Resolve a network address to a domain name or ASCII address * diff --git a/include/net/socketutils.h b/include/net/socketutils.h new file mode 100644 index 0000000000000..8c2d815577698 --- /dev/null +++ b/include/net/socketutils.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Find port in addr:port string. + * + * @param addr_str String of addr[:port] format + * + * @return Pointer to "port" part, or NULL is none. + */ +const char *net_addr_str_find_port(const char *addr_str); + +/** + * @brief Call getaddrinfo() on addr:port string + * + * Convenience function to split addr[:port] string into address vs port + * components (or use default port number), and call getaddrinfo() on the + * result. + * + * @param addr_str String of addr[:port] format + * @param def_port Default port number to use if addr_str doesn't contain it + * @param hints getaddrinfo() hints + * @param res Result of getaddrinfo() (freeaddrinfo() should be called on it + * as usual. + * + * @return Result of getaddrinfo() call. + */ +int net_getaddrinfo_addr_str(const char *addr_str, const char *def_port, + const struct addrinfo *hints, + struct addrinfo **res); diff --git a/subsys/net/lib/CMakeLists.txt b/subsys/net/lib/CMakeLists.txt index 76e3c3754dbed..8a27019824346 100644 --- a/subsys/net/lib/CMakeLists.txt +++ b/subsys/net/lib/CMakeLists.txt @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 +add_subdirectory(utils) add_subdirectory_if_kconfig(coap) add_subdirectory_if_kconfig(lwm2m) add_subdirectory_if_kconfig(socks) diff --git a/subsys/net/lib/sntp/CMakeLists.txt b/subsys/net/lib/sntp/CMakeLists.txt index 5ffac40aba7e0..e6f1b181699a1 100644 --- a/subsys/net/lib/sntp/CMakeLists.txt +++ b/subsys/net/lib/sntp/CMakeLists.txt @@ -2,4 +2,5 @@ zephyr_sources( sntp.c + sntp_simple.c ) diff --git a/subsys/net/lib/sntp/sntp_simple.c b/subsys/net/lib/sntp/sntp_simple.c new file mode 100644 index 0000000000000..36aab49dd4204 --- /dev/null +++ b/subsys/net/lib/sntp/sntp_simple.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include +#include + +int sntp_simple(const char *server, u32_t timeout, struct sntp_time *time) +{ + int res; + static struct addrinfo hints; + struct addrinfo *addr; + struct sntp_ctx sntp_ctx; + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = 0; + /* 123 is the standard SNTP port per RFC4330 */ + res = net_getaddrinfo_addr_str(server, "123", &hints, &addr); + + if (res < 0) { + /* Just in case, as namespace for getaddrinfo errors is + * different from errno errors. + */ + errno = EDOM; + return res; + } + + res = sntp_init(&sntp_ctx, addr->ai_addr, addr->ai_addrlen); + if (res < 0) { + goto freeaddr; + } + + res = sntp_query(&sntp_ctx, timeout, time); + + sntp_close(&sntp_ctx); + +freeaddr: + freeaddrinfo(addr); + + return res; +} diff --git a/subsys/net/lib/utils/CMakeLists.txt b/subsys/net/lib/utils/CMakeLists.txt new file mode 100644 index 0000000000000..dad9f2b5146b2 --- /dev/null +++ b/subsys/net/lib/utils/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + addr_utils.c +) diff --git a/subsys/net/lib/utils/addr_utils.c b/subsys/net/lib/utils/addr_utils.c new file mode 100644 index 0000000000000..8080c9dd9024d --- /dev/null +++ b/subsys/net/lib/utils/addr_utils.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* These utility functions are intended to be on top of POSIX API, and don't + * make sense if it's not available. + */ +#ifdef CONFIG_NET_SOCKETS_POSIX_NAMES + +const char *net_addr_str_find_port(const char *addr_str) +{ + const char *p = strrchr(addr_str, ':'); + + if (p == NULL) { + return NULL; + } + + /* If it's not IPv6 numeric notation, we guaranteedly got a port */ + if (*addr_str != '[') { + return p + 1; + } + + /* IPv6 numeric address, and ':' preceeded by ']' */ + if (p[-1] == ']') { + return p + 1; + } + + /* Otherwise, just raw IPv6 address, ':' is component separator */ + return NULL; +} + +int net_getaddrinfo_addr_str(const char *addr_str, const char *def_port, + const struct addrinfo *hints, + struct addrinfo **res) +{ + const char *port; + char host[NI_MAXHOST]; + + if (addr_str == NULL) { + errno = EINVAL; + return -1; + } + + port = net_addr_str_find_port(addr_str); + + if (port == NULL) { + port = def_port; + } else { + int host_len = port - addr_str - 1; + + if (host_len > sizeof(host) - 1) { + errno = EINVAL; + return -1; + } + strncpy(host, addr_str, host_len + 1); + host[host_len] = '\0'; + addr_str = host; + } + + return getaddrinfo(addr_str, port, hints, res); +} + +#endif