diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/test-net.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/lib/test-net.c b/src/lib/test-net.c new file mode 100644 index 0000000..fb19d5b --- /dev/null +++ b/src/lib/test-net.c @@ -0,0 +1,167 @@ +/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "net.h" + +struct test_net_is_in_network_input { + const char *ip; + const char *net; + unsigned int bits; + bool ret; +}; + +static void test_net_is_in_network(void) +{ + static const struct test_net_is_in_network_input input[] = { + { "1.2.3.4", "1.2.3.4", 32, TRUE }, + { "1.2.3.4", "1.2.3.3", 32, FALSE }, + { "1.2.3.4", "1.2.3.5", 32, FALSE }, + { "1.2.3.4", "1.2.2.4", 32, FALSE }, + { "1.2.3.4", "1.1.3.4", 32, FALSE }, + { "1.2.3.4", "0.2.3.4", 32, FALSE }, + { "1.2.3.253", "1.2.3.254", 31, FALSE }, + { "1.2.3.254", "1.2.3.254", 31, TRUE }, + { "1.2.3.255", "1.2.3.254", 31, TRUE }, + { "1.2.3.255", "1.2.3.0", 24, TRUE }, + { "1.2.255.255", "1.2.254.0", 23, TRUE }, + { "255.255.255.255", "128.0.0.0", 1, TRUE }, + { "255.255.255.255", "127.0.0.0", 1, FALSE }, + { "1234:5678::abcf", "1234:5678::abce", 127, TRUE }, + { "1234:5678::abcd", "1234:5678::abce", 127, FALSE }, + { "123e::ffff", "123e::0", 15, TRUE }, + { "::ffff:1.2.3.4", "1.2.3.4", 32, TRUE }, + { "::ffff:1.2.3.4", "1.2.3.3", 32, FALSE }, + { "::ffff:1.2.3.4", "::ffff:1.2.3.4", 0, FALSE } + }; + struct ip_addr ip, net_ip; + unsigned int i; + + test_begin("net_is_in_network()"); + for (i = 0; i < N_ELEMENTS(input); i++) { + test_assert(net_addr2ip(input[i].ip, &ip) == 0); + test_assert(net_addr2ip(input[i].net, &net_ip) == 0); + test_assert_idx(net_is_in_network(&ip, &net_ip, input[i].bits) == + input[i].ret, i); + } + /* make sure non-IPv4 and non-IPv6 ip_addrs fail */ + test_assert(net_addr2ip("127.0.0.1", &ip) == 0); + net_ip = ip; + net_ip.family = 0; + test_assert(!net_is_in_network(&ip, &net_ip, 0)); + test_assert(!net_is_in_network(&net_ip, &ip, 0)); + test_assert(net_addr2ip("::1", &ip) == 0); + net_ip = ip; + net_ip.family = 0; + test_assert(!net_is_in_network(&ip, &net_ip, 0)); + test_assert(!net_is_in_network(&net_ip, &ip, 0)); + test_end(); +} + +static void test_net_ip2addr(void) +{ + struct ip_addr ip; + + test_begin("net_ip2addr()"); + test_assert(net_addr2ip("127.0.0.1", &ip) == 0 && + ip.family == AF_INET && + ntohl(ip.u.ip4.s_addr) == (0x7f000001)); + test_assert(net_addr2ip("2130706433", &ip) == 0 && + ip.family == AF_INET && + ntohl(ip.u.ip4.s_addr) == (0x7f000001)); + test_assert(strcmp(net_ip2addr(&ip), "127.0.0.1") == 0); + test_assert(net_addr2ip("255.254.253.252", &ip) == 0 && + ip.family == AF_INET && + ntohl(ip.u.ip4.s_addr) == (0xfffefdfc)); + test_assert(strcmp(net_ip2addr(&ip), "255.254.253.252") == 0); + test_assert(net_addr2ip("::5", &ip) == 0 && + ip.family == AF_INET6 && + ip.u.ip6.s6_addr[15] == 5); + test_assert(strcmp(net_ip2addr(&ip), "::5") == 0); + test_assert(net_addr2ip("[::5]", &ip) == 0 && + ip.family == AF_INET6 && + ip.u.ip6.s6_addr[15] == 5); + test_assert(strcmp(net_ip2addr(&ip), "::5") == 0); + ip.family = 123; + test_assert(net_addr2ip("abc", &ip) < 0 && + ip.family == 123); + test_end(); +} + +static void test_net_str2hostport(void) +{ + const char *host; + in_port_t port; + + test_begin("net_str2hostport()"); + /* [IPv6] */ + test_assert(net_str2hostport("[1::4]", 0, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 0); + test_assert(net_str2hostport("[1::4]", 1234, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 1234); + test_assert(net_str2hostport("[1::4]:78", 1234, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 78); + host = NULL; + test_assert(net_str2hostport("[1::4]:", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("[1::4]:0", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("[1::4]:x", 1234, &host, &port) < 0 && host == NULL); + /* IPv6 */ + test_assert(net_str2hostport("1::4", 0, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 0); + test_assert(net_str2hostport("1::4", 1234, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 1234); + /* host */ + test_assert(net_str2hostport("foo", 0, &host, &port) == 0 && + strcmp(host, "foo") == 0 && port == 0); + test_assert(net_str2hostport("foo", 1234, &host, &port) == 0 && + strcmp(host, "foo") == 0 && port == 1234); + test_assert(net_str2hostport("foo:78", 1234, &host, &port) == 0 && + strcmp(host, "foo") == 0 && port == 78); + host = NULL; + test_assert(net_str2hostport("foo:", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("foo:0", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("foo:x", 1234, &host, &port) < 0 && host == NULL); + /* edge cases with multiple ':' - currently these don't return errors, + but perhaps they should. */ + test_assert(net_str2hostport("foo::78", 1234, &host, &port) == 0 && + strcmp(host, "foo::78") == 0 && port == 1234); + test_assert(net_str2hostport("::foo:78", 1234, &host, &port) == 0 && + strcmp(host, "::foo:78") == 0 && port == 1234); + test_assert(net_str2hostport("[::foo]:78", 1234, &host, &port) == 0 && + strcmp(host, "::foo") == 0 && port == 78); + test_assert(net_str2hostport("[::::]", 1234, &host, &port) == 0 && + strcmp(host, "::::") == 0 && port == 1234); + test_assert(net_str2hostport("[::::]:78", 1234, &host, &port) == 0 && + strcmp(host, "::::") == 0 && port == 78); + test_end(); +} + +static void test_net_unix_long_paths(void) +{ +#ifdef ENAMETOOLONG + int long_errno = ENAMETOOLONG; +#else + int long_errno = EOVERFLOW; +#endif + + test_begin("net_*_unix() - long paths"); + + char path[PATH_MAX]; + memset(path, 'x', sizeof(path)-1); + path[sizeof(path)-1] = '\0'; + + test_assert(net_listen_unix(path, 1) == -1); + test_assert(errno == long_errno); + + test_assert(net_connect_unix(path) == -1); + test_assert(errno == long_errno); + + test_end(); +} + +void test_net(void) +{ + test_net_is_in_network(); + test_net_ip2addr(); + test_net_str2hostport(); + test_net_unix_long_paths(); +} |