From 5291f3b2bd607508e44ef825258c42d9918f0002 Mon Sep 17 00:00:00 2001
From: Martine Lenders <mail@martine-lenders.eu>
Date: Mon, 28 Sep 2015 14:40:35 +0200
Subject: [PATCH] gnrc_ipv6_whitelist: initial import

---
 Makefile.dep                                  |  4 +
 sys/include/net/gnrc/ipv6/whitelist.h         | 78 +++++++++++++++++++
 sys/net/gnrc/Makefile                         |  3 +
 sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c   | 16 +++-
 .../network_layer/ipv6/whitelist/Makefile     |  3 +
 .../ipv6/whitelist/gnrc_ipv6_whitelist.c      | 67 ++++++++++++++++
 .../whitelist/gnrc_ipv6_whitelist_print.c     | 36 +++++++++
 7 files changed, 206 insertions(+), 1 deletion(-)
 create mode 100644 sys/include/net/gnrc/ipv6/whitelist.h
 create mode 100644 sys/net/gnrc/network_layer/ipv6/whitelist/Makefile
 create mode 100644 sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist.c
 create mode 100644 sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist_print.c

diff --git a/Makefile.dep b/Makefile.dep
index 89bab4b852..0c29e594ef 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -225,6 +225,10 @@ ifneq (,$(filter gnrc_ipv6_ext,$(USEMODULE)))
   USEMODULE += gnrc_ipv6
 endif
 
+ifneq (,$(filter gnrc_ipv6_whitelist,$(USEMODULE)))
+  USEMODULE += ipv6_addr
+endif
+
 ifneq (,$(filter gnrc_ipv6_router,$(USEMODULE)))
   USEMODULE += gnrc_ipv6
 endif
