Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+1417 -254
-11
include/linux/netfilter_bridge.h
··· 5 5 #include <uapi/linux/netfilter_bridge.h> 6 6 #include <linux/skbuff.h> 7 7 8 - enum 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 8 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 20 9 21 10 int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
-2
include/net/netfilter/nf_conntrack.h
··· 176 176 */ 177 177 void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls); 178 178 179 - void nf_ct_free_hashtable(void *hash, unsigned int size); 180 - 181 179 int nf_conntrack_hash_check_insert(struct nf_conn *ct); 182 180 bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report); 183 181
+7
include/net/netfilter/nf_tables_core.h
··· 71 71 extern struct nft_set_type nft_set_rbtree_type; 72 72 extern struct nft_set_type nft_set_bitmap_type; 73 73 74 + struct nft_expr; 75 + struct nft_regs; 76 + struct nft_pktinfo; 77 + void nft_meta_get_eval(const struct nft_expr *expr, 78 + struct nft_regs *regs, const struct nft_pktinfo *pkt); 79 + void nft_lookup_eval(const struct nft_expr *expr, 80 + struct nft_regs *regs, const struct nft_pktinfo *pkt); 74 81 #endif /* _NET_NF_TABLES_CORE_H */
+106 -1
include/uapi/linux/netfilter/nf_tables.h
··· 1253 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 + */ 1262 + enum 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 1272 * enum nft_masq_attributes - nf_tables masquerade expression attributes 1257 1273 * 1258 1274 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32) ··· 1416 1400 #define NFT_OBJECT_CT_HELPER 3 1417 1401 #define NFT_OBJECT_LIMIT 4 1418 1402 #define NFT_OBJECT_CONNLIMIT 5 1419 - #define __NFT_OBJECT_MAX 6 1403 + #define NFT_OBJECT_TUNNEL 6 1404 + #define __NFT_OBJECT_MAX 7 1420 1405 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) 1421 1406 1422 1407 /** ··· 1479 1462 __NFTA_FLOWTABLE_HOOK_MAX 1480 1463 }; 1481 1464 #define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1) 1465 + 1466 + enum nft_osf_attributes { 1467 + NFTA_OSF_UNSPEC, 1468 + NFTA_OSF_DREG, 1469 + __NFTA_OSF_MAX, 1470 + }; 1471 + #define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1) 1482 1472 1483 1473 /** 1484 1474 * enum nft_device_attributes - nf_tables device netlink attributes ··· 1580 1556 __NFT_NG_MAX 1581 1557 }; 1582 1558 #define NFT_NG_MAX (__NFT_NG_MAX - 1) 1559 + 1560 + enum nft_tunnel_key_ip_attributes { 1561 + NFTA_TUNNEL_KEY_IP_UNSPEC, 1562 + NFTA_TUNNEL_KEY_IP_SRC, 1563 + NFTA_TUNNEL_KEY_IP_DST, 1564 + __NFTA_TUNNEL_KEY_IP_MAX 1565 + }; 1566 + #define NFTA_TUNNEL_KEY_IP_MAX (__NFTA_TUNNEL_KEY_IP_MAX - 1) 1567 + 1568 + enum nft_tunnel_ip6_attributes { 1569 + NFTA_TUNNEL_KEY_IP6_UNSPEC, 1570 + NFTA_TUNNEL_KEY_IP6_SRC, 1571 + NFTA_TUNNEL_KEY_IP6_DST, 1572 + NFTA_TUNNEL_KEY_IP6_FLOWLABEL, 1573 + __NFTA_TUNNEL_KEY_IP6_MAX 1574 + }; 1575 + #define NFTA_TUNNEL_KEY_IP6_MAX (__NFTA_TUNNEL_KEY_IP6_MAX - 1) 1576 + 1577 + enum nft_tunnel_opts_attributes { 1578 + NFTA_TUNNEL_KEY_OPTS_UNSPEC, 1579 + NFTA_TUNNEL_KEY_OPTS_VXLAN, 1580 + NFTA_TUNNEL_KEY_OPTS_ERSPAN, 1581 + __NFTA_TUNNEL_KEY_OPTS_MAX 1582 + }; 1583 + #define NFTA_TUNNEL_KEY_OPTS_MAX (__NFTA_TUNNEL_KEY_OPTS_MAX - 1) 1584 + 1585 + enum nft_tunnel_opts_vxlan_attributes { 1586 + NFTA_TUNNEL_KEY_VXLAN_UNSPEC, 1587 + NFTA_TUNNEL_KEY_VXLAN_GBP, 1588 + __NFTA_TUNNEL_KEY_VXLAN_MAX 1589 + }; 1590 + #define NFTA_TUNNEL_KEY_VXLAN_MAX (__NFTA_TUNNEL_KEY_VXLAN_MAX - 1) 1591 + 1592 + enum nft_tunnel_opts_erspan_attributes { 1593 + NFTA_TUNNEL_KEY_ERSPAN_UNSPEC, 1594 + NFTA_TUNNEL_KEY_ERSPAN_VERSION, 1595 + NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX, 1596 + NFTA_TUNNEL_KEY_ERSPAN_V2_HWID, 1597 + NFTA_TUNNEL_KEY_ERSPAN_V2_DIR, 1598 + __NFTA_TUNNEL_KEY_ERSPAN_MAX 1599 + }; 1600 + #define NFTA_TUNNEL_KEY_ERSPAN_MAX (__NFTA_TUNNEL_KEY_ERSPAN_MAX - 1) 1601 + 1602 + enum nft_tunnel_flags { 1603 + NFT_TUNNEL_F_ZERO_CSUM_TX = (1 << 0), 1604 + NFT_TUNNEL_F_DONT_FRAGMENT = (1 << 1), 1605 + NFT_TUNNEL_F_SEQ_NUMBER = (1 << 2), 1606 + }; 1607 + #define NFT_TUNNEL_F_MASK (NFT_TUNNEL_F_ZERO_CSUM_TX | \ 1608 + NFT_TUNNEL_F_DONT_FRAGMENT | \ 1609 + NFT_TUNNEL_F_SEQ_NUMBER) 1610 + 1611 + enum nft_tunnel_key_attributes { 1612 + NFTA_TUNNEL_KEY_UNSPEC, 1613 + NFTA_TUNNEL_KEY_ID, 1614 + NFTA_TUNNEL_KEY_IP, 1615 + NFTA_TUNNEL_KEY_IP6, 1616 + NFTA_TUNNEL_KEY_FLAGS, 1617 + NFTA_TUNNEL_KEY_TOS, 1618 + NFTA_TUNNEL_KEY_TTL, 1619 + NFTA_TUNNEL_KEY_SPORT, 1620 + NFTA_TUNNEL_KEY_DPORT, 1621 + NFTA_TUNNEL_KEY_OPTS, 1622 + __NFTA_TUNNEL_KEY_MAX 1623 + }; 1624 + #define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1) 1625 + 1626 + enum nft_tunnel_keys { 1627 + NFT_TUNNEL_PATH, 1628 + NFT_TUNNEL_ID, 1629 + __NFT_TUNNEL_MAX 1630 + }; 1631 + #define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1) 1632 + 1633 + enum nft_tunnel_attributes { 1634 + NFTA_TUNNEL_UNSPEC, 1635 + NFTA_TUNNEL_KEY, 1636 + NFTA_TUNNEL_DREG, 1637 + __NFTA_TUNNEL_MAX 1638 + }; 1639 + #define NFTA_TUNNEL_MAX (__NFTA_TUNNEL_MAX - 1) 1583 1640 1584 1641 #endif /* _LINUX_NF_TABLES_H */
+2 -9
include/uapi/linux/netfilter/xt_osf.h
··· 23 23 #include <linux/types.h> 24 24 #include <linux/ip.h> 25 25 #include <linux/tcp.h> 26 - #include <linux/netfilter/nf_osf.h> 26 + #include <linux/netfilter/nfnetlink_osf.h> 27 27 28 28 #define XT_OSF_GENRE NF_OSF_GENRE 29 29 #define XT_OSF_INVERT NF_OSF_INVERT ··· 47 47 #define xt_osf_nlmsg nf_osf_nlmsg 48 48 49 49 #define xt_osf_attr_type nf_osf_attr_type 50 - /* 51 - * Add/remove fingerprint from the kernel. 52 - */ 53 - enum xt_osf_msg_types { 54 - OSF_MSG_ADD, 55 - OSF_MSG_REMOVE, 56 - OSF_MSG_MAX, 57 - }; 50 + #define xt_osf_msg_types nf_osf_msg_types 58 51 59 52 #endif /* _XT_OSF_H */
+11
include/uapi/linux/netfilter_bridge.h
··· 26 26 #define NF_BR_BROUTING 5 27 27 #define NF_BR_NUMHOOKS 6 28 28 29 + enum 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 40 #endif /* _UAPI__LINUX_BRIDGE_NETFILTER_H */
+1
net/bridge/br_netfilter_hooks.c
··· 26 26 #include <linux/if_pppox.h> 27 27 #include <linux/ppp_defs.h> 28 28 #include <linux/netfilter_bridge.h> 29 + #include <uapi/linux/netfilter_bridge.h> 29 30 #include <linux/netfilter_ipv4.h> 30 31 #include <linux/netfilter_ipv6.h> 31 32 #include <linux/netfilter_arp.h>
+1
net/bridge/netfilter/ebtable_filter.c
··· 9 9 */ 10 10 11 11 #include <linux/netfilter_bridge/ebtables.h> 12 + #include <uapi/linux/netfilter_bridge.h> 12 13 #include <linux/module.h> 13 14 14 15 #define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \
+1
net/bridge/netfilter/ebtable_nat.c
··· 9 9 */ 10 10 11 11 #include <linux/netfilter_bridge/ebtables.h> 12 + #include <uapi/linux/netfilter_bridge.h> 12 13 #include <linux/module.h> 13 14 14 15 #define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \
+1
net/core/dst.c
··· 307 307 #endif 308 308 kfree(md_dst); 309 309 } 310 + EXPORT_SYMBOL_GPL(metadata_dst_free); 310 311 311 312 struct metadata_dst __percpu * 312 313 metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags)
+37 -8
net/netfilter/Kconfig
··· 46 46 and is also scheduled to replace the old syslog-based ipt_LOG 47 47 and ip6t_LOG modules. 48 48 49 + config 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 + 49 57 config NF_CONNTRACK 50 58 tristate "Netfilter connection tracking support" 51 59 default m if NETFILTER_ADVANCED=n ··· 106 98 config NF_CONNTRACK_ZONES 107 99 bool 'Connection tracking zones' 108 100 depends on NETFILTER_ADVANCED 109 - depends on NETFILTER_XT_TARGET_CT 110 101 help 111 102 This option enables support for connection tracking zones. 112 103 Normally, each connection needs to have a unique system wide ··· 157 150 If unsure, say `N'. 158 151 159 152 config NF_CONNTRACK_LABELS 160 - bool 153 + bool "Connection tracking labels" 161 154 help 162 155 This option enables support for assigning user-defined flag bits 163 - to connection tracking entries. It selected by the connlabel match. 156 + to connection tracking entries. It can be used with xtables connlabel 157 + match and the nftables ct expression. 164 158 165 159 config NF_CT_PROTO_DCCP 166 160 bool 'DCCP protocol connection tracking support' ··· 365 357 tristate 'Connection tracking timeout tuning via Netlink' 366 358 select NETFILTER_NETLINK 367 359 depends on NETFILTER_ADVANCED 360 + depends on NF_CONNTRACK_TIMEOUT 368 361 help 369 362 This option enables support for connection tracking timeout 370 363 fine-grain tuning. This allows you to attach specific timeout ··· 450 441 tristate 451 442 452 443 endif # NF_CONNTRACK 453 - 454 - config NF_OSF 455 - tristate 456 444 457 445 config NF_TABLES 458 446 select NETFILTER_NETLINK ··· 559 553 This option adds the "nat" expression that you can use to perform 560 554 typical Network Address Translation (NAT) packet transformations. 561 555 556 + config NFT_TUNNEL 557 + tristate "Netfilter nf_tables tunnel module" 558 + help 559 + This option adds the "tunnel" expression that you can use to set 560 + tunneling policies. 561 + 562 562 config NFT_OBJREF 563 563 tristate "Netfilter nf_tables stateful object reference module" 564 564 help ··· 633 621 help 634 622 This option allows matching for the presence or absence of a 635 623 corresponding socket and its attributes. 624 + 625 + config NFT_OSF 626 + tristate "Netfilter nf_tables passive OS fingerprint support" 627 + depends on NETFILTER_ADVANCED 628 + select NETFILTER_NETLINK_OSF 629 + help 630 + This option allows matching packets from an specific OS. 631 + 632 + config NFT_TPROXY 633 + tristate "Netfilter nf_tables tproxy support" 634 + depends on IPV6 || IPV6=n 635 + select NF_DEFRAG_IPV4 636 + select NF_DEFRAG_IPV6 if NF_TABLES_IPV6 637 + select NF_TPROXY_IPV4 638 + select NF_TPROXY_IPV6 if NF_TABLES_IPV6 639 + help 640 + This makes transparent proxy support available in nftables. 636 641 637 642 if NF_TABLES_NETDEV 638 643 ··· 1397 1368 1398 1369 config NETFILTER_XT_MATCH_OSF 1399 1370 tristate '"osf" Passive OS fingerprint match' 1400 - depends on NETFILTER_ADVANCED && NETFILTER_NETLINK 1401 - select NF_OSF 1371 + depends on NETFILTER_ADVANCED 1372 + select NETFILTER_NETLINK_OSF 1402 1373 help 1403 1374 This option selects the Passive OS Fingerprinting match module 1404 1375 that allows to passively match the remote operating system by
+4 -1
net/netfilter/Makefile
··· 20 20 obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o 21 21 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o 22 22 obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o 23 + obj-$(CONFIG_NETFILTER_NETLINK_OSF) += nfnetlink_osf.o 23 24 24 25 # connection tracking 25 26 obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o ··· 101 100 obj-$(CONFIG_NFT_QUOTA) += nft_quota.o 102 101 obj-$(CONFIG_NFT_REJECT) += nft_reject.o 103 102 obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o 103 + obj-$(CONFIG_NFT_TUNNEL) += nft_tunnel.o 104 104 obj-$(CONFIG_NFT_COUNTER) += nft_counter.o 105 105 obj-$(CONFIG_NFT_LOG) += nft_log.o 106 106 obj-$(CONFIG_NFT_MASQ) += nft_masq.o ··· 110 108 obj-$(CONFIG_NFT_FIB) += nft_fib.o 111 109 obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o 112 110 obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o 113 - obj-$(CONFIG_NF_OSF) += nf_osf.o 114 111 obj-$(CONFIG_NFT_SOCKET) += nft_socket.o 112 + obj-$(CONFIG_NFT_OSF) += nft_osf.o 113 + obj-$(CONFIG_NFT_TPROXY) += nft_tproxy.o 115 114 116 115 # nf_tables netdev 117 116 obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
+6 -23
net/netfilter/nf_conntrack_core.c
··· 2022 2022 return net_eq(nf_ct_net(i), data); 2023 2023 } 2024 2024 2025 - void 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 - } 2033 - EXPORT_SYMBOL_GPL(nf_ct_free_hashtable); 2034 - 2035 2025 void nf_conntrack_cleanup_start(void) 2036 2026 { 2037 2027 conntrack_gc_work.exiting = true; ··· 2032 2042 { 2033 2043 RCU_INIT_POINTER(nf_ct_hook, NULL); 2034 2044 cancel_delayed_work_sync(&conntrack_gc_work.dwork); 2035 - nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size); 2045 + kvfree(nf_conntrack_hash); 2036 2046 2037 2047 nf_conntrack_proto_fini(); 2038 2048 nf_conntrack_seqadj_fini(); ··· 2098 2108 { 2099 2109 struct hlist_nulls_head *hash; 2100 2110 unsigned int nr_slots, i; 2101 - size_t sz; 2102 2111 2103 2112 if (*sizep > (UINT_MAX / sizeof(struct hlist_nulls_head))) 2104 2113 return NULL; ··· 2105 2116 BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head)); 2106 2117 nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head)); 2107 2118 2108 - if (nr_slots > (UINT_MAX / sizeof(struct hlist_nulls_head))) 2109 - return NULL; 2110 - 2111 - sz = nr_slots * sizeof(struct hlist_nulls_head); 2112 - hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 2113 - get_order(sz)); 2114 - if (!hash) 2115 - hash = vzalloc(sz); 2119 + hash = kvmalloc_array(nr_slots, sizeof(struct hlist_nulls_head), 2120 + GFP_KERNEL | __GFP_ZERO); 2116 2121 2117 2122 if (hash && nulls) 2118 2123 for (i = 0; i < nr_slots; i++) ··· 2133 2150 2134 2151 old_size = nf_conntrack_htable_size; 2135 2152 if (old_size == hashsize) { 2136 - nf_ct_free_hashtable(hash, hashsize); 2153 + kvfree(hash); 2137 2154 return 0; 2138 2155 } 2139 2156 ··· 2169 2186 local_bh_enable(); 2170 2187 2171 2188 synchronize_net(); 2172 - nf_ct_free_hashtable(old_hash, old_size); 2189 + kvfree(old_hash); 2173 2190 return 0; 2174 2191 } 2175 2192 ··· 2333 2350 err_expect: 2334 2351 kmem_cache_destroy(nf_conntrack_cachep); 2335 2352 err_cachep: 2336 - nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size); 2353 + kvfree(nf_conntrack_hash); 2337 2354 return ret; 2338 2355 } 2339 2356
+1 -1
net/netfilter/nf_conntrack_expect.c
··· 712 712 { 713 713 rcu_barrier(); /* Wait for call_rcu() before destroy */ 714 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 }
+2 -2
net/netfilter/nf_conntrack_helper.c
··· 562 562 563 563 return 0; 564 564 out_extend: 565 - nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); 565 + kvfree(nf_ct_helper_hash); 566 566 return ret; 567 567 } 568 568 569 569 void nf_conntrack_helper_fini(void) 570 570 { 571 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 }
+3 -4
net/netfilter/nf_conntrack_proto.c
··· 940 940 { 941 941 unsigned int i; 942 942 943 - nf_ct_l4proto_unregister(builtin_l4proto, 944 - ARRAY_SIZE(builtin_l4proto)); 945 943 nf_unregister_sockopt(&so_getorigdst); 946 944 #if IS_ENABLED(CONFIG_IPV6) 947 945 nf_unregister_sockopt(&so_getorigdst6); 948 946 #endif 949 - 950 - /* free l3proto protocol tables */ 947 + /* No need to call nf_ct_l4proto_unregister(), the register 948 + * tables are free'd here anyway. 949 + */ 951 950 for (i = 0; i < ARRAY_SIZE(nf_ct_protos); i++) 952 951 kfree(nf_ct_protos[i]); 953 952 }
+2 -2
net/netfilter/nf_nat_core.c
··· 1056 1056 1057 1057 ret = nf_ct_extend_register(&nat_extend); 1058 1058 if (ret < 0) { 1059 - nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size); 1059 + kvfree(nf_nat_bysource); 1060 1060 pr_err("Unable to register extension\n"); 1061 1061 return ret; 1062 1062 } ··· 1094 1094 for (i = 0; i < NFPROTO_NUMPROTO; i++) 1095 1095 kfree(nf_nat_l4protos[i]); 1096 1096 synchronize_net(); 1097 - nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size); 1097 + kvfree(nf_nat_bysource); 1098 1098 unregister_pernet_subsys(&nat_net_ops); 1099 1099 } 1100 1100
+12 -23
net/netfilter/nf_tables_api.c
··· 1442 1442 static int nft_chain_parse_hook(struct net *net, 1443 1443 const struct nlattr * const nla[], 1444 1444 struct nft_chain_hook *hook, u8 family, 1445 - bool create) 1445 + bool autoload) 1446 1446 { 1447 1447 struct nlattr *ha[NFTA_HOOK_MAX + 1]; 1448 1448 const struct nft_chain_type *type; ··· 1467 1467 type = chain_type[family][NFT_CHAIN_T_DEFAULT]; 1468 1468 if (nla[NFTA_CHAIN_TYPE]) { 1469 1469 type = nf_tables_chain_type_lookup(net, nla[NFTA_CHAIN_TYPE], 1470 - family, create); 1470 + family, autoload); 1471 1471 if (IS_ERR(type)) 1472 1472 return PTR_ERR(type); 1473 1473 } ··· 1534 1534 } 1535 1535 1536 1536 static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, 1537 - u8 policy, bool create) 1537 + u8 policy) 1538 1538 { 1539 1539 const struct nlattr * const *nla = ctx->nla; 1540 1540 struct nft_table *table = ctx->table; ··· 1552 1552 struct nft_chain_hook hook; 1553 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 1556 if (err < 0) 1557 1557 return err; 1558 1558 ··· 1643 1643 return err; 1644 1644 } 1645 1645 1646 - static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, 1647 - bool create) 1646 + static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy) 1648 1647 { 1649 1648 const struct nlattr * const *nla = ctx->nla; 1650 1649 struct nft_table *table = ctx->table; ··· 1660 1661 return -EBUSY; 1661 1662 1662 1663 err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family, 1663 - create); 1664 + false); 1664 1665 if (err < 0) 1665 1666 return err; 1666 1667 ··· 1760 1761 u8 policy = NF_ACCEPT; 1761 1762 struct nft_ctx ctx; 1762 1763 u64 handle = 0; 1763 - bool create; 1764 - 1765 - create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 1766 1764 1767 1765 lockdep_assert_held(&net->nft.commit_mutex); 1768 1766 ··· 1824 1828 if (nlh->nlmsg_flags & NLM_F_REPLACE) 1825 1829 return -EOPNOTSUPP; 1826 1830 1827 - return nf_tables_updchain(&ctx, genmask, policy, create); 1831 + return nf_tables_updchain(&ctx, genmask, policy); 1828 1832 } 1829 1833 1830 - return nf_tables_addchain(&ctx, family, genmask, policy, create); 1834 + return nf_tables_addchain(&ctx, family, genmask, policy); 1831 1835 } 1832 1836 1833 1837 static int nf_tables_delchain(struct net *net, struct sock *nlsk, ··· 2525 2529 struct nlattr *tmp; 2526 2530 unsigned int size, i, n, ulen = 0, usize = 0; 2527 2531 int err, rem; 2528 - bool create; 2529 2532 u64 handle, pos_handle; 2530 2533 2531 2534 lockdep_assert_held(&net->nft.commit_mutex); 2532 - 2533 - create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 2534 2535 2535 2536 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask); 2536 2537 if (IS_ERR(table)) { ··· 2558 2565 else 2559 2566 return -EOPNOTSUPP; 2560 2567 } else { 2561 - if (!create || nlh->nlmsg_flags & NLM_F_REPLACE) 2568 + if (!(nlh->nlmsg_flags & NLM_F_CREATE) || 2569 + nlh->nlmsg_flags & NLM_F_REPLACE) 2562 2570 return -EINVAL; 2563 2571 handle = nf_tables_alloc_handle(table); 2564 2572 ··· 3355 3361 struct nft_ctx ctx; 3356 3362 char *name; 3357 3363 unsigned int size; 3358 - bool create; 3359 3364 u64 timeout; 3360 3365 u32 ktype, dtype, flags, policy, gc_int, objtype; 3361 3366 struct nft_set_desc desc; ··· 3454 3461 if (err < 0) 3455 3462 return err; 3456 3463 } 3457 - 3458 - create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 3459 3464 3460 3465 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family, genmask); 3461 3466 if (IS_ERR(table)) { ··· 4020 4029 const struct nlattr *attr) 4021 4030 { 4022 4031 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; 4023 - const struct nft_set_ext *ext; 4024 4032 struct nft_data_desc desc; 4025 4033 struct nft_set_elem elem; 4026 4034 struct sk_buff *skb; ··· 4053 4063 return PTR_ERR(priv); 4054 4064 4055 4065 elem.priv = priv; 4056 - ext = nft_set_elem_ext(set, &elem); 4057 4066 4058 4067 err = -ENOMEM; 4059 4068 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); ··· 5929 5940 if (!net) 5930 5941 return 0; 5931 5942 5932 - nfnl_lock(NFNL_SUBSYS_NFTABLES); 5943 + mutex_lock(&net->nft.commit_mutex); 5933 5944 list_for_each_entry(table, &net->nft.tables, list) { 5934 5945 list_for_each_entry(flowtable, &table->flowtables, list) { 5935 5946 nft_flowtable_event(event, dev, flowtable); 5936 5947 } 5937 5948 } 5938 - nfnl_unlock(NFNL_SUBSYS_NFTABLES); 5949 + mutex_unlock(&net->nft.commit_mutex); 5939 5950 put_net(net); 5940 5951 return NOTIFY_DONE; 5941 5952 }
+15 -1
net/netfilter/nf_tables_core.c
··· 120 120 struct nft_rule *const *rules; 121 121 }; 122 122 123 + static 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 + 123 137 unsigned int 124 138 nft_do_chain(struct nft_pktinfo *pkt, void *priv) 125 139 { ··· 167 153 nft_cmp_fast_eval(expr, &regs); 168 154 else if (expr->ops != &nft_payload_fast_ops || 169 155 !nft_payload_fast_eval(expr, &regs, pkt)) 170 - expr->ops->eval(expr, &regs, pkt); 156 + expr_call_ops_eval(expr, &regs, pkt); 171 157 172 158 if (regs.verdict.code != NFT_CONTINUE) 173 159 break;
+3 -3
net/netfilter/nft_lookup.c
··· 26 26 struct nft_set_binding binding; 27 27 }; 28 28 29 - static void nft_lookup_eval(const struct nft_expr *expr, 30 - struct nft_regs *regs, 31 - const struct nft_pktinfo *pkt) 29 + void nft_lookup_eval(const struct nft_expr *expr, 30 + struct nft_regs *regs, 31 + const struct nft_pktinfo *pkt) 32 32 { 33 33 const struct nft_lookup *priv = nft_expr_priv(expr); 34 34 const struct nft_set *set = priv->set;
+3 -3
net/netfilter/nft_meta.c
··· 41 41 #include "../bridge/br_private.h" 42 42 #endif 43 43 44 - static void nft_meta_get_eval(const struct nft_expr *expr, 45 - struct nft_regs *regs, 46 - const struct nft_pktinfo *pkt) 44 + void nft_meta_get_eval(const struct nft_expr *expr, 45 + struct nft_regs *regs, 46 + const struct nft_pktinfo *pkt) 47 47 { 48 48 const struct nft_meta *priv = nft_expr_priv(expr); 49 49 const struct sk_buff *skb = pkt->skb;
+1 -3
net/netfilter/nft_numgen.c
··· 237 237 priv->map = nft_set_lookup_global(ctx->net, ctx->table, 238 238 tb[NFTA_NG_SET_NAME], 239 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 246 244 static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr *expr)
+106
net/netfilter/nft_osf.c
··· 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 + 9 + struct nft_osf { 10 + enum nft_registers dreg:8; 11 + }; 12 + 13 + static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = { 14 + [NFTA_OSF_DREG] = { .type = NLA_U32 }, 15 + }; 16 + 17 + static 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 + 45 + static 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 + 61 + static 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 + 70 + nla_put_failure: 71 + return -1; 72 + } 73 + 74 + static struct nft_expr_type nft_osf_type; 75 + static 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 + 83 + static 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 + 91 + static int __init nft_osf_module_init(void) 92 + { 93 + return nft_register_expr(&nft_osf_type); 94 + } 95 + 96 + static void __exit nft_osf_module_exit(void) 97 + { 98 + return nft_unregister_expr(&nft_osf_type); 99 + } 100 + 101 + module_init(nft_osf_module_init); 102 + module_exit(nft_osf_module_exit); 103 + 104 + MODULE_LICENSE("GPL"); 105 + MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>"); 106 + MODULE_ALIAS_NFT_EXPR("osf");
+316
net/netfilter/nft_tproxy.c
··· 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 + 15 + struct nft_tproxy { 16 + enum nft_registers sreg_addr:8; 17 + enum nft_registers sreg_port:8; 18 + u8 family; 19 + }; 20 + 21 + static 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) 78 + static 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 + 148 + static 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 + 176 + static 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 + 182 + static 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 + 264 + static 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 + 283 + static struct nft_expr_type nft_tproxy_type; 284 + static 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 + 292 + static 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 + 300 + static int __init nft_tproxy_module_init(void) 301 + { 302 + return nft_register_expr(&nft_tproxy_type); 303 + } 304 + 305 + static void __exit nft_tproxy_module_exit(void) 306 + { 307 + nft_unregister_expr(&nft_tproxy_type); 308 + } 309 + 310 + module_init(nft_tproxy_module_init); 311 + module_exit(nft_tproxy_module_exit); 312 + 313 + MODULE_LICENSE("GPL"); 314 + MODULE_AUTHOR("Máté Eckl"); 315 + MODULE_DESCRIPTION("nf_tables tproxy support module"); 316 + MODULE_ALIAS_NFT_EXPR("tproxy");
+566
net/netfilter/nft_tunnel.c
··· 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 + 15 + struct nft_tunnel { 16 + enum nft_tunnel_keys key:8; 17 + enum nft_registers dreg:8; 18 + }; 19 + 20 + static 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 + 47 + static 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 + 52 + static 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 + 81 + static 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 + 92 + nla_put_failure: 93 + return -1; 94 + } 95 + 96 + static struct nft_expr_type nft_tunnel_type; 97 + static 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 + 105 + static 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 + 113 + struct 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 + 122 + struct nft_tunnel_obj { 123 + struct metadata_dst *md; 124 + struct nft_tunnel_opts opts; 125 + }; 126 + 127 + static 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 + 132 + static 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 + 155 + static 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 + 161 + static 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 + 194 + static 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 + 198 + static 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 + 220 + static 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 + 226 + static 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 + 269 + static 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 + 274 + static 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 + 300 + static 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 + 310 + static 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 + 386 + static 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 + 398 + static 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 + 428 + static 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 + 463 + static 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 + 473 + static 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 + 491 + static 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 + 509 + nla_put_failure: 510 + return -1; 511 + } 512 + 513 + static 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 + 521 + static struct nft_object_type nft_tunnel_obj_type; 522 + static 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 + 531 + static 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 + 539 + static 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 + 554 + static 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 + 560 + module_init(nft_tunnel_module_init); 561 + module_exit(nft_tunnel_module_exit); 562 + 563 + MODULE_LICENSE("GPL"); 564 + MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 565 + MODULE_ALIAS_NFT_EXPR("tunnel"); 566 + MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL);
+1 -3
net/netfilter/xt_connlimit.c
··· 93 93 94 94 /* init private data */ 95 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 102 100 static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
+3 -146
net/netfilter/xt_osf.c
··· 37 37 #include <net/netfilter/nf_log.h> 38 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 - */ 44 - static struct list_head xt_osf_fingers[2]; 45 - 46 - static const struct nla_policy xt_osf_policy[OSF_ATTR_MAX + 1] = { 47 - [OSF_ATTR_FINGER] = { .len = sizeof(struct xt_osf_user_finger) }, 48 - }; 49 - 50 - static 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 - 97 - static 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 - 132 - static 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 - 145 - static 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 - 152 40 static bool 153 41 xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) 154 42 { ··· 47 159 return false; 48 160 49 161 return nf_osf_match(skb, xt_family(p), xt_hooknum(p), xt_in(p), 50 - xt_out(p), info, net, xt_osf_fingers); 162 + xt_out(p), info, net, nf_osf_fingers); 51 163 } 52 164 53 165 static struct xt_match xt_osf_match = { ··· 65 177 66 178 static int __init xt_osf_init(void) 67 179 { 68 - int err = -EINVAL; 69 - int i; 70 - 71 - for (i=0; i<ARRAY_SIZE(xt_osf_fingers); ++i) 72 - INIT_LIST_HEAD(&xt_osf_fingers[i]); 73 - 74 - err = nfnetlink_subsys_register(&xt_osf_nfnetlink); 75 - if (err < 0) { 76 - pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err); 77 - goto err_out_exit; 78 - } 180 + int err; 79 181 80 182 err = xt_register_match(&xt_osf_match); 81 183 if (err) { 82 184 pr_err("Failed to register OS fingerprint " 83 185 "matching module (%d)\n", err); 84 - goto err_out_remove; 186 + return err; 85 187 } 86 188 87 189 return 0; 88 - 89 - err_out_remove: 90 - nfnetlink_subsys_unregister(&xt_osf_nfnetlink); 91 - err_out_exit: 92 - return err; 93 190 } 94 191 95 192 static void __exit xt_osf_fini(void) 96 193 { 97 - struct xt_osf_finger *f; 98 - int i; 99 - 100 - nfnetlink_subsys_unregister(&xt_osf_nfnetlink); 101 194 xt_unregister_match(&xt_osf_match); 102 - 103 - rcu_read_lock(); 104 - for (i=0; i<ARRAY_SIZE(xt_osf_fingers); ++i) { 105 - 106 - list_for_each_entry_rcu(f, &xt_osf_fingers[i], finger_entry) { 107 - list_del_rcu(&f->finger_entry); 108 - kfree_rcu(f, rcu_head); 109 - } 110 - } 111 - rcu_read_unlock(); 112 - 113 - rcu_barrier(); 114 195 } 115 196 116 197 module_init(xt_osf_init);