From 39951a948eb0e053defc49093a82a530725ba9c8 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Sun, 16 Aug 2020 23:16:09 +0200 Subject: [PATCH] net/netif: move gnrc_netif_addr_to/from_str() to netif These functions are independent from GNRC and can be used by stack-agnistoc code. Avoid pulling in a GNRC dependency by moving those two helper functions to `netif`. The old function names are kept as `static inline` wrapper functions to avoid breaking API users. --- sys/include/net/gnrc/netif.h | 14 ++++- sys/include/net/netif.h | 38 +++++++++++++ sys/net/gnrc/netif/gnrc_netif.c | 80 --------------------------- sys/net/netif/netif_util.c | 98 +++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 82 deletions(-) create mode 100644 sys/net/netif/netif_util.c diff --git a/sys/include/net/gnrc/netif.h b/sys/include/net/gnrc/netif.h index 633821a3a7..63bb39fb52 100644 --- a/sys/include/net/gnrc/netif.h +++ b/sys/include/net/gnrc/netif.h @@ -557,6 +557,8 @@ int gnrc_netif_set_from_netdev(gnrc_netif_t *netif, /** * @brief Converts a hardware address to a human readable string. * + * @note Compatibility wrapper for @see netif_addr_to_str + * * @details The format will be like `xx:xx:xx:xx` where `xx` are the bytes * of @p addr in hexadecimal representation. * @@ -570,12 +572,17 @@ int gnrc_netif_set_from_netdev(gnrc_netif_t *netif, * * @return @p out. */ -char *gnrc_netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out); +static inline char *gnrc_netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out) +{ + return netif_addr_to_str(addr, addr_len, out); +} /** * @brief Parses a string of colon-separated hexadecimals to a hardware * address. * + * @note Compatibility wrapper for @see netif_addr_from_str + * * @details The input format must be like `xx:xx:xx:xx` where `xx` will be the * bytes of @p addr in hexadecimal representation. * @@ -590,7 +597,10 @@ char *gnrc_netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out); * @return Actual length of @p out on success. * @return 0, on failure. */ -size_t gnrc_netif_addr_from_str(const char *str, uint8_t *out); +static inline size_t gnrc_netif_addr_from_str(const char *str, uint8_t *out) +{ + return netif_addr_from_str(str, out); +} /** * @brief Send a GNRC packet via a given @ref gnrc_netif_t interface. diff --git a/sys/include/net/netif.h b/sys/include/net/netif.h index a3fddc6fb3..cb81463e39 100644 --- a/sys/include/net/netif.h +++ b/sys/include/net/netif.h @@ -176,6 +176,44 @@ int netif_set_opt(netif_t *netif, netopt_t opt, uint16_t context, */ int netif_register(netif_t *netif); +/** + * @brief Converts a hardware address to a human readable string. + * + * @details The format will be like `xx:xx:xx:xx` where `xx` are the bytes + * of @p addr in hexadecimal representation. + * + * @pre `(out != NULL) && ((addr != NULL) || (addr_len == 0))` + * @pre @p out **MUST** have allocated at least 3 * @p addr_len bytes. + * + * @param[in] addr A hardware address. + * @param[in] addr_len Length of @p addr. + * @param[out] out A string to store the output in. Must at least have + * 3 * @p addr_len bytes allocated. + * + * @return @p out. + */ +char *netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out); + +/** + * @brief Parses a string of colon-separated hexadecimals to a hardware + * address. + * + * @details The input format must be like `xx:xx:xx:xx` where `xx` will be the + * bytes of @p addr in hexadecimal representation. + * + * @pre `(out != NULL)` + * @pre @p out **MUST** have allocated at least + * @ref GNRC_NETIF_L2ADDR_MAXLEN bytes. + * + * @param[in] str A string of colon-separated hexadecimals. + * @param[out] out The resulting hardware address. Must at least have + * @ref GNRC_NETIF_L2ADDR_MAXLEN bytes allocated. + * + * @return Actual length of @p out on success. + * @return 0, on failure. + */ +size_t netif_addr_from_str(const char *str, uint8_t *out); + #ifdef __cplusplus } #endif diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index c7115143ff..184ba17962 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -408,86 +408,6 @@ gnrc_netif_t *gnrc_netif_get_by_pid(kernel_pid_t pid) return NULL; } -char *gnrc_netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out) -{ - char *res = out; - - assert((out != NULL) && ((addr != NULL) || (addr_len == 0U))); - out[0] = '\0'; - for (size_t i = 0; i < addr_len; i++) { - out += fmt_byte_hex((out), *(addr++)); - *(out++) = (i == (addr_len - 1)) ? '\0' : ':'; - } - return res; -} - -static inline int _dehex(char c, int default_) -{ - if ('0' <= c && c <= '9') { - return c - '0'; - } - else if ('A' <= c && c <= 'F') { - return c - 'A' + 10; - } - else if ('a' <= c && c <= 'f') { - return c - 'a' + 10; - } - else { - return default_; - } -} - -size_t gnrc_netif_addr_from_str(const char *str, uint8_t *out) -{ - /* Walk over str from the end. */ - /* Take two chars a time as one hex value (%hhx). */ - /* Leading zeros can be omitted. */ - /* Every non-hexadimal character is a delimiter. */ - /* Leading, tailing and adjacent delimiters are forbidden. */ - const char *end_str = str; - uint8_t *out_end = out; - size_t count = 0; - int assert_cell = 1; - - assert(out != NULL); - if ((str == NULL) || (str[0] == '\0')) { - return 0; - } - /* find end of string */ - while (end_str[1]) { - ++end_str; - } - while (end_str >= str) { - int a = 0, b = _dehex(*end_str--, -1); - - if (b < 0) { - if (assert_cell) { - return 0; - } - else { - assert_cell = 1; - continue; - } - } - assert_cell = 0; - if (end_str >= str) { - a = _dehex(*end_str--, 0); - } - count++; - *out_end++ = (a << 4) | b; - } - if (assert_cell) { - return 0; - } - /* out is reversed */ - while (out < --out_end) { - uint8_t tmp = *out_end; - *out_end = *out; - *out++ = tmp; - } - return count; -} - void gnrc_netif_acquire(gnrc_netif_t *netif) { if (netif && (netif->ops)) { diff --git a/sys/net/netif/netif_util.c b/sys/net/netif/netif_util.c new file mode 100644 index 0000000000..af6bf0eac1 --- /dev/null +++ b/sys/net/netif/netif_util.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * + * 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 Martine Lenders + */ + +#include +#include "fmt.h" + +char *netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out) +{ + char *res = out; + + assert((out != NULL) && ((addr != NULL) || (addr_len == 0U))); + out[0] = '\0'; + for (size_t i = 0; i < addr_len; i++) { + out += fmt_byte_hex((out), *(addr++)); + *(out++) = (i == (addr_len - 1)) ? '\0' : ':'; + } + return res; +} + +static inline int _dehex(char c, int default_) +{ + if ('0' <= c && c <= '9') { + return c - '0'; + } + else if ('A' <= c && c <= 'F') { + return c - 'A' + 10; + } + else if ('a' <= c && c <= 'f') { + return c - 'a' + 10; + } + else { + return default_; + } +} + +size_t netif_addr_from_str(const char *str, uint8_t *out) +{ + /* Walk over str from the end. */ + /* Take two chars a time as one hex value (%hhx). */ + /* Leading zeros can be omitted. */ + /* Every non-hexadimal character is a delimiter. */ + /* Leading, tailing and adjacent delimiters are forbidden. */ + const char *end_str = str; + uint8_t *out_end = out; + size_t count = 0; + int assert_cell = 1; + + assert(out != NULL); + if ((str == NULL) || (str[0] == '\0')) { + return 0; + } + /* find end of string */ + while (end_str[1]) { + ++end_str; + } + while (end_str >= str) { + int a = 0, b = _dehex(*end_str--, -1); + + if (b < 0) { + if (assert_cell) { + return 0; + } + else { + assert_cell = 1; + continue; + } + } + assert_cell = 0; + if (end_str >= str) { + a = _dehex(*end_str--, 0); + } + count++; + *out_end++ = (a << 4) | b; + } + if (assert_cell) { + return 0; + } + /* out is reversed */ + while (out < --out_end) { + uint8_t tmp = *out_end; + *out_end = *out; + *out++ = tmp; + } + return count; +} +/** @} */