net/netlink: Add NETLINK_NETFILTER's CONNTRACK support
Now we only supports conntrack info from NAT entries, to let our apps in user space know the mapping status in NAT. Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
9b77bb16c9
commit
3a844d8dd7
@ -437,6 +437,160 @@
|
||||
|
||||
#define RTM_F_CLONED 0x200 /* This route is cloned */
|
||||
|
||||
/* Attribute definitions for struct nfattr **********************************/
|
||||
|
||||
/* Macros to handle attribute lists */
|
||||
|
||||
#define NFNL_NFA_NEST 0x8000
|
||||
#define NFA_TYPE(attr) ((attr)->nfa_type & 0x7fff)
|
||||
|
||||
#define NFA_MASK (sizeof(uint32_t) - 1)
|
||||
#define NFA_ALIGN(n) (((n) + NFA_MASK) & ~NFA_MASK)
|
||||
#define NFA_OK(nfa, n) \
|
||||
((n) >= (int)sizeof(struct nfattr) && \
|
||||
(nfa)->nfa_len >= sizeof(struct nfattr) && \
|
||||
(nfa)->nfa_len <= (n))
|
||||
#define NFA_NEXT(nfa, attrlen) \
|
||||
((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \
|
||||
(FAR struct nfattr *)(((FAR char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len)))
|
||||
#define NFA_LENGTH(len) ((sizeof(struct nfattr)) + (len))
|
||||
#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len))
|
||||
#define NFA_DATA(nfa) ((FAR void *)(((FAR char *)(nfa)) + NFA_LENGTH(0)))
|
||||
#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
|
||||
|
||||
/* Definitions for struct nfgenmsg ******************************************/
|
||||
|
||||
#define NFM_NFA(n) ((FAR struct nfattr *) \
|
||||
(((FAR char *)(n)) + \
|
||||
NLMSG_ALIGN(sizeof(struct nfgenmsg))))
|
||||
#define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))
|
||||
|
||||
/* Definitions for NETLINK_NETFILTER ****************************************/
|
||||
|
||||
#define NFNETLINK_V0 0
|
||||
|
||||
/* netfilter netlink message types are split in two pieces:
|
||||
* 8 bit subsystem, 8bit operation.
|
||||
*/
|
||||
|
||||
#define NFNL_SUBSYS_ID(x) (((x) & 0xff00) >> 8)
|
||||
#define NFNL_MSG_TYPE(x) ((x) & 0x00ff)
|
||||
|
||||
/* subsystems */
|
||||
|
||||
#define NFNL_SUBSYS_NONE 0
|
||||
#define NFNL_SUBSYS_CTNETLINK 1
|
||||
#define NFNL_SUBSYS_CTNETLINK_EXP 2
|
||||
#define NFNL_SUBSYS_QUEUE 3
|
||||
#define NFNL_SUBSYS_ULOG 4
|
||||
#define NFNL_SUBSYS_OSF 5
|
||||
#define NFNL_SUBSYS_IPSET 6
|
||||
#define NFNL_SUBSYS_ACCT 7
|
||||
#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8
|
||||
#define NFNL_SUBSYS_CTHELPER 9
|
||||
#define NFNL_SUBSYS_NFTABLES 10
|
||||
#define NFNL_SUBSYS_NFT_COMPAT 11
|
||||
#define NFNL_SUBSYS_HOOK 12
|
||||
#define NFNL_SUBSYS_COUNT 13
|
||||
|
||||
/* NETLINK_NETFILTER: subsystem CTNL (ip conntrack netlink) message types */
|
||||
|
||||
#define IPCTNL_MSG_CT_NEW 0
|
||||
#define IPCTNL_MSG_CT_GET 1
|
||||
#define IPCTNL_MSG_CT_DELETE 2
|
||||
#define IPCTNL_MSG_CT_GET_CTRZERO 3
|
||||
#define IPCTNL_MSG_CT_GET_STATS_CPU 4
|
||||
#define IPCTNL_MSG_CT_GET_STATS 5
|
||||
#define IPCTNL_MSG_CT_GET_DYING 6
|
||||
#define IPCTNL_MSG_CT_GET_UNCONFIRMED 7
|
||||
#define IPCTNL_MSG_MAX 8
|
||||
|
||||
/* NETLINK_NETFILTER: Conntrack attributes */
|
||||
|
||||
#define CTA_UNSPEC 0
|
||||
#define CTA_TUPLE_ORIG 1
|
||||
#define CTA_TUPLE_REPLY 2
|
||||
#define CTA_STATUS 3
|
||||
#define CTA_PROTOINFO 4
|
||||
#define CTA_HELP 5
|
||||
#define CTA_NAT_SRC 6
|
||||
#define CTA_TIMEOUT 7
|
||||
#define CTA_MARK 8
|
||||
#define CTA_COUNTERS_ORIG 9
|
||||
#define CTA_COUNTERS_REPLY 10
|
||||
#define CTA_USE 11
|
||||
#define CTA_ID 12
|
||||
#define CTA_NAT_DST 13
|
||||
#define CTA_TUPLE_MASTER 14
|
||||
#define CTA_SEQ_ADJ_ORIG 15
|
||||
#define CTA_NAT_SEQ_ADJ_ORIG CTA_SEQ_ADJ_ORIG
|
||||
#define CTA_SEQ_ADJ_REPLY 16
|
||||
#define CTA_NAT_SEQ_ADJ_REPLY CTA_SEQ_ADJ_REPLY
|
||||
#define CTA_ZONE 18
|
||||
#define CTA_SECCTX 19
|
||||
#define CTA_TIMESTAMP 20
|
||||
#define CTA_MARK_MASK 21
|
||||
#define CTA_LABELS 22
|
||||
#define CTA_LABELS_MASK 23
|
||||
#define CTA_SYNPROXY 24
|
||||
#define CTA_FILTER 25
|
||||
#define CTA_STATUS_MASK 26
|
||||
#define CTA_MAX 26
|
||||
|
||||
/* NETLINK_NETFILTER: Conntrack tuple attributes */
|
||||
|
||||
#define CTA_TUPLE_UNSPEC 0
|
||||
#define CTA_TUPLE_IP 1
|
||||
#define CTA_TUPLE_PROTO 2
|
||||
#define CTA_TUPLE_ZONE 3
|
||||
#define CTA_TUPLE_MAX 3
|
||||
|
||||
/* NETLINK_NETFILTER: Conntrack IP attributes */
|
||||
|
||||
#define CTA_IP_UNSPEC 0
|
||||
#define CTA_IP_V4_SRC 1
|
||||
#define CTA_IP_V4_DST 2
|
||||
#define CTA_IP_V6_SRC 3
|
||||
#define CTA_IP_V6_DST 4
|
||||
#define CTA_IP_MAX 4
|
||||
|
||||
/* NETLINK_NETFILTER: Conntrack protocol attributes */
|
||||
|
||||
#define CTA_PROTO_UNSPEC 0
|
||||
#define CTA_PROTO_NUM 1
|
||||
#define CTA_PROTO_SRC_PORT 2
|
||||
#define CTA_PROTO_DST_PORT 3
|
||||
#define CTA_PROTO_ICMP_ID 4
|
||||
#define CTA_PROTO_ICMP_TYPE 5
|
||||
#define CTA_PROTO_ICMP_CODE 6
|
||||
#define CTA_PROTO_ICMPV6_ID 7
|
||||
#define CTA_PROTO_ICMPV6_TYPE 8
|
||||
#define CTA_PROTO_ICMPV6_CODE 9
|
||||
#define CTA_PROTO_MAX 9
|
||||
|
||||
/* NFnetlink multicast groups (userspace) */
|
||||
|
||||
#define NF_NETLINK_CONNTRACK_NEW 0x00000001
|
||||
#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002
|
||||
#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004
|
||||
#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008
|
||||
#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010
|
||||
#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020
|
||||
|
||||
/* NFnetlink multicast groups */
|
||||
|
||||
#define NFNLGRP_NONE 0
|
||||
#define NFNLGRP_CONNTRACK_NEW 1
|
||||
#define NFNLGRP_CONNTRACK_UPDATE 2
|
||||
#define NFNLGRP_CONNTRACK_DESTROY 3
|
||||
#define NFNLGRP_CONNTRACK_EXP_NEW 4
|
||||
#define NFNLGRP_CONNTRACK_EXP_UPDATE 5
|
||||
#define NFNLGRP_CONNTRACK_EXP_DESTROY 6
|
||||
#define NFNLGRP_NFTABLES 7
|
||||
#define NFNLGRP_ACCT_QUOTA 8
|
||||
#define NFNLGRP_NFTRACE 9
|
||||
#define NFNLGRP_MAX 9
|
||||
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
@ -584,6 +738,25 @@ struct nla_bitfield32
|
||||
uint32_t selector;
|
||||
};
|
||||
|
||||
/* NETLINK_NETFILTER Message Structures *************************************/
|
||||
|
||||
/* These attributes should be manipulated using only the NFA_* */
|
||||
|
||||
struct nfattr
|
||||
{
|
||||
uint16_t nfa_len;
|
||||
uint16_t nfa_type;
|
||||
};
|
||||
|
||||
/* General form of address family dependent message. */
|
||||
|
||||
struct nfgenmsg
|
||||
{
|
||||
uint8_t nfgen_family; /* AF_xxx */
|
||||
uint8_t version; /* nfnetlink version */
|
||||
uint16_t res_id; /* resource id */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Neighbor Discovery userland options
|
||||
*/
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <nuttx/nuttx.h>
|
||||
|
||||
#include "nat/nat.h"
|
||||
#include "netlink/netlink.h"
|
||||
|
||||
#ifdef CONFIG_NET_NAT44
|
||||
|
||||
@ -145,6 +146,10 @@ ipv4_nat_entry_create(uint8_t protocol,
|
||||
hashtable_add(g_nat44_outbound, &entry->hash_outbound,
|
||||
ipv4_nat_outbound_key(local_ip, local_port, protocol));
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
netlink_conntrack_notify(IPCTNL_MSG_CT_NEW, PF_INET, entry);
|
||||
#endif
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -175,6 +180,10 @@ static void ipv4_nat_entry_delete(FAR ipv4_nat_entry_t *entry)
|
||||
entry->local_port,
|
||||
entry->protocol));
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
netlink_conntrack_notify(IPCTNL_MSG_CT_DELETE, PF_INET, entry);
|
||||
#endif
|
||||
|
||||
kmm_free(entry);
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include "inet/inet.h"
|
||||
#include "nat/nat.h"
|
||||
#include "netlink/netlink.h"
|
||||
|
||||
#ifdef CONFIG_NET_NAT66
|
||||
|
||||
@ -135,6 +136,10 @@ ipv6_nat_entry_create(uint8_t protocol, const net_ipv6addr_t external_ip,
|
||||
hashtable_add(g_nat66_outbound, &entry->hash_outbound,
|
||||
ipv6_nat_hash_key(local_ip, local_port, protocol));
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
netlink_conntrack_notify(IPCTNL_MSG_CT_NEW, PF_INET6, entry);
|
||||
#endif
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -168,6 +173,10 @@ static void ipv6_nat_entry_delete(FAR ipv6_nat_entry_t *entry)
|
||||
entry->local_port,
|
||||
entry->protocol));
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
netlink_conntrack_notify(IPCTNL_MSG_CT_DELETE, PF_INET6, entry);
|
||||
#endif
|
||||
|
||||
kmm_free(entry);
|
||||
}
|
||||
|
||||
|
@ -27,5 +27,9 @@ if(CONFIG_NET_NETLINK)
|
||||
list(APPEND SRCS netlink_route.c netlink_attr.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_NETLINK_NETFILTER)
|
||||
list(APPEND SRCS netlink_netfilter.c)
|
||||
endif()
|
||||
|
||||
target_sources(net PRIVATE ${SRCS})
|
||||
endif()
|
||||
|
@ -117,6 +117,15 @@ config NETLINK_VALIDATE_POLICY
|
||||
you pass in are valid.
|
||||
|
||||
endif # NETLINK_ROUTE
|
||||
|
||||
config NETLINK_NETFILTER
|
||||
bool "Netlink Netfilter protocol"
|
||||
default n
|
||||
depends on NET_NAT
|
||||
---help---
|
||||
Support the NETLINK_NETFILTER protocol option, mainly
|
||||
for conntrack with NAT.
|
||||
|
||||
endmenu # Netlink Protocols
|
||||
endif # NET_NETLINK
|
||||
endmenu # Netlink Socket Support
|
||||
|
@ -29,6 +29,10 @@ ifeq ($(CONFIG_NETLINK_ROUTE),y)
|
||||
NET_CSRCS += netlink_route.c netlink_attr.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NETLINK_NETFILTER),y)
|
||||
NET_CSRCS += netlink_netfilter.c
|
||||
endif
|
||||
|
||||
# Include netlink build support
|
||||
|
||||
DEPPATH += --dep-path netlink
|
||||
|
@ -543,7 +543,40 @@ int nla_parse(FAR struct nlattr **tb, int maxtype,
|
||||
FAR const struct nlattr *head,
|
||||
int len, FAR const struct nla_policy *policy,
|
||||
FAR struct netlink_ext_ack *extack);
|
||||
#endif
|
||||
#endif /* CONFIG_NETLINK_ROUTE */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_netfilter_sendto
|
||||
*
|
||||
* Description:
|
||||
* Perform the sendto() operation for the NETLINK_NETFILTER protocol.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
ssize_t netlink_netfilter_sendto(NETLINK_HANDLE handle,
|
||||
FAR const struct nlmsghdr *nlmsg,
|
||||
size_t len, int flags,
|
||||
FAR const struct sockaddr_nl *to,
|
||||
socklen_t tolen);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_conntrack_notify
|
||||
*
|
||||
* Description:
|
||||
* Perform the conntrack broadcast for the NETLINK_NETFILTER protocol.
|
||||
*
|
||||
* Input Parameters:
|
||||
* type - The type of the message, IPCTNL_MSG_CT_*
|
||||
* domain - The domain of the message
|
||||
* nat_entry - The NAT entry
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void netlink_conntrack_notify(uint8_t type, uint8_t domain,
|
||||
FAR const void *nat_entry);
|
||||
|
||||
#endif /* CONFIG_NETLINK_NETFILTER */
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
|
703
net/netlink/netlink_netfilter.c
Normal file
703
net/netlink/netlink_netfilter.c
Normal file
@ -0,0 +1,703 @@
|
||||
/****************************************************************************
|
||||
* net/netlink/netlink_netfilter.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 <assert.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <netpacket/netlink.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/icmp.h>
|
||||
#include <nuttx/net/ip.h>
|
||||
#include <nuttx/net/netlink.h>
|
||||
|
||||
#include "inet/inet.h"
|
||||
#include "nat/nat.h"
|
||||
#include "netlink/netlink.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct nfnl_sendto_request_s
|
||||
{
|
||||
struct nlmsghdr hdr;
|
||||
struct nfgenmsg msg;
|
||||
};
|
||||
|
||||
struct nfnl_info_s
|
||||
{
|
||||
NETLINK_HANDLE handle;
|
||||
FAR const struct nfnl_sendto_request_s *req;
|
||||
};
|
||||
|
||||
struct nfnl_ipv4addr_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
in_addr_t addr;
|
||||
};
|
||||
|
||||
struct nfnl_ipv6addr_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
net_ipv6addr_t addr;
|
||||
};
|
||||
|
||||
struct nfnl_attr_u8_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
uint8_t value;
|
||||
uint8_t pad[3];
|
||||
};
|
||||
|
||||
struct nfnl_attr_u16_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
uint16_t value;
|
||||
uint16_t pad[1];
|
||||
};
|
||||
|
||||
/* Struct of a conntrack tuple
|
||||
* +------+--------------+-----------------+
|
||||
* | attr | CTA_TUPLE_IP | CTA_TUPLE_PROTO |
|
||||
* +------+--------------+-----------------+
|
||||
*/
|
||||
|
||||
/* CTA_TUPLE_IP definitions */
|
||||
|
||||
struct conntrack_tuple_ipv4_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
struct nfnl_ipv4addr_s src;
|
||||
struct nfnl_ipv4addr_s dst;
|
||||
};
|
||||
|
||||
struct conntrack_tuple_ipv6_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
struct nfnl_ipv6addr_s src;
|
||||
struct nfnl_ipv6addr_s dst;
|
||||
};
|
||||
|
||||
/* CTA_TUPLE_PROTO definitions */
|
||||
|
||||
struct conntrack_tuple_tcpudp_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
struct nfnl_attr_u8_s proto;
|
||||
struct nfnl_attr_u16_s sport;
|
||||
struct nfnl_attr_u16_s dport;
|
||||
};
|
||||
|
||||
struct conntrack_tuple_icmp_s
|
||||
{
|
||||
struct nfattr attr;
|
||||
struct nfnl_attr_u8_s proto;
|
||||
struct nfnl_attr_u16_s id;
|
||||
struct nfnl_attr_u8_s type;
|
||||
struct nfnl_attr_u8_s code;
|
||||
};
|
||||
|
||||
/* Struct of a conntrack response
|
||||
* +-----+-----+-----------------+----------------+
|
||||
* | hdr | msg | tuple of origin | tuple of reply |
|
||||
* +-----+-----+-----------------+----------------+
|
||||
*/
|
||||
|
||||
struct conntrack_recvfrom_response_s
|
||||
{
|
||||
struct nlmsghdr hdr;
|
||||
struct nfgenmsg msg;
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
#define SIZEOF_CTNL_RECVFROM_RESPONSE_S(n) \
|
||||
(sizeof(struct conntrack_recvfrom_response_s) + (n) - 1)
|
||||
|
||||
struct conntrack_recvfrom_rsplist_s
|
||||
{
|
||||
sq_entry_t flink;
|
||||
struct conntrack_recvfrom_response_s payload;
|
||||
};
|
||||
|
||||
#define SIZEOF_CTNL_RECVFROM_RSPLIST_S(n) \
|
||||
(sizeof(struct conntrack_recvfrom_rsplist_s) + (n) - 1)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_conntrack_tuple_size
|
||||
*
|
||||
* Description:
|
||||
* Get the size of a CTA_TUPLE. Struct of a conntrack tuple:
|
||||
* +------+--------------+-----------------+
|
||||
* | attr | CTA_TUPLE_IP | CTA_TUPLE_PROTO |
|
||||
* +------+--------------+-----------------+
|
||||
*
|
||||
* Input Parameters:
|
||||
* domain - The domain of the tuple
|
||||
* proto - The protocol of the tuple
|
||||
*
|
||||
* Returned Value:
|
||||
* The size of the tuple.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t netlink_conntrack_tuple_size(uint8_t domain, uint8_t proto)
|
||||
{
|
||||
size_t size = sizeof(struct nfattr);
|
||||
|
||||
switch (domain)
|
||||
{
|
||||
case PF_INET:
|
||||
size += sizeof(struct conntrack_tuple_ipv4_s);
|
||||
break;
|
||||
|
||||
case PF_INET6:
|
||||
size += sizeof(struct conntrack_tuple_ipv6_s);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
size += sizeof(struct conntrack_tuple_tcpudp_s);
|
||||
break;
|
||||
|
||||
case IPPROTO_ICMP:
|
||||
case IPPROTO_ICMP6:
|
||||
size += sizeof(struct conntrack_tuple_icmp_s);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_conntrack_fill_ip
|
||||
*
|
||||
* Description:
|
||||
* Fill the data of a CTA_TUPLE_IP.
|
||||
*
|
||||
* Input Parameters:
|
||||
* buf - The buffer to fill
|
||||
* domain - The domain of the addresses
|
||||
* src - The source address
|
||||
* dst - The destination address
|
||||
*
|
||||
* Returned Value:
|
||||
* The size of the filled data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static size_t netlink_conntrack_fill_ip(FAR void *buf, uint8_t domain,
|
||||
FAR const void *src,
|
||||
FAR const void *dst)
|
||||
{
|
||||
#ifdef CONFIG_NET_NAT44
|
||||
if (domain == PF_INET)
|
||||
{
|
||||
FAR struct conntrack_tuple_ipv4_s *tuple_ipv4 = buf;
|
||||
|
||||
tuple_ipv4->attr.nfa_len = sizeof(struct conntrack_tuple_ipv4_s);
|
||||
tuple_ipv4->attr.nfa_type = CTA_TUPLE_IP | NFNL_NFA_NEST;
|
||||
|
||||
tuple_ipv4->src.attr.nfa_len = NFA_LENGTH(sizeof(in_addr_t));
|
||||
tuple_ipv4->src.attr.nfa_type = CTA_IP_V4_SRC;
|
||||
net_ipv4addr_hdrcopy(&tuple_ipv4->src.addr, src);
|
||||
|
||||
tuple_ipv4->dst.attr.nfa_len = NFA_LENGTH(sizeof(in_addr_t));
|
||||
tuple_ipv4->dst.attr.nfa_type = CTA_IP_V4_DST;
|
||||
net_ipv4addr_hdrcopy(&tuple_ipv4->dst.addr, dst);
|
||||
|
||||
return tuple_ipv4->attr.nfa_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NAT66
|
||||
if (domain == PF_INET6)
|
||||
{
|
||||
FAR struct conntrack_tuple_ipv6_s *tuple_ipv6 = buf;
|
||||
|
||||
tuple_ipv6->attr.nfa_len = sizeof(struct conntrack_tuple_ipv6_s);
|
||||
tuple_ipv6->attr.nfa_type = CTA_TUPLE_IP | NFNL_NFA_NEST;
|
||||
|
||||
tuple_ipv6->src.attr.nfa_len = NFA_LENGTH(sizeof(net_ipv6addr_t));
|
||||
tuple_ipv6->src.attr.nfa_type = CTA_IP_V6_SRC;
|
||||
net_ipv6addr_hdrcopy(tuple_ipv6->src.addr, src);
|
||||
|
||||
tuple_ipv6->dst.attr.nfa_len = NFA_LENGTH(sizeof(net_ipv6addr_t));
|
||||
tuple_ipv6->dst.attr.nfa_type = CTA_IP_V6_DST;
|
||||
net_ipv6addr_hdrcopy(tuple_ipv6->dst.addr, dst);
|
||||
|
||||
return tuple_ipv6->attr.nfa_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_conntrack_fill_proto
|
||||
*
|
||||
* Description:
|
||||
* Fill the data of a CTA_TUPLE_PROTO.
|
||||
*
|
||||
* Input Parameters:
|
||||
* buf - The buffer to fill
|
||||
* proto - The protocol of the tuple
|
||||
* sport - The source port
|
||||
* dport - The destination port
|
||||
* reply - True if the tuple is a reply
|
||||
*
|
||||
* Returned Value:
|
||||
* The size of the filled data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static size_t netlink_conntrack_fill_proto(FAR void *buf, uint8_t proto,
|
||||
uint16_t sport, uint16_t dport,
|
||||
bool reply)
|
||||
{
|
||||
switch (proto)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP
|
||||
case IPPROTO_TCP:
|
||||
#endif
|
||||
#ifdef CONFIG_NET_UDP
|
||||
case IPPROTO_UDP:
|
||||
#endif
|
||||
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
|
||||
{
|
||||
FAR struct conntrack_tuple_tcpudp_s *tuple_tcpudp = buf;
|
||||
|
||||
tuple_tcpudp->attr.nfa_len =
|
||||
sizeof(struct conntrack_tuple_tcpudp_s);
|
||||
tuple_tcpudp->attr.nfa_type = CTA_TUPLE_PROTO | NFNL_NFA_NEST;
|
||||
|
||||
tuple_tcpudp->proto.attr.nfa_len = NFA_LENGTH(sizeof(uint8_t));
|
||||
tuple_tcpudp->proto.attr.nfa_type = CTA_PROTO_NUM;
|
||||
tuple_tcpudp->proto.value = proto;
|
||||
|
||||
tuple_tcpudp->sport.attr.nfa_len = NFA_LENGTH(sizeof(uint16_t));
|
||||
tuple_tcpudp->sport.attr.nfa_type = CTA_PROTO_SRC_PORT;
|
||||
tuple_tcpudp->sport.value = sport;
|
||||
|
||||
tuple_tcpudp->dport.attr.nfa_len = NFA_LENGTH(sizeof(uint16_t));
|
||||
tuple_tcpudp->dport.attr.nfa_type = CTA_PROTO_DST_PORT;
|
||||
tuple_tcpudp->dport.value = dport;
|
||||
|
||||
return tuple_tcpudp->attr.nfa_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_ICMP
|
||||
case IPPROTO_ICMP:
|
||||
#endif
|
||||
#ifdef CONFIG_NET_ICMPv6
|
||||
case IPPROTO_ICMP6:
|
||||
#endif
|
||||
#if defined(CONFIG_NET_ICMP) || defined(CONFIG_NET_ICMPv6)
|
||||
{
|
||||
FAR struct conntrack_tuple_icmp_s *tuple_icmp = buf;
|
||||
|
||||
tuple_icmp->attr.nfa_len = sizeof(struct conntrack_tuple_icmp_s);
|
||||
tuple_icmp->attr.nfa_type = CTA_TUPLE_PROTO | NFNL_NFA_NEST;
|
||||
|
||||
tuple_icmp->proto.attr.nfa_len = NFA_LENGTH(sizeof(uint8_t));
|
||||
tuple_icmp->proto.attr.nfa_type = CTA_PROTO_NUM;
|
||||
tuple_icmp->proto.value = proto;
|
||||
|
||||
tuple_icmp->id.attr.nfa_len = NFA_LENGTH(sizeof(uint16_t));
|
||||
tuple_icmp->id.value = reply ? dport : sport;
|
||||
|
||||
tuple_icmp->type.attr.nfa_len = NFA_LENGTH(sizeof(uint8_t));
|
||||
|
||||
tuple_icmp->code.attr.nfa_len = NFA_LENGTH(sizeof(uint8_t));
|
||||
tuple_icmp->code.value = 0;
|
||||
|
||||
#ifdef CONFIG_NET_ICMP
|
||||
if (proto == IPPROTO_ICMP)
|
||||
{
|
||||
tuple_icmp->id.attr.nfa_type = CTA_PROTO_ICMP_ID;
|
||||
tuple_icmp->type.attr.nfa_type = CTA_PROTO_ICMP_TYPE;
|
||||
tuple_icmp->type.value = reply ? ICMP_ECHO_REPLY :
|
||||
ICMP_ECHO_REQUEST;
|
||||
tuple_icmp->code.attr.nfa_type = CTA_PROTO_ICMP_CODE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_ICMPv6
|
||||
if (proto == IPPROTO_ICMP6)
|
||||
{
|
||||
tuple_icmp->id.attr.nfa_type = CTA_PROTO_ICMPV6_ID;
|
||||
tuple_icmp->type.attr.nfa_type = CTA_PROTO_ICMPV6_TYPE;
|
||||
tuple_icmp->type.value = reply ? ICMPv6_ECHO_REPLY :
|
||||
ICMPv6_ECHO_REQUEST;
|
||||
tuple_icmp->code.attr.nfa_type = CTA_PROTO_ICMPV6_CODE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return tuple_icmp->attr.nfa_len;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_get_ipv4/ipv6_conntrack
|
||||
*
|
||||
* Description:
|
||||
* Get the conntrack response corresponding to an NAT entry.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct netlink_response_s *
|
||||
netlink_get_conntrack(FAR const struct nlmsghdr *req, uint16_t flags,
|
||||
uint8_t type, uint8_t domain, uint8_t proto,
|
||||
FAR const void *lipaddr, uint16_t lport,
|
||||
FAR const void *eipaddr, uint16_t eport,
|
||||
FAR const void *ripaddr, uint16_t rport)
|
||||
{
|
||||
FAR struct conntrack_recvfrom_rsplist_s *entry;
|
||||
FAR struct nfattr *tuple;
|
||||
ssize_t tuple_size = netlink_conntrack_tuple_size(domain, proto);
|
||||
size_t offset = 0;
|
||||
size_t allocsize;
|
||||
size_t rspsize;
|
||||
|
||||
if (tuple_size < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to get tuple size in response.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rspsize = SIZEOF_CTNL_RECVFROM_RESPONSE_S(tuple_size * 2);
|
||||
allocsize = SIZEOF_CTNL_RECVFROM_RSPLIST_S(tuple_size * 2);
|
||||
|
||||
entry = kmm_malloc(allocsize);
|
||||
if (entry == NULL)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate response buffer.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry->payload.hdr.nlmsg_len = rspsize;
|
||||
entry->payload.hdr.nlmsg_type = type | (NFNL_SUBSYS_CTNETLINK << 8);
|
||||
entry->payload.hdr.nlmsg_flags = flags;
|
||||
entry->payload.hdr.nlmsg_seq = req ? req->nlmsg_seq : 0;
|
||||
entry->payload.hdr.nlmsg_pid = req ? req->nlmsg_pid : 0;
|
||||
|
||||
entry->payload.msg.nfgen_family = domain;
|
||||
entry->payload.msg.version = NFNETLINK_V0;
|
||||
entry->payload.msg.res_id = 0;
|
||||
|
||||
/* CTA_TUPLE_ORIG */
|
||||
|
||||
tuple = (FAR struct nfattr *)&entry->payload.data[offset];
|
||||
tuple->nfa_len = tuple_size;
|
||||
tuple->nfa_type = CTA_TUPLE_ORIG | NFNL_NFA_NEST;
|
||||
offset += sizeof(struct nfattr);
|
||||
|
||||
offset += netlink_conntrack_fill_ip(&entry->payload.data[offset], domain,
|
||||
lipaddr, ripaddr);
|
||||
offset += netlink_conntrack_fill_proto(&entry->payload.data[offset], proto,
|
||||
lport, rport, false);
|
||||
|
||||
DEBUGASSERT(offset == tuple_size);
|
||||
|
||||
/* CTA_TUPLE_REPLY */
|
||||
|
||||
tuple = (FAR struct nfattr *)&entry->payload.data[offset];
|
||||
tuple->nfa_len = tuple_size;
|
||||
tuple->nfa_type = CTA_TUPLE_REPLY | NFNL_NFA_NEST;
|
||||
offset += sizeof(struct nfattr);
|
||||
|
||||
offset += netlink_conntrack_fill_ip(&entry->payload.data[offset], domain,
|
||||
ripaddr, eipaddr);
|
||||
offset += netlink_conntrack_fill_proto(&entry->payload.data[offset], proto,
|
||||
rport, eport, true);
|
||||
|
||||
DEBUGASSERT(offset == tuple_size * 2);
|
||||
|
||||
return (FAR struct netlink_response_s *)entry;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_NAT44
|
||||
static FAR struct netlink_response_s *
|
||||
netlink_get_ipv4_conntrack(FAR const struct nlmsghdr *req,
|
||||
FAR const ipv4_nat_entry_t *entry,
|
||||
uint16_t flags, uint8_t type)
|
||||
{
|
||||
#ifndef CONFIG_NET_NAT44_SYMMETRIC
|
||||
const in_addr_t any = INADDR_ANY;
|
||||
#endif
|
||||
return netlink_get_conntrack(req, flags, type, PF_INET, entry->protocol,
|
||||
&entry->local_ip, entry->local_port,
|
||||
&entry->external_ip, entry->external_port,
|
||||
#ifdef CONFIG_NET_NAT44_SYMMETRIC
|
||||
&entry->peer_ip, entry->peer_port
|
||||
#else
|
||||
&any, 0 /* Zero-address */
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NAT66
|
||||
static FAR struct netlink_response_s *
|
||||
netlink_get_ipv6_conntrack(FAR const struct nlmsghdr *req,
|
||||
FAR const ipv6_nat_entry_t *entry,
|
||||
uint16_t flags, uint8_t type)
|
||||
{
|
||||
return netlink_get_conntrack(req, flags, type, PF_INET6, entry->protocol,
|
||||
entry->local_ip, entry->local_port,
|
||||
entry->external_ip, entry->external_port,
|
||||
#ifdef CONFIG_NET_NAT66_SYMMETRIC
|
||||
entry->peer_ip, entry->peer_port
|
||||
#else
|
||||
g_ipv6_unspecaddr, 0 /* Zero-address */
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_add_ipv4/ipv6_conntrack
|
||||
*
|
||||
* Description:
|
||||
* Add the conntrack response of an IPv4/IPv6 NAT entry.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_NAT44
|
||||
static void netlink_add_ipv4_conntrack(FAR ipv4_nat_entry_t *entry,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct nfnl_info_s *info = arg;
|
||||
FAR struct netlink_response_s *resp;
|
||||
uint16_t flags = NLM_F_MULTI | NLM_F_DUMP_FILTERED;
|
||||
|
||||
resp = netlink_get_ipv4_conntrack(&info->req->hdr, entry, flags,
|
||||
IPCTNL_MSG_CT_NEW);
|
||||
if (resp != NULL)
|
||||
{
|
||||
netlink_add_response(info->handle, resp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NAT66
|
||||
static void netlink_add_ipv6_conntrack(FAR ipv6_nat_entry_t *entry,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct nfnl_info_s *info = arg;
|
||||
FAR struct netlink_response_s *resp;
|
||||
uint16_t flags = NLM_F_MULTI | NLM_F_DUMP_FILTERED;
|
||||
|
||||
resp = netlink_get_ipv6_conntrack(&info->req->hdr, entry, flags,
|
||||
IPCTNL_MSG_CT_NEW);
|
||||
|
||||
if (resp != NULL)
|
||||
{
|
||||
netlink_add_response(info->handle, resp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_list_conntrack
|
||||
*
|
||||
* Description:
|
||||
* Return the entire NAT table.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int netlink_list_conntrack(NETLINK_HANDLE handle,
|
||||
FAR const struct nfnl_sendto_request_s *req)
|
||||
{
|
||||
struct nfnl_info_s info;
|
||||
uint8_t type = NFNL_MSG_TYPE(req->hdr.nlmsg_type);
|
||||
if (type != IPCTNL_MSG_CT_GET)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
info.handle = handle;
|
||||
info.req = req;
|
||||
|
||||
switch (req->msg.nfgen_family)
|
||||
{
|
||||
#ifdef CONFIG_NET_NAT44
|
||||
case AF_INET:
|
||||
ipv4_nat_entry_foreach(netlink_add_ipv4_conntrack, &info);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NAT66
|
||||
case AF_INET6:
|
||||
ipv6_nat_entry_foreach(netlink_add_ipv6_conntrack, &info);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return netlink_add_terminator(handle, &req->hdr, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_netfilter_sendto
|
||||
*
|
||||
* Description:
|
||||
* Perform the sendto() operation for the NETLINK_NETFILTER protocol.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t netlink_netfilter_sendto(NETLINK_HANDLE handle,
|
||||
FAR const struct nlmsghdr *nlmsg,
|
||||
size_t len, int flags,
|
||||
FAR const struct sockaddr_nl *to,
|
||||
socklen_t tolen)
|
||||
{
|
||||
FAR const struct nfnl_sendto_request_s *req =
|
||||
(FAR const struct nfnl_sendto_request_s *)nlmsg;
|
||||
ssize_t ret = -ENOSYS;
|
||||
uint8_t subsys;
|
||||
|
||||
DEBUGASSERT(handle != NULL && nlmsg != NULL &&
|
||||
nlmsg->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||
len >= sizeof(struct nlmsghdr) &&
|
||||
len >= nlmsg->nlmsg_len && to != NULL &&
|
||||
tolen >= sizeof(struct sockaddr_nl));
|
||||
|
||||
/* Split subsys and type from nlmsg->nlmsg_type */
|
||||
|
||||
subsys = NFNL_SUBSYS_ID(nlmsg->nlmsg_type);
|
||||
|
||||
/* Handle according to the subsystem */
|
||||
|
||||
switch (subsys)
|
||||
{
|
||||
case NFNL_SUBSYS_CTNETLINK:
|
||||
ret = netlink_list_conntrack(handle, req);
|
||||
break;
|
||||
}
|
||||
|
||||
/* On success, return the size of the request that was processed */
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netlink_conntrack_notify
|
||||
*
|
||||
* Description:
|
||||
* Perform the conntrack broadcast for the NETLINK_NETFILTER protocol.
|
||||
*
|
||||
* Input Parameters:
|
||||
* type - The type of the message, IPCTNL_MSG_CT_*
|
||||
* domain - The domain of the message
|
||||
* nat_entry - The NAT entry
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void netlink_conntrack_notify(uint8_t type, uint8_t domain,
|
||||
FAR const void *nat_entry)
|
||||
{
|
||||
FAR struct netlink_response_s *resp;
|
||||
uint16_t flags;
|
||||
int group;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case IPCTNL_MSG_CT_NEW:
|
||||
group = NFNLGRP_CONNTRACK_NEW;
|
||||
flags = NLM_F_EXCL | NLM_F_CREATE;
|
||||
break;
|
||||
|
||||
case IPCTNL_MSG_CT_DELETE:
|
||||
group = NFNLGRP_CONNTRACK_DESTROY;
|
||||
flags = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (domain)
|
||||
{
|
||||
#ifdef CONFIG_NET_NAT44
|
||||
case PF_INET:
|
||||
resp = netlink_get_ipv4_conntrack(NULL, nat_entry, flags, type);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NAT66
|
||||
case PF_INET6:
|
||||
resp = netlink_get_ipv6_conntrack(NULL, nat_entry, flags, type);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp != NULL)
|
||||
{
|
||||
netlink_add_broadcast(group, resp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NETLINK_NETFILTER */
|
@ -129,6 +129,11 @@ static int netlink_setup(FAR struct socket *psock)
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
case NETLINK_NETFILTER:
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
@ -621,6 +626,15 @@ static ssize_t netlink_sendmsg(FAR struct socket *psock,
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETLINK_NETFILTER
|
||||
case NETLINK_NETFILTER:
|
||||
ret = netlink_netfilter_sendto(conn, nlmsg,
|
||||
msg->msg_iov->iov_len, flags,
|
||||
(FAR const struct sockaddr_nl *)to,
|
||||
tolen);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user