aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-08-05 19:25:22 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-05 19:25:22 -0400
commit074fb8801667add0b63083af90a3af6edca9532c (patch)
tree44244193ce484025e6dfb6eaef43342f93d73f3f
parentc1c8626fcebed467184ffd8de0ab5c9f9d9c3594 (diff)
parent483f3fdcc70b3c3a1f314235ab0066f3dbd4cfbe (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following patchset contains Netfilter updates for your net-next tree: 1) Support for transparent proxying for nf_tables, from Mate Eckl. 2) Patchset to add OS passive fingerprint recognition for nf_tables, from Fernando Fernandez. This takes common code from xt_osf and place it into the new nfnetlink_osf module for codebase sharing. 3) Lightweight tunneling support for nf_tables. 4) meta and lookup are likely going to be used in rulesets, make them direct calls. From Florian Westphal. A bunch of incremental updates: 5) use PTR_ERR_OR_ZERO() from nft_numgen, from YueHaibing. 6) Use kvmalloc_array() to allocate hashtables, from Li RongQing. 7) Explicit dependencies between nfnetlink_cttimeout and conntrack timeout extensions, from Harsha Sharma. 8) Simplify NLM_F_CREATE handling in nf_tables. 9) Removed unused variable in the get element command, from YueHaibing. 10) Expose bridge hook priorities through uapi, from Mate Eckl. And a few fixes for previous Netfilter batch for net-next: 11) Use per-netns mutex from flowtable event, from Florian Westphal. 12) Remove explicit dependency on iptables CT target from conntrack zones, from Florian. 13) Fix use-after-free in rmmod nf_conntrack path, also from Florian. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter/nfnetlink_osf.h (renamed from include/linux/netfilter/nf_osf.h)13
-rw-r--r--include/linux/netfilter_bridge.h11
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_tables_core.h7
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h107
-rw-r--r--include/uapi/linux/netfilter/nfnetlink_osf.h (renamed from include/uapi/linux/netfilter/nf_osf.h)9
-rw-r--r--include/uapi/linux/netfilter/xt_osf.h11
-rw-r--r--include/uapi/linux/netfilter_bridge.h11
-rw-r--r--net/bridge/br_netfilter_hooks.c1
-rw-r--r--net/bridge/netfilter/ebtable_filter.c1
-rw-r--r--net/bridge/netfilter/ebtable_nat.c1
-rw-r--r--net/core/dst.c1
-rw-r--r--net/netfilter/Kconfig45
-rw-r--r--net/netfilter/Makefile5
-rw-r--r--net/netfilter/nf_conntrack_core.c29
-rw-r--r--net/netfilter/nf_conntrack_expect.c2
-rw-r--r--net/netfilter/nf_conntrack_helper.c4
-rw-r--r--net/netfilter/nf_conntrack_proto.c7
-rw-r--r--net/netfilter/nf_nat_core.c4
-rw-r--r--net/netfilter/nf_tables_api.c35
-rw-r--r--net/netfilter/nf_tables_core.c16
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c6
-rw-r--r--net/netfilter/nfnetlink_osf.c (renamed from net/netfilter/nf_osf.c)186
-rw-r--r--net/netfilter/nft_lookup.c6
-rw-r--r--net/netfilter/nft_meta.c6
-rw-r--r--net/netfilter/nft_numgen.c4
-rw-r--r--net/netfilter/nft_osf.c106
-rw-r--r--net/netfilter/nft_tproxy.c316
-rw-r--r--net/netfilter/nft_tunnel.c566
-rw-r--r--net/netfilter/xt_connlimit.c4
-rw-r--r--net/netfilter/xt_osf.c149
31 files changed, 1417 insertions, 254 deletions
diff --git a/include/linux/netfilter/nf_osf.h b/include/linux/netfilter/nfnetlink_osf.h
index 0e114c492fb8..a7311bc03d3a 100644
--- a/include/linux/netfilter/nf_osf.h
+++ b/include/linux/netfilter/nfnetlink_osf.h
@@ -1,4 +1,8 @@
1#include <uapi/linux/netfilter/nf_osf.h> 1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _NFOSF_H
3#define _NFOSF_H
4
5#include <uapi/linux/netfilter/nfnetlink_osf.h>
2 6
3/* Initial window size option state machine: multiple of mss, mtu or 7/* Initial window size option state machine: multiple of mss, mtu or
4 * plain numeric value. Can also be made as plain numeric value which 8 * plain numeric value. Can also be made as plain numeric value which
@@ -21,6 +25,8 @@ enum osf_fmatch_states {
21 FMATCH_OPT_WRONG, 25 FMATCH_OPT_WRONG,
22}; 26};
23 27
28extern struct list_head nf_osf_fingers[2];
29
24struct nf_osf_finger { 30struct nf_osf_finger {
25 struct rcu_head rcu_head; 31 struct rcu_head rcu_head;
26 struct list_head finger_entry; 32 struct list_head finger_entry;
@@ -31,3 +37,8 @@ bool nf_osf_match(const struct sk_buff *skb, u_int8_t family,
31 int hooknum, struct net_device *in, struct net_device *out, 37 int hooknum, struct net_device *in, struct net_device *out,
32 const struct nf_osf_info *info, struct net *net, 38 const struct nf_osf_info *info, struct net *net,
33 const struct list_head *nf_osf_fingers); 39 const struct list_head *nf_osf_fingers);
40
41const char *nf_osf_find(const struct sk_buff *skb,
42 const struct list_head *nf_osf_fingers);
43
44#endif /* _NFOSF_H */
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index b671fdfd212b..fa0686500970 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -5,17 +5,6 @@
5#include <uapi/linux/netfilter_bridge.h> 5#include <uapi/linux/netfilter_bridge.h>
6#include <linux/skbuff.h> 6#include <linux/skbuff.h>
7 7
8enum nf_br_hook_priorities {
9 NF_BR_PRI_FIRST = INT_MIN,
10 NF_BR_PRI_NAT_DST_BRIDGED = -300,
11 NF_BR_PRI_FILTER_BRIDGED = -200,
12 NF_BR_PRI_BRNF = 0,
13 NF_BR_PRI_NAT_DST_OTHER = 100,
14 NF_BR_PRI_FILTER_OTHER = 200,
15 NF_BR_PRI_NAT_SRC = 300,
16 NF_BR_PRI_LAST = INT_MAX,
17};
18
19#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 8#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
20 9
21int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); 10int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index a2b0ed025908..7e012312cd61 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -176,8 +176,6 @@ void nf_ct_netns_put(struct net *net, u8 nfproto);
176 */ 176 */
177void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls); 177void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
178 178
179void nf_ct_free_hashtable(void *hash, unsigned int size);
180
181int nf_conntrack_hash_check_insert(struct nf_conn *ct); 179int nf_conntrack_hash_check_insert(struct nf_conn *ct);
182bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report); 180bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report);
183 181
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index a05134507e7b..8da837d2aaf9 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -71,4 +71,11 @@ extern struct nft_set_type nft_set_hash_fast_type;
71extern struct nft_set_type nft_set_rbtree_type; 71extern struct nft_set_type nft_set_rbtree_type;
72extern struct nft_set_type nft_set_bitmap_type; 72extern struct nft_set_type nft_set_bitmap_type;
73 73
74struct nft_expr;
75struct nft_regs;
76struct nft_pktinfo;
77void nft_meta_get_eval(const struct nft_expr *expr,
78 struct nft_regs *regs, const struct nft_pktinfo *pkt);
79void nft_lookup_eval(const struct nft_expr *expr,
80 struct nft_regs *regs, const struct nft_pktinfo *pkt);
74#endif /* _NET_NF_TABLES_CORE_H */ 81#endif /* _NET_NF_TABLES_CORE_H */
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index f466860bcf75..357862d948de 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1253,6 +1253,22 @@ enum nft_nat_attributes {
1253#define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1) 1253#define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1)
1254 1254
1255/** 1255/**
1256 * enum nft_tproxy_attributes - nf_tables tproxy expression netlink attributes
1257 *
1258 * NFTA_TPROXY_FAMILY: Target address family (NLA_U32: nft_registers)
1259 * NFTA_TPROXY_REG_ADDR: Target address register (NLA_U32: nft_registers)
1260 * NFTA_TPROXY_REG_PORT: Target port register (NLA_U32: nft_registers)
1261 */
1262enum nft_tproxy_attributes {
1263 NFTA_TPROXY_UNSPEC,
1264 NFTA_TPROXY_FAMILY,
1265 NFTA_TPROXY_REG_ADDR,
1266 NFTA_TPROXY_REG_PORT,
1267 __NFTA_TPROXY_MAX
1268};
1269#define NFTA_TPROXY_MAX (__NFTA_TPROXY_MAX - 1)
1270
1271/**
1256 * enum nft_masq_attributes - nf_tables masquerade expression attributes 1272 * enum nft_masq_attributes - nf_tables masquerade expression attributes
1257 * 1273 *
1258 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32) 1274 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
@@ -1400,7 +1416,8 @@ enum nft_ct_helper_attributes {
1400#define NFT_OBJECT_CT_HELPER 3 1416#define NFT_OBJECT_CT_HELPER 3
1401#define NFT_OBJECT_LIMIT 4 1417#define NFT_OBJECT_LIMIT 4
1402#define NFT_OBJECT_CONNLIMIT 5 1418#define NFT_OBJECT_CONNLIMIT 5
1403#define __NFT_OBJECT_MAX 6 1419#define NFT_OBJECT_TUNNEL 6
1420#define __NFT_OBJECT_MAX 7
1404#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) 1421#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
1405 1422
1406/** 1423/**
@@ -1463,6 +1480,13 @@ enum nft_flowtable_hook_attributes {
1463}; 1480};
1464#define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1) 1481#define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1)
1465 1482
1483enum nft_osf_attributes {
1484 NFTA_OSF_UNSPEC,
1485 NFTA_OSF_DREG,
1486 __NFTA_OSF_MAX,
1487};
1488#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)
1489
1466/** 1490/**
1467 * enum nft_device_attributes - nf_tables device netlink attributes 1491 * enum nft_device_attributes - nf_tables device netlink attributes
1468 * 1492 *
@@ -1557,4 +1581,85 @@ enum nft_ng_types {
1557}; 1581};
1558#define NFT_NG_MAX (__NFT_NG_MAX - 1) 1582#define NFT_NG_MAX (__NFT_NG_MAX - 1)
1559 1583
1584enum nft_tunnel_key_ip_attributes {
1585 NFTA_TUNNEL_KEY_IP_UNSPEC,
1586 NFTA_TUNNEL_KEY_IP_SRC,
1587 NFTA_TUNNEL_KEY_IP_DST,
1588 __NFTA_TUNNEL_KEY_IP_MAX
1589};
1590#define NFTA_TUNNEL_KEY_IP_MAX (__NFTA_TUNNEL_KEY_IP_MAX - 1)
1591
1592enum nft_tunnel_ip6_attributes {
1593 NFTA_TUNNEL_KEY_IP6_UNSPEC,
1594 NFTA_TUNNEL_KEY_IP6_SRC,
1595 NFTA_TUNNEL_KEY_IP6_DST,
1596 NFTA_TUNNEL_KEY_IP6_FLOWLABEL,
1597 __NFTA_TUNNEL_KEY_IP6_MAX
1598};
1599#define NFTA_TUNNEL_KEY_IP6_MAX (__NFTA_TUNNEL_KEY_IP6_MAX - 1)
1600
1601enum nft_tunnel_opts_attributes {
1602 NFTA_TUNNEL_KEY_OPTS_UNSPEC,
1603 NFTA_TUNNEL_KEY_OPTS_VXLAN,
1604 NFTA_TUNNEL_KEY_OPTS_ERSPAN,
1605 __NFTA_TUNNEL_KEY_OPTS_MAX
1606};
1607#define NFTA_TUNNEL_KEY_OPTS_MAX (__NFTA_TUNNEL_KEY_OPTS_MAX - 1)
1608
1609enum nft_tunnel_opts_vxlan_attributes {
1610 NFTA_TUNNEL_KEY_VXLAN_UNSPEC,
1611 NFTA_TUNNEL_KEY_VXLAN_GBP,
1612 __NFTA_TUNNEL_KEY_VXLAN_MAX
1613};
1614#define NFTA_TUNNEL_KEY_VXLAN_MAX (__NFTA_TUNNEL_KEY_VXLAN_MAX - 1)
1615
1616enum nft_tunnel_opts_erspan_attributes {
1617 NFTA_TUNNEL_KEY_ERSPAN_UNSPEC,
1618 NFTA_TUNNEL_KEY_ERSPAN_VERSION,
1619 NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
1620 NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
1621 NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
1622 __NFTA_TUNNEL_KEY_ERSPAN_MAX
1623};
1624#define NFTA_TUNNEL_KEY_ERSPAN_MAX (__NFTA_TUNNEL_KEY_ERSPAN_MAX - 1)
1625
1626enum nft_tunnel_flags {
1627 NFT_TUNNEL_F_ZERO_CSUM_TX = (1 << 0),
1628 NFT_TUNNEL_F_DONT_FRAGMENT = (1 << 1),
1629 NFT_TUNNEL_F_SEQ_NUMBER = (1 << 2),
1630};
1631#define NFT_TUNNEL_F_MASK (NFT_TUNNEL_F_ZERO_CSUM_TX | \
1632 NFT_TUNNEL_F_DONT_FRAGMENT | \
1633 NFT_TUNNEL_F_SEQ_NUMBER)
1634
1635enum nft_tunnel_key_attributes {
1636 NFTA_TUNNEL_KEY_UNSPEC,
1637 NFTA_TUNNEL_KEY_ID,
1638 NFTA_TUNNEL_KEY_IP,
1639 NFTA_TUNNEL_KEY_IP6,
1640 NFTA_TUNNEL_KEY_FLAGS,
1641 NFTA_TUNNEL_KEY_TOS,
1642 NFTA_TUNNEL_KEY_TTL,
1643 NFTA_TUNNEL_KEY_SPORT,
1644 NFTA_TUNNEL_KEY_DPORT,
1645 NFTA_TUNNEL_KEY_OPTS,
1646 __NFTA_TUNNEL_KEY_MAX
1647};
1648#define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1)
1649
1650enum nft_tunnel_keys {
1651 NFT_TUNNEL_PATH,
1652 NFT_TUNNEL_ID,
1653 __NFT_TUNNEL_MAX
1654};
1655#define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1)
1656
1657enum nft_tunnel_attributes {
1658 NFTA_TUNNEL_UNSPEC,
1659 NFTA_TUNNEL_KEY,
1660 NFTA_TUNNEL_DREG,
1661 __NFTA_TUNNEL_MAX
1662};
1663#define NFTA_TUNNEL_MAX (__NFTA_TUNNEL_MAX - 1)
1664
1560#endif /* _LINUX_NF_TABLES_H */ 1665#endif /* _LINUX_NF_TABLES_H */
diff --git a/include/uapi/linux/netfilter/nf_osf.h b/include/uapi/linux/netfilter/nfnetlink_osf.h
index 3738116b2bbe..3b93fbb9fc24 100644
--- a/include/uapi/linux/netfilter/nf_osf.h
+++ b/include/uapi/linux/netfilter/nfnetlink_osf.h
@@ -94,4 +94,13 @@ enum nf_osf_attr_type {
94 OSF_ATTR_MAX, 94 OSF_ATTR_MAX,
95}; 95};
96 96
97/*
98 * Add/remove fingerprint from the kernel.
99 */
100enum nf_osf_msg_types {
101 OSF_MSG_ADD,
102 OSF_MSG_REMOVE,
103 OSF_MSG_MAX,
104};
105
97#endif /* _NF_OSF_H */ 106#endif /* _NF_OSF_H */
diff --git a/include/uapi/linux/netfilter/xt_osf.h b/include/uapi/linux/netfilter/xt_osf.h
index b189007f4f28..c56c59605c2b 100644
--- a/include/uapi/linux/netfilter/xt_osf.h
+++ b/include/uapi/linux/netfilter/xt_osf.h
@@ -23,7 +23,7 @@
23#include <linux/types.h> 23#include <linux/types.h>
24#include <linux/ip.h> 24#include <linux/ip.h>
25#include <linux/tcp.h> 25#include <linux/tcp.h>
26#include <linux/netfilter/nf_osf.h> 26#include <linux/netfilter/nfnetlink_osf.h>
27 27
28#define XT_OSF_GENRE NF_OSF_GENRE 28#define XT_OSF_GENRE NF_OSF_GENRE
29#define XT_OSF_INVERT NF_OSF_INVERT 29#define XT_OSF_INVERT NF_OSF_INVERT
@@ -47,13 +47,6 @@
47#define xt_osf_nlmsg nf_osf_nlmsg 47#define xt_osf_nlmsg nf_osf_nlmsg
48 48
49#define xt_osf_attr_type nf_osf_attr_type 49#define xt_osf_attr_type nf_osf_attr_type
50/* 50#define xt_osf_msg_types nf_osf_msg_types
51 * Add/remove fingerprint from the kernel.
52 */
53enum xt_osf_msg_types {
54 OSF_MSG_ADD,
55 OSF_MSG_REMOVE,
56 OSF_MSG_MAX,
57};
58 51
59#endif /* _XT_OSF_H */ 52#endif /* _XT_OSF_H */
diff --git a/include/uapi/linux/netfilter_bridge.h b/include/uapi/linux/netfilter_bridge.h
index 12fb77633f83..156ccd089df1 100644
--- a/include/uapi/linux/netfilter_bridge.h
+++ b/include/uapi/linux/netfilter_bridge.h
@@ -26,4 +26,15 @@
26#define NF_BR_BROUTING 5 26#define NF_BR_BROUTING 5
27#define NF_BR_NUMHOOKS 6 27#define NF_BR_NUMHOOKS 6
28 28
29enum nf_br_hook_priorities {
30 NF_BR_PRI_FIRST = INT_MIN,
31 NF_BR_PRI_NAT_DST_BRIDGED = -300,
32 NF_BR_PRI_FILTER_BRIDGED = -200,
33 NF_BR_PRI_BRNF = 0,
34 NF_BR_PRI_NAT_DST_OTHER = 100,
35 NF_BR_PRI_FILTER_OTHER = 200,
36 NF_BR_PRI_NAT_SRC = 300,
37 NF_BR_PRI_LAST = INT_MAX,
38};
39
29#endif /* _UAPI__LINUX_BRIDGE_NETFILTER_H */ 40#endif /* _UAPI__LINUX_BRIDGE_NETFILTER_H */
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 9b16eaf33819..6e0dc6bcd32a 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -26,6 +26,7 @@
26#include <linux/if_pppox.h> 26#include <linux/if_pppox.h>
27#include <linux/ppp_defs.h> 27#include <linux/ppp_defs.h>
28#include <linux/netfilter_bridge.h> 28#include <linux/netfilter_bridge.h>
29#include <uapi/linux/netfilter_bridge.h>
29#include <linux/netfilter_ipv4.h> 30#include <linux/netfilter_ipv4.h>
30#include <linux/netfilter_ipv6.h> 31#include <linux/netfilter_ipv6.h>
31#include <linux/netfilter_arp.h> 32#include <linux/netfilter_arp.h>
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index c41da5fac84f..550324c516ee 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/netfilter_bridge/ebtables.h> 11#include <linux/netfilter_bridge/ebtables.h>
12#include <uapi/linux/netfilter_bridge.h>
12#include <linux/module.h> 13#include <linux/module.h>
13 14
14#define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \ 15#define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 08df7406ecb3..c0fb3ca518af 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/netfilter_bridge/ebtables.h> 11#include <linux/netfilter_bridge/ebtables.h>
12#include <uapi/linux/netfilter_bridge.h>
12#include <linux/module.h> 13#include <linux/module.h>
13 14
14#define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \ 15#define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \
diff --git a/net/core/dst.c b/net/core/dst.c
index 2d9b37f8944a..81ccf20e2826 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -307,6 +307,7 @@ void metadata_dst_free(struct metadata_dst *md_dst)
307#endif 307#endif
308 kfree(md_dst); 308 kfree(md_dst);
309} 309}
310EXPORT_SYMBOL_GPL(metadata_dst_free);
310 311
311struct metadata_dst __percpu * 312struct metadata_dst __percpu *
312metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags) 313metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags)
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 6f6c959aeb8f..71709c104081 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -46,6 +46,14 @@ config NETFILTER_NETLINK_LOG
46 and is also scheduled to replace the old syslog-based ipt_LOG 46 and is also scheduled to replace the old syslog-based ipt_LOG
47 and ip6t_LOG modules. 47 and ip6t_LOG modules.
48 48
49config NETFILTER_NETLINK_OSF
50 tristate "Netfilter OSF over NFNETLINK interface"
51 depends on NETFILTER_ADVANCED
52 select NETFILTER_NETLINK
53 help
54 If this option is enabled, the kernel will include support
55 for passive OS fingerprint via NFNETLINK.
56
49config NF_CONNTRACK 57config NF_CONNTRACK
50 tristate "Netfilter connection tracking support" 58 tristate "Netfilter connection tracking support"
51 default m if NETFILTER_ADVANCED=n 59 default m if NETFILTER_ADVANCED=n
@@ -98,7 +106,6 @@ config NF_CONNTRACK_SECMARK
98config NF_CONNTRACK_ZONES 106config NF_CONNTRACK_ZONES
99 bool 'Connection tracking zones' 107 bool 'Connection tracking zones'
100 depends on NETFILTER_ADVANCED 108 depends on NETFILTER_ADVANCED
101 depends on NETFILTER_XT_TARGET_CT
102 help 109 help
103 This option enables support for connection tracking zones. 110 This option enables support for connection tracking zones.
104 Normally, each connection needs to have a unique system wide 111 Normally, each connection needs to have a unique system wide
@@ -150,10 +157,11 @@ config NF_CONNTRACK_TIMESTAMP
150 If unsure, say `N'. 157 If unsure, say `N'.
151 158
152config NF_CONNTRACK_LABELS 159config NF_CONNTRACK_LABELS
153 bool 160 bool "Connection tracking labels"
154 help 161 help
155 This option enables support for assigning user-defined flag bits 162 This option enables support for assigning user-defined flag bits
156 to connection tracking entries. It selected by the connlabel match. 163 to connection tracking entries. It can be used with xtables connlabel
164 match and the nftables ct expression.
157 165
158config NF_CT_PROTO_DCCP 166config NF_CT_PROTO_DCCP
159 bool 'DCCP protocol connection tracking support' 167 bool 'DCCP protocol connection tracking support'
@@ -357,6 +365,7 @@ config NF_CT_NETLINK_TIMEOUT
357 tristate 'Connection tracking timeout tuning via Netlink' 365 tristate 'Connection tracking timeout tuning via Netlink'
358 select NETFILTER_NETLINK 366 select NETFILTER_NETLINK
359 depends on NETFILTER_ADVANCED 367 depends on NETFILTER_ADVANCED
368 depends on NF_CONNTRACK_TIMEOUT
360 help 369 help
361 This option enables support for connection tracking timeout 370 This option enables support for connection tracking timeout
362 fine-grain tuning. This allows you to attach specific timeout 371 fine-grain tuning. This allows you to attach specific timeout
@@ -442,9 +451,6 @@ config NETFILTER_SYNPROXY
442 451
443endif # NF_CONNTRACK 452endif # NF_CONNTRACK
444 453
445config NF_OSF
446 tristate
447
448config NF_TABLES 454config NF_TABLES
449 select NETFILTER_NETLINK 455 select NETFILTER_NETLINK
450 tristate "Netfilter nf_tables support" 456 tristate "Netfilter nf_tables support"
@@ -553,6 +559,12 @@ config NFT_NAT
553 This option adds the "nat" expression that you can use to perform 559 This option adds the "nat" expression that you can use to perform
554 typical Network Address Translation (NAT) packet transformations. 560 typical Network Address Translation (NAT) packet transformations.
555 561
562config NFT_TUNNEL
563 tristate "Netfilter nf_tables tunnel module"
564 help
565 This option adds the "tunnel" expression that you can use to set
566 tunneling policies.
567
556config NFT_OBJREF 568config NFT_OBJREF
557 tristate "Netfilter nf_tables stateful object reference module" 569 tristate "Netfilter nf_tables stateful object reference module"
558 help 570 help
@@ -622,6 +634,23 @@ config NFT_SOCKET
622 This option allows matching for the presence or absence of a 634 This option allows matching for the presence or absence of a
623 corresponding socket and its attributes. 635 corresponding socket and its attributes.
624 636
637config NFT_OSF
638 tristate "Netfilter nf_tables passive OS fingerprint support"
639 depends on NETFILTER_ADVANCED
640 select NETFILTER_NETLINK_OSF
641 help
642 This option allows matching packets from an specific OS.
643
644config NFT_TPROXY
645 tristate "Netfilter nf_tables tproxy support"
646 depends on IPV6 || IPV6=n
647 select NF_DEFRAG_IPV4
648 select NF_DEFRAG_IPV6 if NF_TABLES_IPV6
649 select NF_TPROXY_IPV4
650 select NF_TPROXY_IPV6 if NF_TABLES_IPV6
651 help
652 This makes transparent proxy support available in nftables.
653
625if NF_TABLES_NETDEV 654if NF_TABLES_NETDEV
626 655
627config NF_DUP_NETDEV 656config NF_DUP_NETDEV
@@ -1368,8 +1397,8 @@ config NETFILTER_XT_MATCH_NFACCT
1368 1397
1369config NETFILTER_XT_MATCH_OSF 1398config NETFILTER_XT_MATCH_OSF
1370 tristate '"osf" Passive OS fingerprint match' 1399 tristate '"osf" Passive OS fingerprint match'
1371 depends on NETFILTER_ADVANCED && NETFILTER_NETLINK 1400 depends on NETFILTER_ADVANCED
1372 select NF_OSF 1401 select NETFILTER_NETLINK_OSF
1373 help 1402 help
1374 This option selects the Passive OS Fingerprinting match module 1403 This option selects the Passive OS Fingerprinting match module
1375 that allows to passively match the remote operating system by 1404 that allows to passively match the remote operating system by
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index dd26e4961f43..16895e045b66 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
20obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o 20obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
21obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o 21obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
22obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o 22obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
23obj-$(CONFIG_NETFILTER_NETLINK_OSF) += nfnetlink_osf.o
23 24
24# connection tracking 25# connection tracking
25obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o 26obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
@@ -100,6 +101,7 @@ obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
100obj-$(CONFIG_NFT_QUOTA) += nft_quota.o 101obj-$(CONFIG_NFT_QUOTA) += nft_quota.o
101obj-$(CONFIG_NFT_REJECT) += nft_reject.o 102obj-$(CONFIG_NFT_REJECT) += nft_reject.o
102obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o 103obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o
104obj-$(CONFIG_NFT_TUNNEL) += nft_tunnel.o
103obj-$(CONFIG_NFT_COUNTER) += nft_counter.o 105obj-$(CONFIG_NFT_COUNTER) += nft_counter.o
104obj-$(CONFIG_NFT_LOG) += nft_log.o 106obj-$(CONFIG_NFT_LOG) += nft_log.o
105obj-$(CONFIG_NFT_MASQ) += nft_masq.o 107obj-$(CONFIG_NFT_MASQ) += nft_masq.o
@@ -108,8 +110,9 @@ obj-$(CONFIG_NFT_HASH) += nft_hash.o
108obj-$(CONFIG_NFT_FIB) += nft_fib.o 110obj-$(CONFIG_NFT_FIB) += nft_fib.o
109obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o 111obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o
110obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o 112obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o
111obj-$(CONFIG_NF_OSF) += nf_osf.o
112obj-$(CONFIG_NFT_SOCKET) += nft_socket.o 113obj-$(CONFIG_NFT_SOCKET) += nft_socket.o
114obj-$(CONFIG_NFT_OSF) += nft_osf.o
115obj-$(CONFIG_NFT_TPROXY) += nft_tproxy.o
113 116
114# nf_tables netdev 117# nf_tables netdev
115obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o 118obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8a113ca1eea2..a676d5f76bdc 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -2022,16 +2022,6 @@ static int kill_all(struct nf_conn *i, void *data)
2022 return net_eq(nf_ct_net(i), data); 2022 return net_eq(nf_ct_net(i), data);
2023} 2023}
2024 2024
2025void nf_ct_free_hashtable(void *hash, unsigned int size)
2026{
2027 if (is_vmalloc_addr(hash))
2028 vfree(hash);
2029 else
2030 free_pages((unsigned long)hash,
2031 get_order(sizeof(struct hlist_head) * size));
2032}
2033EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
2034
2035void nf_conntrack_cleanup_start(void) 2025void nf_conntrack_cleanup_start(void)
2036{ 2026{
2037 conntrack_gc_work.exiting = true; 2027 conntrack_gc_work.exiting = true;
@@ -2042,7 +2032,7 @@ void nf_conntrack_cleanup_end(void)
2042{ 2032{
2043 RCU_INIT_POINTER(nf_ct_hook, NULL); 2033 RCU_INIT_POINTER(nf_ct_hook, NULL);
2044 cancel_delayed_work_sync(&conntrack_gc_work.dwork); 2034 cancel_delayed_work_sync(&conntrack_gc_work.dwork);
2045 nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size); 2035 kvfree(nf_conntrack_hash);
2046 2036
2047 nf_conntrack_proto_fini(); 2037 nf_conntrack_proto_fini();
2048 nf_conntrack_seqadj_fini(); 2038 nf_conntrack_seqadj_fini();
@@ -2108,7 +2098,6 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
2108{ 2098{
2109 struct hlist_nulls_head *hash; 2099 struct hlist_nulls_head *hash;
2110 unsigned int nr_slots, i; 2100 unsigned int nr_slots, i;
2111 size_t sz;
2112 2101
2113 if (*sizep > (UINT_MAX / sizeof(struct hlist_nulls_head))) 2102 if (*sizep > (UINT_MAX / sizeof(struct hlist_nulls_head)))
2114 return NULL; 2103 return NULL;
@@ -2116,14 +2105,8 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
2116 BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head)); 2105 BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head));
2117 nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head)); 2106 nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head));
2118 2107
2119 if (nr_slots > (UINT_MAX / sizeof(struct hlist_nulls_head))) 2108 hash = kvmalloc_array(nr_slots, sizeof(struct hlist_nulls_head),
2120 return NULL; 2109 GFP_KERNEL | __GFP_ZERO);
2121
2122 sz = nr_slots * sizeof(struct hlist_nulls_head);
2123 hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
2124 get_order(sz));
2125 if (!hash)
2126 hash = vzalloc(sz);
2127 2110
2128 if (hash && nulls) 2111 if (hash && nulls)
2129 for (i = 0; i < nr_slots; i++) 2112 for (i = 0; i < nr_slots; i++)
@@ -2150,7 +2133,7 @@ int nf_conntrack_hash_resize(unsigned int hashsize)
2150 2133
2151 old_size = nf_conntrack_htable_size; 2134 old_size = nf_conntrack_htable_size;
2152 if (old_size == hashsize) { 2135 if (old_size == hashsize) {
2153 nf_ct_free_hashtable(hash, hashsize); 2136 kvfree(hash);
2154 return 0; 2137 return 0;
2155 } 2138 }
2156 2139
@@ -2186,7 +2169,7 @@ int nf_conntrack_hash_resize(unsigned int hashsize)
2186 local_bh_enable(); 2169 local_bh_enable();
2187 2170
2188 synchronize_net(); 2171 synchronize_net();
2189 nf_ct_free_hashtable(old_hash, old_size); 2172 kvfree(old_hash);
2190 return 0; 2173 return 0;
2191} 2174}
2192 2175
@@ -2350,7 +2333,7 @@ err_acct:
2350err_expect: 2333err_expect:
2351 kmem_cache_destroy(nf_conntrack_cachep); 2334 kmem_cache_destroy(nf_conntrack_cachep);
2352err_cachep: 2335err_cachep:
2353 nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size); 2336 kvfree(nf_conntrack_hash);
2354 return ret; 2337 return ret;
2355} 2338}
2356 2339
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 3f586ba23d92..27b84231db10 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -712,5 +712,5 @@ void nf_conntrack_expect_fini(void)
712{ 712{
713 rcu_barrier(); /* Wait for call_rcu() before destroy */ 713 rcu_barrier(); /* Wait for call_rcu() before destroy */
714 kmem_cache_destroy(nf_ct_expect_cachep); 714 kmem_cache_destroy(nf_ct_expect_cachep);
715 nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_hsize); 715 kvfree(nf_ct_expect_hash);
716} 716}
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index d557a425289d..e24b762ffa1d 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -562,12 +562,12 @@ int nf_conntrack_helper_init(void)
562 562
563 return 0; 563 return 0;
564out_extend: 564out_extend:
565 nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); 565 kvfree(nf_ct_helper_hash);
566 return ret; 566 return ret;
567} 567}
568 568
569void nf_conntrack_helper_fini(void) 569void nf_conntrack_helper_fini(void)
570{ 570{
571 nf_ct_extend_unregister(&helper_extend); 571 nf_ct_extend_unregister(&helper_extend);
572 nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); 572 kvfree(nf_ct_helper_hash);
573} 573}
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 803607a90102..30070732ee50 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -940,14 +940,13 @@ void nf_conntrack_proto_fini(void)
940{ 940{
941 unsigned int i; 941 unsigned int i;
942 942
943 nf_ct_l4proto_unregister(builtin_l4proto,
944 ARRAY_SIZE(builtin_l4proto));
945 nf_unregister_sockopt(&so_getorigdst); 943 nf_unregister_sockopt(&so_getorigdst);
946#if IS_ENABLED(CONFIG_IPV6) 944#if IS_ENABLED(CONFIG_IPV6)
947 nf_unregister_sockopt(&so_getorigdst6); 945 nf_unregister_sockopt(&so_getorigdst6);
948#endif 946#endif
949 947 /* No need to call nf_ct_l4proto_unregister(), the register
950 /* free l3proto protocol tables */ 948 * tables are free'd here anyway.
949 */
951 for (i = 0; i < ARRAY_SIZE(nf_ct_protos); i++) 950 for (i = 0; i < ARRAY_SIZE(nf_ct_protos); i++)
952 kfree(nf_ct_protos[i]); 951 kfree(nf_ct_protos[i]);
953} 952}
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 6366f0c0b8c1..e2b196054dfc 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -1056,7 +1056,7 @@ static int __init nf_nat_init(void)
1056 1056
1057 ret = nf_ct_extend_register(&nat_extend); 1057 ret = nf_ct_extend_register(&nat_extend);
1058 if (ret < 0) { 1058 if (ret < 0) {
1059 nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size); 1059 kvfree(nf_nat_bysource);
1060 pr_err("Unable to register extension\n"); 1060 pr_err("Unable to register extension\n");
1061 return ret; 1061 return ret;
1062 } 1062 }
@@ -1094,7 +1094,7 @@ static void __exit nf_nat_cleanup(void)
1094 for (i = 0; i < NFPROTO_NUMPROTO; i++) 1094 for (i = 0; i < NFPROTO_NUMPROTO; i++)
1095 kfree(nf_nat_l4protos[i]); 1095 kfree(nf_nat_l4protos[i]);
1096 synchronize_net(); 1096 synchronize_net();
1097 nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size); 1097 kvfree(nf_nat_bysource);
1098 unregister_pernet_subsys(&nat_net_ops); 1098 unregister_pernet_subsys(&nat_net_ops);
1099} 1099}
1100 1100
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f18085639807..67cdd5c4f4f5 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1442,7 +1442,7 @@ struct nft_chain_hook {
1442static int nft_chain_parse_hook(struct net *net, 1442static int nft_chain_parse_hook(struct net *net,
1443 const struct nlattr * const nla[], 1443 const struct nlattr * const nla[],
1444 struct nft_chain_hook *hook, u8 family, 1444 struct nft_chain_hook *hook, u8 family,
1445 bool create) 1445 bool autoload)
1446{ 1446{
1447 struct nlattr *ha[NFTA_HOOK_MAX + 1]; 1447 struct nlattr *ha[NFTA_HOOK_MAX + 1];
1448 const struct nft_chain_type *type; 1448 const struct nft_chain_type *type;
@@ -1467,7 +1467,7 @@ static int nft_chain_parse_hook(struct net *net,
1467 type = chain_type[family][NFT_CHAIN_T_DEFAULT]; 1467 type = chain_type[family][NFT_CHAIN_T_DEFAULT];
1468 if (nla[NFTA_CHAIN_TYPE]) { 1468 if (nla[NFTA_CHAIN_TYPE]) {
1469 type = nf_tables_chain_type_lookup(net, nla[NFTA_CHAIN_TYPE], 1469 type = nf_tables_chain_type_lookup(net, nla[NFTA_CHAIN_TYPE],
1470 family, create); 1470 family, autoload);
1471 if (IS_ERR(type)) 1471 if (IS_ERR(type))
1472 return PTR_ERR(type); 1472 return PTR_ERR(type);
1473 } 1473 }
@@ -1534,7 +1534,7 @@ static struct nft_rule **nf_tables_chain_alloc_rules(const struct nft_chain *cha
1534} 1534}
1535 1535
1536static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, 1536static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
1537 u8 policy, bool create) 1537 u8 policy)
1538{ 1538{
1539 const struct nlattr * const *nla = ctx->nla; 1539 const struct nlattr * const *nla = ctx->nla;
1540 struct nft_table *table = ctx->table; 1540 struct nft_table *table = ctx->table;
@@ -1552,7 +1552,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
1552 struct nft_chain_hook hook; 1552 struct nft_chain_hook hook;
1553 struct nf_hook_ops *ops; 1553 struct nf_hook_ops *ops;
1554 1554
1555 err = nft_chain_parse_hook(net, nla, &hook, family, create); 1555 err = nft_chain_parse_hook(net, nla, &hook, family, true);
1556 if (err < 0) 1556 if (err < 0)
1557 return err; 1557 return err;
1558 1558
@@ -1643,8 +1643,7 @@ err1:
1643 return err; 1643 return err;
1644} 1644}
1645 1645
1646static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, 1646static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy)
1647 bool create)
1648{ 1647{
1649 const struct nlattr * const *nla = ctx->nla; 1648 const struct nlattr * const *nla = ctx->nla;
1650 struct nft_table *table = ctx->table; 1649 struct nft_table *table = ctx->table;
@@ -1661,7 +1660,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
1661 return -EBUSY; 1660 return -EBUSY;
1662 1661
1663 err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family, 1662 err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
1664 create); 1663 false);
1665 if (err < 0) 1664 if (err < 0)
1666 return err; 1665 return err;
1667 1666
@@ -1761,9 +1760,6 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1761 u8 policy = NF_ACCEPT; 1760 u8 policy = NF_ACCEPT;
1762 struct nft_ctx ctx; 1761 struct nft_ctx ctx;
1763 u64 handle = 0; 1762 u64 handle = 0;
1764 bool create;
1765
1766 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
1767 1763
1768 lockdep_assert_held(&net->nft.commit_mutex); 1764 lockdep_assert_held(&net->nft.commit_mutex);
1769 1765
@@ -1828,10 +1824,10 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1828 if (nlh->nlmsg_flags & NLM_F_REPLACE) 1824 if (nlh->nlmsg_flags & NLM_F_REPLACE)
1829 return -EOPNOTSUPP; 1825 return -EOPNOTSUPP;
1830 1826
1831 return nf_tables_updchain(&ctx, genmask, policy, create); 1827 return nf_tables_updchain(&ctx, genmask, policy);
1832 } 1828 }
1833 1829
1834 return nf_tables_addchain(&ctx, family, genmask, policy, create); 1830 return nf_tables_addchain(&ctx, family, genmask, policy);
1835} 1831}
1836 1832
1837static int nf_tables_delchain(struct net *net, struct sock *nlsk, 1833static int nf_tables_delchain(struct net *net, struct sock *nlsk,
@@ -2529,13 +2525,10 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2529 struct nlattr *tmp; 2525 struct nlattr *tmp;
2530 unsigned int size, i, n, ulen = 0, usize = 0; 2526 unsigned int size, i, n, ulen = 0, usize = 0;
2531 int err, rem; 2527 int err, rem;
2532 bool create;
2533 u64 handle, pos_handle; 2528 u64 handle, pos_handle;
2534 2529
2535 lockdep_assert_held(&net->nft.commit_mutex); 2530 lockdep_assert_held(&net->nft.commit_mutex);
2536 2531
2537 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
2538
2539 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask); 2532 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask);
2540 if (IS_ERR(table)) { 2533 if (IS_ERR(table)) {
2541 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]); 2534 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
@@ -2565,7 +2558,8 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2565 else 2558 else
2566 return -EOPNOTSUPP; 2559 return -EOPNOTSUPP;
2567 } else { 2560 } else {
2568 if (!create || nlh->nlmsg_flags & NLM_F_REPLACE) 2561 if (!(nlh->nlmsg_flags & NLM_F_CREATE) ||
2562 nlh->nlmsg_flags & NLM_F_REPLACE)
2569 return -EINVAL; 2563 return -EINVAL;
2570 handle = nf_tables_alloc_handle(table); 2564 handle = nf_tables_alloc_handle(table);
2571 2565
@@ -3361,7 +3355,6 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
3361 struct nft_ctx ctx; 3355 struct nft_ctx ctx;
3362 char *name; 3356 char *name;
3363 unsigned int size; 3357 unsigned int size;
3364 bool create;
3365 u64 timeout; 3358 u64 timeout;
3366 u32 ktype, dtype, flags, policy, gc_int, objtype; 3359 u32 ktype, dtype, flags, policy, gc_int, objtype;
3367 struct nft_set_desc desc; 3360 struct nft_set_desc desc;
@@ -3462,8 +3455,6 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
3462 return err; 3455 return err;
3463 } 3456 }
3464 3457
3465 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
3466
3467 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family, genmask); 3458 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family, genmask);
3468 if (IS_ERR(table)) { 3459 if (IS_ERR(table)) {
3469 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]); 3460 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
@@ -4029,7 +4020,6 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4029 const struct nlattr *attr) 4020 const struct nlattr *attr)
4030{ 4021{
4031 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; 4022 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
4032 const struct nft_set_ext *ext;
4033 struct nft_data_desc desc; 4023 struct nft_data_desc desc;
4034 struct nft_set_elem elem; 4024 struct nft_set_elem elem;
4035 struct sk_buff *skb; 4025 struct sk_buff *skb;
@@ -4063,7 +4053,6 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4063 return PTR_ERR(priv); 4053 return PTR_ERR(priv);
4064 4054
4065 elem.priv = priv; 4055 elem.priv = priv;
4066 ext = nft_set_elem_ext(set, &elem);
4067 4056
4068 err = -ENOMEM; 4057 err = -ENOMEM;
4069 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); 4058 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
@@ -5940,13 +5929,13 @@ static int nf_tables_flowtable_event(struct notifier_block *this,
5940 if (!net) 5929 if (!net)
5941 return 0; 5930 return 0;
5942 5931
5943 nfnl_lock(NFNL_SUBSYS_NFTABLES); 5932 mutex_lock(&net->nft.commit_mutex);
5944 list_for_each_entry(table, &net->nft.tables, list) { 5933 list_for_each_entry(table, &net->nft.tables, list) {
5945 list_for_each_entry(flowtable, &table->flowtables, list) { 5934 list_for_each_entry(flowtable, &table->flowtables, list) {
5946 nft_flowtable_event(event, dev, flowtable); 5935 nft_flowtable_event(event, dev, flowtable);
5947 } 5936 }
5948 } 5937 }
5949 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 5938 mutex_unlock(&net->nft.commit_mutex);
5950 put_net(net); 5939 put_net(net);
5951 return NOTIFY_DONE; 5940 return NOTIFY_DONE;
5952} 5941}
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 8de912ca53d3..ffd5c0f9412b 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -120,6 +120,20 @@ struct nft_jumpstack {
120 struct nft_rule *const *rules; 120 struct nft_rule *const *rules;
121}; 121};
122 122
123static void expr_call_ops_eval(const struct nft_expr *expr,
124 struct nft_regs *regs,
125 struct nft_pktinfo *pkt)
126{
127 unsigned long e = (unsigned long)expr->ops->eval;
128
129 if (e == (unsigned long)nft_meta_get_eval)
130 nft_meta_get_eval(expr, regs, pkt);
131 else if (e == (unsigned long)nft_lookup_eval)
132 nft_lookup_eval(expr, regs, pkt);
133 else
134 expr->ops->eval(expr, regs, pkt);
135}
136
123unsigned int 137unsigned int
124nft_do_chain(struct nft_pktinfo *pkt, void *priv) 138nft_do_chain(struct nft_pktinfo *pkt, void *priv)
125{ 139{
@@ -153,7 +167,7 @@ next_rule:
153 nft_cmp_fast_eval(expr, &regs); 167 nft_cmp_fast_eval(expr, &regs);
154 else if (expr->ops != &nft_payload_fast_ops || 168 else if (expr->ops != &nft_payload_fast_ops ||
155 !nft_payload_fast_eval(expr, &regs, pkt)) 169 !nft_payload_fast_eval(expr, &regs, pkt))
156 expr->ops->eval(expr, &regs, pkt); 170 expr_call_ops_eval(expr, &regs, pkt);
157 171
158 if (regs.verdict.code != NFT_CONTINUE) 172 if (regs.verdict.code != NFT_CONTINUE)
159 break; 173 break;
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index d9d952fad3e0..4199e5300575 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -503,7 +503,6 @@ err:
503 return err; 503 return err;
504} 504}
505 505
506#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
507static struct ctnl_timeout * 506static struct ctnl_timeout *
508ctnl_timeout_find_get(struct net *net, const char *name) 507ctnl_timeout_find_get(struct net *net, const char *name)
509{ 508{
@@ -534,7 +533,6 @@ static void ctnl_timeout_put(struct ctnl_timeout *timeout)
534 533
535 module_put(THIS_MODULE); 534 module_put(THIS_MODULE);
536} 535}
537#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
538 536
539static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = { 537static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
540 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout, 538 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout,
@@ -605,10 +603,8 @@ static int __init cttimeout_init(void)
605 "nfnetlink.\n"); 603 "nfnetlink.\n");
606 goto err_out; 604 goto err_out;
607 } 605 }
608#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
609 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get); 606 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get);
610 RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put); 607 RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put);
611#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
612 return 0; 608 return 0;
613 609
614err_out: 610err_out:
@@ -621,11 +617,9 @@ static void __exit cttimeout_exit(void)
621 nfnetlink_subsys_unregister(&cttimeout_subsys); 617 nfnetlink_subsys_unregister(&cttimeout_subsys);
622 618
623 unregister_pernet_subsys(&cttimeout_ops); 619 unregister_pernet_subsys(&cttimeout_ops);
624#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
625 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); 620 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL);
626 RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); 621 RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL);
627 synchronize_rcu(); 622 synchronize_rcu();
628#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
629} 623}
630 624
631module_init(cttimeout_init); 625module_init(cttimeout_init);
diff --git a/net/netfilter/nf_osf.c b/net/netfilter/nfnetlink_osf.c
index b44d62d5d9a9..f9dba62c450f 100644
--- a/net/netfilter/nf_osf.c
+++ b/net/netfilter/nfnetlink_osf.c
@@ -18,7 +18,14 @@
18#include <linux/netfilter/nfnetlink.h> 18#include <linux/netfilter/nfnetlink.h>
19#include <linux/netfilter/x_tables.h> 19#include <linux/netfilter/x_tables.h>
20#include <net/netfilter/nf_log.h> 20#include <net/netfilter/nf_log.h>
21#include <linux/netfilter/nf_osf.h> 21#include <linux/netfilter/nfnetlink_osf.h>
22
23/*
24 * Indexed by dont-fragment bit.
25 * It is the only constant value in the fingerprint.
26 */
27struct list_head nf_osf_fingers[2];
28EXPORT_SYMBOL_GPL(nf_osf_fingers);
22 29
23static inline int nf_osf_ttl(const struct sk_buff *skb, 30static inline int nf_osf_ttl(const struct sk_buff *skb,
24 int ttl_check, unsigned char f_ttl) 31 int ttl_check, unsigned char f_ttl)
@@ -249,4 +256,181 @@ nf_osf_match(const struct sk_buff *skb, u_int8_t family,
249} 256}
250EXPORT_SYMBOL_GPL(nf_osf_match); 257EXPORT_SYMBOL_GPL(nf_osf_match);
251 258
259const char *nf_osf_find(const struct sk_buff *skb,
260 const struct list_head *nf_osf_fingers)
261{
262 const struct iphdr *ip = ip_hdr(skb);
263 const struct nf_osf_user_finger *f;
264 unsigned char opts[MAX_IPOPTLEN];
265 const struct nf_osf_finger *kf;
266 struct nf_osf_hdr_ctx ctx;
267 const struct tcphdr *tcp;
268 const char *genre = NULL;
269
270 memset(&ctx, 0, sizeof(ctx));
271
272 tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts);
273 if (!tcp)
274 return false;
275
276 list_for_each_entry_rcu(kf, &nf_osf_fingers[ctx.df], finger_entry) {
277 f = &kf->finger;
278 if (!nf_osf_match_one(skb, f, -1, &ctx))
279 continue;
280
281 genre = f->genre;
282 break;
283 }
284
285 return genre;
286}
287EXPORT_SYMBOL_GPL(nf_osf_find);
288
289static const struct nla_policy nfnl_osf_policy[OSF_ATTR_MAX + 1] = {
290 [OSF_ATTR_FINGER] = { .len = sizeof(struct nf_osf_user_finger) },
291};
292
293static int nfnl_osf_add_callback(struct net *net, struct sock *ctnl,
294 struct sk_buff *skb, const struct nlmsghdr *nlh,
295 const struct nlattr * const osf_attrs[],
296 struct netlink_ext_ack *extack)
297{
298 struct nf_osf_user_finger *f;
299 struct nf_osf_finger *kf = NULL, *sf;
300 int err = 0;
301
302 if (!capable(CAP_NET_ADMIN))
303 return -EPERM;
304
305 if (!osf_attrs[OSF_ATTR_FINGER])
306 return -EINVAL;
307
308 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
309 return -EINVAL;
310
311 f = nla_data(osf_attrs[OSF_ATTR_FINGER]);
312
313 kf = kmalloc(sizeof(struct nf_osf_finger), GFP_KERNEL);
314 if (!kf)
315 return -ENOMEM;
316
317 memcpy(&kf->finger, f, sizeof(struct nf_osf_user_finger));
318
319 list_for_each_entry(sf, &nf_osf_fingers[!!f->df], finger_entry) {
320 if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger)))
321 continue;
322
323 kfree(kf);
324 kf = NULL;
325
326 if (nlh->nlmsg_flags & NLM_F_EXCL)
327 err = -EEXIST;
328 break;
329 }
330
331 /*
332 * We are protected by nfnl mutex.
333 */
334 if (kf)
335 list_add_tail_rcu(&kf->finger_entry, &nf_osf_fingers[!!f->df]);
336
337 return err;
338}
339
340static int nfnl_osf_remove_callback(struct net *net, struct sock *ctnl,
341 struct sk_buff *skb,
342 const struct nlmsghdr *nlh,
343 const struct nlattr * const osf_attrs[],
344 struct netlink_ext_ack *extack)
345{
346 struct nf_osf_user_finger *f;
347 struct nf_osf_finger *sf;
348 int err = -ENOENT;
349
350 if (!capable(CAP_NET_ADMIN))
351 return -EPERM;
352
353 if (!osf_attrs[OSF_ATTR_FINGER])
354 return -EINVAL;
355
356 f = nla_data(osf_attrs[OSF_ATTR_FINGER]);
357
358 list_for_each_entry(sf, &nf_osf_fingers[!!f->df], finger_entry) {
359 if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger)))
360 continue;
361
362 /*
363 * We are protected by nfnl mutex.
364 */
365 list_del_rcu(&sf->finger_entry);
366 kfree_rcu(sf, rcu_head);
367
368 err = 0;
369 break;
370 }
371
372 return err;
373}
374
375static const struct nfnl_callback nfnl_osf_callbacks[OSF_MSG_MAX] = {
376 [OSF_MSG_ADD] = {
377 .call = nfnl_osf_add_callback,
378 .attr_count = OSF_ATTR_MAX,
379 .policy = nfnl_osf_policy,
380 },
381 [OSF_MSG_REMOVE] = {
382 .call = nfnl_osf_remove_callback,
383 .attr_count = OSF_ATTR_MAX,
384 .policy = nfnl_osf_policy,
385 },
386};
387
388static const struct nfnetlink_subsystem nfnl_osf_subsys = {
389 .name = "osf",
390 .subsys_id = NFNL_SUBSYS_OSF,
391 .cb_count = OSF_MSG_MAX,
392 .cb = nfnl_osf_callbacks,
393};
394
395static int __init nfnl_osf_init(void)
396{
397 int err = -EINVAL;
398 int i;
399
400 for (i = 0; i < ARRAY_SIZE(nf_osf_fingers); ++i)
401 INIT_LIST_HEAD(&nf_osf_fingers[i]);
402
403 err = nfnetlink_subsys_register(&nfnl_osf_subsys);
404 if (err < 0) {
405 pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err);
406 goto err_out_exit;
407 }
408 return 0;
409
410err_out_exit:
411 return err;
412}
413
414static void __exit nfnl_osf_fini(void)
415{
416 struct nf_osf_finger *f;
417 int i;
418
419 nfnetlink_subsys_unregister(&nfnl_osf_subsys);
420
421 rcu_read_lock();
422 for (i = 0; i < ARRAY_SIZE(nf_osf_fingers); ++i) {
423 list_for_each_entry_rcu(f, &nf_osf_fingers[i], finger_entry) {
424 list_del_rcu(&f->finger_entry);
425 kfree_rcu(f, rcu_head);
426 }
427 }
428 rcu_read_unlock();
429
430 rcu_barrier();
431}
432
433module_init(nfnl_osf_init);
434module_exit(nfnl_osf_fini);
435
252MODULE_LICENSE("GPL"); 436MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
index c2a1d84cdfc4..ad13e8643599 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -26,9 +26,9 @@ struct nft_lookup {
26 struct nft_set_binding binding; 26 struct nft_set_binding binding;
27}; 27};
28 28
29static void nft_lookup_eval(const struct nft_expr *expr, 29void nft_lookup_eval(const struct nft_expr *expr,
30 struct nft_regs *regs, 30 struct nft_regs *regs,
31 const struct nft_pktinfo *pkt) 31 const struct nft_pktinfo *pkt)
32{ 32{
33 const struct nft_lookup *priv = nft_expr_priv(expr); 33 const struct nft_lookup *priv = nft_expr_priv(expr);
34 const struct nft_set *set = priv->set; 34 const struct nft_set *set = priv->set;
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 2b94dcc43456..297fe7d97c18 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -41,9 +41,9 @@ static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
41#include "../bridge/br_private.h" 41#include "../bridge/br_private.h"
42#endif 42#endif
43 43
44static void nft_meta_get_eval(const struct nft_expr *expr, 44void nft_meta_get_eval(const struct nft_expr *expr,
45 struct nft_regs *regs, 45 struct nft_regs *regs,
46 const struct nft_pktinfo *pkt) 46 const struct nft_pktinfo *pkt)
47{ 47{
48 const struct nft_meta *priv = nft_expr_priv(expr); 48 const struct nft_meta *priv = nft_expr_priv(expr);
49 const struct sk_buff *skb = pkt->skb; 49 const struct sk_buff *skb = pkt->skb;
diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c
index 1f4d0854cf70..649d1700ec5b 100644
--- a/net/netfilter/nft_numgen.c
+++ b/net/netfilter/nft_numgen.c
@@ -237,10 +237,8 @@ static int nft_ng_random_map_init(const struct nft_ctx *ctx,
237 priv->map = nft_set_lookup_global(ctx->net, ctx->table, 237 priv->map = nft_set_lookup_global(ctx->net, ctx->table,
238 tb[NFTA_NG_SET_NAME], 238 tb[NFTA_NG_SET_NAME],
239 tb[NFTA_NG_SET_ID], genmask); 239 tb[NFTA_NG_SET_ID], genmask);
240 if (IS_ERR(priv->map))
241 return PTR_ERR(priv->map);
242 240
243 return 0; 241 return PTR_ERR_OR_ZERO(priv->map);
244} 242}
245 243
246static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr) 244static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr)
diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c
new file mode 100644
index 000000000000..9b2f3de7be4f
--- /dev/null
+++ b/net/netfilter/nft_osf.c
@@ -0,0 +1,106 @@
1#include <net/ip.h>
2#include <net/tcp.h>
3
4#include <net/netfilter/nf_tables.h>
5#include <linux/netfilter/nfnetlink_osf.h>
6
7#define OSF_GENRE_SIZE 32
8
9struct nft_osf {
10 enum nft_registers dreg:8;
11};
12
13static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = {
14 [NFTA_OSF_DREG] = { .type = NLA_U32 },
15};
16
17static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
18 const struct nft_pktinfo *pkt)
19{
20 struct nft_osf *priv = nft_expr_priv(expr);
21 u32 *dest = &regs->data[priv->dreg];
22 struct sk_buff *skb = pkt->skb;
23 const struct tcphdr *tcp;
24 struct tcphdr _tcph;
25 const char *os_name;
26
27 tcp = skb_header_pointer(skb, ip_hdrlen(skb),
28 sizeof(struct tcphdr), &_tcph);
29 if (!tcp) {
30 regs->verdict.code = NFT_BREAK;
31 return;
32 }
33 if (!tcp->syn) {
34 regs->verdict.code = NFT_BREAK;
35 return;
36 }
37
38 os_name = nf_osf_find(skb, nf_osf_fingers);
39 if (!os_name)
40 strncpy((char *)dest, "unknown", IFNAMSIZ);
41 else
42 strncpy((char *)dest, os_name, IFNAMSIZ);
43}
44
45static int nft_osf_init(const struct nft_ctx *ctx,
46 const struct nft_expr *expr,
47 const struct nlattr * const tb[])
48{
49 struct nft_osf *priv = nft_expr_priv(expr);
50 int err;
51
52 priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]);
53 err = nft_validate_register_store(ctx, priv->dreg, NULL,
54 NFTA_DATA_VALUE, OSF_GENRE_SIZE);
55 if (err < 0)
56 return err;
57
58 return 0;
59}
60
61static int nft_osf_dump(struct sk_buff *skb, const struct nft_expr *expr)
62{
63 const struct nft_osf *priv = nft_expr_priv(expr);
64
65 if (nft_dump_register(skb, NFTA_OSF_DREG, priv->dreg))
66 goto nla_put_failure;
67
68 return 0;
69
70nla_put_failure:
71 return -1;
72}
73
74static struct nft_expr_type nft_osf_type;
75static const struct nft_expr_ops nft_osf_op = {
76 .eval = nft_osf_eval,
77 .size = NFT_EXPR_SIZE(sizeof(struct nft_osf)),
78 .init = nft_osf_init,
79 .dump = nft_osf_dump,
80 .type = &nft_osf_type,
81};
82
83static struct nft_expr_type nft_osf_type __read_mostly = {
84 .ops = &nft_osf_op,
85 .name = "osf",
86 .owner = THIS_MODULE,
87 .policy = nft_osf_policy,
88 .maxattr = NFTA_OSF_MAX,
89};
90
91static int __init nft_osf_module_init(void)
92{
93 return nft_register_expr(&nft_osf_type);
94}
95
96static void __exit nft_osf_module_exit(void)
97{
98 return nft_unregister_expr(&nft_osf_type);
99}
100
101module_init(nft_osf_module_init);
102module_exit(nft_osf_module_exit);
103
104MODULE_LICENSE("GPL");
105MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>");
106MODULE_ALIAS_NFT_EXPR("osf");
diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c
new file mode 100644
index 000000000000..eff99dffc842
--- /dev/null
+++ b/net/netfilter/nft_tproxy.c
@@ -0,0 +1,316 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/module.h>
3#include <linux/netfilter/nf_tables.h>
4#include <net/netfilter/nf_tables.h>
5#include <net/netfilter/nf_tables_core.h>
6#include <net/netfilter/nf_tproxy.h>
7#include <net/inet_sock.h>
8#include <net/tcp.h>
9#include <linux/if_ether.h>
10#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
11#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
12#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
13#endif
14
15struct nft_tproxy {
16 enum nft_registers sreg_addr:8;
17 enum nft_registers sreg_port:8;
18 u8 family;
19};
20
21static void nft_tproxy_eval_v4(const struct nft_expr *expr,
22 struct nft_regs *regs,
23 const struct nft_pktinfo *pkt)
24{
25 const struct nft_tproxy *priv = nft_expr_priv(expr);
26 struct sk_buff *skb = pkt->skb;
27 const struct iphdr *iph = ip_hdr(skb);
28 struct udphdr _hdr, *hp;
29 __be32 taddr = 0;
30 __be16 tport = 0;
31 struct sock *sk;
32
33 hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
34 if (!hp) {
35 regs->verdict.code = NFT_BREAK;
36 return;
37 }
38
39 /* check if there's an ongoing connection on the packet addresses, this
40 * happens if the redirect already happened and the current packet
41 * belongs to an already established connection
42 */
43 sk = nf_tproxy_get_sock_v4(nft_net(pkt), skb, iph->protocol,
44 iph->saddr, iph->daddr,
45 hp->source, hp->dest,
46 skb->dev, NF_TPROXY_LOOKUP_ESTABLISHED);
47
48 if (priv->sreg_addr)
49 taddr = regs->data[priv->sreg_addr];
50 taddr = nf_tproxy_laddr4(skb, taddr, iph->daddr);
51
52 if (priv->sreg_port)
53 tport = regs->data[priv->sreg_port];
54 if (!tport)
55 tport = hp->dest;
56
57 /* UDP has no TCP_TIME_WAIT state, so we never enter here */
58 if (sk && sk->sk_state == TCP_TIME_WAIT) {
59 /* reopening a TIME_WAIT connection needs special handling */
60 sk = nf_tproxy_handle_time_wait4(nft_net(pkt), skb, taddr, tport, sk);
61 } else if (!sk) {
62 /* no, there's no established connection, check if
63 * there's a listener on the redirected addr/port
64 */
65 sk = nf_tproxy_get_sock_v4(nft_net(pkt), skb, iph->protocol,
66 iph->saddr, taddr,
67 hp->source, tport,
68 skb->dev, NF_TPROXY_LOOKUP_LISTENER);
69 }
70
71 if (sk && nf_tproxy_sk_is_transparent(sk))
72 nf_tproxy_assign_sock(skb, sk);
73 else
74 regs->verdict.code = NFT_BREAK;
75}
76
77#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
78static void nft_tproxy_eval_v6(const struct nft_expr *expr,
79 struct nft_regs *regs,
80 const struct nft_pktinfo *pkt)
81{
82 const struct nft_tproxy *priv = nft_expr_priv(expr);
83 struct sk_buff *skb = pkt->skb;
84 const struct ipv6hdr *iph = ipv6_hdr(skb);
85 struct in6_addr taddr = {0};
86 int thoff = pkt->xt.thoff;
87 struct udphdr _hdr, *hp;
88 __be16 tport = 0;
89 struct sock *sk;
90 int l4proto;
91
92 if (!pkt->tprot_set) {
93 regs->verdict.code = NFT_BREAK;
94 return;
95 }
96 l4proto = pkt->tprot;
97
98 hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
99 if (hp == NULL) {
100 regs->verdict.code = NFT_BREAK;
101 return;
102 }
103
104 /* check if there's an ongoing connection on the packet addresses, this
105 * happens if the redirect already happened and the current packet
106 * belongs to an already established connection
107 */
108 sk = nf_tproxy_get_sock_v6(nft_net(pkt), skb, thoff, l4proto,
109 &iph->saddr, &iph->daddr,
110 hp->source, hp->dest,
111 nft_in(pkt), NF_TPROXY_LOOKUP_ESTABLISHED);
112
113 if (priv->sreg_addr)
114 memcpy(&taddr, &regs->data[priv->sreg_addr], sizeof(taddr));
115 taddr = *nf_tproxy_laddr6(skb, &taddr, &iph->daddr);
116
117 if (priv->sreg_port)
118 tport = regs->data[priv->sreg_port];
119 if (!tport)
120 tport = hp->dest;
121
122 /* UDP has no TCP_TIME_WAIT state, so we never enter here */
123 if (sk && sk->sk_state == TCP_TIME_WAIT) {
124 /* reopening a TIME_WAIT connection needs special handling */
125 sk = nf_tproxy_handle_time_wait6(skb, l4proto, thoff,
126 nft_net(pkt),
127 &taddr,
128 tport,
129 sk);
130 } else if (!sk) {
131 /* no there's no established connection, check if
132 * there's a listener on the redirected addr/port
133 */
134 sk = nf_tproxy_get_sock_v6(nft_net(pkt), skb, thoff,
135 l4proto, &iph->saddr, &taddr,
136 hp->source, tport,
137 nft_in(pkt), NF_TPROXY_LOOKUP_LISTENER);
138 }
139
140 /* NOTE: assign_sock consumes our sk reference */
141 if (sk && nf_tproxy_sk_is_transparent(sk))
142 nf_tproxy_assign_sock(skb, sk);
143 else
144 regs->verdict.code = NFT_BREAK;
145}
146#endif
147
148static void nft_tproxy_eval(const struct nft_expr *expr,
149 struct nft_regs *regs,
150 const struct nft_pktinfo *pkt)
151{
152 const struct nft_tproxy *priv = nft_expr_priv(expr);
153
154 switch (nft_pf(pkt)) {
155 case NFPROTO_IPV4:
156 switch (priv->family) {
157 case NFPROTO_IPV4:
158 case NFPROTO_UNSPEC:
159 nft_tproxy_eval_v4(expr, regs, pkt);
160 return;
161 }
162 break;
163#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
164 case NFPROTO_IPV6:
165 switch (priv->family) {
166 case NFPROTO_IPV6:
167 case NFPROTO_UNSPEC:
168 nft_tproxy_eval_v6(expr, regs, pkt);
169 return;
170 }
171#endif
172 }
173 regs->verdict.code = NFT_BREAK;
174}
175
176static const struct nla_policy nft_tproxy_policy[NFTA_TPROXY_MAX + 1] = {
177 [NFTA_TPROXY_FAMILY] = { .type = NLA_U32 },
178 [NFTA_TPROXY_REG_ADDR] = { .type = NLA_U32 },
179 [NFTA_TPROXY_REG_PORT] = { .type = NLA_U32 },
180};
181
182static int nft_tproxy_init(const struct nft_ctx *ctx,
183 const struct nft_expr *expr,
184 const struct nlattr * const tb[])
185{
186 struct nft_tproxy *priv = nft_expr_priv(expr);
187 unsigned int alen = 0;
188 int err;
189
190 if (!tb[NFTA_TPROXY_FAMILY] ||
191 (!tb[NFTA_TPROXY_REG_ADDR] && !tb[NFTA_TPROXY_REG_PORT]))
192 return -EINVAL;
193
194 priv->family = ntohl(nla_get_be32(tb[NFTA_TPROXY_FAMILY]));
195
196 switch (ctx->family) {
197 case NFPROTO_IPV4:
198 if (priv->family != NFPROTO_IPV4)
199 return -EINVAL;
200 break;
201#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
202 case NFPROTO_IPV6:
203 if (priv->family != NFPROTO_IPV6)
204 return -EINVAL;
205 break;
206#endif
207 case NFPROTO_INET:
208 break;
209 default:
210 return -EOPNOTSUPP;
211 }
212
213 /* Address is specified but the rule family is not set accordingly */
214 if (priv->family == NFPROTO_UNSPEC && tb[NFTA_TPROXY_REG_ADDR])
215 return -EINVAL;
216
217 switch (priv->family) {
218 case NFPROTO_IPV4:
219 alen = FIELD_SIZEOF(union nf_inet_addr, in);
220 err = nf_defrag_ipv4_enable(ctx->net);
221 if (err)
222 return err;
223 break;
224#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
225 case NFPROTO_IPV6:
226 alen = FIELD_SIZEOF(union nf_inet_addr, in6);
227 err = nf_defrag_ipv6_enable(ctx->net);
228 if (err)
229 return err;
230 break;
231#endif
232 case NFPROTO_UNSPEC:
233 /* No address is specified here */
234 err = nf_defrag_ipv4_enable(ctx->net);
235 if (err)
236 return err;
237#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
238 err = nf_defrag_ipv6_enable(ctx->net);
239 if (err)
240 return err;
241#endif
242 break;
243 default:
244 return -EOPNOTSUPP;
245 }
246
247 if (tb[NFTA_TPROXY_REG_ADDR]) {
248 priv->sreg_addr = nft_parse_register(tb[NFTA_TPROXY_REG_ADDR]);
249 err = nft_validate_register_load(priv->sreg_addr, alen);
250 if (err < 0)
251 return err;
252 }
253
254 if (tb[NFTA_TPROXY_REG_PORT]) {
255 priv->sreg_port = nft_parse_register(tb[NFTA_TPROXY_REG_PORT]);
256 err = nft_validate_register_load(priv->sreg_port, sizeof(u16));
257 if (err < 0)
258 return err;
259 }
260
261 return 0;
262}
263
264static int nft_tproxy_dump(struct sk_buff *skb,
265 const struct nft_expr *expr)
266{
267 const struct nft_tproxy *priv = nft_expr_priv(expr);
268
269 if (nla_put_be32(skb, NFTA_TPROXY_FAMILY, htonl(priv->family)))
270 return -1;
271
272 if (priv->sreg_addr &&
273 nft_dump_register(skb, NFTA_TPROXY_REG_ADDR, priv->sreg_addr))
274 return -1;
275
276 if (priv->sreg_port &&
277 nft_dump_register(skb, NFTA_TPROXY_REG_PORT, priv->sreg_port))
278 return -1;
279
280 return 0;
281}
282
283static struct nft_expr_type nft_tproxy_type;
284static const struct nft_expr_ops nft_tproxy_ops = {
285 .type = &nft_tproxy_type,
286 .size = NFT_EXPR_SIZE(sizeof(struct nft_tproxy)),
287 .eval = nft_tproxy_eval,
288 .init = nft_tproxy_init,
289 .dump = nft_tproxy_dump,
290};
291
292static struct nft_expr_type nft_tproxy_type __read_mostly = {
293 .name = "tproxy",
294 .ops = &nft_tproxy_ops,
295 .policy = nft_tproxy_policy,
296 .maxattr = NFTA_TPROXY_MAX,
297 .owner = THIS_MODULE,
298};
299
300static int __init nft_tproxy_module_init(void)
301{
302 return nft_register_expr(&nft_tproxy_type);
303}
304
305static void __exit nft_tproxy_module_exit(void)
306{
307 nft_unregister_expr(&nft_tproxy_type);
308}
309
310module_init(nft_tproxy_module_init);
311module_exit(nft_tproxy_module_exit);
312
313MODULE_LICENSE("GPL");
314MODULE_AUTHOR("Máté Eckl");
315MODULE_DESCRIPTION("nf_tables tproxy support module");
316MODULE_ALIAS_NFT_EXPR("tproxy");
diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c
new file mode 100644
index 000000000000..3a15f219e4e7
--- /dev/null
+++ b/net/netfilter/nft_tunnel.c
@@ -0,0 +1,566 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/kernel.h>
3#include <linux/init.h>
4#include <linux/module.h>
5#include <linux/seqlock.h>
6#include <linux/netlink.h>
7#include <linux/netfilter.h>
8#include <linux/netfilter/nf_tables.h>
9#include <net/netfilter/nf_tables.h>
10#include <net/dst_metadata.h>
11#include <net/ip_tunnels.h>
12#include <net/vxlan.h>
13#include <net/erspan.h>
14
15struct nft_tunnel {
16 enum nft_tunnel_keys key:8;
17 enum nft_registers dreg:8;
18};
19
20static void nft_tunnel_get_eval(const struct nft_expr *expr,
21 struct nft_regs *regs,
22 const struct nft_pktinfo *pkt)
23{
24 const struct nft_tunnel *priv = nft_expr_priv(expr);
25 u32 *dest = &regs->data[priv->dreg];
26 struct ip_tunnel_info *tun_info;
27
28 tun_info = skb_tunnel_info(pkt->skb);
29
30 switch (priv->key) {
31 case NFT_TUNNEL_PATH:
32 nft_reg_store8(dest, !!tun_info);
33 break;
34 case NFT_TUNNEL_ID:
35 if (!tun_info) {
36 regs->verdict.code = NFT_BREAK;
37 return;
38 }
39 *dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id));
40 break;
41 default:
42 WARN_ON(1);
43 regs->verdict.code = NFT_BREAK;
44 }
45}
46
47static const struct nla_policy nft_tunnel_policy[NFTA_TUNNEL_MAX + 1] = {
48 [NFTA_TUNNEL_KEY] = { .type = NLA_U32 },
49 [NFTA_TUNNEL_DREG] = { .type = NLA_U32 },
50};
51
52static int nft_tunnel_get_init(const struct nft_ctx *ctx,
53 const struct nft_expr *expr,
54 const struct nlattr * const tb[])
55{
56 struct nft_tunnel *priv = nft_expr_priv(expr);
57 u32 len;
58
59 if (!tb[NFTA_TUNNEL_KEY] &&
60 !tb[NFTA_TUNNEL_DREG])
61 return -EINVAL;
62
63 priv->key = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY]));
64 switch (priv->key) {
65 case NFT_TUNNEL_PATH:
66 len = sizeof(u8);
67 break;
68 case NFT_TUNNEL_ID:
69 len = sizeof(u32);
70 break;
71 default:
72 return -EOPNOTSUPP;
73 }
74
75 priv->dreg = nft_parse_register(tb[NFTA_TUNNEL_DREG]);
76
77 return nft_validate_register_store(ctx, priv->dreg, NULL,
78 NFT_DATA_VALUE, len);
79}
80
81static int nft_tunnel_get_dump(struct sk_buff *skb,
82 const struct nft_expr *expr)
83{
84 const struct nft_tunnel *priv = nft_expr_priv(expr);
85
86 if (nla_put_be32(skb, NFTA_TUNNEL_KEY, htonl(priv->key)))
87 goto nla_put_failure;
88 if (nft_dump_register(skb, NFTA_TUNNEL_DREG, priv->dreg))
89 goto nla_put_failure;
90 return 0;
91
92nla_put_failure:
93 return -1;
94}
95
96static struct nft_expr_type nft_tunnel_type;
97static const struct nft_expr_ops nft_tunnel_get_ops = {
98 .type = &nft_tunnel_type,
99 .size = NFT_EXPR_SIZE(sizeof(struct nft_tunnel)),
100 .eval = nft_tunnel_get_eval,
101 .init = nft_tunnel_get_init,
102 .dump = nft_tunnel_get_dump,
103};
104
105static struct nft_expr_type nft_tunnel_type __read_mostly = {
106 .name = "tunnel",
107 .ops = &nft_tunnel_get_ops,
108 .policy = nft_tunnel_policy,
109 .maxattr = NFTA_TUNNEL_MAX,
110 .owner = THIS_MODULE,
111};
112
113struct nft_tunnel_opts {
114 union {
115 struct vxlan_metadata vxlan;
116 struct erspan_metadata erspan;
117 } u;
118 u32 len;
119 __be16 flags;
120};
121
122struct nft_tunnel_obj {
123 struct metadata_dst *md;
124 struct nft_tunnel_opts opts;
125};
126
127static const struct nla_policy nft_tunnel_ip_policy[NFTA_TUNNEL_KEY_IP_MAX + 1] = {
128 [NFTA_TUNNEL_KEY_IP_SRC] = { .type = NLA_U32 },
129 [NFTA_TUNNEL_KEY_IP_DST] = { .type = NLA_U32 },
130};
131
132static int nft_tunnel_obj_ip_init(const struct nft_ctx *ctx,
133 const struct nlattr *attr,
134 struct ip_tunnel_info *info)
135{
136 struct nlattr *tb[NFTA_TUNNEL_KEY_IP_MAX + 1];
137 int err;
138
139 err = nla_parse_nested(tb, NFTA_TUNNEL_KEY_IP_MAX, attr,
140 nft_tunnel_ip_policy, NULL);
141 if (err < 0)
142 return err;
143
144 if (!tb[NFTA_TUNNEL_KEY_IP_DST])
145 return -EINVAL;
146
147 if (tb[NFTA_TUNNEL_KEY_IP_SRC])
148 info->key.u.ipv4.src = nla_get_be32(tb[NFTA_TUNNEL_KEY_IP_SRC]);
149 if (tb[NFTA_TUNNEL_KEY_IP_DST])
150 info->key.u.ipv4.dst = nla_get_be32(tb[NFTA_TUNNEL_KEY_IP_DST]);
151
152 return 0;
153}
154
155static const struct nla_policy nft_tunnel_ip6_policy[NFTA_TUNNEL_KEY_IP6_MAX + 1] = {
156 [NFTA_TUNNEL_KEY_IP6_SRC] = { .len = sizeof(struct in6_addr), },
157 [NFTA_TUNNEL_KEY_IP6_DST] = { .len = sizeof(struct in6_addr), },
158 [NFTA_TUNNEL_KEY_IP6_FLOWLABEL] = { .type = NLA_U32, }
159};
160
161static int nft_tunnel_obj_ip6_init(const struct nft_ctx *ctx,
162 const struct nlattr *attr,
163 struct ip_tunnel_info *info)
164{
165 struct nlattr *tb[NFTA_TUNNEL_KEY_IP6_MAX + 1];
166 int err;
167
168 err = nla_parse_nested(tb, NFTA_TUNNEL_KEY_IP6_MAX, attr,
169 nft_tunnel_ip6_policy, NULL);
170 if (err < 0)
171 return err;
172
173 if (!tb[NFTA_TUNNEL_KEY_IP6_DST])
174 return -EINVAL;
175
176 if (tb[NFTA_TUNNEL_KEY_IP6_SRC]) {
177 memcpy(&info->key.u.ipv6.src,
178 nla_data(tb[NFTA_TUNNEL_KEY_IP6_SRC]),
179 sizeof(struct in6_addr));
180 }
181 if (tb[NFTA_TUNNEL_KEY_IP6_DST]) {
182 memcpy(&info->key.u.ipv6.dst,
183 nla_data(tb[NFTA_TUNNEL_KEY_IP6_DST]),
184 sizeof(struct in6_addr));
185 }
186 if (tb[NFTA_TUNNEL_KEY_IP6_FLOWLABEL])
187 info->key.label = nla_get_be32(tb[NFTA_TUNNEL_KEY_IP6_FLOWLABEL]);
188
189 info->mode |= IP_TUNNEL_INFO_IPV6;
190
191 return 0;
192}
193
194static const struct nla_policy nft_tunnel_opts_vxlan_policy[NFTA_TUNNEL_KEY_VXLAN_MAX + 1] = {
195 [NFTA_TUNNEL_KEY_VXLAN_GBP] = { .type = NLA_U32 },
196};
197
198static int nft_tunnel_obj_vxlan_init(const struct nlattr *attr,
199 struct nft_tunnel_opts *opts)
200{
201 struct nlattr *tb[NFTA_TUNNEL_KEY_VXLAN_MAX + 1];
202 int err;
203
204 err = nla_parse_nested(tb, NFTA_TUNNEL_KEY_VXLAN_MAX, attr,
205 nft_tunnel_opts_vxlan_policy, NULL);
206 if (err < 0)
207 return err;
208
209 if (!tb[NFTA_TUNNEL_KEY_VXLAN_GBP])
210 return -EINVAL;
211
212 opts->u.vxlan.gbp = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_VXLAN_GBP]));
213
214 opts->len = sizeof(struct vxlan_metadata);
215 opts->flags = TUNNEL_VXLAN_OPT;
216
217 return 0;
218}
219
220static const struct nla_policy nft_tunnel_opts_erspan_policy[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = {
221 [NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX] = { .type = NLA_U32 },
222 [NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] = { .type = NLA_U8 },
223 [NFTA_TUNNEL_KEY_ERSPAN_V2_HWID] = { .type = NLA_U8 },
224};
225
226static int nft_tunnel_obj_erspan_init(const struct nlattr *attr,
227 struct nft_tunnel_opts *opts)
228{
229 struct nlattr *tb[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1];
230 uint8_t hwid, dir;
231 int err, version;
232
233 err = nla_parse_nested(tb, NFTA_TUNNEL_KEY_ERSPAN_MAX, attr,
234 nft_tunnel_opts_erspan_policy, NULL);
235 if (err < 0)
236 return err;
237
238 version = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]));
239 switch (version) {
240 case ERSPAN_VERSION:
241 if (!tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX])
242 return -EINVAL;
243
244 opts->u.erspan.u.index =
245 nla_get_be32(tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]);
246 break;
247 case ERSPAN_VERSION2:
248 if (!tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] ||
249 !tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID])
250 return -EINVAL;
251
252 hwid = nla_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]);
253 dir = nla_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]);
254
255 set_hwid(&opts->u.erspan.u.md2, hwid);
256 opts->u.erspan.u.md2.dir = dir;
257 break;
258 default:
259 return -EOPNOTSUPP;
260 }
261 opts->u.erspan.version = version;
262
263 opts->len = sizeof(struct erspan_metadata);
264 opts->flags = TUNNEL_ERSPAN_OPT;
265
266 return 0;
267}
268
269static const struct nla_policy nft_tunnel_opts_policy[NFTA_TUNNEL_KEY_OPTS_MAX + 1] = {
270 [NFTA_TUNNEL_KEY_OPTS_VXLAN] = { .type = NLA_NESTED, },
271 [NFTA_TUNNEL_KEY_OPTS_ERSPAN] = { .type = NLA_NESTED, },
272};
273
274static int nft_tunnel_obj_opts_init(const struct nft_ctx *ctx,
275 const struct nlattr *attr,
276 struct ip_tunnel_info *info,
277 struct nft_tunnel_opts *opts)
278{
279 struct nlattr *tb[NFTA_TUNNEL_KEY_OPTS_MAX + 1];
280 int err;
281
282 err = nla_parse_nested(tb, NFTA_TUNNEL_KEY_OPTS_MAX, attr,
283 nft_tunnel_opts_policy, NULL);
284 if (err < 0)
285 return err;
286
287 if (tb[NFTA_TUNNEL_KEY_OPTS_VXLAN]) {
288 err = nft_tunnel_obj_vxlan_init(tb[NFTA_TUNNEL_KEY_OPTS_VXLAN],
289 opts);
290 } else if (tb[NFTA_TUNNEL_KEY_OPTS_ERSPAN]) {
291 err = nft_tunnel_obj_erspan_init(tb[NFTA_TUNNEL_KEY_OPTS_ERSPAN],
292 opts);
293 } else {
294 return -EOPNOTSUPP;
295 }
296
297 return err;
298}
299
300static const struct nla_policy nft_tunnel_key_policy[NFTA_TUNNEL_KEY_MAX + 1] = {
301 [NFTA_TUNNEL_KEY_IP] = { .type = NLA_NESTED, },
302 [NFTA_TUNNEL_KEY_IP6] = { .type = NLA_NESTED, },
303 [NFTA_TUNNEL_KEY_ID] = { .type = NLA_U32, },
304 [NFTA_TUNNEL_KEY_FLAGS] = { .type = NLA_U32, },
305 [NFTA_TUNNEL_KEY_TOS] = { .type = NLA_U8, },
306 [NFTA_TUNNEL_KEY_TTL] = { .type = NLA_U8, },
307 [NFTA_TUNNEL_KEY_OPTS] = { .type = NLA_NESTED, },
308};
309
310static int nft_tunnel_obj_init(const struct nft_ctx *ctx,
311 const struct nlattr * const tb[],
312 struct nft_object *obj)
313{
314 struct nft_tunnel_obj *priv = nft_obj_data(obj);
315 struct ip_tunnel_info info;
316 struct metadata_dst *md;
317 int err;
318
319 if (!tb[NFTA_TUNNEL_KEY_ID])
320 return -EINVAL;
321
322 memset(&info, 0, sizeof(info));
323 info.mode = IP_TUNNEL_INFO_TX;
324 info.key.tun_id = key32_to_tunnel_id(nla_get_be32(tb[NFTA_TUNNEL_KEY_ID]));
325 info.key.tun_flags = TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_NOCACHE;
326
327 if (tb[NFTA_TUNNEL_KEY_IP]) {
328 err = nft_tunnel_obj_ip_init(ctx, tb[NFTA_TUNNEL_KEY_IP], &info);
329 if (err < 0)
330 return err;
331 } else if (tb[NFTA_TUNNEL_KEY_IP6]) {
332 err = nft_tunnel_obj_ip6_init(ctx, tb[NFTA_TUNNEL_KEY_IP6], &info);
333 if (err < 0)
334 return err;
335 } else {
336 return -EINVAL;
337 }
338
339 if (tb[NFTA_TUNNEL_KEY_SPORT]) {
340 info.key.tp_src = nla_get_be16(tb[NFTA_TUNNEL_KEY_SPORT]);
341 }
342 if (tb[NFTA_TUNNEL_KEY_DPORT]) {
343 info.key.tp_dst = nla_get_be16(tb[NFTA_TUNNEL_KEY_DPORT]);
344 }
345
346 if (tb[NFTA_TUNNEL_KEY_FLAGS]) {
347 u32 tun_flags;
348
349 tun_flags = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_FLAGS]));
350 if (tun_flags & ~NFT_TUNNEL_F_MASK)
351 return -EOPNOTSUPP;
352
353 if (tun_flags & NFT_TUNNEL_F_ZERO_CSUM_TX)
354 info.key.tun_flags &= ~TUNNEL_CSUM;
355 if (tun_flags & NFT_TUNNEL_F_DONT_FRAGMENT)
356 info.key.tun_flags |= TUNNEL_DONT_FRAGMENT;
357 if (tun_flags & NFT_TUNNEL_F_SEQ_NUMBER)
358 info.key.tun_flags |= TUNNEL_SEQ;
359 }
360 if (tb[NFTA_TUNNEL_KEY_TOS])
361 info.key.tos = nla_get_u8(tb[NFTA_TUNNEL_KEY_TOS]);
362 if (tb[NFTA_TUNNEL_KEY_TTL])
363 info.key.ttl = nla_get_u8(tb[NFTA_TUNNEL_KEY_TTL]);
364 else
365 info.key.ttl = U8_MAX;
366
367 if (tb[NFTA_TUNNEL_KEY_OPTS]) {
368 err = nft_tunnel_obj_opts_init(ctx, tb[NFTA_TUNNEL_KEY_OPTS],
369 &info, &priv->opts);
370 if (err < 0)
371 return err;
372 }
373
374 md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL, GFP_KERNEL);
375 if (!md)
376 return -ENOMEM;
377
378 memcpy(&md->u.tun_info, &info, sizeof(info));
379 ip_tunnel_info_opts_set(&md->u.tun_info, &priv->opts.u, priv->opts.len,
380 priv->opts.flags);
381 priv->md = md;
382
383 return 0;
384}
385
386static inline void nft_tunnel_obj_eval(struct nft_object *obj,
387 struct nft_regs *regs,
388 const struct nft_pktinfo *pkt)
389{
390 struct nft_tunnel_obj *priv = nft_obj_data(obj);
391 struct sk_buff *skb = pkt->skb;
392
393 skb_dst_drop(skb);
394 dst_hold((struct dst_entry *) priv->md);
395 skb_dst_set(skb, (struct dst_entry *) priv->md);
396}
397
398static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info)
399{
400 struct nlattr *nest;
401
402 if (info->mode & IP_TUNNEL_INFO_IPV6) {
403 nest = nla_nest_start(skb, NFTA_TUNNEL_KEY_IP6);
404 if (!nest)
405 return -1;
406
407 if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC, &info->key.u.ipv6.src) < 0 ||
408 nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST, &info->key.u.ipv6.dst) < 0 ||
409 nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL, info->key.label))
410 return -1;
411
412 nla_nest_end(skb, nest);
413 } else {
414 nest = nla_nest_start(skb, NFTA_TUNNEL_KEY_IP);
415 if (!nest)
416 return -1;
417
418 if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC, info->key.u.ipv4.src) < 0 ||
419 nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST, info->key.u.ipv4.dst) < 0)
420 return -1;
421
422 nla_nest_end(skb, nest);
423 }
424
425 return 0;
426}
427
428static int nft_tunnel_opts_dump(struct sk_buff *skb,
429 struct nft_tunnel_obj *priv)
430{
431 struct nft_tunnel_opts *opts = &priv->opts;
432 struct nlattr *nest;
433
434 nest = nla_nest_start(skb, NFTA_TUNNEL_KEY_OPTS);
435 if (!nest)
436 return -1;
437
438 if (opts->flags & TUNNEL_VXLAN_OPT) {
439 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_VXLAN_GBP,
440 htonl(opts->u.vxlan.gbp)))
441 return -1;
442 } else if (opts->flags & TUNNEL_ERSPAN_OPT) {
443 switch (opts->u.erspan.version) {
444 case ERSPAN_VERSION:
445 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
446 opts->u.erspan.u.index))
447 return -1;
448 break;
449 case ERSPAN_VERSION2:
450 if (nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
451 get_hwid(&opts->u.erspan.u.md2)) ||
452 nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
453 opts->u.erspan.u.md2.dir))
454 return -1;
455 break;
456 }
457 }
458 nla_nest_end(skb, nest);
459
460 return 0;
461}
462
463static int nft_tunnel_ports_dump(struct sk_buff *skb,
464 struct ip_tunnel_info *info)
465{
466 if (nla_put_be16(skb, NFTA_TUNNEL_KEY_SPORT, htons(info->key.tp_src)) < 0 ||
467 nla_put_be16(skb, NFTA_TUNNEL_KEY_DPORT, htons(info->key.tp_dst)) < 0)
468 return -1;
469
470 return 0;
471}
472
473static int nft_tunnel_flags_dump(struct sk_buff *skb,
474 struct ip_tunnel_info *info)
475{
476 u32 flags = 0;
477
478 if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)
479 flags |= NFT_TUNNEL_F_DONT_FRAGMENT;
480 if (!(info->key.tun_flags & TUNNEL_CSUM))
481 flags |= NFT_TUNNEL_F_ZERO_CSUM_TX;
482 if (info->key.tun_flags & TUNNEL_SEQ)
483 flags |= NFT_TUNNEL_F_SEQ_NUMBER;
484
485 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_FLAGS, htonl(flags)) < 0)
486 return -1;
487
488 return 0;
489}
490
491static int nft_tunnel_obj_dump(struct sk_buff *skb,
492 struct nft_object *obj, bool reset)
493{
494 struct nft_tunnel_obj *priv = nft_obj_data(obj);
495 struct ip_tunnel_info *info = &priv->md->u.tun_info;
496
497 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ID,
498 tunnel_id_to_key32(info->key.tun_id)) ||
499 nft_tunnel_ip_dump(skb, info) < 0 ||
500 nft_tunnel_ports_dump(skb, info) < 0 ||
501 nft_tunnel_flags_dump(skb, info) < 0 ||
502 nla_put_u8(skb, NFTA_TUNNEL_KEY_TOS, info->key.tos) ||
503 nla_put_u8(skb, NFTA_TUNNEL_KEY_TTL, info->key.ttl) ||
504 nft_tunnel_opts_dump(skb, priv) < 0)
505 goto nla_put_failure;
506
507 return 0;
508
509nla_put_failure:
510 return -1;
511}
512
513static void nft_tunnel_obj_destroy(const struct nft_ctx *ctx,
514 struct nft_object *obj)
515{
516 struct nft_tunnel_obj *priv = nft_obj_data(obj);
517
518 metadata_dst_free(priv->md);
519}
520
521static struct nft_object_type nft_tunnel_obj_type;
522static const struct nft_object_ops nft_tunnel_obj_ops = {
523 .type = &nft_tunnel_obj_type,
524 .size = sizeof(struct nft_tunnel_obj),
525 .eval = nft_tunnel_obj_eval,
526 .init = nft_tunnel_obj_init,
527 .destroy = nft_tunnel_obj_destroy,
528 .dump = nft_tunnel_obj_dump,
529};
530
531static struct nft_object_type nft_tunnel_obj_type __read_mostly = {
532 .type = NFT_OBJECT_TUNNEL,
533 .ops = &nft_tunnel_obj_ops,
534 .maxattr = NFTA_TUNNEL_KEY_MAX,
535 .policy = nft_tunnel_key_policy,
536 .owner = THIS_MODULE,
537};
538
539static int __init nft_tunnel_module_init(void)
540{
541 int err;
542
543 err = nft_register_expr(&nft_tunnel_type);
544 if (err < 0)
545 return err;
546
547 err = nft_register_obj(&nft_tunnel_obj_type);
548 if (err < 0)
549 nft_unregister_expr(&nft_tunnel_type);
550
551 return err;
552}
553
554static void __exit nft_tunnel_module_exit(void)
555{
556 nft_unregister_obj(&nft_tunnel_obj_type);
557 nft_unregister_expr(&nft_tunnel_type);
558}
559
560module_init(nft_tunnel_module_init);
561module_exit(nft_tunnel_module_exit);
562
563MODULE_LICENSE("GPL");
564MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
565MODULE_ALIAS_NFT_EXPR("tunnel");
566MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL);
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 6275106ccf50..bc6c8ab0fa62 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -93,10 +93,8 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
93 93
94 /* init private data */ 94 /* init private data */
95 info->data = nf_conncount_init(par->net, par->family, keylen); 95 info->data = nf_conncount_init(par->net, par->family, keylen);
96 if (IS_ERR(info->data))
97 return PTR_ERR(info->data);
98 96
99 return 0; 97 return PTR_ERR_OR_ZERO(info->data);
100} 98}
101 99
102static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) 100static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 9cfef73b4107..bf7bba80e24c 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -37,118 +37,6 @@
37#include <net/netfilter/nf_log.h> 37#include <net/netfilter/nf_log.h>
38#include <linux/netfilter/xt_osf.h> 38#include <linux/netfilter/xt_osf.h>
39 39
40/*
41 * Indexed by dont-fragment bit.
42 * It is the only constant value in the fingerprint.
43 */
44static struct list_head xt_osf_fingers[2];
45
46static const struct nla_policy xt_osf_policy[OSF_ATTR_MAX + 1] = {
47 [OSF_ATTR_FINGER] = { .len = sizeof(struct xt_osf_user_finger) },
48};
49
50static int xt_osf_add_callback(struct net *net, struct sock *ctnl,
51 struct sk_buff *skb, const struct nlmsghdr *nlh,
52 const struct nlattr * const osf_attrs[],
53 struct netlink_ext_ack *extack)
54{
55 struct xt_osf_user_finger *f;
56 struct xt_osf_finger *kf = NULL, *sf;
57 int err = 0;
58
59 if (!capable(CAP_NET_ADMIN))
60 return -EPERM;
61
62 if (!osf_attrs[OSF_ATTR_FINGER])
63 return -EINVAL;
64
65 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
66 return -EINVAL;
67
68 f = nla_data(osf_attrs[OSF_ATTR_FINGER]);
69
70 kf = kmalloc(sizeof(struct xt_osf_finger), GFP_KERNEL);
71 if (!kf)
72 return -ENOMEM;
73
74 memcpy(&kf->finger, f, sizeof(struct xt_osf_user_finger));
75
76 list_for_each_entry(sf, &xt_osf_fingers[!!f->df], finger_entry) {
77 if (memcmp(&sf->finger, f, sizeof(struct xt_osf_user_finger)))
78 continue;
79
80 kfree(kf);
81 kf = NULL;
82
83 if (nlh->nlmsg_flags & NLM_F_EXCL)
84 err = -EEXIST;
85 break;
86 }
87
88 /*
89 * We are protected by nfnl mutex.
90 */
91 if (kf)
92 list_add_tail_rcu(&kf->finger_entry, &xt_osf_fingers[!!f->df]);
93
94 return err;
95}
96
97static int xt_osf_remove_callback(struct net *net, struct sock *ctnl,
98 struct sk_buff *skb,
99 const struct nlmsghdr *nlh,
100 const struct nlattr * const osf_attrs[],
101 struct netlink_ext_ack *extack)
102{
103 struct xt_osf_user_finger *f;
104 struct xt_osf_finger *sf;
105 int err = -ENOENT;
106
107 if (!capable(CAP_NET_ADMIN))
108 return -EPERM;
109
110 if (!osf_attrs[OSF_ATTR_FINGER])
111 return -EINVAL;
112
113 f = nla_data(osf_attrs[OSF_ATTR_FINGER]);
114
115 list_for_each_entry(sf, &xt_osf_fingers[!!f->df], finger_entry) {
116 if (memcmp(&sf->finger, f, sizeof(struct xt_osf_user_finger)))
117 continue;
118
119 /*
120 * We are protected by nfnl mutex.
121 */
122 list_del_rcu(&sf->finger_entry);
123 kfree_rcu(sf, rcu_head);
124
125 err = 0;
126 break;
127 }
128
129 return err;
130}
131
132static const struct nfnl_callback xt_osf_nfnetlink_callbacks[OSF_MSG_MAX] = {
133 [OSF_MSG_ADD] = {
134 .call = xt_osf_add_callback,
135 .attr_count = OSF_ATTR_MAX,
136 .policy = xt_osf_policy,
137 },
138 [OSF_MSG_REMOVE] = {
139 .call = xt_osf_remove_callback,
140 .attr_count = OSF_ATTR_MAX,
141 .policy = xt_osf_policy,
142 },
143};
144
145static const struct nfnetlink_subsystem xt_osf_nfnetlink = {
146 .name = "osf",
147 .subsys_id = NFNL_SUBSYS_OSF,
148 .cb_count = OSF_MSG_MAX,
149 .cb = xt_osf_nfnetlink_callbacks,
150};
151
152static bool 40static bool
153xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) 41xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
154{ 42{
@@ -159,7 +47,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
159 return false; 47 return false;
160 48
161 return nf_osf_match(skb, xt_family(p), xt_hooknum(p), xt_in(p), 49 return nf_osf_match(skb, xt_family(p), xt_hooknum(p), xt_in(p),
162 xt_out(p), info, net, xt_osf_fingers); 50 xt_out(p), info, net, nf_osf_fingers);
163} 51}
164 52
165static struct xt_match xt_osf_match = { 53static struct xt_match xt_osf_match = {
@@ -177,52 +65,21 @@ static struct xt_match xt_osf_match = {
177 65
178static int __init xt_osf_init(void) 66static int __init xt_osf_init(void)
179{ 67{
180 int err = -EINVAL; 68 int err;
181 int i;
182
183 for (i=0; i<ARRAY_SIZE(xt_osf_fingers); ++i)
184 INIT_LIST_HEAD(&xt_osf_fingers[i]);
185
186 err = nfnetlink_subsys_register(&xt_osf_nfnetlink);
187 if (err < 0) {
188 pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err);
189 goto err_out_exit;
190 }
191 69
192 err = xt_register_match(&xt_osf_match); 70 err = xt_register_match(&xt_osf_match);
193 if (err) { 71 if (err) {
194 pr_err("Failed to register OS fingerprint " 72 pr_err("Failed to register OS fingerprint "
195 "matching module (%d)\n", err); 73 "matching module (%d)\n", err);
196 goto err_out_remove; 74 return err;
197 } 75 }
198 76
199 return 0; 77 return 0;
200
201err_out_remove:
202 nfnetlink_subsys_unregister(&xt_osf_nfnetlink);
203err_out_exit:
204 return err;
205} 78}
206 79
207static void __exit xt_osf_fini(void) 80static void __exit xt_osf_fini(void)
208{ 81{
209 struct xt_osf_finger *f;
210 int i;
211
212 nfnetlink_subsys_unregister(&xt_osf_nfnetlink);
213 xt_unregister_match(&xt_osf_match); 82 xt_unregister_match(&xt_osf_match);
214
215 rcu_read_lock();
216 for (i=0; i<ARRAY_SIZE(xt_osf_fingers); ++i) {
217
218 list_for_each_entry_rcu(f, &xt_osf_fingers[i], finger_entry) {
219 list_del_rcu(&f->finger_entry);
220 kfree_rcu(f, rcu_head);
221 }
222 }
223 rcu_read_unlock();
224
225 rcu_barrier();
226} 83}
227 84
228module_init(xt_osf_init); 85module_init(xt_osf_init);