diff --git a/Makefile.dep b/Makefile.dep index 89bab4b8528336da0cd47d46922791a5183a677e..0c29e594ef854862c66c1d939e81019e95f1f6ae 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 0000000000000000000000000000000000000000..b954b8e0d975af201aed332ccb17b65fc99d5d74 --- /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 cc7f891353857d4411005f2fdab7625cd7762556..6ac2001c7a705084ec9aa167c0242e691b0d1512 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 4d89ec19415e8339dafaf0dca4f2a3d93cccc979..74d138d232bcfec6e7c6ff15e24da3c1b046f088 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 0000000000000000000000000000000000000000..0638a322b9360022ea99e35459d229711988bcbf --- /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 0000000000000000000000000000000000000000..d2beae522469b90fcbfa97ce919a868663126137 --- /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 0000000000000000000000000000000000000000..9d2ad072ba5a00fc67561f683b997f3da14bebdb --- /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))); + } + } +} + +/** @} */