From 2b2141924282a046b9f199374da2aa0da058656a Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Mon, 14 Apr 2014 15:22:08 +0400 Subject: [PATCH] inet: allow scopeid in uv_inet_pton We already support it in `uv_ip6_addr` anyway. See https://github.com/joyent/node/issues/7395 --- src/inet.c | 16 ++++++++++++++-- test/test-ip6-addr.c | 42 ++++++++++++++++++++++++++++++++++++++++++ test/test-list.h | 2 ++ uv.gyp | 1 + 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/inet.c b/src/inet.c index a30c0d15..9220de64 100644 --- a/src/inet.c +++ b/src/inet.c @@ -225,7 +225,7 @@ static int inet_pton6(const char *src, unsigned char *dst) { curtok = src; seen_xdigits = 0; val = 0; - while ((ch = *src++) != '\0') { + while ((ch = *src++) != '\0' && ch != '%') { const char *pch; if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) @@ -256,7 +256,19 @@ static int inet_pton6(const char *src, unsigned char *dst) { continue; } if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) { - int err = inet_pton4(curtok, tp); + int err; + + /* Scope id present, parse ipv4 addr without it */ + pch = strchr(curtok, '%'); + if (pch != NULL) { + char tmp[sizeof "255.255.255.255"]; + + memcpy(tmp, curtok, pch - curtok); + curtok = tmp; + src = pch; + } + + err = inet_pton4(curtok, tp); if (err == 0) { tp += sizeof(struct in_addr); seen_xdigits = 0; diff --git a/test/test-ip6-addr.c b/test/test-ip6-addr.c index ddd08122..0d2606ee 100644 --- a/test/test-ip6-addr.c +++ b/test/test-ip6-addr.c @@ -97,3 +97,45 @@ TEST_IMPL(ip6_addr_link_local) { RETURN_SKIP("Qualified link-local addresses are not supported."); #endif } + + +#define GOOD_ADDR_LIST(X) \ + X("::") \ + X("::1") \ + X("fe80::1") \ + X("fe80::") \ + X("fe80::2acf:daff:fedd:342a") \ + X("fe80:0:0:0:2acf:daff:fedd:342a") \ + X("fe80:0:0:0:2acf:daff:1.2.3.4") \ + +#define BAD_ADDR_LIST(X) \ + X(":::1") \ + X("abcde::1") \ + X("fe80:0:0:0:2acf:daff:fedd:342a:5678") \ + X("fe80:0:0:0:2acf:daff:abcd:1.2.3.4") \ + X("fe80:0:0:2acf:daff:1.2.3.4.5") \ + +#define TEST_GOOD(ADDR) \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR, &addr)); \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \ + ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \ + +#define TEST_BAD(ADDR) \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR, &addr)); \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \ + ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \ + +TEST_IMPL(ip6_pton) { + struct in6_addr addr; + + GOOD_ADDR_LIST(TEST_GOOD) + BAD_ADDR_LIST(TEST_BAD) + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#undef GOOD_ADDR_LIST +#undef BAD_ADDR_LIST diff --git a/test/test-list.h b/test/test-list.h index d16219e1..afb9a7ac 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -41,6 +41,7 @@ TEST_DECLARE (semaphore_2) TEST_DECLARE (semaphore_3) TEST_DECLARE (tty) TEST_DECLARE (stdio_over_pipes) +TEST_DECLARE (ip6_pton) TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_after_write) #ifndef _WIN32 @@ -295,6 +296,7 @@ TASK_LIST_START TEST_ENTRY (pipe_server_close) TEST_ENTRY (tty) TEST_ENTRY (stdio_over_pipes) + TEST_ENTRY (ip6_pton) TEST_ENTRY (ipc_listen_before_write) TEST_ENTRY (ipc_listen_after_write) #ifndef _WIN32 diff --git a/uv.gyp b/uv.gyp index 5425dd63..710bd40b 100644 --- a/uv.gyp +++ b/uv.gyp @@ -321,6 +321,7 @@ 'test/test-getsockname.c', 'test/test-hrtime.c', 'test/test-idle.c', + 'test/test-ip6-addr.c', 'test/test-ipc.c', 'test/test-ipc-send-recv.c', 'test/test-list.h',