summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Zidek <mzidek@redhat.com>2013-10-01 16:22:13 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-10-17 14:11:29 +0200
commit2e57e339798f47ad84cae9121559d19192b79146 (patch)
treeadbcd9630eaad846b93685008b65cdbd0b3123c5
parent6dc5ddd177e3b0ffe4315827aa8df7f33340585c (diff)
downloadsssd-2e57e339798f47ad84cae9121559d19192b79146.tar.gz
sssd-2e57e339798f47ad84cae9121559d19192b79146.tar.xz
sssd-2e57e339798f47ad84cae9121559d19192b79146.zip
util: Add functions to check if IP addresses is special
Added functions to check if given IP address is a special address (broadcast, multicast...).
-rw-r--r--src/tests/util-tests.c124
-rw-r--r--src/util/util.c57
-rw-r--r--src/util/util.h13
3 files changed, 194 insertions, 0 deletions
diff --git a/src/tests/util-tests.c b/src/tests/util-tests.c
index fd3dfb9bb..82ab5a0e8 100644
--- a/src/tests/util-tests.c
+++ b/src/tests/util-tests.c
@@ -808,6 +808,128 @@ START_TEST(test_split_on_separator)
}
END_TEST
+struct check_ip_test_data {
+ const char *str_ipaddr;
+ uint8_t flags;
+ bool expected_ret;
+};
+
+START_TEST(test_check_ipv4_addr)
+{
+ int a;
+ int num_of_tests;
+ int ret;
+ bool bret;
+ struct in_addr addr;
+ struct check_ip_test_data tst_data[] = {
+ {
+ "192.168.100.1", /* input IPv4 address */
+ 0, /* flags value */
+ true /* Expected return value */
+ },
+ {
+ "224.0.0.22", /* multicast address */
+ SSS_NO_MULTICAST,
+ false
+ },
+ {
+ "192.186.0.224",
+ SSS_NO_MULTICAST,
+ true
+ },
+ {
+ "127.0.0.1",
+ SSS_NO_LOOPBACK,
+ false
+ },
+ {
+ "169.254.0.11",
+ SSS_NO_LINKLOCAL,
+ false
+ },
+ {
+ "255.255.255.255",
+ SSS_NO_BROADCAST,
+ false
+ },
+ {
+ "255.255.255.255",
+ SSS_NO_SPECIAL,
+ false
+ },
+ {
+ "192.168.254.169",
+ SSS_NO_SPECIAL,
+ true
+ },
+ };
+
+ num_of_tests = sizeof(tst_data) / sizeof(struct check_ip_test_data);
+
+ for (a = 0; a < num_of_tests; a++) {
+ /* fill sockaddr_in structure */
+
+ ret = inet_pton(AF_INET, tst_data[a].str_ipaddr, &addr);
+ fail_if(ret != 1, "inet_pton failed.");
+
+ bret = check_ipv4_addr(&addr, tst_data[a].flags);
+ fail_unless(bret == tst_data[a].expected_ret,
+ "check_ipv4_addr failed (iteration %d)", a);
+ }
+}
+END_TEST
+
+START_TEST(test_check_ipv6_addr)
+{
+ int a;
+ int num_of_tests;
+ int ret;
+ bool bret;
+ struct in6_addr addr;
+ struct check_ip_test_data tst_data[] = {
+ {
+ "fde9:7e3f:1ed3:24a5::4", /* input IPv6 address */
+ 0, /* flags value */
+ true /* Expected return value */
+ },
+ {
+ "fe80::f2de:f1ff:fefa:67f0",
+ SSS_NO_LINKLOCAL,
+ false
+ },
+ {
+ "::1",
+ SSS_NO_LOOPBACK,
+ false
+ },
+ {
+ "ff00::123",
+ SSS_NO_MULTICAST,
+ false
+ },
+ {
+ "ff00::321",
+ SSS_NO_SPECIAL,
+ false
+ },
+ };
+
+ num_of_tests = sizeof(tst_data) / sizeof(struct check_ip_test_data);
+
+ for (a = 0; a < num_of_tests; a++) {
+ /* fill sockaddr_in structure */
+
+ ret = inet_pton(AF_INET6, tst_data[a].str_ipaddr, &addr);
+ fail_if(ret != 1, "inet_pton failed.");
+
+ bret = check_ipv6_addr(&addr, tst_data[a].flags);
+ fail_unless(bret == tst_data[a].expected_ret,
+ "check_ipv6_addr failed (iteration %d)", a);
+
+ }
+}
+END_TEST
+
START_TEST(test_is_host_in_domain)
{
struct {
@@ -851,6 +973,8 @@ Suite *util_suite(void)
tcase_add_test (tc_util, test_add_string_to_list);
tcase_add_test (tc_util, test_string_in_list);
tcase_add_test (tc_util, test_split_on_separator);
+ tcase_add_test (tc_util, test_check_ipv4_addr);
+ tcase_add_test (tc_util, test_check_ipv6_addr);
tcase_add_test (tc_util, test_is_host_in_domain);
tcase_set_timeout(tc_util, 60);
diff --git a/src/util/util.c b/src/util/util.c
index fb3bed146..9ab154db3 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -22,6 +22,7 @@
#include <netdb.h>
#include <poll.h>
#include <sys/socket.h>
+#include <arpa/inet.h>
#include "talloc.h"
#include "util/util.h"
@@ -739,3 +740,59 @@ bool is_host_in_domain(const char *host, const char *domain)
return false;
}
+
+/* addr is in network order for both IPv4 and IPv6 versions */
+bool check_ipv4_addr(struct in_addr *addr, uint8_t flags)
+{
+ char straddr[INET_ADDRSTRLEN];
+
+ if (inet_ntop(AF_INET, addr, straddr, INET_ADDRSTRLEN) == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("inet_ntop failed, won't log IP addresses\n"));
+ snprintf(straddr, INET_ADDRSTRLEN, "unknown");
+ }
+
+ if ((flags & SSS_NO_MULTICAST) && IN_MULTICAST(ntohl(addr->s_addr))) {
+ DEBUG(SSSDBG_FUNC_DATA, ("Multicast IPv4 address %s\n", straddr));
+ return false;
+ } else if ((flags & SSS_NO_LOOPBACK)
+ && inet_netof(*addr) == IN_LOOPBACKNET) {
+ DEBUG(SSSDBG_FUNC_DATA, ("Loopback IPv4 address %s\n", straddr));
+ return false;
+ } else if ((flags & SSS_NO_LINKLOCAL)
+ && (addr->s_addr & htonl(0xffff0000)) == htonl(0xa9fe0000)) {
+ /* 169.254.0.0/16 */
+ DEBUG(SSSDBG_FUNC_DATA, ("Link-local IPv4 address %s\n", straddr));
+ return false;
+ } else if ((flags & SSS_NO_BROADCAST)
+ && addr->s_addr == htonl(INADDR_BROADCAST)) {
+ DEBUG(SSSDBG_FUNC_DATA, ("Broadcast IPv4 address %s\n", straddr));
+ return false;
+ }
+
+ return true;
+}
+
+bool check_ipv6_addr(struct in6_addr *addr, uint8_t flags)
+{
+ char straddr[INET6_ADDRSTRLEN];
+
+ if (inet_ntop(AF_INET6, addr, straddr, INET6_ADDRSTRLEN) == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("inet_ntop failed, won't log IP addresses\n"));
+ snprintf(straddr, INET6_ADDRSTRLEN, "unknown");
+ }
+
+ if ((flags & SSS_NO_LINKLOCAL) && IN6_IS_ADDR_LINKLOCAL(addr)) {
+ DEBUG(SSSDBG_FUNC_DATA, ("Link local IPv6 address %s\n", straddr));
+ return false;
+ } else if ((flags & SSS_NO_LOOPBACK) && IN6_IS_ADDR_LOOPBACK(addr)) {
+ DEBUG(SSSDBG_FUNC_DATA, ("Loopback IPv6 address %s\n", straddr));
+ return false;
+ } else if ((flags & SSS_NO_MULTICAST) && IN6_IS_ADDR_MULTICAST(addr)) {
+ DEBUG(SSSDBG_FUNC_DATA, ("Multicast IPv6 address %s\n", straddr));
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 98b86e9db..3789c278c 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -37,6 +37,7 @@
#include <pcre.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <arpa/inet.h>
#include <talloc.h>
#include <tevent.h>
@@ -438,6 +439,18 @@ errno_t check_and_open_readonly(const char *filename, int *fd, const uid_t uid,
enum check_file_type type);
/* from util.c */
+#define SSS_NO_LINKLOCAL 0x01
+#define SSS_NO_LOOPBACK 0x02
+#define SSS_NO_MULTICAST 0x04
+#define SSS_NO_BROADCAST 0x08
+
+#define SSS_NO_SPECIAL \
+ (SSS_NO_LINKLOCAL|SSS_NO_LOOPBACK|SSS_NO_MULTICAST|SSS_NO_BROADCAST)
+
+/* These two functions accept addr in network order */
+bool check_ipv4_addr(struct in_addr *addr, uint8_t check);
+bool check_ipv6_addr(struct in6_addr *addr, uint8_t check);
+
int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
const char sep, bool trim, bool skip_empty,
char ***_list, int *size);