diff --git a/Knot.files b/Knot.files index 65b4712014b60ee45d8c88d289a5c5b132b6cf37..dd77c651d5833226bab7a15176f665916afcce3f 100644 --- a/Knot.files +++ b/Knot.files @@ -526,6 +526,7 @@ tests/rrl.c tests/rrset.c tests/rrset_wire.c tests/server.c +tests/sockaddr.c tests/test_conf.h tests/tsig_key.c tests/wire.c diff --git a/src/contrib/sockaddr.c b/src/contrib/sockaddr.c index a571e0c7a0b82bbdf7bc7d4329e8027f4af1a5c1..f6ecd59af8d794fd589923ee0aabaf4d7b70eddf 100644 --- a/src/contrib/sockaddr.c +++ b/src/contrib/sockaddr.c @@ -240,3 +240,22 @@ char *sockaddr_hostname(void) freeaddrinfo(info); return hname; } + +bool sockaddr_is_any(const struct sockaddr_storage *ss) +{ + if (ss == NULL) { + return false; + } + + if (ss->ss_family == AF_INET) { + const struct sockaddr_in *sa = (struct sockaddr_in *)ss; + return sa->sin_addr.s_addr == INADDR_ANY; + } + + if (ss->ss_family == AF_INET6) { + const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss; + return memcmp(&sa6->sin6_addr, &in6addr_any, sizeof(sa6->sin6_addr)) == 0; + } + + return false; +} diff --git a/src/contrib/sockaddr.h b/src/contrib/sockaddr.h index 9a2c0ea67803ff96eee5ee93e281439f4cf62ced..ede9a5838288aabf6f51332f49b5169f6b4860e4 100644 --- a/src/contrib/sockaddr.h +++ b/src/contrib/sockaddr.h @@ -29,8 +29,9 @@ #define __POSIX_VISIBLE = 200112 #endif -#include <sys/types.h> +#include <stdbool.h> #include <sys/socket.h> +#include <sys/types.h> #include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -132,4 +133,9 @@ void sockaddr_port_set(struct sockaddr_storage *ss, uint16_t port); */ char *sockaddr_hostname(void); +/*! + * \brief Check if address is ANY address. + */ +bool sockaddr_is_any(const struct sockaddr_storage *ss); + /*! @} */ diff --git a/tests/.gitignore b/tests/.gitignore index 3f188dfb72a0cb19479cd0335cd821d497526663..a45978541bfa76cf2acdd9148a9e93b2fcae3049 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -43,6 +43,7 @@ rrl rrset rrset_wire server +sockaddr tsig_key wire wire_ctx diff --git a/tests/Makefile.am b/tests/Makefile.am index df890a1ec1844c5759437f59b982302d23faa4e9..0147745fe6ea0bdd36a9b033b821f225860338fe 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -46,6 +46,7 @@ check_PROGRAMS = \ rrset \ rrset_wire \ server \ + sockaddr \ tsig_key \ wire \ wire_ctx \ diff --git a/tests/sockaddr.c b/tests/sockaddr.c new file mode 100644 index 0000000000000000000000000000000000000000..665a922567b10a645e7e27b77d8712729e63c594 --- /dev/null +++ b/tests/sockaddr.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <tap/basic.h> + +#include "contrib/sockaddr.h" + +static void test_sockaddr_is_any(void) +{ + struct sockaddr_storage invalid = { 0 }; + ok(!sockaddr_is_any(&invalid), "sockaddr_is_any: invalid"); + + struct sockaddr_storage path = { 0 }; + path.ss_family = AF_UNIX; + ok(!sockaddr_is_any(&path), "sockaddr_is_any: unix"); + + struct sockaddr_storage ipv4_local = { 0 }; + sockaddr_set(&ipv4_local, AF_INET, "127.0.0.1", 0); + ok(!sockaddr_is_any(&ipv4_local), "sockaddr_is_any: IPv4 local"); + + struct sockaddr_storage ipv4_any = { 0 }; + sockaddr_set(&ipv4_any, AF_INET, "0.0.0.0", 0); + ok(sockaddr_is_any(&ipv4_any), "sockaddr_is_any: IPv4 any"); + + struct sockaddr_storage ipv6_local = { 0 }; + sockaddr_set(&ipv6_local, AF_INET6, "::1", 0); + ok(!sockaddr_is_any(&ipv6_local), "sockaddr_is_any: IPv6 local"); + + struct sockaddr_storage ipv6_any = { 0 }; + sockaddr_set(&ipv6_any, AF_INET6, "::", 0); + ok(sockaddr_is_any(&ipv6_any), "sockaddr_is_any: IPv6 any"); +} + +int main(int argc, char *argv[]) +{ + plan_lazy(); + + test_sockaddr_is_any(); + + return 0; +}