diff --git a/sys/include/net/ipv4/addr.h b/sys/include/net/ipv4/addr.h index 9a5e5454a9..858e926078 100644 --- a/sys/include/net/ipv4/addr.h +++ b/sys/include/net/ipv4/addr.h @@ -22,6 +22,7 @@ #include #include +#include #include "byteorder.h" @@ -74,8 +75,8 @@ char *ipv4_addr_to_str(char *result, const ipv4_addr_t *addr, uint8_t result_len * @brief Converts an IPv4 address string representation to a byte-represented * IPv4 address * - * @param[in] result The resulting byte representation - * @param[in] addr An IPv4 address string representation + * @param[out] result The resulting byte representation + * @param[in] addr An IPv4 address string representation * * @return @p result, on success * @return NULL, if @p addr was malformed @@ -83,6 +84,23 @@ char *ipv4_addr_to_str(char *result, const ipv4_addr_t *addr, uint8_t result_len */ ipv4_addr_t *ipv4_addr_from_str(ipv4_addr_t *result, const char *addr); +/** + * @brief Converts an IPv4 address from a buffer of characters to a + * byte-represented IPv4 address + * + * @note @p addr_len should be between 0 and IPV4_ADDR_MAX_STR_LEN + * + * @param[out] result The resulting byte representation + * @param[in] addr An IPv4 address string representation + * @param[in] addr_len The amount of characters to parse + * + * @return @p result, on success + * @return NULL, if @p addr was malformed + * @return NULL, if @p result or @p addr was NULL + */ +ipv4_addr_t *ipv4_addr_from_buf(ipv4_addr_t *result, const char *addr, + size_t addr_len); + #ifdef __cplusplus } #endif diff --git a/sys/net/network_layer/ipv4/addr/ipv4_addr_from_str.c b/sys/net/network_layer/ipv4/addr/ipv4_addr_from_str.c index 8c10c85088..7d76b78daf 100644 --- a/sys/net/network_layer/ipv4/addr/ipv4_addr_from_str.c +++ b/sys/net/network_layer/ipv4/addr/ipv4_addr_from_str.c @@ -13,6 +13,7 @@ */ #include +#include #include #include "net/ipv4/addr.h" @@ -20,12 +21,15 @@ #define DEC "0123456789" /* based on inet_pton4() by Paul Vixie */ -ipv4_addr_t *ipv4_addr_from_str(ipv4_addr_t *result, const char *addr) +ipv4_addr_t *ipv4_addr_from_buf(ipv4_addr_t *result, const char *addr, + size_t addr_len) { - uint8_t saw_digit, octets, ch; + uint8_t saw_digit, octets; uint8_t tmp[sizeof(ipv4_addr_t)], *tp; + const char *start = addr; - if ((result == NULL) || (addr == NULL)) { + if ((result == NULL) || (addr == NULL) || (addr_len == 0) || + (addr_len > IPV4_ADDR_MAX_STR_LEN)) { return NULL; } @@ -33,7 +37,8 @@ ipv4_addr_t *ipv4_addr_from_str(ipv4_addr_t *result, const char *addr) octets = 0; *(tp = tmp) = 0; - while ((ch = *addr++) != '\0') { + while ((size_t)(addr - start) < addr_len) { + uint8_t ch = *addr++; const char *pch; if ((pch = strchr(DEC, ch)) != NULL) { @@ -74,5 +79,14 @@ ipv4_addr_t *ipv4_addr_from_str(ipv4_addr_t *result, const char *addr) return result; } +ipv4_addr_t *ipv4_addr_from_str(ipv4_addr_t *result, const char *addr) +{ + if ((result == NULL) || (addr == NULL)) { + return NULL; + } + + return ipv4_addr_from_buf(result, addr, strlen(addr)); +} + /** @} */ diff --git a/tests/unittests/tests-ipv4_addr/tests-ipv4_addr.c b/tests/unittests/tests-ipv4_addr/tests-ipv4_addr.c index bab4918e8e..5bf790dd76 100644 --- a/tests/unittests/tests-ipv4_addr/tests-ipv4_addr.c +++ b/tests/unittests/tests-ipv4_addr/tests-ipv4_addr.c @@ -132,6 +132,34 @@ static void test_ipv4_addr_from_str__success2(void) TEST_ASSERT(ipv4_addr_equal(&a, &result)); } +static void test_ipv4_addr_from_buf__success(void) +{ + ipv4_addr_t a = { { 1, 1, 1, 1 } }; + ipv4_addr_t result; + + TEST_ASSERT_NOT_NULL(ipv4_addr_from_buf(&result, "1.1.1.1%tap0", 7)); + TEST_ASSERT(ipv4_addr_equal(&a, &result)); +} + +static void test_ipv4_addr_from_buf__result_NULL(void) +{ + TEST_ASSERT_NULL(ipv4_addr_from_buf(NULL, "::", 2)); +} + +static void test_ipv4_addr_from_buf__illegal_chars(void) +{ + ipv4_addr_t result; + + TEST_ASSERT_NULL(ipv4_addr_from_buf(&result, "1.1.1.1%tap0", 13)); +} + +static void test_ipv4_addr_from_buf__too_long_len(void) +{ + ipv4_addr_t result; + + TEST_ASSERT_NULL(ipv4_addr_from_buf(&result, "1.1.1.1", IPV4_ADDR_MAX_STR_LEN + 1)); +} + Test *tests_ipv4_addr_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -150,6 +178,10 @@ Test *tests_ipv4_addr_tests(void) new_TestFixture(test_ipv4_addr_from_str__result_NULL), new_TestFixture(test_ipv4_addr_from_str__success), new_TestFixture(test_ipv4_addr_from_str__success2), + new_TestFixture(test_ipv4_addr_from_buf__success), + new_TestFixture(test_ipv4_addr_from_buf__result_NULL), + new_TestFixture(test_ipv4_addr_from_buf__illegal_chars), + new_TestFixture(test_ipv4_addr_from_buf__too_long_len), }; EMB_UNIT_TESTCALLER(ipv4_addr_tests, NULL, NULL, fixtures);