From fdadfe279cd9a090ee5601402013fdf4f1712e40 Mon Sep 17 00:00:00 2001 From: Hauke Petersen <hauke.petersen@fu-berlin.de> Date: Tue, 16 May 2017 16:24:48 +0200 Subject: [PATCH] net: added link layer address filter module --- Makefile.dep | 4 + makefiles/pseudomodules.inc.mk | 2 + sys/Makefile | 3 + sys/include/net/l2filter.h | 129 +++++++++++++++++++++++++ sys/net/link_layer/l2filter/Makefile | 1 + sys/net/link_layer/l2filter/l2filter.c | 107 ++++++++++++++++++++ 6 files changed, 246 insertions(+) create mode 100644 sys/include/net/l2filter.h create mode 100644 sys/net/link_layer/l2filter/Makefile create mode 100644 sys/net/link_layer/l2filter/l2filter.c diff --git a/Makefile.dep b/Makefile.dep index 4cb063dc9c..bff528ba0b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -594,6 +594,10 @@ ifneq (,$(filter spiffs,$(USEMODULE))) USEMODULE += mtd endif +ifneq (,$(filter l2filter_%,$(USEMODULE))) + USEMODULE += l2filter +endif + # include package dependencies -include $(USEPKG:%=$(RIOTPKG)/%/Makefile.dep) diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index d922c62116..990b5eda6a 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -17,6 +17,8 @@ PSEUDOMODULES += gnrc_sixlowpan_router PSEUDOMODULES += gnrc_sixlowpan_router_default PSEUDOMODULES += gnrc_sock_check_reuse PSEUDOMODULES += gnrc_txtsnd +PSEUDOMODULES += l2filter_blacklist +PSEUDOMODULES += l2filter_whitelist PSEUDOMODULES += log PSEUDOMODULES += log_printfnoformat PSEUDOMODULES += lwip_arp diff --git a/sys/Makefile b/sys/Makefile index 206985f5c1..143b65e2b1 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -125,6 +125,9 @@ endif ifneq (,$(filter devfs,$(USEMODULE))) DIRS += fs/devfs endif +ifneq (,$(filter l2filter,$(USEMODULE))) + DIRS += net/link_layer/l2filter +endif DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE}))) diff --git a/sys/include/net/l2filter.h b/sys/include/net/l2filter.h new file mode 100644 index 0000000000..3e6403ebc8 --- /dev/null +++ b/sys/include/net/l2filter.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @defgroup net_l2filter Link layer address filter + * @ingroup net + * @brief Module for filtering (black- or white-listing) link layer + * addresses + * + * This module is used as a base for filtering link layer addresses. It allows + * to be (globally) configured in either blacklist or in whitelist mode. This + * configuration is done via RIOTs module system, for whitelist mode simply + * include the module `L2FILTER_WHITELIST`, for blacklist mode include + * `L2FILTER_BLACKLIST`. + * + * The actual memory for the filter lists should be allocated for every network + * device. This is done centrally in netdev_t type. + * + * @{ + * @file + * @brief Link layer address filter interface definition + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + */ + +#ifndef L2FILTER_H +#define L2FILTER_H + +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> +#include <errno.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Maximal length of addresses that can be stored in the filter list + */ +#ifndef L2FILTER_ADDR_MAXLEN +#define L2FILTER_ADDR_MAXLEN (8U) +#endif + +/** + * @brief Number of slots in each filter list (filter entries per device) + */ +#ifndef L2FILTER_LISTSIZE +#define L2FILTER_LISTSIZE (8U) +#endif + +/** + * @brief Filter list entries + * + * The filter list supports address entries with differing length. This is + * useful e.g. for IEEE802.15.4, where the list can store short and long + * addresses at the same time. + */ +typedef struct { + uint8_t addr[L2FILTER_ADDR_MAXLEN]; /**< link layer address */ + size_t addr_len; /**< address length in byte */ +} l2filter_t; + +/** + * @brief Add an entry to a devices filter list + * + * @param[in,out] list pointer to the filter list + * @param[in] addr address to be added to list + * @param[in] addr_len size of @p addr [in byte] + * + * @pre @p list != NULL + * @pre @p addr != NULL + * @pre @p addr_maxlen <= @ref L2FILTER_ADDR_MAXLEN + * + * @return 0 on success + * @return -ENOMEM if no empty slot left in list + */ +int l2filter_add(l2filter_t *list, const void *addr, size_t addr_len); + +/** + * @brief Remove an entry from the given filter list + * + * @param[in,out] list pointer to the filter list + * @param[in] addr address to remove from the list + * @param[in] addr_len length of @p addr [in byte] + * + * @pre @p list != NULL + * @pre @p addr != NULL + * @pre @p addr_maxlen <= @ref L2FILTER_ADDR_MAXLEN + * + * @return 0 on success + * @return -ENOENT if @p addr was not found in @p list + */ +int l2filter_rm(l2filter_t *list, const void *addr, size_t addr_len); + +/** + * @brief Check if the given address passes the set filters + * + * Independent if the l2filter module is used in blacklist or in whitelist mode, + * this function returns whether the given address passes the filter. In + * whitelist mode, this means that the given address has to be in the list, in + * blacklist mode this means that the given address is not in the list. + * + * @param[in] list list with black-/whitelisted addresses + * @param[in] addr address to check against the entries in @p list + * @param[in] addr_len length of @p addr [in byte] + * + * @pre @p list != NULL + * @pre @p addr != NULL + * @pre @p addr_maxlen <= @ref L2FILTER_ADDR_MAXLEN + * + * @return in whitelist mode: true if @p addr is in @p list + * @return in whitelist mode: false if @p addr is not in @p list + * @return in blacklist mode: true if @p addr is not in @p list + * @return in blacklist mode: false if @p addr is in @p list + */ +bool l2filter_pass(const l2filter_t *list, const void *addr, size_t addr_len); + +#ifdef __cplusplus +} +#endif + +#endif /* L2FILTER_H */ +/** @} */ diff --git a/sys/net/link_layer/l2filter/Makefile b/sys/net/link_layer/l2filter/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/net/link_layer/l2filter/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/l2filter/l2filter.c b/sys/net/link_layer/l2filter/l2filter.c new file mode 100644 index 0000000000..b9a50e3d55 --- /dev/null +++ b/sys/net/link_layer/l2filter/l2filter.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @ingroup net_l2filter + * @{ + * + * @file + * @brief Link layer address filter implementation + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * + * @} + */ + +#include <string.h> + +#include "assert.h" +#include "net/l2filter.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static inline bool match(const l2filter_t *filter, + const void *addr, size_t addr_len) +{ + return ((filter->addr_len == addr_len) && + (memcmp(filter->addr, addr, addr_len) == 0)); +} + +void l2filter_init(l2filter_t *list) +{ + assert(list); + + for (unsigned i = 0; i < L2FILTER_LISTSIZE; i++) { + list[i].addr_len = 0; + } +} + +int l2filter_add(l2filter_t *list, const void *addr, size_t addr_len) +{ + assert(list && addr && (addr_len <= L2FILTER_ADDR_MAXLEN)); + + int res = -ENOMEM; + + for (unsigned i = 0; i < L2FILTER_LISTSIZE; i++) { + if (list[i].addr_len == 0) { + list[i].addr_len = addr_len; + memcpy(list[i].addr, addr, addr_len); + res = 0; + break; + } + } + + return res; +} + +int l2filter_rm(l2filter_t *list, const void *addr, size_t addr_len) +{ + assert(list && addr && (addr_len <= L2FILTER_ADDR_MAXLEN)); + + int res = -ENOENT; + + for (unsigned i = 0; i < L2FILTER_LISTSIZE; i++) { + if (match(&list[i], addr, addr_len)) { + list[i].addr_len = 0; + res = 0; + break; + } + } + + return res; +} + +bool l2filter_pass(const l2filter_t *list, const void *addr, size_t addr_len) +{ + assert(list && addr && (addr_len <= L2FILTER_ADDR_MAXLEN)); + +#ifdef MODULE_L2FILTER_WHITELIST + bool res = false; + for (unsigned i = 0; i < L2FILTER_LISTSIZE; i++) { + if (match(&list[i], addr, addr_len)) { + DEBUG("[l2filter] whitelist: address match -> packet passes\n"); + res = true; + break; + } + } + DEBUG("[l2filter] whitelist: no match -> packet dropped\n"); +#else + bool res = true; + for (unsigned i = 0; i < L2FILTER_LISTSIZE; i++) { + if (match(&list[i], addr, addr_len)) { + DEBUG("[l2filter] blacklist: address match -> packet dropped\n"); + res = false; + break; + } + } + DEBUG("[l2fitler] blacklist: no match -> packet passes\n"); +#endif + + return res; +} -- GitLab