mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 13:13:08 +08:00
net: Add set/getsockopt options compatible with iptables.
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
@@ -60,6 +60,18 @@
|
||||
#define IPT_TARGET(e) \
|
||||
((FAR struct xt_entry_target *)((FAR uint8_t *)(e) + (e)->target_offset))
|
||||
|
||||
/* Auto fill common fields of entry and target. */
|
||||
|
||||
#define IPT_FILL_ENTRY(e, target_name) \
|
||||
do \
|
||||
{ \
|
||||
(e)->entry.target_offset = sizeof((e)->entry); \
|
||||
(e)->entry.next_offset = sizeof(*(e)); \
|
||||
(e)->target.target.u.target_size = sizeof(*(e)) - sizeof((e)->entry); \
|
||||
strcpy((e)->target.target.u.user.name, (target_name)); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define TABLE_NAME_NAT "nat"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
@@ -330,6 +330,7 @@ menuconfig NET_6LOWPAN
|
||||
source "net/sixlowpan/Kconfig"
|
||||
source "net/ipforward/Kconfig"
|
||||
source "net/nat/Kconfig"
|
||||
source "net/netfilter/Kconfig"
|
||||
|
||||
endmenu # Internet Protocol Selection
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ include ieee802154/Make.defs
|
||||
include devif/Make.defs
|
||||
include ipforward/Make.defs
|
||||
include nat/Make.defs
|
||||
include netfilter/Make.defs
|
||||
include route/Make.defs
|
||||
include procfs/Make.defs
|
||||
include usrsock/Make.defs
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ SOCK_CSRCS += inet_globals.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_IPv4),y)
|
||||
SOCK_CSRCS += ipv4_setsockopt.c ipv4_getsockname.c ipv4_getpeername.c ipv4_build_header.c
|
||||
SOCK_CSRCS += ipv4_setsockopt.c ipv4_getsockopt.c ipv4_getsockname.c ipv4_getpeername.c ipv4_build_header.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_IPv6),y)
|
||||
|
||||
@@ -161,6 +161,38 @@ int ipv6_setsockopt(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_getsockopt
|
||||
*
|
||||
* Description:
|
||||
* ipv4_getsockopt() retrieve the value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'psock' argument. If
|
||||
* the size of the option value is greater than 'value_len', the value
|
||||
* stored in the object pointed to by the 'value' argument will be silently
|
||||
* truncated. Otherwise, the length pointed to by the 'value_len' argument
|
||||
* will be modified to indicate the actual length of the 'value'.
|
||||
*
|
||||
* See <netinet/in.h> for the a complete list of values of IPv4 protocol
|
||||
* socket options.
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock Socket structure of the socket to query
|
||||
* option identifies the option to get
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_getsockopt() for
|
||||
* the list of possible error values.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int ipv4_getsockopt(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_getsockname and ipv6_sockname
|
||||
*
|
||||
|
||||
+14
-10
@@ -739,19 +739,23 @@ static int inet_get_socketlevel_option(FAR struct socket *psock, int option,
|
||||
static int inet_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
if (level == SOL_SOCKET)
|
||||
switch (level)
|
||||
{
|
||||
return inet_get_socketlevel_option(psock, option, value, value_len);
|
||||
}
|
||||
case SOL_SOCKET:
|
||||
return inet_get_socketlevel_option(psock, option, value, value_len);
|
||||
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
else if (level == IPPROTO_TCP)
|
||||
{
|
||||
return tcp_getsockopt(psock, option, value, value_len);
|
||||
}
|
||||
case IPPROTO_TCP:
|
||||
return tcp_getsockopt(psock, option, value, value_len);
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return -ENOPROTOOPT;
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
case IPPROTO_IP:
|
||||
return ipv4_getsockopt(psock, option, value, value_len);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/****************************************************************************
|
||||
* net/inet/ipv4_getsockopt.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 <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "netfilter/iptables.h"
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv4_getsockopt
|
||||
*
|
||||
* Description:
|
||||
* ipv4_getsockopt() retrieve the value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'psock' argument. If
|
||||
* the size of the option value is greater than 'value_len', the value
|
||||
* stored in the object pointed to by the 'value' argument will be silently
|
||||
* truncated. Otherwise, the length pointed to by the 'value_len' argument
|
||||
* will be modified to indicate the actual length of the 'value'.
|
||||
*
|
||||
* See <netinet/in.h> for the a complete list of values of IPv4 protocol
|
||||
* socket options.
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock Socket structure of the socket to query
|
||||
* option identifies the option to get
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_getsockopt() for
|
||||
* the list of possible error values.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ipv4_getsockopt(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ninfo("option: %d\n", option);
|
||||
|
||||
net_lock();
|
||||
switch (option)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPTABLES
|
||||
case IPT_SO_GET_INFO:
|
||||
case IPT_SO_GET_ENTRIES:
|
||||
ret = ipt_getsockopt(psock, option, value, value_len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized IPv4 option: %d\n", option);
|
||||
ret = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "netdev/netdev.h"
|
||||
#include "netfilter/iptables.h"
|
||||
#include "igmp/igmp.h"
|
||||
#include "inet/inet.h"
|
||||
#include "udp/udp.h"
|
||||
@@ -261,6 +262,12 @@ int ipv4_setsockopt(FAR struct socket *psock, int option,
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPTABLES
|
||||
case IPT_SO_SET_REPLACE:
|
||||
ret = ipt_setsockopt(psock, option, value, value_len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized IPv4 option: %d\n", option);
|
||||
ret = -ENOPROTOOPT;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config NET_IPTABLES
|
||||
bool "Iptables Interface"
|
||||
default y
|
||||
depends on NET_IPv4
|
||||
depends on NET_SOCKOPTS
|
||||
depends on NET_NAT # May change dependency if we have firewall later.
|
||||
---help---
|
||||
Enable or disable iptables compatible interface (for NAT).
|
||||
@@ -0,0 +1,36 @@
|
||||
############################################################################
|
||||
# net/netfilter/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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Netfilter source files
|
||||
|
||||
ifeq ($(CONFIG_NET_IPTABLES),y)
|
||||
|
||||
NET_CSRCS += ipt_sockopt.c
|
||||
|
||||
ifeq ($(CONFIG_NET_NAT),y)
|
||||
NET_CSRCS += ipt_nat.c
|
||||
endif
|
||||
|
||||
# Include Netfilter build support
|
||||
|
||||
DEPPATH += --dep-path netfilter
|
||||
VPATH += :netfilter
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,126 @@
|
||||
/****************************************************************************
|
||||
* net/netfilter/ipt_nat.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 <debug.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/net/netfilter/nf_nat.h>
|
||||
|
||||
#include "nat/nat.h"
|
||||
#include "netdev/netdev.h"
|
||||
#include "netfilter/iptables.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: adjust_nat
|
||||
*
|
||||
* Description:
|
||||
* Callback for netdev_foreach, enable/disable NAT on dev.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device to adjust NAT.
|
||||
* arg - The input ipt_replace config of NAT.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int adjust_nat(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
{
|
||||
FAR const struct ipt_replace *repl = arg;
|
||||
FAR struct ipt_entry *entry;
|
||||
FAR struct xt_entry_target *target;
|
||||
|
||||
ipt_entry_for_every(entry, repl->entries, repl->size)
|
||||
{
|
||||
target = IPT_TARGET(entry);
|
||||
if (strcmp(target->u.user.name, XT_MASQUERADE_TARGET) == 0 &&
|
||||
strcmp(dev->d_ifname, entry->ip.outiface) == 0)
|
||||
{
|
||||
ipv4_nat_enable(dev);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ipv4_nat_disable(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_nat_init
|
||||
*
|
||||
* Description:
|
||||
* Init NAT table data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ipt_replace *ipt_nat_init(void)
|
||||
{
|
||||
return ipt_alloc_table(TABLE_NAME_NAT, 1 << NF_INET_POST_ROUTING);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_nat_apply
|
||||
*
|
||||
* Description:
|
||||
* Try to apply NAT rules, will do nothing if failed.
|
||||
*
|
||||
* Input Parameters:
|
||||
* repl - The config got from user space to control NAT table.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ipt_nat_apply(FAR const struct ipt_replace *repl)
|
||||
{
|
||||
FAR struct ipt_entry *entry;
|
||||
FAR struct xt_entry_target *target;
|
||||
|
||||
/* Check config first. */
|
||||
|
||||
ipt_entry_for_every(entry, repl->entries, repl->size)
|
||||
{
|
||||
target = IPT_TARGET(entry);
|
||||
if (strcmp(target->u.user.name, XT_MASQUERADE_TARGET) == 0 &&
|
||||
netdev_findbyname(entry->ip.outiface) == NULL)
|
||||
{
|
||||
/* MASQUERADE specified but no WAN device, don't apply. */
|
||||
|
||||
nwarn("WARNING: Trying to apply nat on nonexistent dev: %s",
|
||||
entry->ip.outiface);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do actual work. */
|
||||
|
||||
netdev_foreach(adjust_nat, (FAR void *)repl);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
/****************************************************************************
|
||||
* net/netfilter/ipt_sockopt.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 <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "netfilter/iptables.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define SWAP(a,b,t) do { t = a; a = b; b = t; } while (0)
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Structure to store all info we need, including table data and
|
||||
* init/apply functions.
|
||||
*/
|
||||
|
||||
struct ipt_table_s
|
||||
{
|
||||
FAR struct ipt_replace *repl;
|
||||
FAR struct ipt_replace *(*init_func)(void);
|
||||
FAR int (*apply_func)(FAR const struct ipt_replace *);
|
||||
};
|
||||
|
||||
/* Following structs represent the layout of an entry with standard/error
|
||||
* target (without matches). Mainly used to simplify initialization (entry
|
||||
* creation), not suggested to use under other situations, because there
|
||||
* might be matches between entry and target in data from user space.
|
||||
*/
|
||||
|
||||
struct ipt_standard_entry_s
|
||||
{
|
||||
struct ipt_entry entry;
|
||||
struct xt_standard_target target;
|
||||
};
|
||||
|
||||
struct ipt_error_entry_s
|
||||
{
|
||||
struct ipt_entry entry;
|
||||
struct xt_error_target target;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct ipt_table_s g_tables[] =
|
||||
{
|
||||
#ifdef CONFIG_NET_NAT
|
||||
{NULL, ipt_nat_init, ipt_nat_apply},
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_table_init
|
||||
*
|
||||
* Description:
|
||||
* Try initialize the table data if not initialized.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ipt_table_init(FAR struct ipt_table_s *table)
|
||||
{
|
||||
if (table->repl == NULL && table->init_func != NULL)
|
||||
{
|
||||
table->repl = table->init_func();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_table
|
||||
*
|
||||
* Description:
|
||||
* Find table data by table name.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct ipt_table_s *ipt_table(FAR const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(g_tables); i++)
|
||||
{
|
||||
ipt_table_init(&g_tables[i]);
|
||||
if (g_tables[i].repl != NULL &&
|
||||
strcmp(g_tables[i].repl->name, name) == 0)
|
||||
{
|
||||
return &g_tables[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_table_repl
|
||||
*
|
||||
* Description:
|
||||
* Find table data by table name.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct ipt_replace *ipt_table_repl(FAR const char *name)
|
||||
{
|
||||
FAR struct ipt_table_s *table = ipt_table(name);
|
||||
if (table)
|
||||
{
|
||||
return table->repl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: get_info
|
||||
*
|
||||
* Description:
|
||||
* Fill table info into ipt_getinfo structure.
|
||||
*
|
||||
* Input Parameters:
|
||||
* get, len - The parameters from getsockopt.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int get_info(FAR struct ipt_getinfo *get, FAR socklen_t *len)
|
||||
{
|
||||
FAR struct ipt_replace *repl;
|
||||
|
||||
if (*len != sizeof(*get))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
repl = ipt_table_repl(get->name);
|
||||
if (repl == NULL)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
get->valid_hooks = repl->valid_hooks;
|
||||
memcpy(get->hook_entry, repl->hook_entry, sizeof(get->hook_entry));
|
||||
memcpy(get->underflow, repl->underflow, sizeof(get->underflow));
|
||||
get->num_entries = repl->num_entries;
|
||||
get->size = repl->size;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: get_entries
|
||||
*
|
||||
* Description:
|
||||
* Fill entry info into ipt_get_entries structure.
|
||||
*
|
||||
* Input Parameters:
|
||||
* get, len - The parameters from getsockopt.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int get_entries(FAR struct ipt_get_entries *get, FAR socklen_t *len)
|
||||
{
|
||||
FAR struct ipt_replace *repl;
|
||||
|
||||
if (*len < sizeof(*get) || *len != sizeof(*get) + get->size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
repl = ipt_table_repl(get->name);
|
||||
if (repl == NULL)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (get->size != repl->size)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
memcpy(get->entrytable, repl->entries, get->size);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: check_replace
|
||||
*
|
||||
* Description:
|
||||
* Check whether an ipt_replace structure from user space is valid.
|
||||
*
|
||||
* Input Parameters:
|
||||
* repl - The ipt_replace structure to check.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if repl is valid, otherwise -EINVAL.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int check_replace(FAR const struct ipt_replace *repl)
|
||||
{
|
||||
FAR struct ipt_entry *entry;
|
||||
unsigned int entry_count = 0;
|
||||
|
||||
ipt_entry_for_every(entry, repl->entries, repl->size)
|
||||
{
|
||||
entry_count++;
|
||||
}
|
||||
|
||||
if (entry_count != repl->num_entries)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* May add more checks later. */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: replace_entries
|
||||
*
|
||||
* Description:
|
||||
* Apply replace data to kernel tables.
|
||||
*
|
||||
* Input Parameters:
|
||||
* repl, len - The parameters from setsockopt.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int replace_entries(FAR const struct ipt_replace *repl, socklen_t len)
|
||||
{
|
||||
int ret;
|
||||
FAR struct ipt_replace *new_repl;
|
||||
FAR struct ipt_table_s *table = ipt_table(repl->name);
|
||||
|
||||
if (table == NULL || table->repl == NULL)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (len < sizeof(*repl) || len != sizeof(*repl) + repl->size ||
|
||||
repl->valid_hooks != table->repl->valid_hooks)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check replace struct before applying it. */
|
||||
|
||||
ret = check_replace(repl);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
new_repl = kmm_malloc(sizeof(*new_repl) + repl->size);
|
||||
if (new_repl == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Try to apply the config in replace data. */
|
||||
|
||||
ret = table->apply_func(repl);
|
||||
|
||||
/* If successfully applied, save data into kernel space. */
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
FAR struct ipt_replace *tmp;
|
||||
memcpy(new_repl, repl, sizeof(*repl) + repl->size);
|
||||
SWAP(table->repl, new_repl, tmp);
|
||||
}
|
||||
|
||||
kmm_free(new_repl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_alloc_table
|
||||
*
|
||||
* Description:
|
||||
* Allocate an initial table info with valid_hooks specified.
|
||||
* Will generate a default entry with standard target for each valid hook,
|
||||
* and an entry with error target at the end of entry table.
|
||||
*
|
||||
* Input Parameters:
|
||||
* table - The name of the table.
|
||||
* valid_hooks - The valid_hooks of the table, it's a bitmask.
|
||||
*
|
||||
* Returned Value:
|
||||
* Newly generated ipt_replace structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ipt_replace *ipt_alloc_table(FAR const char *table,
|
||||
unsigned int valid_hooks)
|
||||
{
|
||||
FAR struct ipt_replace *repl;
|
||||
FAR struct ipt_standard_entry_s *entry;
|
||||
FAR struct ipt_error_entry_s *error_entry;
|
||||
size_t entry_size;
|
||||
unsigned int hook;
|
||||
unsigned int num_hooks;
|
||||
|
||||
if (valid_hooks == 0 || valid_hooks > (1 << NF_INET_NUMHOOKS))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
num_hooks = popcount(valid_hooks);
|
||||
|
||||
/* There will be num_hooks entries with standard target (ACCEPT). */
|
||||
|
||||
entry_size = num_hooks * sizeof(struct ipt_standard_entry_s);
|
||||
|
||||
/* An error target as final entry. */
|
||||
|
||||
entry_size += sizeof(struct ipt_error_entry_s);
|
||||
|
||||
repl = kmm_zalloc(sizeof(*repl) + entry_size);
|
||||
if (repl == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(repl->name, table);
|
||||
repl->valid_hooks = valid_hooks;
|
||||
repl->num_entries = num_hooks + 1;
|
||||
repl->size = entry_size;
|
||||
|
||||
entry = (FAR struct ipt_standard_entry_s *)(repl + 1);
|
||||
|
||||
for (hook = 0; hook < NF_INET_NUMHOOKS; hook++)
|
||||
{
|
||||
if ((valid_hooks >> hook & 0x01) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
repl->hook_entry[hook] = (uintptr_t)entry - (uintptr_t)(repl + 1);
|
||||
repl->underflow[hook] = repl->hook_entry[hook];
|
||||
|
||||
entry->target.verdict = -NF_ACCEPT - 1;
|
||||
IPT_FILL_ENTRY(entry, XT_STANDARD_TARGET);
|
||||
|
||||
entry++;
|
||||
}
|
||||
|
||||
error_entry = (FAR struct ipt_error_entry_s *)entry;
|
||||
strcpy(error_entry->target.errorname, XT_ERROR_TARGET);
|
||||
IPT_FILL_ENTRY(error_entry, XT_ERROR_TARGET);
|
||||
|
||||
return repl;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_setsockopt
|
||||
*
|
||||
* Description:
|
||||
* setsockopt function of iptables.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ipt_setsockopt(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case IPT_SO_SET_REPLACE:
|
||||
return replace_entries(value, value_len);
|
||||
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_getsockopt
|
||||
*
|
||||
* Description:
|
||||
* getsockopt function of iptables.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ipt_getsockopt(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case IPT_SO_GET_INFO:
|
||||
return get_info(value, value_len);
|
||||
|
||||
case IPT_SO_GET_ENTRIES:
|
||||
return get_entries(value, value_len);
|
||||
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
* net/netfilter/iptables.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_NETFILTER_IPTABLES_H
|
||||
#define __NET_NETFILTER_IPTABLES_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/netfilter/ip_tables.h>
|
||||
|
||||
#ifdef CONFIG_NET_IPTABLES
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_setsockopt
|
||||
*
|
||||
* Description:
|
||||
* setsockopt function of iptables.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ipt_setsockopt(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_getsockopt
|
||||
*
|
||||
* Description:
|
||||
* getsockopt function of iptables.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ipt_getsockopt(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_alloc_table
|
||||
*
|
||||
* Description:
|
||||
* Allocate an initial table info with valid_hooks specified.
|
||||
* Will generate a default entry with standard target for each valid hook,
|
||||
* and an entry with error target at the end of entry table.
|
||||
*
|
||||
* Input Parameters:
|
||||
* table - The name of the table.
|
||||
* valid_hooks - The valid_hooks of the table, it's a bitmap of hooks.
|
||||
*
|
||||
* Returned Value:
|
||||
* Newly generated ipt_replace structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ipt_replace *ipt_alloc_table(FAR const char *table,
|
||||
unsigned int valid_hooks);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_nat_init
|
||||
*
|
||||
* Description:
|
||||
* Init NAT table data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_NAT
|
||||
FAR struct ipt_replace *ipt_nat_init(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipt_nat_apply
|
||||
*
|
||||
* Description:
|
||||
* Try to apply NAT rules, will do nothing if failed.
|
||||
*
|
||||
* Input Parameters:
|
||||
* repl - The config got from user space to control NAT table.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_NAT
|
||||
int ipt_nat_apply(FAR const struct ipt_replace *repl);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_IPTABLES */
|
||||
#endif /* __NET_NETFILTER_IPTABLES_H */
|
||||
Reference in New Issue
Block a user