From 882bcbe92eb41fe029281925802baa36741a1e5a Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 24 Mar 2015 15:13:26 +0100 Subject: [PATCH] netif: add functions to parse and output hardware addresses --- sys/include/net/ng_netif.h | 38 +++++++++++ .../ng_netif/ng_netif_addr_from_str.c | 60 +++++++++++++++++ .../ng_netif/ng_netif_addr_to_str.c | 46 +++++++++++++ tests/unittests/tests-netif/tests-netif.c | 66 +++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c create mode 100644 sys/net/crosslayer/ng_netif/ng_netif_addr_to_str.c diff --git a/sys/include/net/ng_netif.h b/sys/include/net/ng_netif.h index e739217b67..788c3966aa 100644 --- a/sys/include/net/ng_netif.h +++ b/sys/include/net/ng_netif.h @@ -90,6 +90,44 @@ void ng_netif_remove(kernel_pid_t pid); */ kernel_pid_t *ng_netif_get(size_t *size); +/** + * @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 @p out_len >= 3 * @p addr_len + * + * @param[out] out A string to store the output in. + * @param[out] out_len Length of @p out. Must be at least + * 3 * @p addr_len long. + * @param[in] addr A hardware address. + * @param[in] addr_len Length of @p addr. + * + * @return Copy of @p out on success. + * @return NULL, if @p out_len < 3 * @p addr_len. + */ +char *ng_netif_addr_to_str(char *out, size_t out_len, uint8_t *addr, + size_t addr_len); + +/** + * @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. + * Changes @p str for simple parsing purposes. Make a copy if you + * need it later. + * + * @param[out] out The resulting hardware address. + * @param[out] out_len Length of @p out. + * @param[in] str A string of colon-separated hexadecimals. + * + * @return Actual length of @p out on success. + * @return 0, on failure. + */ +size_t ng_netif_addr_from_str(uint8_t *out, size_t out_len, char *str); + #ifdef __cplusplus } #endif diff --git a/sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c b/sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c new file mode 100644 index 0000000000..8f86cfb492 --- /dev/null +++ b/sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Martine Lenders + * + * 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 + */ + +#include "net/ng_netif.h" + +static uint8_t _parse_byte(char *str) +{ + uint8_t res = 0; + + for (int i = 0; i < 2; i++) { /* iterate over half-bytes */ + if ((str[i] >= '0') && (str[i] <= '9')) { /* if '0'-'9' */ + res |= (str[i] - '0') << (4 * (1 - i)); /* set half-byte to 0-9 */ + } + else if ((str[i] >= 'a') && (str[i] <= 'f')) { /* if 'a'-'f' */ + res |= (str[i] - 'a' + 10) << (4 * (1 - i));/* set half-byte to 10-15 */ + } + + /* interpret any other character as 0 */ + } + + return res; +} + +size_t ng_netif_addr_from_str(uint8_t *out, size_t out_len, char *str) +{ + size_t res = 0; + char *byte_str = str; + int end = 0; + + while (end == 0) { + str++; + + if ((res >= out_len) || ((str - byte_str) > 2)) { + /* no space left or byte_str has become > 2 chars */ + return 0; + } + + if ((*str == ':') || (*str == '\0')) { + end = (*str == '\0'); + *str = '\0'; + out[res++] = _parse_byte(byte_str); + byte_str = ++str; + } + } + + return res; +} + +/** @} */ diff --git a/sys/net/crosslayer/ng_netif/ng_netif_addr_to_str.c b/sys/net/crosslayer/ng_netif/ng_netif_addr_to_str.c new file mode 100644 index 0000000000..58722efb94 --- /dev/null +++ b/sys/net/crosslayer/ng_netif/ng_netif_addr_to_str.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2015 Martine Lenders + * + * 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 + */ + +#include "net/ng_netif.h" + +static inline char _half_byte_to_char(uint8_t half_byte) +{ + return (half_byte < 10) ? ('0' + half_byte) : ('a' + (half_byte - 10)); +} + +char *ng_netif_addr_to_str(char *out, size_t out_len, uint8_t *addr, + size_t addr_len) +{ + size_t i; + + if (out_len < (3 * addr_len)) { /* 2 for every byte, 1 for ':' or '\0' */ + return NULL; + } + + for (i = 0; i < addr_len; i++) { + out[(3 * i)] = _half_byte_to_char(addr[i] >> 4); + out[(3 * i) + 1] = _half_byte_to_char(addr[i] & 0xf); + + if (i != (addr_len - 1)) { + out[(3 * i) + 2] = ':'; + } + else { + out[(3 * i) + 2] = '\0'; + } + } + + return out; +} + +/** @} */ diff --git a/tests/unittests/tests-netif/tests-netif.c b/tests/unittests/tests-netif/tests-netif.c index 1a7ace5c89..eaa848f1bc 100644 --- a/tests/unittests/tests-netif/tests-netif.c +++ b/tests/unittests/tests-netif/tests-netif.c @@ -157,6 +157,65 @@ static void test_ng_netif_get__full(void) TEST_ASSERT_EQUAL_INT(NG_NETIF_NUMOF, size); } +static void test_ng_netif_addr_to_str__out_too_short(void) +{ + uint8_t addr[] = {0x05, 0xcd}; + char out[2]; + + TEST_ASSERT_NULL(ng_netif_addr_to_str(out, sizeof(out), addr, sizeof(addr))); +} + +static void test_ng_netif_addr_to_str__success(void) +{ + uint8_t addr[] = {0x05, 0xcd}; + char out[3 * sizeof(addr)]; + + TEST_ASSERT_EQUAL_STRING("05:cd", ng_netif_addr_to_str(out, sizeof(out), + addr, sizeof(addr))); +} + +static void test_ng_netif_addr_from_str__out_too_short(void) +{ + char str[] = "05:cd"; + uint8_t out[1]; + + TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); +} + +static void test_ng_netif_addr_from_str__ill_formated1(void) +{ + char str[] = "576:cd"; + uint8_t out[sizeof(str)]; + + TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); +} + +static void test_ng_netif_addr_from_str__ill_formated2(void) +{ + char str[] = TEST_STRING8; + uint8_t out[sizeof(str)]; + + TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); +} + +static void test_ng_netif_addr_from_str__ill_formated3(void) +{ + char str[] = "05-cd"; + uint8_t out[sizeof(str)]; + + TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); +} + +static void test_ng_netif_addr_from_str__success(void) +{ + char str[] = "05:cd"; + uint8_t out[2]; + + TEST_ASSERT_EQUAL_INT(2, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(0x05, out[0]); + TEST_ASSERT_EQUAL_INT(0xcd, out[1]); +} + Test *tests_netif_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -170,6 +229,13 @@ Test *tests_netif_tests(void) new_TestFixture(test_ng_netif_get__empty), new_TestFixture(test_ng_netif_get__success_3_minus_one), new_TestFixture(test_ng_netif_get__full), + new_TestFixture(test_ng_netif_addr_to_str__out_too_short), + new_TestFixture(test_ng_netif_addr_to_str__success), + new_TestFixture(test_ng_netif_addr_from_str__out_too_short), + new_TestFixture(test_ng_netif_addr_from_str__ill_formated1), + new_TestFixture(test_ng_netif_addr_from_str__ill_formated2), + new_TestFixture(test_ng_netif_addr_from_str__ill_formated3), + new_TestFixture(test_ng_netif_addr_from_str__success), }; EMB_UNIT_TESTCALLER(netif_tests, set_up, NULL, fixtures);