1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

sys/net/ipv6: add ipv6_addr_from_buf function

This allows to parse IPv6 address from strings that not end with '\0'.
This commit is contained in:
Leandro Lanzieri 2020-10-29 14:44:05 +01:00
parent 4305fcc010
commit f14c898dd0
No known key found for this signature in database
GPG Key ID: 13559905E2EBEAA5
3 changed files with 67 additions and 8 deletions

View File

@ -720,8 +720,8 @@ char *ipv6_addr_to_str(char *result, const ipv6_addr_t *addr, uint8_t result_len
* RFC 5952
* </a>
*
* @param[in] result The resulting byte representation
* @param[in] addr An IPv6 address string representation
* @param[out] result The resulting byte representation
* @param[in] addr An IPv6 address string representation
*
* @return @p result, on success
* @return NULL, if @p addr was malformed
@ -729,6 +729,27 @@ char *ipv6_addr_to_str(char *result, const ipv6_addr_t *addr, uint8_t result_len
*/
ipv6_addr_t *ipv6_addr_from_str(ipv6_addr_t *result, const char *addr);
/**
* @brief Converts an IPv6 address from a buffer of characters to a
* byte-represented IPv6 address
*
* @see <a href="https://tools.ietf.org/html/rfc5952">
* RFC 5952
* </a>
*
* @note @p addr_len should be between 0 and IPV6_ADDR_MAX_STR_LEN
*
* @param[out] result The resulting byte representation
* @param[in] addr An IPv6 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
*/
ipv6_addr_t *ipv6_addr_from_buf(ipv6_addr_t *result, const char *addr,
size_t addr_len);
/**
* @brief split IPv6 address string representation and return remaining string
*

View File

@ -38,18 +38,20 @@
#define HEX_U "0123456789ABCDEF"
/* based on inet_pton6() by Paul Vixie */
ipv6_addr_t *ipv6_addr_from_str(ipv6_addr_t *result, const char *addr)
ipv6_addr_t *ipv6_addr_from_buf(ipv6_addr_t *result, const char *addr,
size_t addr_len)
{
uint8_t *colonp = 0;
const char *start = addr;
#ifdef MODULE_IPV4_ADDR
const char *curtok = addr;
#endif
uint32_t val = 0;
char ch;
uint8_t saw_xdigit = 0;
uint8_t i = 0;
if ((result == NULL) || (addr == NULL)) {
if ((result == NULL) || (addr == NULL) || (addr_len == 0) ||
(addr_len > IPV6_ADDR_MAX_STR_LEN)) {
return NULL;
}
@ -62,7 +64,8 @@ ipv6_addr_t *ipv6_addr_from_str(ipv6_addr_t *result, const char *addr)
}
}
while ((ch = *addr++) != '\0') {
while ((size_t)(addr - start) < addr_len) {
char ch = *addr++;
const char *pch;
const char *xdigits;
@ -109,8 +112,8 @@ ipv6_addr_t *ipv6_addr_from_str(ipv6_addr_t *result, const char *addr)
#ifdef MODULE_IPV4_ADDR
if (ch == '.' && ((i + sizeof(ipv4_addr_t)) <= sizeof(ipv6_addr_t)) &&
ipv4_addr_from_str((ipv4_addr_t *)(&(result->u8[i])),
curtok) != NULL) {
ipv4_addr_from_buf((ipv4_addr_t *)(&(result->u8[i])),
curtok, addr_len - (curtok - start)) != NULL) {
i += sizeof(ipv4_addr_t);
saw_xdigit = 0;
break; /* '\0' was seen by ipv4_addr_from_str(). */
@ -151,6 +154,15 @@ ipv6_addr_t *ipv6_addr_from_str(ipv6_addr_t *result, const char *addr)
return result;
}
ipv6_addr_t *ipv6_addr_from_str(ipv6_addr_t *result, const char *addr)
{
if ((result == NULL) || (addr == NULL)) {
return NULL;
}
return ipv6_addr_from_buf(result, addr, strlen(addr));
}
/**
* @}
*/

View File

@ -1056,6 +1056,30 @@ static void test_ipv6_addr_split_prefix__with_prefix(void)
TEST_ASSERT_EQUAL_INT(strcmp("fd00:dead:beef::1", a), 0);
}
static void test_ipv6_addr_from_buf__success(void)
{
ipv6_addr_t a = { {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 255, 255, 255, 255
}
};
ipv6_addr_t result;
#ifdef MODULE_IPV4_ADDR
TEST_ASSERT_NOT_NULL(ipv6_addr_from_buf(&result, "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255%tap0", 45));
#else
TEST_ASSERT_NOT_NULL(ipv6_addr_from_buf(&result, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%tap0", 39));
#endif
TEST_ASSERT(ipv6_addr_equal(&a, &result));
}
static void test_ipv6_addr_from_buf__too_long_len(void)
{
ipv6_addr_t result;
TEST_ASSERT_NULL(ipv6_addr_from_buf(&result, "::1", IPV6_ADDR_MAX_STR_LEN + 1));
}
Test *tests_ipv6_addr_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
@ -1148,6 +1172,8 @@ Test *tests_ipv6_addr_tests(void)
new_TestFixture(test_ipv6_addr_split_iface__with_iface),
new_TestFixture(test_ipv6_addr_split_prefix__no_prefix),
new_TestFixture(test_ipv6_addr_split_prefix__with_prefix),
new_TestFixture(test_ipv6_addr_from_buf__success),
new_TestFixture(test_ipv6_addr_from_buf__too_long_len),
};
EMB_UNIT_TESTCALLER(ipv6_addr_tests, NULL, NULL, fixtures);