diff --git a/sys/include/net/gnrc/ipv6/whitelist.h b/sys/include/net/gnrc/ipv6/whitelist.h
new file mode 100644
index 0000000000..b954b8e0d9
--- /dev/null
+++ b/sys/include/net/gnrc/ipv6/whitelist.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    gnrc_ipv6_whitelist Allows to whitelist certain IPv6 source addresses for
+ *                                  reception.
+ * @ingroup     gnrc_ipv6
+ * @brief       This allows you to only accept IPv6 addresses that are defined in this list.
+ * @{
+ *
+ * @file
+ * @brief   IPv6 whitelist definitions
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef GNRC_IPV6_WHITELIST_H_
+#define GNRC_IPV6_WHITELIST_H_
+
+#include <stdbool.h>
+
+#include "net/ipv6/addr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Maximum size of the whitelist.
+ */
+#ifndef GNRC_IPV6_WHITELIST_SIZE
+#define GNRC_IPV6_WHITELIST_SIZE    (8)
+#endif
+
+/**
+ * @brief   Adds an IPv6 address to the whitelist.
+ *
+ * @param[in] addr  An IPv6 address.
+ *
+ * @return  0, on success.
+ * @return  -1, if whitelist is full.
+ */
+int gnrc_ipv6_whitelist_add(const ipv6_addr_t *addr);
+
+/**
+ * @brief   Removes an IPv6 address from the whitelist.
+ *
+ * Addresses not in the whitelist will be ignored.
+ *
+ * @param[in] addr  An IPv6 address.
+ */
+void gnrc_ipv6_whitelist_del(const ipv6_addr_t *addr);
+
+/**
+ * @brief   Checks if an IPv6 address is whitelisted.
+ *
+ * @param[in] addr  An IPv6 address.
+ *
+ * @return  true, if @p addr is whitelisted.
+ * @return  false, if @p addr is not whitelisted.
+ */
+bool gnrc_ipv6_whitelisted(const ipv6_addr_t *addr);
+
+/**
+ * @brief   Prints the whitelist.
+ */
+void gnrc_ipv6_whitelist_print(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GNRC_IPV6_WHITELIST_H_ */
+/** @} */
diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile
index cc7f891353..6ac2001c7a 100644
--- a/sys/net/gnrc/Makefile
+++ b/sys/net/gnrc/Makefile
@@ -28,6 +28,9 @@ endif
 ifneq (,$(filter gnrc_ipv6_netif,$(USEMODULE)))
     DIRS += network_layer/ipv6/netif
 endif
+ifneq (,$(filter gnrc_ipv6_whitelist,$(USEMODULE)))
+    DIRS += network_layer/ipv6/whitelist
+endif
 ifneq (,$(filter gnrc_ndp,$(USEMODULE)))
     DIRS += network_layer/ndp
 endif
diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c
index 4d89ec1941..74d138d232 100644
--- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c
+++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c
@@ -30,6 +30,7 @@
 
 #include "net/gnrc/ipv6/nc.h"
 #include "net/gnrc/ipv6/netif.h"
+#include "net/gnrc/ipv6/whitelist.h"
 
 #include "net/gnrc/ipv6.h"
 
@@ -706,6 +707,13 @@ static void _receive(gnrc_pktsnip_t *pkt)
             gnrc_pktbuf_release(pkt);
             return;
         }
+#ifdef MODULE_GNRC_IPV6_WHITELIST
+        if (!gnrc_ipv6_whitelisted(&((ipv6_hdr_t *)(ipv6->data))->src)) {
+            DEBUG("ipv6: Source address not whitelisted, dropping packet\n");
+            gnrc_pktbuf_release(pkt);
+            return;
+        }
+#endif
     }
     else {
         if (!ipv6_hdr_is(pkt->data)) {
@@ -713,7 +721,13 @@ static void _receive(gnrc_pktsnip_t *pkt)
             gnrc_pktbuf_release(pkt);
             return;
         }
-
+#ifdef MODULE_GNRC_IPV6_WHITELIST
+        if (!gnrc_ipv6_whitelisted(&((ipv6_hdr_t *)(pkt->data))->src)) {
+            DEBUG("ipv6: Source address not whitelisted, dropping packet\n");
+            gnrc_pktbuf_release(pkt);
+            return;
+        }
+#endif
         /* seize ipv6 as a temporary variable */
         ipv6 = gnrc_pktbuf_start_write(pkt);
 
diff --git a/sys/net/gnrc/network_layer/ipv6/whitelist/Makefile b/sys/net/gnrc/network_layer/ipv6/whitelist/Makefile
new file mode 100644
index 0000000000..0638a322b9
--- /dev/null
+++ b/sys/net/gnrc/network_layer/ipv6/whitelist/Makefile
@@ -0,0 +1,3 @@
+MODULE = gnrc_ipv6_whitelist
+
+include $(RIOTBASE)/Makefile.base
diff --git a/sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist.c b/sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist.c
new file mode 100644
index 0000000000..d2beae5224
--- /dev/null
+++ b/sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include "bitfield.h"
+
+#include "net/gnrc/ipv6/whitelist.h"
+
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
+
+ipv6_addr_t gnrc_ipv6_whitelist[GNRC_IPV6_WHITELIST_SIZE];
+BITFIELD(gnrc_ipv6_whitelist_set, GNRC_IPV6_WHITELIST_SIZE);
+
+#if ENABLE_DEBUG
+static char addr_str[IPV6_ADDR_MAX_STR_LEN];
+#endif
+
+int gnrc_ipv6_whitelist_add(const ipv6_addr_t *addr)
+{
+    for (int i = 0; i < GNRC_IPV6_WHITELIST_SIZE; i++) {
+        if (!bf_isset(gnrc_ipv6_whitelist_set, i)) {
+            bf_set(gnrc_ipv6_whitelist_set, i);
+            gnrc_ipv6_whitelist[i].u64[0].u64 = addr->u64[0].u64;
+            gnrc_ipv6_whitelist[i].u64[1].u64 = addr->u64[1].u64;
+            DEBUG("IPv6 whitelist: whitelisted %s\n",
+                  ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
+            return 0;
+        }
+    }
+    return -1;
+}
+
+void gnrc_ipv6_whitelist_del(const ipv6_addr_t *addr)
+{
+    for (int i = 0; i < GNRC_IPV6_WHITELIST_SIZE; i++) {
+        if (ipv6_addr_equal(addr, &gnrc_ipv6_whitelist[i])) {
+            bf_unset(gnrc_ipv6_whitelist_set, i);
+            DEBUG("IPv6 whitelist: unwhitelisted %s\n",
+                  ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
+        }
+    }
+}
+
+bool gnrc_ipv6_whitelisted(const ipv6_addr_t *addr)
+{
+    for (int i = 0; i < GNRC_IPV6_WHITELIST_SIZE; i++) {
+        if (bf_isset(gnrc_ipv6_whitelist_set, i) &&
+            ipv6_addr_equal(addr, &gnrc_ipv6_whitelist[i])) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/** @} */
diff --git a/sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist_print.c b/sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist_print.c
new file mode 100644
index 0000000000..9d2ad072ba
--- /dev/null
+++ b/sys/net/gnrc/network_layer/ipv6/whitelist/gnrc_ipv6_whitelist_print.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <stdio.h>
+
+#include "bitfield.h"
+#include "net/ipv6/addr.h"
+
+#include "net/gnrc/ipv6/whitelist.h"
+
+extern ipv6_addr_t gnrc_ipv6_whitelist[GNRC_IPV6_WHITELIST_SIZE];
+extern BITFIELD(gnrc_ipv6_whitelist_set, GNRC_IPV6_WHITELIST_SIZE);
+
+void gnrc_ipv6_whitelist_print(void)
+{
+    char addr_str[IPV6_ADDR_MAX_STR_LEN];
+    for (int i = 0; i < GNRC_IPV6_WHITELIST_SIZE; i++) {
+        if (bf_isset(gnrc_ipv6_whitelist_set, i)) {
+            puts(ipv6_addr_to_str(addr_str, &gnrc_ipv6_whitelist[i], sizeof(addr_str)));
+        }
+    }
+}
+
+/** @} */
-- 
GitLab