Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZOOKEEPER-3726: invalid ipv6 address comparison #1252

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions zookeeper-client/zookeeper-client-c/src/addrvec.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,26 @@ int addrvec_contains(const addrvec_t *avec, const struct sockaddr_storage *addr)

for (i = 0; i < avec->count; i++)
{
if(memcmp(&avec->data[i], addr, INET_ADDRSTRLEN) == 0)
return 1;
if (avec->data[i].ss_family != addr->ss_family)
continue;
switch (addr->ss_family) {
case AF_INET:
if (memcmp(&((struct sockaddr_in*)&avec->data[i])->sin_addr,
&((struct sockaddr_in*)addr)->sin_addr,
sizeof(struct in_addr)) == 0)
return 1;
break;
#ifdef AF_INET6
vtyulb marked this conversation as resolved.
Show resolved Hide resolved
case AF_INET6:
if (memcmp(&((struct sockaddr_in6*)&avec->data[i])->sin6_addr,
&((struct sockaddr_in6*)addr)->sin6_addr,
sizeof(struct in6_addr)) == 0)
return 1;
break;
#endif
default:
break;
}
}

return 0;
Expand Down
83 changes: 83 additions & 0 deletions zookeeper-client/zookeeper-client-c/tests/TestReconfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#include <exception>
#include <stdlib.h>

extern "C" {
#include <src/addrvec.h>
}

#include "Util.h"
#include "LibCMocks.h"
#include "ZKMocks.h"
Expand Down Expand Up @@ -218,6 +222,10 @@ class Zookeeper_reconfig : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST(testcycleNextServer);
CPPUNIT_TEST(testMigrateOrNot);
CPPUNIT_TEST(testMigrationCycle);
CPPUNIT_TEST(testAddrVecContainsIPv4);
#ifdef AF_INET6
CPPUNIT_TEST(testAddrVecContainsIPv6);
#endif

// In threaded mode each 'create' is a thread -- it's not practical to create
// 10,000 threads to test load balancing. The load balancing code can easily
Expand Down Expand Up @@ -609,6 +617,81 @@ class Zookeeper_reconfig : public CPPUNIT_NS::TestFixture
numServers = 9;
updateAllClientsAndServers(numServers);
}

/**
* This tests that client can detect server's ipv4 address change.
*
* (1) We generate some address and put in addr, which saddr point to
* (2) Add all addresses that differ by one bit from the source
* (3) Add same address, but set ipv6 protocol
* (4) Ensure, that our address is not equal to any of generated,
* and that it equals to itself
*/
void testAddrVecContainsIPv4() {
addrvec_t vec;
addrvec_init(&vec);

sockaddr_storage addr;
sockaddr_in* saddr = (sockaddr_in*)&addr;
saddr->sin_family = AF_INET;
saddr->sin_port = htons((u_short)1234);
saddr->sin_addr.s_addr = INADDR_ANY;

CPPUNIT_ASSERT(sizeof(saddr->sin_addr.s_addr) == 4);

for (int i = 0; i < 32; i++) {
saddr->sin_addr.s_addr ^= (1 << i);
addrvec_append(&vec, &addr);
saddr->sin_addr.s_addr ^= (1 << i);
}

saddr->sin_family = AF_INET6;
addrvec_append(&vec, &addr);
saddr->sin_family = AF_INET;

CPPUNIT_ASSERT(!addrvec_contains(&vec, &addr));
addrvec_append(&vec, &addr);
CPPUNIT_ASSERT(addrvec_contains(&vec, &addr));
addrvec_free(&vec);
}

/**
* This tests that client can detect server's ipv6 address change.
*
* Same logic as in previous testAddrVecContainsIPv4 method,
* but we keep in mind, that ipv6 is 128-bit long.
*/
#ifdef AF_INET6
void testAddrVecContainsIPv6() {
addrvec_t vec;
addrvec_init(&vec);

sockaddr_storage addr;
sockaddr_in6* saddr = (sockaddr_in6*)&addr;
saddr->sin6_family = AF_INET6;
saddr->sin6_port = htons((u_short)1234);
saddr->sin6_addr = in6addr_any;

CPPUNIT_ASSERT(sizeof(saddr->sin6_addr.s6_addr) == 16);

for (int i = 0; i < 16; i++) {
for (int j = 0; j < 8; j++) {
saddr->sin6_addr.s6_addr[i] ^= (1 << j);
addrvec_append(&vec, &addr);
saddr->sin6_addr.s6_addr[i] ^= (1 << j);
}
}

saddr->sin6_family = AF_INET;
addrvec_append(&vec, &addr);
saddr->sin6_family = AF_INET6;

CPPUNIT_ASSERT(!addrvec_contains(&vec, &addr));
addrvec_append(&vec, &addr);
CPPUNIT_ASSERT(addrvec_contains(&vec, &addr));
addrvec_free(&vec);
}
#endif
};

CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_reconfig);