net: Support IP packet filter
Add a firewall compatible with Linux's iptables and ip6tables, with chains at similar points in the packet processing path. NIC ─> ipv[46]_input ┬> ipv[46]_forward ─> [FORWARD] ┬> devif_poll_out ─> NIC │ │ │ ┌> tcp ┐ │ │ ├> udp ┤ │ └> [INPUT] ┼> icmp ┼> [OUTPUT] ┘ ├> icmp6 ┤ └> ... ┘ Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
914b8367ba
commit
f7181676b7
12 changed files with 1078 additions and 6 deletions
|
@ -359,6 +359,7 @@ menuconfig NET_6LOWPAN
|
|||
source "net/sixlowpan/Kconfig"
|
||||
source "net/ipforward/Kconfig"
|
||||
source "net/nat/Kconfig"
|
||||
source "net/ipfilter/Kconfig"
|
||||
source "net/netfilter/Kconfig"
|
||||
source "net/ipfrag/Kconfig"
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ include sixlowpan/Make.defs
|
|||
include bluetooth/Make.defs
|
||||
include ieee802154/Make.defs
|
||||
include devif/Make.defs
|
||||
include ipfilter/Make.defs
|
||||
include ipforward/Make.defs
|
||||
include nat/Make.defs
|
||||
include netfilter/Make.defs
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "mld/mld.h"
|
||||
#include "ipforward/ipforward.h"
|
||||
#include "sixlowpan/sixlowpan.h"
|
||||
#include "ipfilter/ipfilter.h"
|
||||
#include "ipfrag/ipfrag.h"
|
||||
#include "inet/inet.h"
|
||||
|
||||
|
@ -184,6 +185,32 @@ static void devif_packet_conversion(FAR struct net_driver_s *dev,
|
|||
# define devif_packet_conversion(dev,pkttype)
|
||||
#endif /* CONFIG_NET_6LOWPAN */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: devif_poll_local_out
|
||||
*
|
||||
* Description:
|
||||
* Generic callback before device output to build L2 headers before sending
|
||||
* with packet filter for TCP/UDP/ICMP(v6).
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called from the MAC device driver with the network
|
||||
* locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
static int devif_poll_local_out(FAR struct net_driver_s *dev,
|
||||
devif_poll_callback_t callback)
|
||||
{
|
||||
/* Maybe we need to reply REJECT to ourself, so filter before loopback. */
|
||||
|
||||
ipfilter_out(dev);
|
||||
return devif_poll_out(dev, callback);
|
||||
}
|
||||
#else
|
||||
# define devif_poll_local_out(dev, callback) devif_poll_out(dev, callback)
|
||||
#endif /* CONFIG_NET_IPFILTER */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: devif_poll_pkt_connections
|
||||
*
|
||||
|
@ -397,7 +424,7 @@ static inline int devif_poll_icmp(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Call back into the driver */
|
||||
|
||||
bstop = devif_poll_out(dev, callback);
|
||||
bstop = devif_poll_local_out(dev, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,7 +471,7 @@ static inline int devif_poll_icmpv6(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Call back into the driver */
|
||||
|
||||
bstop = devif_poll_out(dev, callback);
|
||||
bstop = devif_poll_local_out(dev, callback);
|
||||
}
|
||||
}
|
||||
while (!bstop && (conn = icmpv6_nextconn(conn)) != NULL);
|
||||
|
@ -581,7 +608,7 @@ static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Call back into the driver */
|
||||
|
||||
bstop = devif_poll_out(dev, callback);
|
||||
bstop = devif_poll_local_out(dev, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +653,7 @@ static inline int devif_poll_tcp_connections(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Call back into the driver */
|
||||
|
||||
bstop = devif_poll_out(dev, callback);
|
||||
bstop = devif_poll_local_out(dev, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
#include "ipforward/ipforward.h"
|
||||
#include "devif/devif.h"
|
||||
#include "nat/nat.h"
|
||||
#include "ipfilter/ipfilter.h"
|
||||
#include "ipfrag/ipfrag.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
|
@ -392,6 +393,14 @@ static int ipv4_in(FAR struct net_driver_s *dev)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
if (ipv4_filter_in(dev) != IPFILTER_TARGET_ACCEPT)
|
||||
{
|
||||
ninfo("Drop/Reject INPUT packet due to filter.\n");
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now process the incoming packet according to the protocol. */
|
||||
|
||||
switch (ipv4->proto)
|
||||
|
@ -434,7 +443,11 @@ static int ipv4_in(FAR struct net_driver_s *dev)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) || \
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
ipfilter_out(dev);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) || defined(CONFIG_NET_IPFILTER) || \
|
||||
(defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK))
|
||||
done:
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "ipforward/ipforward.h"
|
||||
#include "inet/inet.h"
|
||||
#include "devif/devif.h"
|
||||
#include "ipfilter/ipfilter.h"
|
||||
#include "ipfrag/ipfrag.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -420,6 +421,14 @@ static int ipv6_in(FAR struct net_driver_s *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
if (ipv6_filter_in(dev) != IPFILTER_TARGET_ACCEPT)
|
||||
{
|
||||
ninfo("Drop/Reject INPUT packet due to filter.\n");
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now process the incoming packet according to the protocol specified in
|
||||
* the next header IPv6 field.
|
||||
*/
|
||||
|
@ -518,7 +527,11 @@ static int ipv6_in(FAR struct net_driver_s *dev)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_IPFORWARD
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
ipfilter_out(dev);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) || defined(CONFIG_NET_IPFILTER)
|
||||
done:
|
||||
#endif
|
||||
|
||||
|
|
27
net/ipfilter/CMakeLists.txt
Normal file
27
net/ipfilter/CMakeLists.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
# ##############################################################################
|
||||
# net/ipfilter/CMakeLists.txt
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
# IP filter source files
|
||||
|
||||
if(CONFIG_NET_IPFILTER)
|
||||
|
||||
target_sources(net PRIVATE ipfilter.c)
|
||||
|
||||
endif()
|
16
net/ipfilter/Kconfig
Normal file
16
net/ipfilter/Kconfig
Normal file
|
@ -0,0 +1,16 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config NET_IPFILTER
|
||||
bool "Enable IP packet filter (firewall)"
|
||||
default n
|
||||
depends on NET_IPv4 || NET_IPv6
|
||||
---help---
|
||||
Enable this option to enable the IP packet filter (firewall).
|
||||
Our IP packet filter is a netfilter-like packet filter that
|
||||
operates on the IP (and transport) layer. It is a stateless
|
||||
packet filter that can be used to filter packets based on
|
||||
source and destination IP addresses, source and destination
|
||||
ports, protocol, and interface.
|
32
net/ipfilter/Make.defs
Normal file
32
net/ipfilter/Make.defs
Normal file
|
@ -0,0 +1,32 @@
|
|||
############################################################################
|
||||
# net/ipfilter/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# IP filter source files
|
||||
|
||||
ifeq ($(CONFIG_NET_IPFILTER),y)
|
||||
|
||||
NET_CSRCS += ipfilter.c
|
||||
|
||||
# Include IP filter build support
|
||||
|
||||
DEPPATH += --dep-path ipfilter
|
||||
VPATH += :ipfilter
|
||||
|
||||
endif
|
632
net/ipfilter/ipfilter.c
Normal file
632
net/ipfilter/ipfilter.c
Normal file
|
@ -0,0 +1,632 @@
|
|||
/****************************************************************************
|
||||
* net/ipfilter/ipfilter.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/net/icmpv6.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/net/udp.h>
|
||||
#include <nuttx/queue.h>
|
||||
|
||||
#include "icmp/icmp.h"
|
||||
#include "icmpv6/icmpv6.h"
|
||||
#include "ipfilter/ipfilter.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define SPORT_MATCH(entry, sport) \
|
||||
(((sport) >= (entry)->match.tcpudp.sports[0] && \
|
||||
(sport) <= (entry)->match.tcpudp.sports[1]) ^ (entry)->inv_sport)
|
||||
|
||||
#define DPORT_MATCH(entry, dport) \
|
||||
(((dport) >= (entry)->match.tcpudp.dports[0] && \
|
||||
(dport) <= (entry)->match.tcpudp.dports[1]) ^ (entry)->inv_dport)
|
||||
|
||||
#define ICMP_MATCH(entry, icmphdr) \
|
||||
(((entry)->match.icmp.type == 0xFF || \
|
||||
(entry)->match.icmp.type == (icmphdr)->type) ^ (entry)->inv_icmp)
|
||||
|
||||
/* Getting L4 header from IPv4/IPv6 header. */
|
||||
|
||||
#define IPv4_L4HDR(ipv4) \
|
||||
((FAR void *)((FAR uint8_t *)(ipv4) + (((ipv4)->vhl & IPv4_HLMASK) << 2)))
|
||||
|
||||
#define IPv6_L4HDR(ipv6, proto) \
|
||||
((FAR void *)(net_ipv6_payload((FAR struct ipv6_hdr_s *)(ipv6), &(proto))))
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
static sq_queue_t g_ipv4_filters[IPFILTER_CHAIN_MAX];
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
static sq_queue_t g_ipv6_filters[IPFILTER_CHAIN_MAX];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_match_device
|
||||
*
|
||||
* Description:
|
||||
* Match the packet with the filter entries on devices.
|
||||
*
|
||||
* Input Parameters:
|
||||
* entry - The filter entry to match
|
||||
* indev - The network device that the packet comes from
|
||||
* outdev - The network device that the packet goes to
|
||||
*
|
||||
* Returned Value:
|
||||
* true - The input packet is matched
|
||||
* false - The input packet is not matched
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool ipfilter_match_device(FAR const struct ipfilter_entry_s *entry,
|
||||
FAR const struct net_driver_s *indev,
|
||||
FAR const struct net_driver_s *outdev)
|
||||
{
|
||||
bool matched;
|
||||
|
||||
if (indev != NULL && entry->indev != NULL)
|
||||
{
|
||||
matched = (indev == entry->indev) ^ entry->inv_indev;
|
||||
if (!matched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (outdev != NULL && entry->outdev != NULL)
|
||||
{
|
||||
matched = (outdev == entry->outdev) ^ entry->inv_outdev;
|
||||
if (!matched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_match_proto
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Input Parameters:
|
||||
*
|
||||
* Returned Value:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool ipfilter_match_proto(FAR const struct ipfilter_entry_s *entry,
|
||||
FAR const void *l4hdr, uint8_t proto)
|
||||
{
|
||||
bool matched;
|
||||
|
||||
if (entry->proto)
|
||||
{
|
||||
matched = (entry->proto == proto) ^ entry->inv_proto;
|
||||
if (!matched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry->inv_proto)
|
||||
{
|
||||
/* Cannot match port/type for inversed proto, just success. */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IP_PROTO_TCP:
|
||||
case IP_PROTO_UDP:
|
||||
if (entry->match_tcpudp)
|
||||
{
|
||||
/* Ports in TCP & UDP headers have same offset. */
|
||||
|
||||
FAR const struct udp_hdr_s *udp = l4hdr;
|
||||
return SPORT_MATCH(entry, NTOHS(udp->srcport)) &&
|
||||
DPORT_MATCH(entry, NTOHS(udp->destport));
|
||||
}
|
||||
|
||||
case IP_PROTO_ICMP:
|
||||
if (entry->match_icmp)
|
||||
{
|
||||
FAR const struct icmp_hdr_s *icmp = l4hdr;
|
||||
return ICMP_MATCH(entry, icmp);
|
||||
}
|
||||
|
||||
case IP_PROTO_ICMP6:
|
||||
if (entry->match_icmp)
|
||||
{
|
||||
FAR const struct icmpv6_hdr_s *icmpv6 = l4hdr;
|
||||
return ICMP_MATCH(entry, icmpv6);
|
||||
}
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_filter_match / ipv6_filter_match
|
||||
*
|
||||
* Description:
|
||||
* Match the input packet with the filter entries in the specified chain.
|
||||
*
|
||||
* Input Parameters:
|
||||
* indev - The network device that the packet comes from
|
||||
* outdev - The network device that the packet goes to
|
||||
* ipv4/ipv6 - The IPv4/IPv6 header
|
||||
* chain - The chain to match the filter entries
|
||||
*
|
||||
* Returned Value:
|
||||
* IPFILTER_TARGET_ACCEPT(0) - The input packet is accepted
|
||||
* IPFILTER_TARGET_DROP(-1) - The input packet needs to be dropped
|
||||
* IPFILTER_TARGET_REJECT(-2) - The input packet is rejected
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
static int ipv4_filter_match(FAR const struct net_driver_s *indev,
|
||||
FAR const struct net_driver_s *outdev,
|
||||
FAR const struct ipv4_hdr_s *ipv4,
|
||||
enum ipfilter_chain_e chain)
|
||||
{
|
||||
FAR const struct ipv4_filter_entry_s *filter;
|
||||
FAR const sq_queue_t *queue = &g_ipv4_filters[chain];
|
||||
FAR const sq_entry_t *entry;
|
||||
FAR const void *l4hdr;
|
||||
in_addr_t ipaddr;
|
||||
bool matched;
|
||||
|
||||
/* Handle unexpected status, return ACCEPT to indicate doing nothing. */
|
||||
|
||||
if ((indev == NULL && outdev == NULL) || ipv4 == NULL)
|
||||
{
|
||||
return IPFILTER_TARGET_ACCEPT;
|
||||
}
|
||||
|
||||
l4hdr = IPv4_L4HDR(ipv4);
|
||||
|
||||
sq_for_every(queue, entry)
|
||||
{
|
||||
filter = (FAR struct ipv4_filter_entry_s *)entry;
|
||||
|
||||
/* Match device */
|
||||
|
||||
if (!ipfilter_match_device(&filter->common, indev, outdev))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Match addresses */
|
||||
|
||||
ipaddr = net_ip4addr_conv32(ipv4->srcipaddr);
|
||||
matched = net_ipv4addr_maskcmp(filter->sip, ipaddr, filter->smsk)
|
||||
^ filter->common.inv_srcip;
|
||||
if (!matched)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ipaddr = net_ip4addr_conv32(ipv4->destipaddr);
|
||||
matched = net_ipv4addr_maskcmp(filter->dip, ipaddr, filter->dmsk)
|
||||
^ filter->common.inv_dstip;
|
||||
if (!matched)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Match protocol */
|
||||
|
||||
if (!ipfilter_match_proto(&filter->common, l4hdr, ipv4->proto))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Return the target action if matched. */
|
||||
|
||||
return filter->common.target;
|
||||
}
|
||||
|
||||
/* Normally there should be a default rule in chain, won't reach here. */
|
||||
|
||||
ninfo("No filter matched, maybe uninitialized.\n");
|
||||
return IPFILTER_TARGET_ACCEPT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
static int ipv6_filter_match(FAR const struct net_driver_s *indev,
|
||||
FAR const struct net_driver_s *outdev,
|
||||
FAR const struct ipv6_hdr_s *ipv6,
|
||||
enum ipfilter_chain_e chain)
|
||||
{
|
||||
FAR const struct ipv6_filter_entry_s *filter;
|
||||
FAR const sq_queue_t *queue = &g_ipv6_filters[chain];
|
||||
FAR const sq_entry_t *entry;
|
||||
FAR const void *l4hdr;
|
||||
uint8_t proto;
|
||||
bool matched;
|
||||
|
||||
/* Handle unexpected status, return ACCEPT to indicate doing nothing. */
|
||||
|
||||
if ((indev == NULL && outdev == NULL) || ipv6 == NULL)
|
||||
{
|
||||
return IPFILTER_TARGET_ACCEPT;
|
||||
}
|
||||
|
||||
l4hdr = IPv6_L4HDR(ipv6, proto);
|
||||
|
||||
sq_for_every(queue, entry)
|
||||
{
|
||||
filter = (FAR struct ipv6_filter_entry_s *)entry;
|
||||
|
||||
/* Match device */
|
||||
|
||||
if (!ipfilter_match_device(&filter->common, indev, outdev))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Match addresses */
|
||||
|
||||
matched = net_ipv6addr_maskcmp(filter->sip, ipv6->srcipaddr,
|
||||
filter->smsk)
|
||||
^ filter->common.inv_srcip;
|
||||
if (!matched)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
matched = net_ipv6addr_maskcmp(filter->dip, ipv6->destipaddr,
|
||||
filter->dmsk)
|
||||
^ filter->common.inv_dstip;
|
||||
if (!matched)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Match protocol */
|
||||
|
||||
if (!ipfilter_match_proto(&filter->common, l4hdr, proto))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Return the target action if matched. */
|
||||
|
||||
return filter->common.target;
|
||||
}
|
||||
|
||||
/* Normally there should be a default rule in chain, won't reach here. */
|
||||
|
||||
ninfo("No filter matched, maybe uninitialized.\n");
|
||||
return IPFILTER_TARGET_ACCEPT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_cfg_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate a new filter configuration entry for the given address family.
|
||||
*
|
||||
* Input Parameters:
|
||||
* family - The address family of the filter entry
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the newly allocated filter entry. NULL is returned on
|
||||
* failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ipfilter_entry_s *ipfilter_cfg_alloc(sa_family_t family)
|
||||
{
|
||||
/* We may optimize alloc / free later if we really have lots of configs. */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (family == PF_INET)
|
||||
{
|
||||
return kmm_zalloc(sizeof(struct ipv4_filter_entry_s));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET6)
|
||||
{
|
||||
return kmm_zalloc(sizeof(struct ipv6_filter_entry_s));
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_cfg_add
|
||||
*
|
||||
* Description:
|
||||
* Add a new filter configuration entry for the given address family to the
|
||||
* end of specified chain.
|
||||
*
|
||||
* Input Parameters:
|
||||
* entry - The filter entry to add
|
||||
* family - The address family of the filter entry
|
||||
* chain - The chain to add the filter entry to
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ipfilter_cfg_add(FAR struct ipfilter_entry_s *entry,
|
||||
sa_family_t family, enum ipfilter_chain_e chain)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (family == PF_INET)
|
||||
{
|
||||
sq_addlast((FAR sq_entry_t *)entry, &g_ipv4_filters[chain]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET6)
|
||||
{
|
||||
sq_addlast((FAR sq_entry_t *)entry, &g_ipv6_filters[chain]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_cfg_clear
|
||||
*
|
||||
* Description:
|
||||
* Clear all filter configuration entries for the given address family from
|
||||
* the specified chain.
|
||||
*
|
||||
* Input Parameters:
|
||||
* family - The address family of the filter entry to clear
|
||||
* chain - The chain to clear the filter entries from
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ipfilter_cfg_clear(sa_family_t family, enum ipfilter_chain_e chain)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (family == PF_INET)
|
||||
{
|
||||
FAR sq_queue_t *queue = &g_ipv4_filters[chain];
|
||||
while (!sq_empty(queue))
|
||||
{
|
||||
kmm_free(sq_remfirst(queue));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET6)
|
||||
{
|
||||
FAR sq_queue_t *queue = &g_ipv6_filters[chain];
|
||||
while (!sq_empty(queue))
|
||||
{
|
||||
kmm_free(sq_remfirst(queue));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_filter_in / ipv6_filter_in
|
||||
*
|
||||
* Description:
|
||||
* Handling IPv4/IPv6 filter on local input. Do nothing if the input
|
||||
* packet is accepted, set d_len to 0 if the input packet needs to be
|
||||
* dropped, and set d_iob to reject reply if the input packet is rejected.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The network device that the packet comes from
|
||||
*
|
||||
* Returned Value:
|
||||
* IPFILTER_TARGET_ACCEPT(0) - The input packet is accepted
|
||||
* IPFILTER_TARGET_DROP(-1) - The input packet needs to be dropped
|
||||
* IPFILTER_TARGET_REJECT(-2) - The input packet is rejected
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked. The d_iob and d_len in the dev are set.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int ipv4_filter_in(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||
int ret = ipv4_filter_match(dev, NULL, ipv4, IPFILTER_CHAIN_INPUT);
|
||||
|
||||
if (ret == IPFILTER_TARGET_DROP)
|
||||
{
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
if (ret == IPFILTER_TARGET_REJECT)
|
||||
{
|
||||
/* TODO: Support more --reject-with types later. */
|
||||
|
||||
icmp_reply(dev, ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACH);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int ipv6_filter_in(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
int ret = ipv6_filter_match(dev, NULL, ipv6, IPFILTER_CHAIN_INPUT);
|
||||
|
||||
if (ret == IPFILTER_TARGET_DROP)
|
||||
{
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
if (ret == IPFILTER_TARGET_REJECT)
|
||||
{
|
||||
/* TODO: Support more --reject-with types later. */
|
||||
|
||||
icmpv6_reply(dev, ICMPv6_DEST_UNREACHABLE, ICMPv6_ADDR_UNREACH, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_out
|
||||
*
|
||||
* Description:
|
||||
* Handling filter on local output. Do nothing if the output packet
|
||||
* is accepted, set d_len to 0 if the output packet needs to be dropped,
|
||||
* and set d_iob to reject reply if the output packet is rejected.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The network device that the packet goes to
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked. Only IPv4 and IPv6 packets call this function.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ipfilter_out(FAR struct net_driver_s *dev)
|
||||
{
|
||||
if (dev->d_iob == NULL || dev->d_len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (IFF_IS_IPv4(dev->d_flags))
|
||||
{
|
||||
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||
int ret = ipv4_filter_match(NULL, dev, ipv4, IPFILTER_CHAIN_OUTPUT);
|
||||
|
||||
if (ret == IPFILTER_TARGET_DROP)
|
||||
{
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
if (ret == IPFILTER_TARGET_REJECT)
|
||||
{
|
||||
icmp_reply(dev, ICMP_DEST_UNREACHABLE, ICMP_NET_UNREACH);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (IFF_IS_IPv6(dev->d_flags))
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
|
||||
int ret = ipv6_filter_match(NULL, dev, ipv6, IPFILTER_CHAIN_OUTPUT);
|
||||
|
||||
if (ret == IPFILTER_TARGET_DROP)
|
||||
{
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
if (ret == IPFILTER_TARGET_REJECT)
|
||||
{
|
||||
icmpv6_reply(dev, ICMPv6_DEST_UNREACHABLE, ICMPv6_ADDR_UNREACH, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_filter_fwd / ipv6_filter_fwd
|
||||
*
|
||||
* Description:
|
||||
* Handling IPv4/IPv6 filter on forwarding. Just return the target action,
|
||||
* and relies on the caller to do the actual drop / reject.
|
||||
*
|
||||
* Input Parameters:
|
||||
* indev - The network device that the packet comes from
|
||||
* outdev - The network device that the packet goes to
|
||||
* ipv4/ipv6 - The IPv4/IPv6 header
|
||||
*
|
||||
* Returned Value:
|
||||
* IPFILTER_TARGET_ACCEPT(0) - The input packet is accepted
|
||||
* IPFILTER_TARGET_DROP(-1) - The input packet needs to be dropped
|
||||
* IPFILTER_TARGET_REJECT(-2) - The input packet needs to be rejected
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv4)
|
||||
int ipv4_filter_fwd(FAR struct net_driver_s *indev,
|
||||
FAR struct net_driver_s *outdev,
|
||||
FAR struct ipv4_hdr_s *ipv4)
|
||||
{
|
||||
return ipv4_filter_match(indev, outdev, ipv4, IPFILTER_CHAIN_FORWARD);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
|
||||
int ipv6_filter_fwd(FAR struct net_driver_s *indev,
|
||||
FAR struct net_driver_s *outdev,
|
||||
FAR struct ipv6_hdr_s *ipv6)
|
||||
{
|
||||
return ipv6_filter_match(indev, outdev, ipv6, IPFILTER_CHAIN_FORWARD);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_IPFILTER */
|
266
net/ipfilter/ipfilter.h
Normal file
266
net/ipfilter/ipfilter.h
Normal file
|
@ -0,0 +1,266 @@
|
|||
/****************************************************************************
|
||||
* net/ipfilter/ipfilter.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __NET_IPFILTER_IPFILTER_H
|
||||
#define __NET_IPFILTER_IPFILTER_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/compiler.h>
|
||||
#include <nuttx/net/ip.h>
|
||||
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define IPFILTER_TARGET_ACCEPT (0)
|
||||
#define IPFILTER_TARGET_DROP (-1)
|
||||
#define IPFILTER_TARGET_REJECT (-2)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
enum ipfilter_chain_e
|
||||
{
|
||||
IPFILTER_CHAIN_INPUT = 0, /* = NF_IP_LOCAL_IN - 1, Input chain */
|
||||
IPFILTER_CHAIN_FORWARD = 1, /* = NF_IP_FORWARD - 1, Forward chain */
|
||||
IPFILTER_CHAIN_OUTPUT = 2, /* = NF_IP_LOCAL_OUT - 1, Output chain */
|
||||
IPFILTER_CHAIN_MAX
|
||||
};
|
||||
|
||||
/* The filter configuration entry */
|
||||
|
||||
struct ipfilter_entry_s
|
||||
{
|
||||
FAR struct ipfilter_entry_s *flink;
|
||||
|
||||
FAR struct net_driver_s *indev;
|
||||
FAR struct net_driver_s *outdev;
|
||||
|
||||
union /* Matches in host byte order (because it's range) */
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t sports[2]; /* Source port range */
|
||||
uint16_t dports[2]; /* Destination port range */
|
||||
} tcpudp;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t type; /* Type to match, 0xFF = ALL (Same as Linux) */
|
||||
} icmp;
|
||||
} match;
|
||||
|
||||
uint8_t proto; /* Protocol to match, 0 = ALL (Same as Linux) */
|
||||
int8_t target;
|
||||
|
||||
/* Match flags, whether we need to match protocol in detail */
|
||||
|
||||
uint8_t match_tcpudp : 1; /* Match TCP/UDP */
|
||||
uint8_t match_icmp : 1; /* Match ICMP */
|
||||
|
||||
/* Inverse flags */
|
||||
|
||||
uint8_t inv_indev : 1; /* Inverse input device */
|
||||
uint8_t inv_outdev : 1; /* Inverse output device */
|
||||
uint8_t inv_proto : 1; /* Inverse protocol */
|
||||
uint8_t inv_srcip : 1; /* Inverse source IP */
|
||||
uint8_t inv_dstip : 1; /* Inverse destination IP */
|
||||
uint8_t inv_sport : 1; /* Inverse source port */
|
||||
uint8_t inv_dport : 1; /* Inverse destination port */
|
||||
uint8_t inv_icmp : 1; /* Inverse ICMP type */
|
||||
};
|
||||
|
||||
struct ipv4_filter_entry_s
|
||||
{
|
||||
struct ipfilter_entry_s common;
|
||||
|
||||
/* Addresses in network byte order */
|
||||
|
||||
in_addr_t sip;
|
||||
in_addr_t dip;
|
||||
in_addr_t smsk;
|
||||
in_addr_t dmsk;
|
||||
};
|
||||
|
||||
struct ipv6_filter_entry_s
|
||||
{
|
||||
struct ipfilter_entry_s common;
|
||||
|
||||
/* Addresses in network byte order */
|
||||
|
||||
net_ipv6addr_t sip;
|
||||
net_ipv6addr_t dip;
|
||||
net_ipv6addr_t smsk;
|
||||
net_ipv6addr_t dmsk;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_cfg_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate a new filter configuration entry for the given address family.
|
||||
*
|
||||
* Input Parameters:
|
||||
* family - The address family of the filter entry
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the newly allocated filter entry. NULL is returned on
|
||||
* failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ipfilter_entry_s *ipfilter_cfg_alloc(sa_family_t family);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_cfg_add
|
||||
*
|
||||
* Description:
|
||||
* Add a new filter configuration entry for the given address family to the
|
||||
* end of specified chain.
|
||||
*
|
||||
* Input Parameters:
|
||||
* entry - The filter entry to add
|
||||
* family - The address family of the filter entry
|
||||
* chain - The chain to add the filter entry to
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ipfilter_cfg_add(FAR struct ipfilter_entry_s *entry,
|
||||
sa_family_t family, enum ipfilter_chain_e chain);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_cfg_clear
|
||||
*
|
||||
* Description:
|
||||
* Clear all filter configuration entries for the given address family from
|
||||
* the specified chain.
|
||||
*
|
||||
* Input Parameters:
|
||||
* family - The address family of the filter entry to clear
|
||||
* chain - The chain to clear the filter entries from
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ipfilter_cfg_clear(sa_family_t family, enum ipfilter_chain_e chain);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_filter_in / ipv6_filter_in
|
||||
*
|
||||
* Description:
|
||||
* Handling IPv4/IPv6 filter on local input. Do nothing if the input
|
||||
* packet is accepted, set d_len to 0 if the input packet needs to be
|
||||
* dropped, and set d_iob to reject reply if the input packet is rejected.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The network device that the packet comes from
|
||||
*
|
||||
* Returned Value:
|
||||
* IPFILTER_TARGET_ACCEPT(0) - The input packet is accepted
|
||||
* IPFILTER_TARGET_DROP(-1) - The input packet needs to be dropped
|
||||
* IPFILTER_TARGET_REJECT(-2) - The input packet is rejected
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked. The d_iob and d_len in the dev are set.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int ipv4_filter_in(FAR struct net_driver_s *dev);
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int ipv6_filter_in(FAR struct net_driver_s *dev);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipfilter_out
|
||||
*
|
||||
* Description:
|
||||
* Handling filter on local output. Do nothing if the output packet
|
||||
* is accepted, set d_len to 0 if the output packet needs to be dropped,
|
||||
* and set d_iob to reject reply if the output packet is rejected.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The network device that the packet goes to
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked. Only IPv4 and IPv6 packets call this function.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ipfilter_out(FAR struct net_driver_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_filter_fwd / ipv6_filter_fwd
|
||||
*
|
||||
* Description:
|
||||
* Handling IPv4/IPv6 filter on forwarding. Just return the target action,
|
||||
* and relies on the caller to do the actual drop / reject.
|
||||
*
|
||||
* Input Parameters:
|
||||
* indev - The network device that the packet comes from
|
||||
* outdev - The network device that the packet goes to
|
||||
* ipv4/ipv6 - The IPv4/IPv6 header
|
||||
*
|
||||
* Returned Value:
|
||||
* IPFILTER_TARGET_ACCEPT(0) - The input packet is accepted
|
||||
* IPFILTER_TARGET_DROP(-1) - The input packet needs to be dropped
|
||||
* IPFILTER_TARGET_REJECT(-2) - The input packet needs to be rejected
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv4)
|
||||
int ipv4_filter_fwd(FAR struct net_driver_s *indev,
|
||||
FAR struct net_driver_s *outdev,
|
||||
FAR struct ipv4_hdr_s *ipv4);
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
|
||||
int ipv6_filter_fwd(FAR struct net_driver_s *indev,
|
||||
FAR struct net_driver_s *outdev,
|
||||
FAR struct ipv6_hdr_s *ipv6);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_IPFILTER */
|
||||
#endif /* __NET_IPFILTER_IPFILTER_H */
|
|
@ -38,6 +38,7 @@
|
|||
#include "utils/utils.h"
|
||||
#include "sixlowpan/sixlowpan.h"
|
||||
#include "icmp/icmp.h"
|
||||
#include "ipfilter/ipfilter.h"
|
||||
#include "ipforward/ipforward.h"
|
||||
#include "nat/nat.h"
|
||||
#include "devif/devif.h"
|
||||
|
@ -214,6 +215,27 @@ static int ipv4_dev_forward(FAR struct net_driver_s *dev,
|
|||
#endif
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
/* Do filter before forwarding, to make sure we drop silently before
|
||||
* replying any other errors.
|
||||
*/
|
||||
|
||||
ret = ipv4_filter_fwd(dev, fwddev, ipv4);
|
||||
if (ret < 0)
|
||||
{
|
||||
ninfo("Drop/Reject FORWARD packet due to filter %d\n", ret);
|
||||
|
||||
/* Let ipv4_forward reply the reject. */
|
||||
|
||||
if (ret == IPFILTER_TARGET_REJECT)
|
||||
{
|
||||
ret = -ENETUNREACH;
|
||||
}
|
||||
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Verify that the full packet will fit within the forwarding device's MTU
|
||||
* if DF is set.
|
||||
*/
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "sixlowpan/sixlowpan.h"
|
||||
#include "devif/devif.h"
|
||||
#include "icmpv6/icmpv6.h"
|
||||
#include "ipfilter/ipfilter.h"
|
||||
#include "ipforward/ipforward.h"
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
|
||||
|
@ -337,6 +338,27 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
|||
#endif
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_NET_IPFILTER
|
||||
/* Do filter before forwarding, to make sure we drop silently before
|
||||
* replying any other errors.
|
||||
*/
|
||||
|
||||
ret = ipv6_filter_fwd(dev, fwddev, ipv6);
|
||||
if (ret < 0)
|
||||
{
|
||||
ninfo("Drop/Reject FORWARD packet due to filter %d\n", ret);
|
||||
|
||||
/* Let ipv6_forward reply the reject. */
|
||||
|
||||
if (ret == IPFILTER_TARGET_REJECT)
|
||||
{
|
||||
ret = -ENETUNREACH;
|
||||
}
|
||||
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the interface isn't "up", we can't forward. */
|
||||
|
||||
if ((fwddev->d_flags & IFF_UP) == 0)
|
||||
|
|
Loading…
Reference in a new issue