History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says: ==================== Netfilter/IPVS updates for net-next The following patchset contains Netfilter/IPVS updates for your net-next tree. Basically, a new extension for ip6tables, simplification work of nf_tables that saves us 500 LoC, allow raw table registration before defragmentation, conversion of the SNMP helper to use the ASN.1 code generator, unique 64-bit handle for all nf_tables objects and fixes to address fallout from previous nf-next batch. More specifically, they are: 1) Seven patches to remove family abstraction layer (struct nft_af_info) in nf_tables, this simplifies our codebase and it saves us 64 bytes per net namespace. 2) Add IPv6 segment routing header matching for ip6tables, from Ahmed Abdelsalam. 3) Allow to register iptable_raw table before defragmentation, some people do not want to waste cycles on defragmenting traffic that is going to be dropped, hence add a new module parameter to enable this behaviour in iptables and ip6tables. From Subash Abhinov Kasiviswanathan. This patch needed a couple of follow up patches to get things tidy from Arnd Bergmann. 4) SNMP helper uses the ASN.1 code generator, from Taehee Yoo. Several patches for this helper to prepare this change are also part of this patch series. 5) Add 64-bit handles to uniquely objects in nf_tables, from Harsha Sharma. 6) Remove log message that several netfilter subsystems print at boot/load time. 7) Restore x_tables module autoloading, that got broken in a previous patch to allow singleton NAT hook callback registration per hook spot, from Florian Westphal. Moreover, return EBUSY to report that the singleton NAT hook slot is already in instead. 8) Several fixes for the new nf_tables flowtable representation, including incorrect error check after nf_tables_flowtable_lookup(), missing Kconfig dependencies that lead to build breakage and missing initialization of priority and hooknum in flowtable object. 9) Missing NETFILTER_FAMILY_ARP dependency in Kconfig for the clusterip target. This is due to recent updates in the core to shrink the hook array size and compile it out if no specific family is enabled via .config file. Patch from Florian Westphal. 10) Remove duplicated include header files, from Wei Yongjun. 11) Sparse warning fix for the NFPROTO_INET handling from the core due to missing static function definition, also from Wei Yongjun. 12) Restore ICMPv6 Parameter Problem error reporting when defragmentation fails, from Subash Abhinov Kasiviswanathan. 13) Remove obsolete owner field initialization from struct file_operations, patch from Alexey Dobriyan. 14) Use boolean datatype where needed in the Netfilter codebase, from Gustavo A. R. Silva. 15) Remove double semicolon in dynset nf_tables expression, from Luis de Bethencourt. ====================

David S. Miller committed 8 years ago

Commit cbcbeed2 parents ea9722e e55311662 files · +1241 −2226Browse files

Unified · Split

62 files
  1. include/net/netfilter/nf_tables.h +14 −34
  2. include/net/netns/nftables.h +1 −7
  3. include/uapi/linux/netfilter/nf_tables.h +10 −0
  4. include/uapi/linux/netfilter_ipv4.h +1 −0
  5. include/uapi/linux/netfilter_ipv6.h +1 −0
  6. include/uapi/linux/netfilter_ipv6/ip6t_srh.h +57 −0
  7. net/bridge/netfilter/ebtables.c +0 −2
  8. net/bridge/netfilter/nf_tables_bridge.c +2 −52
  9. net/ipv4/netfilter/Kconfig +4 −1
  10. net/ipv4/netfilter/Makefile +6 −0
  11. net/ipv4/netfilter/arp_tables.c +0 −1
  12. net/ipv4/netfilter/ip_tables.c +0 −1
  13. net/ipv4/netfilter/iptable_raw.c +28 −3
  14. net/ipv4/netfilter/nf_defrag_ipv4.c +2 −0
  15. net/ipv4/netfilter/nf_nat_snmp_basic.asn1 +177 −0
  16. net/ipv4/netfilter/nf_nat_snmp_basic.c +0 −1286
  17. net/ipv4/netfilter/nf_nat_snmp_basic_main.c +235 −0
  18. net/ipv4/netfilter/nf_tables_arp.c +2 −47
  19. net/ipv4/netfilter/nf_tables_ipv4.c +2 −47
  20. net/ipv6/netfilter/Kconfig +11 −1
  21. net/ipv6/netfilter/Makefile +1 −0
  22. net/ipv6/netfilter/ip6_tables.c +0 −1
  23. net/ipv6/netfilter/ip6t_srh.c +161 −0
  24. net/ipv6/netfilter/ip6table_raw.c +28 −3
  25. net/ipv6/netfilter/nf_conntrack_reasm.c +10 −5
  26. net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +3 −0
  27. net/ipv6/netfilter/nf_flow_table_ipv6.c +0 −1
  28. net/ipv6/netfilter/nf_tables_ipv6.c +2 −47
  29. net/netfilter/Kconfig +4 −2
  30. net/netfilter/core.c +3 −3
  31. net/netfilter/ipset/ip_set_core.c +2 −1
  32. net/netfilter/ipvs/ip_vs_app.c +0 −1
  33. net/netfilter/ipvs/ip_vs_conn.c +0 −2
  34. net/netfilter/ipvs/ip_vs_ctl.c +0 −3
  35. net/netfilter/nf_conncount.c +1 −1
  36. net/netfilter/nf_conntrack_core.c +0 −6
  37. net/netfilter/nf_conntrack_expect.c +0 −1
  38. net/netfilter/nf_conntrack_netlink.c +0 −5
  39. net/netfilter/nf_conntrack_standalone.c +0 −2
  40. net/netfilter/nf_log.c +0 −1
  41. net/netfilter/nf_queue.c +0 −2
  42. net/netfilter/nf_synproxy_core.c +0 −1
  43. net/netfilter/nf_tables_api.c +428 −504
  44. net/netfilter/nf_tables_inet.c +2 −47
  45. net/netfilter/nf_tables_netdev.c +13 −57
  46. net/netfilter/nfnetlink.c +0 −4
  47. net/netfilter/nfnetlink_acct.c +0 −2
  48. net/netfilter/nfnetlink_cttimeout.c +0 −2
  49. net/netfilter/nfnetlink_log.c +0 −1
  50. net/netfilter/nfnetlink_queue.c +0 −1
  51. net/netfilter/nft_compat.c +8 −10
  52. net/netfilter/nft_ct.c +8 −8
  53. net/netfilter/nft_dynset.c +1 −1
  54. net/netfilter/nft_flow_offload.c +2 −2
  55. net/netfilter/nft_log.c +2 −2
  56. net/netfilter/nft_masq.c +1 −1
  57. net/netfilter/nft_meta.c +2 −2
  58. net/netfilter/nft_nat.c +1 −1
  59. net/netfilter/nft_redir.c +1 −1
  60. net/netfilter/x_tables.c +2 −5
  61. net/netfilter/xt_hashlimit.c +1 −4
  62. net/netfilter/xt_ipcomp.c +1 −1
include/net/netfilter/nf_tables.h+14−34
@@ -143,22 +143,22 @@ static inline void nft_data_debug(const struct nft_data *data) · 142 unmodified lines
143143 * struct nft_ctx - nf_tables rule/set context
144144 *
145145 * @net: net namespace
146− * @afi: address family info
147146 * @table: the table the chain is contained in
148147 * @chain: the chain the rule is contained in
149148 * @nla: netlink attributes
150149 * @portid: netlink portID of the original message
151150 * @seq: netlink sequence number
151+ * @family: protocol family
152152 * @report: notify via unicast netlink message
153153 */
154154 struct nft_ctx {
155155 struct net *net;
156− struct nft_af_info *afi;
157156 struct nft_table *table;
158157 struct nft_chain *chain;
159158 const struct nlattr * const *nla;
160159 u32 portid;
161160 u32 seq;
161+ u8 family;
162162 bool report;
163163 };
164164
@@ -374,6 +374,7 @@ void nft_unregister_set(struct nft_set_type *type); · 209 unmodified lines
374374 * @list: table set list node
375375 * @bindings: list of set bindings
376376 * @name: name of the set
377+ * @handle: unique handle of the set
377378 * @ktype: key type (numeric type defined by userspace, not used in the kernel)
378379 * @dtype: data type (verdict or numeric type defined by userspace)
379380 * @objtype: object type (see NFT_OBJECT_* definitions)
@@ -396,6 +397,7 @@ struct nft_set { · 16 unmodified lines
396397 struct list_head list;
397398 struct list_head bindings;
398399 char *name;
400+ u64 handle;
399401 u32 ktype;
400402 u32 dtype;
401403 u32 objtype;
@@ -946,9 +948,11 @@ unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv); · 544 unmodified lines
946948 * @objects: stateful objects in the table
947949 * @flowtables: flow tables in the table
948950 * @hgenerator: handle generator state
951+ * @handle: table handle
949952 * @use: number of chain references to this table
950953 * @flags: table flag (see enum nft_table_flags)
951954 * @genmask: generation mask
955+ * @afinfo: address family info
952956 * @name: name of the table
953957 */
954958 struct nft_table {
@@ -958,38 +962,14 @@ struct nft_table { · 3 unmodified lines
958962 struct list_head objects;
959963 struct list_head flowtables;
960964 u64 hgenerator;
965+ u64 handle;
961966 u32 use;
962− u16 flags:14,
967+ u16 family:6,
968+ flags:8,
963969 genmask:2;
964970 char *name;
965971 };
966972
967−enum nft_af_flags {
968− NFT_AF_NEEDS_DEV = (1 << 0),
969−};
970−
971−/**
972− * struct nft_af_info - nf_tables address family info
973− *
974− * @list: used internally
975− * @family: address family
976− * @nhooks: number of hooks in this family
977− * @owner: module owner
978− * @tables: used internally
979− * @flags: family flags
980− */
981−struct nft_af_info {
982− struct list_head list;
983− int family;
984− unsigned int nhooks;
985− struct module *owner;
986− struct list_head tables;
987− u32 flags;
988−};
989−
990−int nft_register_afinfo(struct net *, struct nft_af_info *);
991−void nft_unregister_afinfo(struct net *, struct nft_af_info *);
992−
993973 int nft_register_chain_type(const struct nf_chain_type *);
994974 void nft_unregister_chain_type(const struct nf_chain_type *);
995975
@@ -1007,9 +987,9 @@ int nft_verdict_dump(struct sk_buff *skb, int type, · 11 unmodified lines
1007987 * @name: name of this stateful object
1008988 * @genmask: generation mask
1009989 * @use: number of references to this stateful object
1010− * @data: object data, layout depends on type
990+ * @handle: unique object handle
1011991 * @ops: object operations
1012− * @data: pointer to object data
992+ * @data: object data, layout depends on type
1013993 */
1014994 struct nft_object {
1015995 struct list_head list;
@@ -1017,6 +997,7 @@ struct nft_object { · 1 unmodified line
1017997 struct nft_table *table;
1018998 u32 genmask:2,
1019999 use:30;
1000+ u64 handle;
10201001 /* runtime data below here */
10211002 const struct nft_object_ops *ops ____cacheline_aligned;
10221003 unsigned char data[]
@@ -1098,6 +1079,7 @@ void nft_unregister_obj(struct nft_object_type *obj_type); · 75 unmodified lines
10981079 * @ops_len: number of hooks in array
10991080 * @genmask: generation mask
11001081 * @use: number of references to this flow table
1082+ * @handle: unique object handle
11011083 * @data: rhashtable and garbage collector
11021084 * @ops: array of hooks
11031085 */
@@ -1110,6 +1092,7 @@ struct nft_flowtable { · 6 unmodified lines
11101092 int ops_len;
11111093 u32 genmask:2,
11121094 use:30;
1095+ u64 handle;
11131096 /* runtime data below here */
11141097 struct nf_hook_ops *ops ____cacheline_aligned;
11151098 struct nf_flowtable data;
@@ -1154,9 +1137,6 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, · 38 unmodified lines
11541137
11551138 void nft_trace_notify(struct nft_traceinfo *info);
11561139
1157−#define MODULE_ALIAS_NFT_FAMILY(family) \
1158− MODULE_ALIAS("nft-afinfo-" __stringify(family))
1159−
11601140 #define MODULE_ALIAS_NFT_CHAIN(family, name) \
11611141 MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
11621142
include/net/netns/nftables.h+1−7
@@ -7,14 +7,8 @@ · 6 unmodified lines
77 struct nft_af_info;
88
99 struct netns_nftables {
10− struct list_head af_info;
10+ struct list_head tables;
1111 struct list_head commit_list;
12− struct nft_af_info *ipv4;
13− struct nft_af_info *ipv6;
14− struct nft_af_info *inet;
15− struct nft_af_info *arp;
16− struct nft_af_info *bridge;
17− struct nft_af_info *netdev;
1812 unsigned int base_seq;
1913 u8 gencursor;
2014 };
include/uapi/linux/netfilter/nf_tables.h+10−0
@@ -174,6 +174,8 @@ enum nft_table_attributes { · 173 unmodified lines
174174 NFTA_TABLE_NAME,
175175 NFTA_TABLE_FLAGS,
176176 NFTA_TABLE_USE,
177+ NFTA_TABLE_HANDLE,
178+ NFTA_TABLE_PAD,
177179 __NFTA_TABLE_MAX
178180 };
179181 #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
@@ -317,6 +319,7 @@ enum nft_set_desc_attributes { · 137 unmodified lines
317319 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
318320 * @NFTA_SET_USERDATA: user data (NLA_BINARY)
319321 * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
322+ * @NFTA_SET_HANDLE: set handle (NLA_U64)
320323 */
321324 enum nft_set_attributes {
322325 NFTA_SET_UNSPEC,
@@ -335,6 +338,7 @@ enum nft_set_attributes { · 12 unmodified lines
335338 NFTA_SET_USERDATA,
336339 NFTA_SET_PAD,
337340 NFTA_SET_OBJ_TYPE,
341+ NFTA_SET_HANDLE,
338342 __NFTA_SET_MAX
339343 };
340344 #define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -1314,6 +1318,7 @@ enum nft_ct_helper_attributes { · 973 unmodified lines
13141318 * @NFTA_OBJ_TYPE: stateful object type (NLA_U32)
13151319 * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
13161320 * @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
1321+ * @NFTA_OBJ_HANDLE: object handle (NLA_U64)
13171322 */
13181323 enum nft_object_attributes {
13191324 NFTA_OBJ_UNSPEC,
@@ -1322,6 +1327,8 @@ enum nft_object_attributes { · 2 unmodified lines
13221327 NFTA_OBJ_TYPE,
13231328 NFTA_OBJ_DATA,
13241329 NFTA_OBJ_USE,
1330+ NFTA_OBJ_HANDLE,
1331+ NFTA_OBJ_PAD,
13251332 __NFTA_OBJ_MAX
13261333 };
13271334 #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
@@ -1333,6 +1340,7 @@ enum nft_object_attributes { · 5 unmodified lines
13331340 * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING)
13341341 * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
13351342 * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
1343+ * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
13361344 */
13371345 enum nft_flowtable_attributes {
13381346 NFTA_FLOWTABLE_UNSPEC,
@@ -1340,6 +1348,8 @@ enum nft_flowtable_attributes { · 1 unmodified line
13401348 NFTA_FLOWTABLE_NAME,
13411349 NFTA_FLOWTABLE_HOOK,
13421350 NFTA_FLOWTABLE_USE,
1351+ NFTA_FLOWTABLE_HANDLE,
1352+ NFTA_FLOWTABLE_PAD,
13431353 __NFTA_FLOWTABLE_MAX
13441354 };
13451355 #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1)
include/uapi/linux/netfilter_ipv4.h+1−0
@@ -57,6 +57,7 @@ · 56 unmodified lines
5757
5858 enum nf_ip_hook_priorities {
5959 NF_IP_PRI_FIRST = INT_MIN,
60+ NF_IP_PRI_RAW_BEFORE_DEFRAG = -450,
6061 NF_IP_PRI_CONNTRACK_DEFRAG = -400,
6162 NF_IP_PRI_RAW = -300,
6263 NF_IP_PRI_SELINUX_FIRST = -225,
include/uapi/linux/netfilter_ipv6.h+1−0
@@ -62,6 +62,7 @@ · 61 unmodified lines
6262
6363 enum nf_ip6_hook_priorities {
6464 NF_IP6_PRI_FIRST = INT_MIN,
65+ NF_IP6_PRI_RAW_BEFORE_DEFRAG = -450,
6566 NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
6667 NF_IP6_PRI_RAW = -300,
6768 NF_IP6_PRI_SELINUX_FIRST = -225,
include/uapi/linux/netfilter_ipv6/ip6t_srh.h+57−0
@@ -0,0 +1,57 @@
1+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+#ifndef _IP6T_SRH_H
3+#define _IP6T_SRH_H
4+
5+#include <linux/types.h>
6+#include <linux/netfilter.h>
7+
8+/* Values for "mt_flags" field in struct ip6t_srh */
9+#define IP6T_SRH_NEXTHDR 0x0001
10+#define IP6T_SRH_LEN_EQ 0x0002
11+#define IP6T_SRH_LEN_GT 0x0004
12+#define IP6T_SRH_LEN_LT 0x0008
13+#define IP6T_SRH_SEGS_EQ 0x0010
14+#define IP6T_SRH_SEGS_GT 0x0020
15+#define IP6T_SRH_SEGS_LT 0x0040
16+#define IP6T_SRH_LAST_EQ 0x0080
17+#define IP6T_SRH_LAST_GT 0x0100
18+#define IP6T_SRH_LAST_LT 0x0200
19+#define IP6T_SRH_TAG 0x0400
20+#define IP6T_SRH_MASK 0x07FF
21+
22+/* Values for "mt_invflags" field in struct ip6t_srh */
23+#define IP6T_SRH_INV_NEXTHDR 0x0001
24+#define IP6T_SRH_INV_LEN_EQ 0x0002
25+#define IP6T_SRH_INV_LEN_GT 0x0004
26+#define IP6T_SRH_INV_LEN_LT 0x0008
27+#define IP6T_SRH_INV_SEGS_EQ 0x0010
28+#define IP6T_SRH_INV_SEGS_GT 0x0020
29+#define IP6T_SRH_INV_SEGS_LT 0x0040
30+#define IP6T_SRH_INV_LAST_EQ 0x0080
31+#define IP6T_SRH_INV_LAST_GT 0x0100
32+#define IP6T_SRH_INV_LAST_LT 0x0200
33+#define IP6T_SRH_INV_TAG 0x0400
34+#define IP6T_SRH_INV_MASK 0x07FF
35+
36+/**
37+ * struct ip6t_srh - SRH match options
38+ * @ next_hdr: Next header field of SRH
39+ * @ hdr_len: Extension header length field of SRH
40+ * @ segs_left: Segments left field of SRH
41+ * @ last_entry: Last entry field of SRH
42+ * @ tag: Tag field of SRH
43+ * @ mt_flags: match options
44+ * @ mt_invflags: Invert the sense of match options
45+ */
46+
47+struct ip6t_srh {
48+ __u8 next_hdr;
49+ __u8 hdr_len;
50+ __u8 segs_left;
51+ __u8 last_entry;
52+ __u16 tag;
53+ __u16 mt_flags;
54+ __u16 mt_invflags;
55+};
56+
57+#endif /*_IP6T_SRH_H*/
net/bridge/netfilter/ebtables.c+0−2
@@ -2445,7 +2445,6 @@ static int __init ebtables_init(void) · 2444 unmodified lines
24452445 return ret;
24462446 }
24472447
2448− printk(KERN_INFO "Ebtables v2.0 registered\n");
24492448 return 0;
24502449 }
24512450
@@ -2453,7 +2452,6 @@ static void __exit ebtables_fini(void) · 1 unmodified line
24532452 {
24542453 nf_unregister_sockopt(&ebt_sockopts);
24552454 xt_unregister_target(&ebt_standard_target);
2456− printk(KERN_INFO "Ebtables v2.0 unregistered\n");
24572455 }
24582456
24592457 EXPORT_SYMBOL(ebt_register_table);
net/bridge/netfilter/nf_tables_bridge.c+2−52
@@ -42,40 +42,6 @@ nft_do_chain_bridge(void *priv, · 41 unmodified lines
4242 return nft_do_chain(&pkt, priv);
4343 }
4444
45−static struct nft_af_info nft_af_bridge __read_mostly = {
46− .family = NFPROTO_BRIDGE,
47− .nhooks = NF_BR_NUMHOOKS,
48− .owner = THIS_MODULE,
49−};
50−
51−static int nf_tables_bridge_init_net(struct net *net)
52−{
53− net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
54− if (net->nft.bridge == NULL)
55− return -ENOMEM;
56−
57− memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge));
58−
59− if (nft_register_afinfo(net, net->nft.bridge) < 0)
60− goto err;
61−
62− return 0;
63−err:
64− kfree(net->nft.bridge);
65− return -ENOMEM;
66−}
67−
68−static void nf_tables_bridge_exit_net(struct net *net)
69−{
70− nft_unregister_afinfo(net, net->nft.bridge);
71− kfree(net->nft.bridge);
72−}
73−
74−static struct pernet_operations nf_tables_bridge_net_ops = {
75− .init = nf_tables_bridge_init_net,
76− .exit = nf_tables_bridge_exit_net,
77−};
78−
7945 static const struct nf_chain_type filter_bridge = {
8046 .name = "filter",
8147 .type = NFT_CHAIN_T_DEFAULT,
@@ -97,27 +63,11 @@ static const struct nf_chain_type filter_bridge = { · 15 unmodified lines
9763
9864 static int __init nf_tables_bridge_init(void)
9965 {
100− int ret;
101−
102− ret = nft_register_chain_type(&filter_bridge);
103− if (ret < 0)
104− return ret;
105−
106− ret = register_pernet_subsys(&nf_tables_bridge_net_ops);
107− if (ret < 0)
108− goto err_register_subsys;
109−
110− return ret;
111−
112−err_register_subsys:
113− nft_unregister_chain_type(&filter_bridge);
114−
115− return ret;
66+ return nft_register_chain_type(&filter_bridge);
11667 }
11768
11869 static void __exit nf_tables_bridge_exit(void)
11970 {
120− unregister_pernet_subsys(&nf_tables_bridge_net_ops);
12171 nft_unregister_chain_type(&filter_bridge);
12272 }
12373
@@ -126,4 +76,4 @@ module_exit(nf_tables_bridge_exit); · 2 unmodified lines
12676
12777 MODULE_LICENSE("GPL");
12878 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
129−MODULE_ALIAS_NFT_FAMILY(AF_BRIDGE);
79+MODULE_ALIAS_NFT_CHAIN(AF_BRIDGE, "filter");
net/ipv4/netfilter/Kconfig+4−1
@@ -79,8 +79,9 @@ config NF_TABLES_ARP · 78 unmodified lines
7979 endif # NF_TABLES
8080
8181 config NF_FLOW_TABLE_IPV4
82− select NF_FLOW_TABLE
8382 tristate "Netfilter flow table IPv4 module"
83+ depends on NF_CONNTRACK && NF_TABLES
84+ select NF_FLOW_TABLE
8485 help
8586 This option adds the flow table IPv4 support.
8687
@@ -157,6 +158,7 @@ config NF_NAT_SNMP_BASIC · 70 unmodified lines
157158 depends on NF_CONNTRACK_SNMP
158159 depends on NETFILTER_ADVANCED
159160 default NF_NAT && NF_CONNTRACK_SNMP
161+ select ASN1
160162 ---help---
161163
162164 This module implements an Application Layer Gateway (ALG) for
@@ -342,6 +344,7 @@ config IP_NF_TARGET_CLUSTERIP · 179 unmodified lines
342344 depends on NF_CONNTRACK_IPV4
343345 depends on NETFILTER_ADVANCED
344346 select NF_CONNTRACK_MARK
347+ select NETFILTER_FAMILY_ARP
345348 help
346349 The CLUSTERIP target allows you to build load-balancing clusters of
347350 network servers without having a dedicated load-balancing
net/ipv4/netfilter/Makefile+6−0
@@ -27,9 +27,15 @@ obj-$(CONFIG_NF_REJECT_IPV4) += nf_reject_ipv4.o · 26 unmodified lines
2727 # NAT helpers (nf_conntrack)
2828 obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
2929 obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
30+
31+nf_nat_snmp_basic-y := nf_nat_snmp_basic-asn1.o nf_nat_snmp_basic_main.o
32+nf_nat_snmp_basic-y : nf_nat_snmp_basic-asn1.h nf_nat_snmp_basic-asn1.c
3033 obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
34+clean-files := nf_nat_snmp_basic-asn1.c nf_nat_snmp_basic-asn1.h
35+
3136 obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o
3237
38+
3339 # NAT protocols (nf_nat)
3440 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
3541
net/ipv4/netfilter/arp_tables.c+0−1
@@ -1656,7 +1656,6 @@ static int __init arp_tables_init(void) · 1655 unmodified lines
16561656 if (ret < 0)
16571657 goto err4;
16581658
1659− pr_info("arp_tables: (C) 2002 David S. Miller\n");
16601659 return 0;
16611660
16621661 err4:
net/ipv4/netfilter/ip_tables.c+0−1
@@ -1939,7 +1939,6 @@ static int __init ip_tables_init(void) · 1938 unmodified lines
19391939 if (ret < 0)
19401940 goto err5;
19411941
1942− pr_info("(C) 2000-2006 Netfilter Core Team\n");
19431942 return 0;
19441943
19451944 err5:
net/ipv4/netfilter/iptable_raw.c+28−3
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 *
44 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
55 */
6+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
67 #include <linux/module.h>
78 #include <linux/netfilter_ipv4/ip_tables.h>
89 #include <linux/slab.h>
@@ -12,6 +13,10 @@ · 3 unmodified lines
1213
1314 static int __net_init iptable_raw_table_init(struct net *net);
1415
16+static bool raw_before_defrag __read_mostly;
17+MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
18+module_param(raw_before_defrag, bool, 0000);
19+
1520 static const struct xt_table packet_raw = {
1621 .name = "raw",
1722 .valid_hooks = RAW_VALID_HOOKS,
@@ -21,6 +26,15 @@ static const struct xt_table packet_raw = { · 3 unmodified lines
2126 .table_init = iptable_raw_table_init,
2227 };
2328
29+static const struct xt_table packet_raw_before_defrag = {
30+ .name = "raw",
31+ .valid_hooks = RAW_VALID_HOOKS,
32+ .me = THIS_MODULE,
33+ .af = NFPROTO_IPV4,
34+ .priority = NF_IP_PRI_RAW_BEFORE_DEFRAG,
35+ .table_init = iptable_raw_table_init,
36+};
37+
2438 /* The work comes in here from netfilter.c. */
2539 static unsigned int
2640 iptable_raw_hook(void *priv, struct sk_buff *skb,
@@ -34,15 +48,19 @@ static struct nf_hook_ops *rawtable_ops __read_mostly; · 7 unmodified lines
3448 static int __net_init iptable_raw_table_init(struct net *net)
3549 {
3650 struct ipt_replace *repl;
51+ const struct xt_table *table = &packet_raw;
3752 int ret;
3853
54+ if (raw_before_defrag)
55+ table = &packet_raw_before_defrag;
56+
3957 if (net->ipv4.iptable_raw)
4058 return 0;
4159
42− repl = ipt_alloc_initial_table(&packet_raw);
60+ repl = ipt_alloc_initial_table(table);
4361 if (repl == NULL)
4462 return -ENOMEM;
45− ret = ipt_register_table(net, &packet_raw, repl, rawtable_ops,
63+ ret = ipt_register_table(net, table, repl, rawtable_ops,
4664 &net->ipv4.iptable_raw);
4765 kfree(repl);
4866 return ret;
@@ -63,8 +81,15 @@ static struct pernet_operations iptable_raw_net_ops = { · 14 unmodified lines
6381 static int __init iptable_raw_init(void)
6482 {
6583 int ret;
84+ const struct xt_table *table = &packet_raw;
85+
86+ if (raw_before_defrag) {
87+ table = &packet_raw_before_defrag;
88+
89+ pr_info("Enabling raw table before defrag\n");
90+ }
6691
67− rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook);
92+ rawtable_ops = xt_hook_ops_alloc(table, iptable_raw_hook);
6893 if (IS_ERR(rawtable_ops))
6994 return PTR_ERR(rawtable_ops);
7095
net/ipv4/netfilter/nf_defrag_ipv4.c+2−0
@@ -78,6 +78,8 @@ static unsigned int ipv4_conntrack_defrag(void *priv, · 77 unmodified lines
7878 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb)))
7979 return NF_ACCEPT;
8080 #endif
81+ if (skb->_nfct == IP_CT_UNTRACKED)
82+ return NF_ACCEPT;
8183 #endif
8284 /* Gather fragments. */
8385 if (ip_is_fragment(ip_hdr(skb))) {
net/ipv4/netfilter/nf_nat_snmp_basic.asn1+177−0
@@ -0,0 +1,177 @@
1+Message ::=
2+ SEQUENCE {
3+ version
4+ INTEGER ({snmp_version}),
5+
6+ community
7+ OCTET STRING,
8+
9+ pdu
10+ PDUs
11+ }
12+
13+
14+ObjectName ::=
15+ OBJECT IDENTIFIER
16+
17+ObjectSyntax ::=
18+ CHOICE {
19+ simple
20+ SimpleSyntax,
21+
22+ application-wide
23+ ApplicationSyntax
24+ }
25+
26+SimpleSyntax ::=
27+ CHOICE {
28+ integer-value
29+ INTEGER,
30+
31+ string-value
32+ OCTET STRING,
33+
34+ objectID-value
35+ OBJECT IDENTIFIER
36+ }
37+
38+ApplicationSyntax ::=
39+ CHOICE {
40+ ipAddress-value
41+ IpAddress,
42+
43+ counter-value
44+ Counter32,
45+
46+ timeticks-value
47+ TimeTicks,
48+
49+ arbitrary-value
50+ Opaque,
51+
52+ big-counter-value
53+ Counter64,
54+
55+ unsigned-integer-value
56+ Unsigned32
57+ }
58+
59+IpAddress ::=
60+ [APPLICATION 0]
61+ IMPLICIT OCTET STRING OPTIONAL ({snmp_helper})
62+
63+Counter32 ::=
64+ [APPLICATION 1]
65+ IMPLICIT INTEGER OPTIONAL
66+
67+Unsigned32 ::=
68+ [APPLICATION 2]
69+ IMPLICIT INTEGER OPTIONAL
70+
71+Gauge32 ::= Unsigned32 OPTIONAL
72+
73+TimeTicks ::=
74+ [APPLICATION 3]
75+ IMPLICIT INTEGER OPTIONAL
76+
77+Opaque ::=
78+ [APPLICATION 4]
79+ IMPLICIT OCTET STRING OPTIONAL
80+
81+Counter64 ::=
82+ [APPLICATION 6]
83+ IMPLICIT INTEGER OPTIONAL
84+
85+PDUs ::=
86+ CHOICE {
87+ get-request
88+ GetRequest-PDU,
89+
90+ get-next-request
91+ GetNextRequest-PDU,
92+
93+ get-bulk-request
94+ GetBulkRequest-PDU,
95+
96+ response
97+ Response-PDU,
98+
99+ set-request
100+ SetRequest-PDU,
101+
102+ inform-request
103+ InformRequest-PDU,
104+
105+ snmpV2-trap
106+ SNMPv2-Trap-PDU,
107+
108+ report
109+ Report-PDU
110+ }
111+
112+GetRequest-PDU ::=
113+ [0] IMPLICIT PDU OPTIONAL
114+
115+GetNextRequest-PDU ::=
116+ [1] IMPLICIT PDU OPTIONAL
117+
118+Response-PDU ::=
119+ [2] IMPLICIT PDU OPTIONAL
120+
121+SetRequest-PDU ::=
122+ [3] IMPLICIT PDU OPTIONAL
123+
124+-- [4] is obsolete
125+
126+GetBulkRequest-PDU ::=
127+ [5] IMPLICIT PDU OPTIONAL
128+
129+InformRequest-PDU ::=
130+ [6] IMPLICIT PDU OPTIONAL
131+
132+SNMPv2-Trap-PDU ::=
133+ [7] IMPLICIT PDU OPTIONAL
134+
135+Report-PDU ::=
136+ [8] IMPLICIT PDU OPTIONAL
137+
138+PDU ::=
139+ SEQUENCE {
140+ request-id
141+ INTEGER,
142+
143+ error-status
144+ INTEGER,
145+
146+ error-index
147+ INTEGER,
148+
149+ variable-bindings
150+ VarBindList
151+ }
152+
153+
154+VarBind ::=
155+ SEQUENCE {
156+ name
157+ ObjectName,
158+
159+ CHOICE {
160+ value
161+ ObjectSyntax,
162+
163+ unSpecified
164+ NULL,
165+
166+ noSuchObject
167+ [0] IMPLICIT NULL,
168+
169+ noSuchInstance
170+ [1] IMPLICIT NULL,
171+
172+ endOfMibView
173+ [2] IMPLICIT NULL
174+ }
175+}
176+
177+VarBindList ::= SEQUENCE OF VarBind
net/ipv4/netfilter/nf_nat_snmp_basic.c+0−1286
@@ -1,1286 +0,0 @@
1−/*
2− * nf_nat_snmp_basic.c
3− *
4− * Basic SNMP Application Layer Gateway
5− *
6− * This IP NAT module is intended for use with SNMP network
7− * discovery and monitoring applications where target networks use
8− * conflicting private address realms.
9− *
10− * Static NAT is used to remap the networks from the view of the network
11− * management system at the IP layer, and this module remaps some application
12− * layer addresses to match.
13− *
14− * The simplest form of ALG is performed, where only tagged IP addresses
15− * are modified. The module does not need to be MIB aware and only scans
16− * messages at the ASN.1/BER level.
17− *
18− * Currently, only SNMPv1 and SNMPv2 are supported.
19− *
20− * More information on ALG and associated issues can be found in
21− * RFC 2962
22− *
23− * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory
24− * McLean & Jochen Friedrich, stripped down for use in the kernel.
25− *
26− * Copyright (c) 2000 RP Internet (www.rpi.net.au).
27− *
28− * This program is free software; you can redistribute it and/or modify
29− * it under the terms of the GNU General Public License as published by
30− * the Free Software Foundation; either version 2 of the License, or
31− * (at your option) any later version.
32− * This program is distributed in the hope that it will be useful,
33− * but WITHOUT ANY WARRANTY; without even the implied warranty of
34− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35− * GNU General Public License for more details.
36− * You should have received a copy of the GNU General Public License
37− * along with this program; if not, see <http://www.gnu.org/licenses/>.
38− *
39− * Author: James Morris <jmorris@intercode.com.au>
40− *
41− * Copyright (c) 2006-2010 Patrick McHardy <kaber@trash.net>
42− */
43−#include <linux/module.h>
44−#include <linux/moduleparam.h>
45−#include <linux/types.h>
46−#include <linux/kernel.h>
47−#include <linux/slab.h>
48−#include <linux/in.h>
49−#include <linux/ip.h>
50−#include <linux/udp.h>
51−#include <net/checksum.h>
52−#include <net/udp.h>
53−
54−#include <net/netfilter/nf_nat.h>
55−#include <net/netfilter/nf_conntrack_expect.h>
56−#include <net/netfilter/nf_conntrack_helper.h>
57−#include <net/netfilter/nf_nat_helper.h>
58−#include <linux/netfilter/nf_conntrack_snmp.h>
59−
60−MODULE_LICENSE("GPL");
61−MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
62−MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
63−MODULE_ALIAS("ip_nat_snmp_basic");
64−
65−#define SNMP_PORT 161
66−#define SNMP_TRAP_PORT 162
67−#define NOCT1(n) (*(u8 *)(n))
68−
69−static int debug;
70−static DEFINE_SPINLOCK(snmp_lock);
71−
72−/*
73− * Application layer address mapping mimics the NAT mapping, but
74− * only for the first octet in this case (a more flexible system
75− * can be implemented if needed).
76− */
77−struct oct1_map
78−{
79− u_int8_t from;
80− u_int8_t to;
81−};
82−
83−
84−/*****************************************************************************
85− *
86− * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
87− *
88− *****************************************************************************/
89−
90−/* Class */
91−#define ASN1_UNI 0 /* Universal */
92−#define ASN1_APL 1 /* Application */
93−#define ASN1_CTX 2 /* Context */
94−#define ASN1_PRV 3 /* Private */
95−
96−/* Tag */
97−#define ASN1_EOC 0 /* End Of Contents */
98−#define ASN1_BOL 1 /* Boolean */
99−#define ASN1_INT 2 /* Integer */
100−#define ASN1_BTS 3 /* Bit String */
101−#define ASN1_OTS 4 /* Octet String */
102−#define ASN1_NUL 5 /* Null */
103−#define ASN1_OJI 6 /* Object Identifier */
104−#define ASN1_OJD 7 /* Object Description */
105−#define ASN1_EXT 8 /* External */
106−#define ASN1_SEQ 16 /* Sequence */
107−#define ASN1_SET 17 /* Set */
108−#define ASN1_NUMSTR 18 /* Numerical String */
109−#define ASN1_PRNSTR 19 /* Printable String */
110−#define ASN1_TEXSTR 20 /* Teletext String */
111−#define ASN1_VIDSTR 21 /* Video String */
112−#define ASN1_IA5STR 22 /* IA5 String */
113−#define ASN1_UNITIM 23 /* Universal Time */
114−#define ASN1_GENTIM 24 /* General Time */
115−#define ASN1_GRASTR 25 /* Graphical String */
116−#define ASN1_VISSTR 26 /* Visible String */
117−#define ASN1_GENSTR 27 /* General String */
118−
119−/* Primitive / Constructed methods*/
120−#define ASN1_PRI 0 /* Primitive */
121−#define ASN1_CON 1 /* Constructed */
122−
123−/*
124− * Error codes.
125− */
126−#define ASN1_ERR_NOERROR 0
127−#define ASN1_ERR_DEC_EMPTY 2
128−#define ASN1_ERR_DEC_EOC_MISMATCH 3
129−#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
130−#define ASN1_ERR_DEC_BADVALUE 5
131−
132−/*
133− * ASN.1 context.
134− */
135−struct asn1_ctx
136−{
137− int error; /* Error condition */
138− unsigned char *pointer; /* Octet just to be decoded */
139− unsigned char *begin; /* First octet */
140− unsigned char *end; /* Octet after last octet */
141−};
142−
143−/*
144− * Octet string (not null terminated)
145− */
146−struct asn1_octstr
147−{
148− unsigned char *data;
149− unsigned int len;
150−};
151−
152−static void asn1_open(struct asn1_ctx *ctx,
153− unsigned char *buf,
154− unsigned int len)
155−{
156− ctx->begin = buf;
157− ctx->end = buf + len;
158− ctx->pointer = buf;
159− ctx->error = ASN1_ERR_NOERROR;
160−}
161−
162−static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
163−{
164− if (ctx->pointer >= ctx->end) {
165− ctx->error = ASN1_ERR_DEC_EMPTY;
166− return 0;
167− }
168− *ch = *(ctx->pointer)++;
169− return 1;
170−}
171−
172−static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
173−{
174− unsigned char ch;
175−
176− *tag = 0;
177−
178− do
179− {
180− if (!asn1_octet_decode(ctx, &ch))
181− return 0;
182− *tag <<= 7;
183− *tag |= ch & 0x7F;
184− } while ((ch & 0x80) == 0x80);
185− return 1;
186−}
187−
188−static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
189− unsigned int *cls,
190− unsigned int *con,
191− unsigned int *tag)
192−{
193− unsigned char ch;
194−
195− if (!asn1_octet_decode(ctx, &ch))
196− return 0;
197−
198− *cls = (ch & 0xC0) >> 6;
199− *con = (ch & 0x20) >> 5;
200− *tag = (ch & 0x1F);
201−
202− if (*tag == 0x1F) {
203− if (!asn1_tag_decode(ctx, tag))
204− return 0;
205− }
206− return 1;
207−}
208−
209−static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
210− unsigned int *def,
211− unsigned int *len)
212−{
213− unsigned char ch, cnt;
214−
215− if (!asn1_octet_decode(ctx, &ch))
216− return 0;
217−
218− if (ch == 0x80)
219− *def = 0;
220− else {
221− *def = 1;
222−
223− if (ch < 0x80)
224− *len = ch;
225− else {
226− cnt = ch & 0x7F;
227− *len = 0;
228−
229− while (cnt > 0) {
230− if (!asn1_octet_decode(ctx, &ch))
231− return 0;
232− *len <<= 8;
233− *len |= ch;
234− cnt--;
235− }
236− }
237− }
238−
239− /* don't trust len bigger than ctx buffer */
240− if (*len > ctx->end - ctx->pointer)
241− return 0;
242−
243− return 1;
244−}
245−
246−static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
247− unsigned char **eoc,
248− unsigned int *cls,
249− unsigned int *con,
250− unsigned int *tag)
251−{
252− unsigned int def, len;
253−
254− if (!asn1_id_decode(ctx, cls, con, tag))
255− return 0;
256−
257− def = len = 0;
258− if (!asn1_length_decode(ctx, &def, &len))
259− return 0;
260−
261− /* primitive shall be definite, indefinite shall be constructed */
262− if (*con == ASN1_PRI && !def)
263− return 0;
264−
265− if (def)
266− *eoc = ctx->pointer + len;
267− else
268− *eoc = NULL;
269− return 1;
270−}
271−
272−static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
273−{
274− unsigned char ch;
275−
276− if (eoc == NULL) {
277− if (!asn1_octet_decode(ctx, &ch))
278− return 0;
279−
280− if (ch != 0x00) {
281− ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
282− return 0;
283− }
284−
285− if (!asn1_octet_decode(ctx, &ch))
286− return 0;
287−
288− if (ch != 0x00) {
289− ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
290− return 0;
291− }
292− return 1;
293− } else {
294− if (ctx->pointer != eoc) {
295− ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
296− return 0;
297− }
298− return 1;
299− }
300−}
301−
302−static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc)
303−{
304− ctx->pointer = eoc;
305− return 1;
306−}
307−
308−static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
309− unsigned char *eoc,
310− long *integer)
311−{
312− unsigned char ch;
313− unsigned int len;
314−
315− if (!asn1_octet_decode(ctx, &ch))
316− return 0;
317−
318− *integer = (signed char) ch;
319− len = 1;
320−
321− while (ctx->pointer < eoc) {
322− if (++len > sizeof (long)) {
323− ctx->error = ASN1_ERR_DEC_BADVALUE;
324− return 0;
325− }
326−
327− if (!asn1_octet_decode(ctx, &ch))
328− return 0;
329−
330− *integer <<= 8;
331− *integer |= ch;
332− }
333− return 1;
334−}
335−
336−static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
337− unsigned char *eoc,
338− unsigned int *integer)
339−{
340− unsigned char ch;
341− unsigned int len;
342−
343− if (!asn1_octet_decode(ctx, &ch))
344− return 0;
345−
346− *integer = ch;
347− if (ch == 0) len = 0;
348− else len = 1;
349−
350− while (ctx->pointer < eoc) {
351− if (++len > sizeof (unsigned int)) {
352− ctx->error = ASN1_ERR_DEC_BADVALUE;
353− return 0;
354− }
355−
356− if (!asn1_octet_decode(ctx, &ch))
357− return 0;
358−
359− *integer <<= 8;
360− *integer |= ch;
361− }
362− return 1;
363−}
364−
365−static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
366− unsigned char *eoc,
367− unsigned long *integer)
368−{
369− unsigned char ch;
370− unsigned int len;
371−
372− if (!asn1_octet_decode(ctx, &ch))
373− return 0;
374−
375− *integer = ch;
376− if (ch == 0) len = 0;
377− else len = 1;
378−
379− while (ctx->pointer < eoc) {
380− if (++len > sizeof (unsigned long)) {
381− ctx->error = ASN1_ERR_DEC_BADVALUE;
382− return 0;
383− }
384−
385− if (!asn1_octet_decode(ctx, &ch))
386− return 0;
387−
388− *integer <<= 8;
389− *integer |= ch;
390− }
391− return 1;
392−}
393−
394−static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,
395− unsigned char *eoc,
396− unsigned char **octets,
397− unsigned int *len)
398−{
399− unsigned char *ptr;
400−
401− *len = 0;
402−
403− *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
404− if (*octets == NULL)
405− return 0;
406−
407− ptr = *octets;
408− while (ctx->pointer < eoc) {
409− if (!asn1_octet_decode(ctx, ptr++)) {
410− kfree(*octets);
411− *octets = NULL;
412− return 0;
413− }
414− (*len)++;
415− }
416− return 1;
417−}
418−
419−static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,
420− unsigned long *subid)
421−{
422− unsigned char ch;
423−
424− *subid = 0;
425−
426− do {
427− if (!asn1_octet_decode(ctx, &ch))
428− return 0;
429−
430− *subid <<= 7;
431− *subid |= ch & 0x7F;
432− } while ((ch & 0x80) == 0x80);
433− return 1;
434−}
435−
436−static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
437− unsigned char *eoc,
438− unsigned long **oid,
439− unsigned int *len)
440−{
441− unsigned long subid;
442− unsigned long *optr;
443− size_t size;
444−
445− size = eoc - ctx->pointer + 1;
446−
447− /* first subid actually encodes first two subids */
448− if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
449− return 0;
450−
451− *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
452− if (*oid == NULL)
453− return 0;
454−
455− optr = *oid;
456−
457− if (!asn1_subid_decode(ctx, &subid)) {
458− kfree(*oid);
459− *oid = NULL;
460− return 0;
461− }
462−
463− if (subid < 40) {
464− optr[0] = 0;
465− optr[1] = subid;
466− } else if (subid < 80) {
467− optr[0] = 1;
468− optr[1] = subid - 40;
469− } else {
470− optr[0] = 2;
471− optr[1] = subid - 80;
472− }
473−
474− *len = 2;
475− optr += 2;
476−
477− while (ctx->pointer < eoc) {
478− if (++(*len) > size) {
479− ctx->error = ASN1_ERR_DEC_BADVALUE;
480− kfree(*oid);
481− *oid = NULL;
482− return 0;
483− }
484−
485− if (!asn1_subid_decode(ctx, optr++)) {
486− kfree(*oid);
487− *oid = NULL;
488− return 0;
489− }
490− }
491− return 1;
492−}
493−
494−/*****************************************************************************
495− *
496− * SNMP decoding routines (gxsnmp author Dirk Wisse)
497− *
498− *****************************************************************************/
499−
500−/* SNMP Versions */
501−#define SNMP_V1 0
502−#define SNMP_V2C 1
503−#define SNMP_V2 2
504−#define SNMP_V3 3
505−
506−/* Default Sizes */
507−#define SNMP_SIZE_COMM 256
508−#define SNMP_SIZE_OBJECTID 128
509−#define SNMP_SIZE_BUFCHR 256
510−#define SNMP_SIZE_BUFINT 128
511−#define SNMP_SIZE_SMALLOBJECTID 16
512−
513−/* Requests */
514−#define SNMP_PDU_GET 0
515−#define SNMP_PDU_NEXT 1
516−#define SNMP_PDU_RESPONSE 2
517−#define SNMP_PDU_SET 3
518−#define SNMP_PDU_TRAP1 4
519−#define SNMP_PDU_BULK 5
520−#define SNMP_PDU_INFORM 6
521−#define SNMP_PDU_TRAP2 7
522−
523−/* Errors */
524−#define SNMP_NOERROR 0
525−#define SNMP_TOOBIG 1
526−#define SNMP_NOSUCHNAME 2
527−#define SNMP_BADVALUE 3
528−#define SNMP_READONLY 4
529−#define SNMP_GENERROR 5
530−#define SNMP_NOACCESS 6
531−#define SNMP_WRONGTYPE 7
532−#define SNMP_WRONGLENGTH 8
533−#define SNMP_WRONGENCODING 9
534−#define SNMP_WRONGVALUE 10
535−#define SNMP_NOCREATION 11
536−#define SNMP_INCONSISTENTVALUE 12
537−#define SNMP_RESOURCEUNAVAILABLE 13
538−#define SNMP_COMMITFAILED 14
539−#define SNMP_UNDOFAILED 15
540−#define SNMP_AUTHORIZATIONERROR 16
541−#define SNMP_NOTWRITABLE 17
542−#define SNMP_INCONSISTENTNAME 18
543−
544−/* General SNMP V1 Traps */
545−#define SNMP_TRAP_COLDSTART 0
546−#define SNMP_TRAP_WARMSTART 1
547−#define SNMP_TRAP_LINKDOWN 2
548−#define SNMP_TRAP_LINKUP 3
549−#define SNMP_TRAP_AUTFAILURE 4
550−#define SNMP_TRAP_EQPNEIGHBORLOSS 5
551−#define SNMP_TRAP_ENTSPECIFIC 6
552−
553−/* SNMPv1 Types */
554−#define SNMP_NULL 0
555−#define SNMP_INTEGER 1 /* l */
556−#define SNMP_OCTETSTR 2 /* c */
557−#define SNMP_DISPLAYSTR 2 /* c */
558−#define SNMP_OBJECTID 3 /* ul */
559−#define SNMP_IPADDR 4 /* uc */
560−#define SNMP_COUNTER 5 /* ul */
561−#define SNMP_GAUGE 6 /* ul */
562−#define SNMP_TIMETICKS 7 /* ul */
563−#define SNMP_OPAQUE 8 /* c */
564−
565−/* Additional SNMPv2 Types */
566−#define SNMP_UINTEGER 5 /* ul */
567−#define SNMP_BITSTR 9 /* uc */
568−#define SNMP_NSAP 10 /* uc */
569−#define SNMP_COUNTER64 11 /* ul */
570−#define SNMP_NOSUCHOBJECT 12
571−#define SNMP_NOSUCHINSTANCE 13
572−#define SNMP_ENDOFMIBVIEW 14
573−
574−union snmp_syntax
575−{
576− unsigned char uc[0]; /* 8 bit unsigned */
577− char c[0]; /* 8 bit signed */
578− unsigned long ul[0]; /* 32 bit unsigned */
579− long l[0]; /* 32 bit signed */
580−};
581−
582−struct snmp_object
583−{
584− unsigned long *id;
585− unsigned int id_len;
586− unsigned short type;
587− unsigned int syntax_len;
588− union snmp_syntax syntax;
589−};
590−
591−struct snmp_request
592−{
593− unsigned long id;
594− unsigned int error_status;
595− unsigned int error_index;
596−};
597−
598−struct snmp_v1_trap
599−{
600− unsigned long *id;
601− unsigned int id_len;
602− unsigned long ip_address; /* pointer */
603− unsigned int general;
604− unsigned int specific;
605− unsigned long time;
606−};
607−
608−/* SNMP types */
609−#define SNMP_IPA 0
610−#define SNMP_CNT 1
611−#define SNMP_GGE 2
612−#define SNMP_TIT 3
613−#define SNMP_OPQ 4
614−#define SNMP_C64 6
615−
616−/* SNMP errors */
617−#define SERR_NSO 0
618−#define SERR_NSI 1
619−#define SERR_EOM 2
620−
621−static inline void mangle_address(unsigned char *begin,
622− unsigned char *addr,
623− const struct oct1_map *map,
624− __sum16 *check);
625−struct snmp_cnv
626−{
627− unsigned int class;
628− unsigned int tag;
629− int syntax;
630−};
631−
632−static const struct snmp_cnv snmp_conv[] = {
633− {ASN1_UNI, ASN1_NUL, SNMP_NULL},
634− {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
635− {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
636− {ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR},
637− {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID},
638− {ASN1_APL, SNMP_IPA, SNMP_IPADDR},
639− {ASN1_APL, SNMP_CNT, SNMP_COUNTER}, /* Counter32 */
640− {ASN1_APL, SNMP_GGE, SNMP_GAUGE}, /* Gauge32 == Unsigned32 */
641− {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS},
642− {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE},
643−
644− /* SNMPv2 data types and errors */
645− {ASN1_UNI, ASN1_BTS, SNMP_BITSTR},
646− {ASN1_APL, SNMP_C64, SNMP_COUNTER64},
647− {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT},
648− {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE},
649− {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW},
650− {0, 0, -1}
651−};
652−
653−static unsigned char snmp_tag_cls2syntax(unsigned int tag,
654− unsigned int cls,
655− unsigned short *syntax)
656−{
657− const struct snmp_cnv *cnv;
658−
659− cnv = snmp_conv;
660−
661− while (cnv->syntax != -1) {
662− if (cnv->tag == tag && cnv->class == cls) {
663− *syntax = cnv->syntax;
664− return 1;
665− }
666− cnv++;
667− }
668− return 0;
669−}
670−
671−static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
672− struct snmp_object **obj)
673−{
674− unsigned int cls, con, tag, len, idlen;
675− unsigned short type;
676− unsigned char *eoc, *end, *p;
677− unsigned long *lp, *id;
678− unsigned long ul;
679− long l;
680−
681− *obj = NULL;
682− id = NULL;
683−
684− if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag))
685− return 0;
686−
687− if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
688− return 0;
689−
690− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
691− return 0;
692−
693− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
694− return 0;
695−
696− if (!asn1_oid_decode(ctx, end, &id, &idlen))
697− return 0;
698−
699− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) {
700− kfree(id);
701− return 0;
702− }
703−
704− if (con != ASN1_PRI) {
705− kfree(id);
706− return 0;
707− }
708−
709− type = 0;
710− if (!snmp_tag_cls2syntax(tag, cls, &type)) {
711− kfree(id);
712− return 0;
713− }
714−
715− l = 0;
716− switch (type) {
717− case SNMP_INTEGER:
718− len = sizeof(long);
719− if (!asn1_long_decode(ctx, end, &l)) {
720− kfree(id);
721− return 0;
722− }
723− *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
724− if (*obj == NULL) {
725− kfree(id);
726− return 0;
727− }
728− (*obj)->syntax.l[0] = l;
729− break;
730− case SNMP_OCTETSTR:
731− case SNMP_OPAQUE:
732− if (!asn1_octets_decode(ctx, end, &p, &len)) {
733− kfree(id);
734− return 0;
735− }
736− *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
737− if (*obj == NULL) {
738− kfree(p);
739− kfree(id);
740− return 0;
741− }
742− memcpy((*obj)->syntax.c, p, len);
743− kfree(p);
744− break;
745− case SNMP_NULL:
746− case SNMP_NOSUCHOBJECT:
747− case SNMP_NOSUCHINSTANCE:
748− case SNMP_ENDOFMIBVIEW:
749− len = 0;
750− *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
751− if (*obj == NULL) {
752− kfree(id);
753− return 0;
754− }
755− if (!asn1_null_decode(ctx, end)) {
756− kfree(id);
757− kfree(*obj);
758− *obj = NULL;
759− return 0;
760− }
761− break;
762− case SNMP_OBJECTID:
763− if (!asn1_oid_decode(ctx, end, &lp, &len)) {
764− kfree(id);
765− return 0;
766− }
767− len *= sizeof(unsigned long);
768− *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
769− if (*obj == NULL) {
770− kfree(lp);
771− kfree(id);
772− return 0;
773− }
774− memcpy((*obj)->syntax.ul, lp, len);
775− kfree(lp);
776− break;
777− case SNMP_IPADDR:
778− if (!asn1_octets_decode(ctx, end, &p, &len)) {
779− kfree(id);
780− return 0;
781− }
782− if (len != 4) {
783− kfree(p);
784− kfree(id);
785− return 0;
786− }
787− *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
788− if (*obj == NULL) {
789− kfree(p);
790− kfree(id);
791− return 0;
792− }
793− memcpy((*obj)->syntax.uc, p, len);
794− kfree(p);
795− break;
796− case SNMP_COUNTER:
797− case SNMP_GAUGE:
798− case SNMP_TIMETICKS:
799− len = sizeof(unsigned long);
800− if (!asn1_ulong_decode(ctx, end, &ul)) {
801− kfree(id);
802− return 0;
803− }
804− *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
805− if (*obj == NULL) {
806− kfree(id);
807− return 0;
808− }
809− (*obj)->syntax.ul[0] = ul;
810− break;
811− default:
812− kfree(id);
813− return 0;
814− }
815−
816− (*obj)->syntax_len = len;
817− (*obj)->type = type;
818− (*obj)->id = id;
819− (*obj)->id_len = idlen;
820−
821− if (!asn1_eoc_decode(ctx, eoc)) {
822− kfree(id);
823− kfree(*obj);
824− *obj = NULL;
825− return 0;
826− }
827− return 1;
828−}
829−
830−static unsigned char noinline_for_stack
831−snmp_request_decode(struct asn1_ctx *ctx, struct snmp_request *request)
832−{
833− unsigned int cls, con, tag;
834− unsigned char *end;
835−
836− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
837− return 0;
838−
839− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
840− return 0;
841−
842− if (!asn1_ulong_decode(ctx, end, &request->id))
843− return 0;
844−
845− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
846− return 0;
847−
848− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
849− return 0;
850−
851− if (!asn1_uint_decode(ctx, end, &request->error_status))
852− return 0;
853−
854− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
855− return 0;
856−
857− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
858− return 0;
859−
860− if (!asn1_uint_decode(ctx, end, &request->error_index))
861− return 0;
862−
863− return 1;
864−}
865−
866−/*
867− * Fast checksum update for possibly oddly-aligned UDP byte, from the
868− * code example in the draft.
869− */
870−static void fast_csum(__sum16 *csum,
871− const unsigned char *optr,
872− const unsigned char *nptr,
873− int offset)
874−{
875− unsigned char s[4];
876−
877− if (offset & 1) {
878− s[0] = ~0;
879− s[1] = ~*optr;
880− s[2] = 0;
881− s[3] = *nptr;
882− } else {
883− s[0] = ~*optr;
884− s[1] = ~0;
885− s[2] = *nptr;
886− s[3] = 0;
887− }
888−
889− *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
890−}
891−
892−/*
893− * Mangle IP address.
894− * - begin points to the start of the snmp messgae
895− * - addr points to the start of the address
896− */
897−static inline void mangle_address(unsigned char *begin,
898− unsigned char *addr,
899− const struct oct1_map *map,
900− __sum16 *check)
901−{
902− if (map->from == NOCT1(addr)) {
903− u_int32_t old;
904−
905− if (debug)
906− memcpy(&old, addr, sizeof(old));
907−
908− *addr = map->to;
909−
910− /* Update UDP checksum if being used */
911− if (*check) {
912− fast_csum(check,
913− &map->from, &map->to, addr - begin);
914−
915− }
916−
917− if (debug)
918− printk(KERN_DEBUG "bsalg: mapped %pI4 to %pI4\n",
919− &old, addr);
920− }
921−}
922−
923−static unsigned char noinline_for_stack
924−snmp_trap_decode(struct asn1_ctx *ctx, struct snmp_v1_trap *trap,
925− const struct oct1_map *map,
926− __sum16 *check)
927−{
928− unsigned int cls, con, tag, len;
929− unsigned char *end;
930−
931− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
932− return 0;
933−
934− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
935− return 0;
936−
937− if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))
938− return 0;
939−
940− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
941− goto err_id_free;
942−
943− if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
944− (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))
945− goto err_id_free;
946−
947− if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))
948− goto err_id_free;
949−
950− /* IPv4 only */
951− if (len != 4)
952− goto err_addr_free;
953−
954− mangle_address(ctx->begin, ctx->pointer - 4, map, check);
955−
956− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
957− goto err_addr_free;
958−
959− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
960− goto err_addr_free;
961−
962− if (!asn1_uint_decode(ctx, end, &trap->general))
963− goto err_addr_free;
964−
965− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
966− goto err_addr_free;
967−
968− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
969− goto err_addr_free;
970−
971− if (!asn1_uint_decode(ctx, end, &trap->specific))
972− goto err_addr_free;
973−
974− if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
975− goto err_addr_free;
976−
977− if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
978− (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))
979− goto err_addr_free;
980−
981− if (!asn1_ulong_decode(ctx, end, &trap->time))
982− goto err_addr_free;
983−
984− return 1;
985−
986−err_addr_free:
987− kfree((unsigned long *)trap->ip_address);
988−
989−err_id_free:
990− kfree(trap->id);
991−
992− return 0;
993−}
994−
995−/*****************************************************************************
996− *
997− * Misc. routines
998− *
999− *****************************************************************************/
1000−
1001−/*
1002− * Parse and mangle SNMP message according to mapping.
1003− * (And this is the fucking 'basic' method).
1004− */
1005−static int snmp_parse_mangle(unsigned char *msg,
1006− u_int16_t len,
1007− const struct oct1_map *map,
1008− __sum16 *check)
1009−{
1010− unsigned char *eoc, *end;
1011− unsigned int cls, con, tag, vers, pdutype;
1012− struct asn1_ctx ctx;
1013− struct asn1_octstr comm;
1014− struct snmp_object *obj;
1015−
1016− if (debug > 1)
1017− print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 16, 1,
1018− msg, len, 0);
1019−
1020− asn1_open(&ctx, msg, len);
1021−
1022− /*
1023− * Start of SNMP message.
1024− */
1025− if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1026− return 0;
1027− if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1028− return 0;
1029−
1030− /*
1031− * Version 1 or 2 handled.
1032− */
1033− if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))
1034− return 0;
1035− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
1036− return 0;
1037− if (!asn1_uint_decode (&ctx, end, &vers))
1038− return 0;
1039− if (debug > 1)
1040− pr_debug("bsalg: snmp version: %u\n", vers + 1);
1041− if (vers > 1)
1042− return 1;
1043−
1044− /*
1045− * Community.
1046− */
1047− if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag))
1048− return 0;
1049− if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
1050− return 0;
1051− if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len))
1052− return 0;
1053− if (debug > 1) {
1054− unsigned int i;
1055−
1056− pr_debug("bsalg: community: ");
1057− for (i = 0; i < comm.len; i++)
1058− pr_cont("%c", comm.data[i]);
1059− pr_cont("\n");
1060− }
1061− kfree(comm.data);
1062−
1063− /*
1064− * PDU type
1065− */
1066− if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype))
1067− return 0;
1068− if (cls != ASN1_CTX || con != ASN1_CON)
1069− return 0;
1070− if (debug > 1) {
1071− static const unsigned char *const pdus[] = {
1072− [SNMP_PDU_GET] = "get",
1073− [SNMP_PDU_NEXT] = "get-next",
1074− [SNMP_PDU_RESPONSE] = "response",
1075− [SNMP_PDU_SET] = "set",
1076− [SNMP_PDU_TRAP1] = "trapv1",
1077− [SNMP_PDU_BULK] = "bulk",
1078− [SNMP_PDU_INFORM] = "inform",
1079− [SNMP_PDU_TRAP2] = "trapv2"
1080− };
1081−
1082− if (pdutype > SNMP_PDU_TRAP2)
1083− pr_debug("bsalg: bad pdu type %u\n", pdutype);
1084− else
1085− pr_debug("bsalg: pdu: %s\n", pdus[pdutype]);
1086− }
1087− if (pdutype != SNMP_PDU_RESPONSE &&
1088− pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)
1089− return 1;
1090−
1091− /*
1092− * Request header or v1 trap
1093− */
1094− if (pdutype == SNMP_PDU_TRAP1) {
1095− struct snmp_v1_trap trap;
1096− unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
1097−
1098− if (ret) {
1099− kfree(trap.id);
1100− kfree((unsigned long *)trap.ip_address);
1101− } else
1102− return ret;
1103−
1104− } else {
1105− struct snmp_request req;
1106−
1107− if (!snmp_request_decode(&ctx, &req))
1108− return 0;
1109−
1110− if (debug > 1)
1111− pr_debug("bsalg: request: id=0x%lx error_status=%u "
1112− "error_index=%u\n", req.id, req.error_status,
1113− req.error_index);
1114− }
1115−
1116− /*
1117− * Loop through objects, look for IP addresses to mangle.
1118− */
1119− if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1120− return 0;
1121−
1122− if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1123− return 0;
1124−
1125− while (!asn1_eoc_decode(&ctx, eoc)) {
1126− unsigned int i;
1127−
1128− if (!snmp_object_decode(&ctx, &obj)) {
1129− if (obj) {
1130− kfree(obj->id);
1131− kfree(obj);
1132− }
1133− return 0;
1134− }
1135−
1136− if (debug > 1) {
1137− pr_debug("bsalg: object: ");
1138− for (i = 0; i < obj->id_len; i++) {
1139− if (i > 0)
1140− pr_cont(".");
1141− pr_cont("%lu", obj->id[i]);
1142− }
1143− pr_cont(": type=%u\n", obj->type);
1144−
1145− }
1146−
1147− if (obj->type == SNMP_IPADDR)
1148− mangle_address(ctx.begin, ctx.pointer - 4, map, check);
1149−
1150− kfree(obj->id);
1151− kfree(obj);
1152− }
1153−
1154− if (!asn1_eoc_decode(&ctx, eoc))
1155− return 0;
1156−
1157− return 1;
1158−}
1159−
1160−/*****************************************************************************
1161− *
1162− * NAT routines.
1163− *
1164− *****************************************************************************/
1165−
1166−/*
1167− * SNMP translation routine.
1168− */
1169−static int snmp_translate(struct nf_conn *ct,
1170− enum ip_conntrack_info ctinfo,
1171− struct sk_buff *skb)
1172−{
1173− struct iphdr *iph = ip_hdr(skb);
1174− struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
1175− u_int16_t udplen = ntohs(udph->len);
1176− u_int16_t paylen = udplen - sizeof(struct udphdr);
1177− int dir = CTINFO2DIR(ctinfo);
1178− struct oct1_map map;
1179−
1180− /*
1181− * Determine mappping for application layer addresses based
1182− * on NAT manipulations for the packet.
1183− */
1184− if (dir == IP_CT_DIR_ORIGINAL) {
1185− /* SNAT traps */
1186− map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
1187− map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
1188− } else {
1189− /* DNAT replies */
1190− map.from = NOCT1(&ct->tuplehash[!dir].tuple.src.u3.ip);
1191− map.to = NOCT1(&ct->tuplehash[dir].tuple.dst.u3.ip);
1192− }
1193−
1194− if (map.from == map.to)
1195− return NF_ACCEPT;
1196−
1197− if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
1198− paylen, &map, &udph->check)) {
1199− net_warn_ratelimited("bsalg: parser failed\n");
1200− return NF_DROP;
1201− }
1202− return NF_ACCEPT;
1203−}
1204−
1205−/* We don't actually set up expectations, just adjust internal IP
1206− * addresses if this is being NATted */
1207−static int help(struct sk_buff *skb, unsigned int protoff,
1208− struct nf_conn *ct,
1209− enum ip_conntrack_info ctinfo)
1210−{
1211− int dir = CTINFO2DIR(ctinfo);
1212− unsigned int ret;
1213− const struct iphdr *iph = ip_hdr(skb);
1214− const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
1215−
1216− /* SNMP replies and originating SNMP traps get mangled */
1217− if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
1218− return NF_ACCEPT;
1219− if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
1220− return NF_ACCEPT;
1221−
1222− /* No NAT? */
1223− if (!(ct->status & IPS_NAT_MASK))
1224− return NF_ACCEPT;
1225−
1226− /*
1227− * Make sure the packet length is ok. So far, we were only guaranteed
1228− * to have a valid length IP header plus 8 bytes, which means we have
1229− * enough room for a UDP header. Just verify the UDP length field so we
1230− * can mess around with the payload.
1231− */
1232− if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) {
1233− net_warn_ratelimited("SNMP: dropping malformed packet src=%pI4 dst=%pI4\n",
1234− &iph->saddr, &iph->daddr);
1235− return NF_DROP;
1236− }
1237−
1238− if (!skb_make_writable(skb, skb->len))
1239− return NF_DROP;
1240−
1241− spin_lock_bh(&snmp_lock);
1242− ret = snmp_translate(ct, ctinfo, skb);
1243− spin_unlock_bh(&snmp_lock);
1244− return ret;
1245−}
1246−
1247−static const struct nf_conntrack_expect_policy snmp_exp_policy = {
1248− .max_expected = 0,
1249− .timeout = 180,
1250−};
1251−
1252−static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
1253− .me = THIS_MODULE,
1254− .help = help,
1255− .expect_policy = &snmp_exp_policy,
1256− .name = "snmp_trap",
1257− .tuple.src.l3num = AF_INET,
1258− .tuple.src.u.udp.port = cpu_to_be16(SNMP_TRAP_PORT),
1259− .tuple.dst.protonum = IPPROTO_UDP,
1260−};
1261−
1262−/*****************************************************************************
1263− *
1264− * Module stuff.
1265− *
1266− *****************************************************************************/
1267−
1268−static int __init nf_nat_snmp_basic_init(void)
1269−{
1270− BUG_ON(nf_nat_snmp_hook != NULL);
1271− RCU_INIT_POINTER(nf_nat_snmp_hook, help);
1272−
1273− return nf_conntrack_helper_register(&snmp_trap_helper);
1274−}
1275−
1276−static void __exit nf_nat_snmp_basic_fini(void)
1277−{
1278− RCU_INIT_POINTER(nf_nat_snmp_hook, NULL);
1279− synchronize_rcu();
1280− nf_conntrack_helper_unregister(&snmp_trap_helper);
1281−}
1282−
1283−module_init(nf_nat_snmp_basic_init);
1284−module_exit(nf_nat_snmp_basic_fini);
1285−
1286−module_param(debug, int, 0600);
net/ipv4/netfilter/nf_nat_snmp_basic_main.c+235−0
@@ -0,0 +1,235 @@
1+/*
2+ * nf_nat_snmp_basic.c
3+ *
4+ * Basic SNMP Application Layer Gateway
5+ *
6+ * This IP NAT module is intended for use with SNMP network
7+ * discovery and monitoring applications where target networks use
8+ * conflicting private address realms.
9+ *
10+ * Static NAT is used to remap the networks from the view of the network
11+ * management system at the IP layer, and this module remaps some application
12+ * layer addresses to match.
13+ *
14+ * The simplest form of ALG is performed, where only tagged IP addresses
15+ * are modified. The module does not need to be MIB aware and only scans
16+ * messages at the ASN.1/BER level.
17+ *
18+ * Currently, only SNMPv1 and SNMPv2 are supported.
19+ *
20+ * More information on ALG and associated issues can be found in
21+ * RFC 2962
22+ *
23+ * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory
24+ * McLean & Jochen Friedrich, stripped down for use in the kernel.
25+ *
26+ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
27+ *
28+ * This program is free software; you can redistribute it and/or modify
29+ * it under the terms of the GNU General Public License as published by
30+ * the Free Software Foundation; either version 2 of the License, or
31+ * (at your option) any later version.
32+ * This program is distributed in the hope that it will be useful,
33+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35+ * GNU General Public License for more details.
36+ * You should have received a copy of the GNU General Public License
37+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
38+ *
39+ * Author: James Morris <jmorris@intercode.com.au>
40+ *
41+ * Copyright (c) 2006-2010 Patrick McHardy <kaber@trash.net>
42+ */
43+#include <linux/module.h>
44+#include <linux/moduleparam.h>
45+#include <linux/types.h>
46+#include <linux/kernel.h>
47+#include <linux/in.h>
48+#include <linux/ip.h>
49+#include <linux/udp.h>
50+#include <net/checksum.h>
51+#include <net/udp.h>
52+
53+#include <net/netfilter/nf_nat.h>
54+#include <net/netfilter/nf_conntrack_expect.h>
55+#include <net/netfilter/nf_conntrack_helper.h>
56+#include <linux/netfilter/nf_conntrack_snmp.h>
57+#include "nf_nat_snmp_basic-asn1.h"
58+
59+MODULE_LICENSE("GPL");
60+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
61+MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
62+MODULE_ALIAS("ip_nat_snmp_basic");
63+
64+#define SNMP_PORT 161
65+#define SNMP_TRAP_PORT 162
66+
67+static DEFINE_SPINLOCK(snmp_lock);
68+
69+struct snmp_ctx {
70+ unsigned char *begin;
71+ __sum16 *check;
72+ __be32 from;
73+ __be32 to;
74+};
75+
76+static void fast_csum(struct snmp_ctx *ctx, unsigned char offset)
77+{
78+ unsigned char s[12] = {0,};
79+ int size;
80+
81+ if (offset & 1) {
82+ memcpy(&s[1], &ctx->from, 4);
83+ memcpy(&s[7], &ctx->to, 4);
84+ s[0] = ~0;
85+ s[1] = ~s[1];
86+ s[2] = ~s[2];
87+ s[3] = ~s[3];
88+ s[4] = ~s[4];
89+ s[5] = ~0;
90+ size = 12;
91+ } else {
92+ memcpy(&s[0], &ctx->from, 4);
93+ memcpy(&s[4], &ctx->to, 4);
94+ s[0] = ~s[0];
95+ s[1] = ~s[1];
96+ s[2] = ~s[2];
97+ s[3] = ~s[3];
98+ size = 8;
99+ }
100+ *ctx->check = csum_fold(csum_partial(s, size,
101+ ~csum_unfold(*ctx->check)));
102+}
103+
104+int snmp_version(void *context, size_t hdrlen, unsigned char tag,
105+ const void *data, size_t datalen)
106+{
107+ if (*(unsigned char *)data > 1)
108+ return -ENOTSUPP;
109+ return 1;
110+}
111+
112+int snmp_helper(void *context, size_t hdrlen, unsigned char tag,
113+ const void *data, size_t datalen)
114+{
115+ struct snmp_ctx *ctx = (struct snmp_ctx *)context;
116+ __be32 *pdata = (__be32 *)data;
117+
118+ if (*pdata == ctx->from) {
119+ pr_debug("%s: %pI4 to %pI4\n", __func__,
120+ (void *)&ctx->from, (void *)&ctx->to);
121+
122+ if (*ctx->check)
123+ fast_csum(ctx, (unsigned char *)data - ctx->begin);
124+ *pdata = ctx->to;
125+ }
126+
127+ return 1;
128+}
129+
130+static int snmp_translate(struct nf_conn *ct, int dir, struct sk_buff *skb)
131+{
132+ struct iphdr *iph = ip_hdr(skb);
133+ struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
134+ u16 datalen = ntohs(udph->len) - sizeof(struct udphdr);
135+ char *data = (unsigned char *)udph + sizeof(struct udphdr);
136+ struct snmp_ctx ctx;
137+ int ret;
138+
139+ if (dir == IP_CT_DIR_ORIGINAL) {
140+ ctx.from = ct->tuplehash[dir].tuple.src.u3.ip;
141+ ctx.to = ct->tuplehash[!dir].tuple.dst.u3.ip;
142+ } else {
143+ ctx.from = ct->tuplehash[!dir].tuple.src.u3.ip;
144+ ctx.to = ct->tuplehash[dir].tuple.dst.u3.ip;
145+ }
146+
147+ if (ctx.from == ctx.to)
148+ return NF_ACCEPT;
149+
150+ ctx.begin = (unsigned char *)udph + sizeof(struct udphdr);
151+ ctx.check = &udph->check;
152+ ret = asn1_ber_decoder(&nf_nat_snmp_basic_decoder, &ctx, data, datalen);
153+ if (ret < 0) {
154+ nf_ct_helper_log(skb, ct, "parser failed\n");
155+ return NF_DROP;
156+ }
157+
158+ return NF_ACCEPT;
159+}
160+
161+/* We don't actually set up expectations, just adjust internal IP
162+ * addresses if this is being NATted
163+ */
164+static int help(struct sk_buff *skb, unsigned int protoff,
165+ struct nf_conn *ct,
166+ enum ip_conntrack_info ctinfo)
167+{
168+ int dir = CTINFO2DIR(ctinfo);
169+ unsigned int ret;
170+ const struct iphdr *iph = ip_hdr(skb);
171+ const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
172+
173+ /* SNMP replies and originating SNMP traps get mangled */
174+ if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
175+ return NF_ACCEPT;
176+ if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
177+ return NF_ACCEPT;
178+
179+ /* No NAT? */
180+ if (!(ct->status & IPS_NAT_MASK))
181+ return NF_ACCEPT;
182+
183+ /* Make sure the packet length is ok. So far, we were only guaranteed
184+ * to have a valid length IP header plus 8 bytes, which means we have
185+ * enough room for a UDP header. Just verify the UDP length field so we
186+ * can mess around with the payload.
187+ */
188+ if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) {
189+ nf_ct_helper_log(skb, ct, "dropping malformed packet\n");
190+ return NF_DROP;
191+ }
192+
193+ if (!skb_make_writable(skb, skb->len)) {
194+ nf_ct_helper_log(skb, ct, "cannot mangle packet");
195+ return NF_DROP;
196+ }
197+
198+ spin_lock_bh(&snmp_lock);
199+ ret = snmp_translate(ct, dir, skb);
200+ spin_unlock_bh(&snmp_lock);
201+ return ret;
202+}
203+
204+static const struct nf_conntrack_expect_policy snmp_exp_policy = {
205+ .max_expected = 0,
206+ .timeout = 180,
207+};
208+
209+static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
210+ .me = THIS_MODULE,
211+ .help = help,
212+ .expect_policy = &snmp_exp_policy,
213+ .name = "snmp_trap",
214+ .tuple.src.l3num = AF_INET,
215+ .tuple.src.u.udp.port = cpu_to_be16(SNMP_TRAP_PORT),
216+ .tuple.dst.protonum = IPPROTO_UDP,
217+};
218+
219+static int __init nf_nat_snmp_basic_init(void)
220+{
221+ BUG_ON(nf_nat_snmp_hook != NULL);
222+ RCU_INIT_POINTER(nf_nat_snmp_hook, help);
223+
224+ return nf_conntrack_helper_register(&snmp_trap_helper);
225+}
226+
227+static void __exit nf_nat_snmp_basic_fini(void)
228+{
229+ RCU_INIT_POINTER(nf_nat_snmp_hook, NULL);
230+ synchronize_rcu();
231+ nf_conntrack_helper_unregister(&snmp_trap_helper);
232+}
233+
234+module_init(nf_nat_snmp_basic_init);
235+module_exit(nf_nat_snmp_basic_fini);
net/ipv4/netfilter/nf_tables_arp.c+2−47
@@ -27,40 +27,6 @@ nft_do_chain_arp(void *priv, · 26 unmodified lines
2727 return nft_do_chain(&pkt, priv);
2828 }
2929
30−static struct nft_af_info nft_af_arp __read_mostly = {
31− .family = NFPROTO_ARP,
32− .nhooks = NF_ARP_NUMHOOKS,
33− .owner = THIS_MODULE,
34−};
35−
36−static int nf_tables_arp_init_net(struct net *net)
37−{
38− net->nft.arp = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
39− if (net->nft.arp== NULL)
40− return -ENOMEM;
41−
42− memcpy(net->nft.arp, &nft_af_arp, sizeof(nft_af_arp));
43−
44− if (nft_register_afinfo(net, net->nft.arp) < 0)
45− goto err;
46−
47− return 0;
48−err:
49− kfree(net->nft.arp);
50− return -ENOMEM;
51−}
52−
53−static void nf_tables_arp_exit_net(struct net *net)
54−{
55− nft_unregister_afinfo(net, net->nft.arp);
56− kfree(net->nft.arp);
57−}
58−
59−static struct pernet_operations nf_tables_arp_net_ops = {
60− .init = nf_tables_arp_init_net,
61− .exit = nf_tables_arp_exit_net,
62−};
63−
6430 static const struct nf_chain_type filter_arp = {
6531 .name = "filter",
6632 .type = NFT_CHAIN_T_DEFAULT,
@@ -76,22 +42,11 @@ static const struct nf_chain_type filter_arp = { · 9 unmodified lines
7642
7743 static int __init nf_tables_arp_init(void)
7844 {
79− int ret;
80−
81− ret = nft_register_chain_type(&filter_arp);
82− if (ret < 0)
83− return ret;
84−
85− ret = register_pernet_subsys(&nf_tables_arp_net_ops);
86− if (ret < 0)
87− nft_unregister_chain_type(&filter_arp);
88−
89− return ret;
45+ return nft_register_chain_type(&filter_arp);
9046 }
9147
9248 static void __exit nf_tables_arp_exit(void)
9349 {
94− unregister_pernet_subsys(&nf_tables_arp_net_ops);
9550 nft_unregister_chain_type(&filter_arp);
9651 }
9752
@@ -100,4 +55,4 @@ module_exit(nf_tables_arp_exit); · 2 unmodified lines
10055
10156 MODULE_LICENSE("GPL");
10257 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
103−MODULE_ALIAS_NFT_FAMILY(3); /* NFPROTO_ARP */
58+MODULE_ALIAS_NFT_CHAIN(3, "filter"); /* NFPROTO_ARP */
net/ipv4/netfilter/nf_tables_ipv4.c+2−47
@@ -30,40 +30,6 @@ static unsigned int nft_do_chain_ipv4(void *priv, · 29 unmodified lines
3030 return nft_do_chain(&pkt, priv);
3131 }
3232
33−static struct nft_af_info nft_af_ipv4 __read_mostly = {
34− .family = NFPROTO_IPV4,
35− .nhooks = NF_INET_NUMHOOKS,
36− .owner = THIS_MODULE,
37−};
38−
39−static int nf_tables_ipv4_init_net(struct net *net)
40−{
41− net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
42− if (net->nft.ipv4 == NULL)
43− return -ENOMEM;
44−
45− memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4));
46−
47− if (nft_register_afinfo(net, net->nft.ipv4) < 0)
48− goto err;
49−
50− return 0;
51−err:
52− kfree(net->nft.ipv4);
53− return -ENOMEM;
54−}
55−
56−static void nf_tables_ipv4_exit_net(struct net *net)
57−{
58− nft_unregister_afinfo(net, net->nft.ipv4);
59− kfree(net->nft.ipv4);
60−}
61−
62−static struct pernet_operations nf_tables_ipv4_net_ops = {
63− .init = nf_tables_ipv4_init_net,
64− .exit = nf_tables_ipv4_exit_net,
65−};
66−
6733 static const struct nf_chain_type filter_ipv4 = {
6834 .name = "filter",
6935 .type = NFT_CHAIN_T_DEFAULT,
@@ -85,22 +51,11 @@ static const struct nf_chain_type filter_ipv4 = { · 15 unmodified lines
8551
8652 static int __init nf_tables_ipv4_init(void)
8753 {
88− int ret;
89−
90− ret = nft_register_chain_type(&filter_ipv4);
91− if (ret < 0)
92− return ret;
93−
94− ret = register_pernet_subsys(&nf_tables_ipv4_net_ops);
95− if (ret < 0)
96− nft_unregister_chain_type(&filter_ipv4);
97−
98− return ret;
54+ return nft_register_chain_type(&filter_ipv4);
9955 }
10056
10157 static void __exit nf_tables_ipv4_exit(void)
10258 {
103− unregister_pernet_subsys(&nf_tables_ipv4_net_ops);
10459 nft_unregister_chain_type(&filter_ipv4);
10560 }
10661
@@ -109,4 +64,4 @@ module_exit(nf_tables_ipv4_exit); · 2 unmodified lines
10964
11065 MODULE_LICENSE("GPL");
11166 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
112−MODULE_ALIAS_NFT_FAMILY(AF_INET);
67+MODULE_ALIAS_NFT_CHAIN(AF_INET, "filter");
net/ipv6/netfilter/Kconfig+11−1
@@ -72,8 +72,9 @@ endif # NF_TABLES_IPV6 · 71 unmodified lines
7272 endif # NF_TABLES
7373
7474 config NF_FLOW_TABLE_IPV6
75− select NF_FLOW_TABLE
7675 tristate "Netfilter flow table IPv6 module"
76+ depends on NF_CONNTRACK && NF_TABLES
77+ select NF_FLOW_TABLE
7778 help
7879 This option adds the flow table IPv6 support.
7980
@@ -240,6 +241,15 @@ config IP6_NF_MATCH_RT · 160 unmodified lines
240241
241242 To compile it as a module, choose M here. If unsure, say N.
242243
244+config IP6_NF_MATCH_SRH
245+ tristate '"srh" Segment Routing header match support'
246+ depends on NETFILTER_ADVANCED
247+ help
248+ srh matching allows you to match packets based on the segment
249+ routing header of the packet.
250+
251+ To compile it as a module, choose M here. If unsure, say N.
252+
243253 # The targets
244254 config IP6_NF_TARGET_HL
245255 tristate '"HL" hoplimit target support'
net/ipv6/netfilter/Makefile+1−0
@@ -57,6 +57,7 @@ obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o · 56 unmodified lines
5757 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
5858 obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
5959 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
60+obj-$(CONFIG_IP6_NF_MATCH_SRH) += ip6t_srh.o
6061
6162 # targets
6263 obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
net/ipv6/netfilter/ip6_tables.c+0−1
@@ -1952,7 +1952,6 @@ static int __init ip6_tables_init(void) · 1951 unmodified lines
19521952 if (ret < 0)
19531953 goto err5;
19541954
1955− pr_info("(C) 2000-2006 Netfilter Core Team\n");
19561955 return 0;
19571956
19581957 err5:
net/ipv6/netfilter/ip6t_srh.c+161−0
@@ -0,0 +1,161 @@
1+/* Kernel module to match Segment Routing Header (SRH) parameters. */
2+
3+/* Author:
4+ * Ahmed Abdelsalam <amsalam20@gmail.com>
5+ *
6+ * This program is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU General Public License
8+ * as published by the Free Software Foundation; either version 2
9+ * of the License, or (at your option) any later version.
10+ */
11+
12+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13+#include <linux/module.h>
14+#include <linux/skbuff.h>
15+#include <linux/ipv6.h>
16+#include <linux/types.h>
17+#include <net/ipv6.h>
18+#include <net/seg6.h>
19+
20+#include <linux/netfilter/x_tables.h>
21+#include <linux/netfilter_ipv6/ip6t_srh.h>
22+#include <linux/netfilter_ipv6/ip6_tables.h>
23+
24+/* Test a struct->mt_invflags and a boolean for inequality */
25+#define NF_SRH_INVF(ptr, flag, boolean) \
26+ ((boolean) ^ !!((ptr)->mt_invflags & (flag)))
27+
28+static bool srh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
29+{
30+ const struct ip6t_srh *srhinfo = par->matchinfo;
31+ struct ipv6_sr_hdr *srh;
32+ struct ipv6_sr_hdr _srh;
33+ int hdrlen, srhoff = 0;
34+
35+ if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
36+ return false;
37+ srh = skb_header_pointer(skb, srhoff, sizeof(_srh), &_srh);
38+ if (!srh)
39+ return false;
40+
41+ hdrlen = ipv6_optlen(srh);
42+ if (skb->len - srhoff < hdrlen)
43+ return false;
44+
45+ if (srh->type != IPV6_SRCRT_TYPE_4)
46+ return false;
47+
48+ if (srh->segments_left > srh->first_segment)
49+ return false;
50+
51+ /* Next Header matching */
52+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
53+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NEXTHDR,
54+ !(srh->nexthdr == srhinfo->next_hdr)))
55+ return false;
56+
57+ /* Header Extension Length matching */
58+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
59+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_EQ,
60+ !(srh->hdrlen == srhinfo->hdr_len)))
61+ return false;
62+
63+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
64+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_GT,
65+ !(srh->hdrlen > srhinfo->hdr_len)))
66+ return false;
67+
68+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
69+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_LT,
70+ !(srh->hdrlen < srhinfo->hdr_len)))
71+ return false;
72+
73+ /* Segments Left matching */
74+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
75+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_EQ,
76+ !(srh->segments_left == srhinfo->segs_left)))
77+ return false;
78+
79+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
80+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_GT,
81+ !(srh->segments_left > srhinfo->segs_left)))
82+ return false;
83+
84+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
85+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_LT,
86+ !(srh->segments_left < srhinfo->segs_left)))
87+ return false;
88+
89+ /**
90+ * Last Entry matching
91+ * Last_Entry field was introduced in revision 6 of the SRH draft.
92+ * It was called First_Segment in the previous revision
93+ */
94+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
95+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_EQ,
96+ !(srh->first_segment == srhinfo->last_entry)))
97+ return false;
98+
99+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
100+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_GT,
101+ !(srh->first_segment > srhinfo->last_entry)))
102+ return false;
103+
104+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
105+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_LT,
106+ !(srh->first_segment < srhinfo->last_entry)))
107+ return false;
108+
109+ /**
110+ * Tag matchig
111+ * Tag field was introduced in revision 6 of the SRH draft.
112+ */
113+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
114+ if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_TAG,
115+ !(srh->tag == srhinfo->tag)))
116+ return false;
117+ return true;
118+}
119+
120+static int srh_mt6_check(const struct xt_mtchk_param *par)
121+{
122+ const struct ip6t_srh *srhinfo = par->matchinfo;
123+
124+ if (srhinfo->mt_flags & ~IP6T_SRH_MASK) {
125+ pr_err("unknown srh match flags %X\n", srhinfo->mt_flags);
126+ return -EINVAL;
127+ }
128+
129+ if (srhinfo->mt_invflags & ~IP6T_SRH_INV_MASK) {
130+ pr_err("unknown srh invflags %X\n", srhinfo->mt_invflags);
131+ return -EINVAL;
132+ }
133+
134+ return 0;
135+}
136+
137+static struct xt_match srh_mt6_reg __read_mostly = {
138+ .name = "srh",
139+ .family = NFPROTO_IPV6,
140+ .match = srh_mt6,
141+ .matchsize = sizeof(struct ip6t_srh),
142+ .checkentry = srh_mt6_check,
143+ .me = THIS_MODULE,
144+};
145+
146+static int __init srh_mt6_init(void)
147+{
148+ return xt_register_match(&srh_mt6_reg);
149+}
150+
151+static void __exit srh_mt6_exit(void)
152+{
153+ xt_unregister_match(&srh_mt6_reg);
154+}
155+
156+module_init(srh_mt6_init);
157+module_exit(srh_mt6_exit);
158+
159+MODULE_LICENSE("GPL");
160+MODULE_DESCRIPTION("Xtables: IPv6 Segment Routing Header match");
161+MODULE_AUTHOR("Ahmed Abdelsalam <amsalam20@gmail.com>");
net/ipv6/netfilter/ip6table_raw.c+28−3
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 *
44 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
55 */
6+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
67 #include <linux/module.h>
78 #include <linux/netfilter_ipv6/ip6_tables.h>
89 #include <linux/slab.h>
@@ -11,6 +12,10 @@ · 2 unmodified lines
1112
1213 static int __net_init ip6table_raw_table_init(struct net *net);
1314
15+static bool raw_before_defrag __read_mostly;
16+MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
17+module_param(raw_before_defrag, bool, 0000);
18+
1419 static const struct xt_table packet_raw = {
1520 .name = "raw",
1621 .valid_hooks = RAW_VALID_HOOKS,
@@ -20,6 +25,15 @@ static const struct xt_table packet_raw = { · 3 unmodified lines
2025 .table_init = ip6table_raw_table_init,
2126 };
2227
28+static const struct xt_table packet_raw_before_defrag = {
29+ .name = "raw",
30+ .valid_hooks = RAW_VALID_HOOKS,
31+ .me = THIS_MODULE,
32+ .af = NFPROTO_IPV6,
33+ .priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG,
34+ .table_init = ip6table_raw_table_init,
35+};
36+
2337 /* The work comes in here from netfilter.c. */
2438 static unsigned int
2539 ip6table_raw_hook(void *priv, struct sk_buff *skb,
@@ -33,15 +47,19 @@ static struct nf_hook_ops *rawtable_ops __read_mostly; · 7 unmodified lines
3347 static int __net_init ip6table_raw_table_init(struct net *net)
3448 {
3549 struct ip6t_replace *repl;
50+ const struct xt_table *table = &packet_raw;
3651 int ret;
3752
53+ if (raw_before_defrag)
54+ table = &packet_raw_before_defrag;
55+
3856 if (net->ipv6.ip6table_raw)
3957 return 0;
4058
41− repl = ip6t_alloc_initial_table(&packet_raw);
59+ repl = ip6t_alloc_initial_table(table);
4260 if (repl == NULL)
4361 return -ENOMEM;
44− ret = ip6t_register_table(net, &packet_raw, repl, rawtable_ops,
62+ ret = ip6t_register_table(net, table, repl, rawtable_ops,
4563 &net->ipv6.ip6table_raw);
4664 kfree(repl);
4765 return ret;
@@ -62,9 +80,16 @@ static struct pernet_operations ip6table_raw_net_ops = { · 14 unmodified lines
6280 static int __init ip6table_raw_init(void)
6381 {
6482 int ret;
83+ const struct xt_table *table = &packet_raw;
84+
85+ if (raw_before_defrag) {
86+ table = &packet_raw_before_defrag;
87+
88+ pr_info("Enabling raw table before defrag\n");
89+ }
6590
6691 /* Register hooks */
67− rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook);
92+ rawtable_ops = xt_hook_ops_alloc(table, ip6table_raw_hook);
6893 if (IS_ERR(rawtable_ops))
6994 return PTR_ERR(rawtable_ops);
7095
net/ipv6/netfilter/nf_conntrack_reasm.c+10−5
@@ -231,7 +231,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, · 230 unmodified lines
231231
232232 if ((unsigned int)end > IPV6_MAXPLEN) {
233233 pr_debug("offset is too large.\n");
234− return -1;
234+ return -EINVAL;
235235 }
236236
237237 ecn = ip6_frag_ecn(ipv6_hdr(skb));
@@ -264,7 +264,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, · 26 unmodified lines
264264 * this case. -DaveM
265265 */
266266 pr_debug("end of fragment not rounded to 8 bytes.\n");
267− return -1;
267+ return -EPROTO;
268268 }
269269 if (end > fq->q.len) {
270270 /* Some bits beyond end -> corruption. */
@@ -358,7 +358,7 @@ found: · 87 unmodified lines
358358 discard_fq:
359359 inet_frag_kill(&fq->q, &nf_frags);
360360 err:
361− return -1;
361+ return -EINVAL;
362362 }
363363
364364 /*
@@ -567,6 +567,7 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff) · 202 unmodified lines
567567
568568 int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
569569 {
570+ u16 savethdr = skb->transport_header;
570571 struct net_device *dev = skb->dev;
571572 int fhoff, nhoff, ret;
572573 struct frag_hdr *fhdr;
@@ -600,8 +601,12 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) · 27 unmodified lines
600601
601602 spin_lock_bh(&fq->q.lock);
602603
603− if (nf_ct_frag6_queue(fq, skb, fhdr, nhoff) < 0) {
604− ret = -EINVAL;
604+ ret = nf_ct_frag6_queue(fq, skb, fhdr, nhoff);
605+ if (ret < 0) {
606+ if (ret == -EPROTO) {
607+ skb->transport_header = savethdr;
608+ ret = 0;
609+ }
605610 goto out_unlock;
606611 }
607612
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c+3−0
@@ -63,6 +63,9 @@ static unsigned int ipv6_defrag(void *priv, · 62 unmodified lines
6363 /* Previously seen (loopback)? */
6464 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb)))
6565 return NF_ACCEPT;
66+
67+ if (skb->_nfct == IP_CT_UNTRACKED)
68+ return NF_ACCEPT;
6669 #endif
6770
6871 err = nf_ct_frag6_gather(state->net, skb,
net/ipv6/netfilter/nf_flow_table_ipv6.c+0−1
@@ -5,7 +5,6 @@ · 4 unmodified lines
55 #include <linux/rhashtable.h>
66 #include <linux/ipv6.h>
77 #include <linux/netdevice.h>
8−#include <linux/ipv6.h>
98 #include <net/ipv6.h>
109 #include <net/ip6_route.h>
1110 #include <net/neighbour.h>
net/ipv6/netfilter/nf_tables_ipv6.c+2−47
@@ -28,40 +28,6 @@ static unsigned int nft_do_chain_ipv6(void *priv, · 27 unmodified lines
2828 return nft_do_chain(&pkt, priv);
2929 }
3030
31−static struct nft_af_info nft_af_ipv6 __read_mostly = {
32− .family = NFPROTO_IPV6,
33− .nhooks = NF_INET_NUMHOOKS,
34− .owner = THIS_MODULE,
35−};
36−
37−static int nf_tables_ipv6_init_net(struct net *net)
38−{
39− net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
40− if (net->nft.ipv6 == NULL)
41− return -ENOMEM;
42−
43− memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6));
44−
45− if (nft_register_afinfo(net, net->nft.ipv6) < 0)
46− goto err;
47−
48− return 0;
49−err:
50− kfree(net->nft.ipv6);
51− return -ENOMEM;
52−}
53−
54−static void nf_tables_ipv6_exit_net(struct net *net)
55−{
56− nft_unregister_afinfo(net, net->nft.ipv6);
57− kfree(net->nft.ipv6);
58−}
59−
60−static struct pernet_operations nf_tables_ipv6_net_ops = {
61− .init = nf_tables_ipv6_init_net,
62− .exit = nf_tables_ipv6_exit_net,
63−};
64−
6531 static const struct nf_chain_type filter_ipv6 = {
6632 .name = "filter",
6733 .type = NFT_CHAIN_T_DEFAULT,
@@ -83,22 +49,11 @@ static const struct nf_chain_type filter_ipv6 = { · 15 unmodified lines
8349
8450 static int __init nf_tables_ipv6_init(void)
8551 {
86− int ret;
87−
88− ret = nft_register_chain_type(&filter_ipv6);
89− if (ret < 0)
90− return ret;
91−
92− ret = register_pernet_subsys(&nf_tables_ipv6_net_ops);
93− if (ret < 0)
94− nft_unregister_chain_type(&filter_ipv6);
95−
96− return ret;
52+ return nft_register_chain_type(&filter_ipv6);
9753 }
9854
9955 static void __exit nf_tables_ipv6_exit(void)
10056 {
101− unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
10257 nft_unregister_chain_type(&filter_ipv6);
10358 }
10459
@@ -107,4 +62,4 @@ module_exit(nf_tables_ipv6_exit); · 2 unmodified lines
10762
10863 MODULE_LICENSE("GPL");
10964 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
110−MODULE_ALIAS_NFT_FAMILY(AF_INET6);
65+MODULE_ALIAS_NFT_CHAIN(AF_INET6, "filter");
net/netfilter/Kconfig+4−2
@@ -506,7 +506,7 @@ config NFT_CT · 505 unmodified lines
506506 connection tracking information such as the flow state.
507507
508508 config NFT_FLOW_OFFLOAD
509− depends on NF_CONNTRACK
509+ depends on NF_CONNTRACK && NF_FLOW_TABLE
510510 tristate "Netfilter nf_tables hardware flow offload module"
511511 help
512512 This option adds the "flow_offload" expression that you can use to
@@ -665,8 +665,9 @@ endif # NF_TABLES_NETDEV · 152 unmodified lines
665665 endif # NF_TABLES
666666
667667 config NF_FLOW_TABLE_INET
668− select NF_FLOW_TABLE
669668 tristate "Netfilter flow table mixed IPv4/IPv6 module"
669+ depends on NF_FLOW_TABLE_IPV4 && NF_FLOW_TABLE_IPV6
670+ select NF_FLOW_TABLE
670671 help
671672 This option adds the flow table mixed IPv4/IPv6 support.
672673
@@ -674,6 +675,7 @@ config NF_FLOW_TABLE_INET · 1 unmodified line
674675
675676 config NF_FLOW_TABLE
676677 tristate "Netfilter flow table module"
678+ depends on NF_CONNTRACK && NF_TABLES
677679 help
678680 This option adds the flow table core infrastructure.
679681
net/netfilter/core.c+3−3
@@ -140,7 +140,7 @@ nf_hook_entries_grow(const struct nf_hook_entries *old, · 139 unmodified lines
140140
141141 if (reg->nat_hook && orig_ops[i]->nat_hook) {
142142 kvfree(new);
143− return ERR_PTR(-EEXIST);
143+ return ERR_PTR(-EBUSY);
144144 }
145145
146146 if (inserted || reg->priority > orig_ops[i]->priority) {
@@ -377,8 +377,8 @@ static void nf_remove_net_hook(struct nf_hook_entries *old, · 230 unmodified lines
377377 }
378378 }
379379
380−void __nf_unregister_net_hook(struct net *net, int pf,
381− const struct nf_hook_ops *reg)
380+static void __nf_unregister_net_hook(struct net *net, int pf,
381+ const struct nf_hook_ops *reg)
382382 {
383383 struct nf_hook_entries __rcu **pp;
384384 struct nf_hook_entries *p;
net/netfilter/ipset/ip_set_core.c+2−1
@@ -2122,7 +2122,6 @@ ip_set_init(void) · 2121 unmodified lines
21222122 return ret;
21232123 }
21242124
2125− pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL);
21262125 return 0;
21272126 }
21282127
@@ -2138,3 +2137,5 @@ ip_set_fini(void) · 9 unmodified lines
21382137
21392138 module_init(ip_set_init);
21402139 module_exit(ip_set_fini);
2140+
2141+MODULE_DESCRIPTION("ip_set: protocol " __stringify(IPSET_PROTOCOL));
net/netfilter/ipvs/ip_vs_app.c+0−1
@@ -595,7 +595,6 @@ static int ip_vs_app_open(struct inode *inode, struct file *file) · 594 unmodified lines
595595 }
596596
597597 static const struct file_operations ip_vs_app_fops = {
598− .owner = THIS_MODULE,
599598 .open = ip_vs_app_open,
600599 .read = seq_read,
601600 .llseek = seq_lseek,
net/netfilter/ipvs/ip_vs_conn.c+0−2
@@ -1143,7 +1143,6 @@ static int ip_vs_conn_open(struct inode *inode, struct file *file) · 1142 unmodified lines
11431143 }
11441144
11451145 static const struct file_operations ip_vs_conn_fops = {
1146− .owner = THIS_MODULE,
11471146 .open = ip_vs_conn_open,
11481147 .read = seq_read,
11491148 .llseek = seq_lseek,
@@ -1221,7 +1220,6 @@ static int ip_vs_conn_sync_open(struct inode *inode, struct file *file) · 71 unmodified lines
12211220 }
12221221
12231222 static const struct file_operations ip_vs_conn_sync_fops = {
1224− .owner = THIS_MODULE,
12251223 .open = ip_vs_conn_sync_open,
12261224 .read = seq_read,
12271225 .llseek = seq_lseek,
net/netfilter/ipvs/ip_vs_ctl.c+0−3
@@ -2116,7 +2116,6 @@ static int ip_vs_info_open(struct inode *inode, struct file *file) · 2115 unmodified lines
21162116 }
21172117
21182118 static const struct file_operations ip_vs_info_fops = {
2119− .owner = THIS_MODULE,
21202119 .open = ip_vs_info_open,
21212120 .read = seq_read,
21222121 .llseek = seq_lseek,
@@ -2161,7 +2160,6 @@ static int ip_vs_stats_seq_open(struct inode *inode, struct file *file) · 38 unmodified lines
21612160 }
21622161
21632162 static const struct file_operations ip_vs_stats_fops = {
2164− .owner = THIS_MODULE,
21652163 .open = ip_vs_stats_seq_open,
21662164 .read = seq_read,
21672165 .llseek = seq_lseek,
@@ -2230,7 +2228,6 @@ static int ip_vs_stats_percpu_seq_open(struct inode *inode, struct file *file) · 62 unmodified lines
22302228 }
22312229
22322230 static const struct file_operations ip_vs_stats_percpu_fops = {
2233− .owner = THIS_MODULE,
22342231 .open = ip_vs_stats_percpu_seq_open,
22352232 .read = seq_read,
22362233 .llseek = seq_lseek,
net/netfilter/nf_conncount.c+1−1
@@ -71,7 +71,7 @@ static inline bool already_closed(const struct nf_conn *conn) · 70 unmodified lines
7171 return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT ||
7272 conn->proto.tcp.state == TCP_CONNTRACK_CLOSE;
7373 else
74− return 0;
74+ return false;
7575 }
7676
7777 static int key_diff(const u32 *a, const u32 *b, unsigned int klen)
net/netfilter/nf_conntrack_core.c+0−6
@@ -58,8 +58,6 @@ · 57 unmodified lines
5858
5959 #include "nf_internals.h"
6060
61−#define NF_CONNTRACK_VERSION "0.5.0"
62−
6361 int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
6462 enum nf_nat_manip_type manip,
6563 const struct nlattr *attr) __read_mostly;
@@ -2068,10 +2066,6 @@ int nf_conntrack_init_start(void) · 2002 unmodified lines
20682066 if (!nf_conntrack_cachep)
20692067 goto err_cachep;
20702068
2071− printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n",
2072− NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
2073− nf_conntrack_max);
2074−
20752069 ret = nf_conntrack_expect_init();
20762070 if (ret < 0)
20772071 goto err_expect;
net/netfilter/nf_conntrack_expect.c+0−1
@@ -649,7 +649,6 @@ static int exp_open(struct inode *inode, struct file *file) · 648 unmodified lines
649649 }
650650
651651 static const struct file_operations exp_file_ops = {
652− .owner = THIS_MODULE,
653652 .open = exp_open,
654653 .read = seq_read,
655654 .llseek = seq_lseek,
net/netfilter/nf_conntrack_netlink.c+0−5
@@ -57,8 +57,6 @@ · 56 unmodified lines
5757
5858 MODULE_LICENSE("GPL");
5959
60−static char __initdata version[] = "0.93";
61−
6260 static int ctnetlink_dump_tuples_proto(struct sk_buff *skb,
6361 const struct nf_conntrack_tuple *tuple,
6462 const struct nf_conntrack_l4proto *l4proto)
@@ -3425,7 +3423,6 @@ static int __init ctnetlink_init(void) · 3360 unmodified lines
34253423 {
34263424 int ret;
34273425
3428− pr_info("ctnetlink v%s: registering with nfnetlink.\n", version);
34293426 ret = nfnetlink_subsys_register(&ctnl_subsys);
34303427 if (ret < 0) {
34313428 pr_err("ctnetlink_init: cannot register with nfnetlink.\n");
@@ -3459,8 +3456,6 @@ err_out: · 27 unmodified lines
34593456
34603457 static void __exit ctnetlink_exit(void)
34613458 {
3462− pr_info("ctnetlink: unregistering from nfnetlink.\n");
3463−
34643459 unregister_pernet_subsys(&ctnetlink_net_ops);
34653460 nfnetlink_subsys_unregister(&ctnl_exp_subsys);
34663461 nfnetlink_subsys_unregister(&ctnl_subsys);
net/netfilter/nf_conntrack_standalone.c+0−2
@@ -382,7 +382,6 @@ static int ct_open(struct inode *inode, struct file *file) · 381 unmodified lines
382382 }
383383
384384 static const struct file_operations ct_file_ops = {
385− .owner = THIS_MODULE,
386385 .open = ct_open,
387386 .read = seq_read,
388387 .llseek = seq_lseek,
@@ -475,7 +474,6 @@ static int ct_cpu_seq_open(struct inode *inode, struct file *file) · 86 unmodified lines
475474 }
476475
477476 static const struct file_operations ct_cpu_seq_fops = {
478− .owner = THIS_MODULE,
479477 .open = ct_cpu_seq_open,
480478 .read = seq_read,
481479 .llseek = seq_lseek,
net/netfilter/nf_log.c+0−1
@@ -402,7 +402,6 @@ static int nflog_open(struct inode *inode, struct file *file) · 401 unmodified lines
402402 }
403403
404404 static const struct file_operations nflog_file_ops = {
405− .owner = THIS_MODULE,
406405 .open = nflog_open,
407406 .read = seq_read,
408407 .llseek = seq_lseek,
net/netfilter/nf_queue.c+0−2
@@ -15,8 +15,6 @@ · 14 unmodified lines
1515 #include <linux/netfilter_bridge.h>
1616 #include <linux/seq_file.h>
1717 #include <linux/rcupdate.h>
18−#include <linux/netfilter_ipv4.h>
19−#include <linux/netfilter_ipv6.h>
2018 #include <net/protocol.h>
2119 #include <net/netfilter/nf_queue.h>
2220 #include <net/dst.h>
net/netfilter/nf_synproxy_core.c+0−1
@@ -317,7 +317,6 @@ static int synproxy_cpu_seq_open(struct inode *inode, struct file *file) · 316 unmodified lines
317317 }
318318
319319 static const struct file_operations synproxy_cpu_seq_fops = {
320− .owner = THIS_MODULE,
321320 .open = synproxy_cpu_seq_open,
322321 .read = seq_read,
323322 .llseek = seq_lseek,
net/netfilter/nf_tables_api.c+428−504
@@ -26,86 +26,19 @@ · 25 unmodified lines
2626 static LIST_HEAD(nf_tables_expressions);
2727 static LIST_HEAD(nf_tables_objects);
2828 static LIST_HEAD(nf_tables_flowtables);
29−
30−/**
31− * nft_register_afinfo - register nf_tables address family info
32− *
33− * @afi: address family info to register
34− *
35− * Register the address family for use with nf_tables. Returns zero on
36− * success or a negative errno code otherwise.
37− */
38−int nft_register_afinfo(struct net *net, struct nft_af_info *afi)
39−{
40− INIT_LIST_HEAD(&afi->tables);
41− nfnl_lock(NFNL_SUBSYS_NFTABLES);
42− list_add_tail_rcu(&afi->list, &net->nft.af_info);
43− nfnl_unlock(NFNL_SUBSYS_NFTABLES);
44− return 0;
45−}
46−EXPORT_SYMBOL_GPL(nft_register_afinfo);
47−
48−static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi);
49−
50−/**
51− * nft_unregister_afinfo - unregister nf_tables address family info
52− *
53− * @afi: address family info to unregister
54− *
55− * Unregister the address family for use with nf_tables.
56− */
57−void nft_unregister_afinfo(struct net *net, struct nft_af_info *afi)
58−{
59− nfnl_lock(NFNL_SUBSYS_NFTABLES);
60− __nft_release_afinfo(net, afi);
61− list_del_rcu(&afi->list);
62− nfnl_unlock(NFNL_SUBSYS_NFTABLES);
63−}
64−EXPORT_SYMBOL_GPL(nft_unregister_afinfo);
65−
66−static struct nft_af_info *nft_afinfo_lookup(struct net *net, int family)
67−{
68− struct nft_af_info *afi;
69−
70− list_for_each_entry(afi, &net->nft.af_info, list) {
71− if (afi->family == family)
72− return afi;
73− }
74− return NULL;
75−}
76−
77−static struct nft_af_info *
78−nf_tables_afinfo_lookup(struct net *net, int family, bool autoload)
79−{
80− struct nft_af_info *afi;
81−
82− afi = nft_afinfo_lookup(net, family);
83− if (afi != NULL)
84− return afi;
85−#ifdef CONFIG_MODULES
86− if (autoload) {
87− nfnl_unlock(NFNL_SUBSYS_NFTABLES);
88− request_module("nft-afinfo-%u", family);
89− nfnl_lock(NFNL_SUBSYS_NFTABLES);
90− afi = nft_afinfo_lookup(net, family);
91− if (afi != NULL)
92− return ERR_PTR(-EAGAIN);
93− }
94−#endif
95− return ERR_PTR(-EAFNOSUPPORT);
96−}
29+static u64 table_handle;
9730
9831 static void nft_ctx_init(struct nft_ctx *ctx,
9932 struct net *net,
10033 const struct sk_buff *skb,
10134 const struct nlmsghdr *nlh,
102− struct nft_af_info *afi,
35+ u8 family,
10336 struct nft_table *table,
10437 struct nft_chain *chain,
10538 const struct nlattr * const *nla)
10639 {
10740 ctx->net = net;
108− ctx->afi = afi;
41+ ctx->family = family;
10942 ctx->table = table;
11043 ctx->chain = chain;
11144 ctx->nla = nla;
@@ -385,30 +318,61 @@ static int nft_delflowtable(struct nft_ctx *ctx, · 273 unmodified lines
385318 * Tables
386319 */
387320
388−static struct nft_table *nft_table_lookup(const struct nft_af_info *afi,
321+static struct nft_table *nft_table_lookup(const struct net *net,
389322 const struct nlattr *nla,
390− u8 genmask)
323+ u8 family, u8 genmask)
391324 {
392325 struct nft_table *table;
393326
394− list_for_each_entry(table, &afi->tables, list) {
327+ list_for_each_entry(table, &net->nft.tables, list) {
395328 if (!nla_strcmp(nla, table->name) &&
329+ table->family == family &&
330+ nft_active_genmask(table, genmask))
331+ return table;
332+ }
333+ return NULL;
334+}
335+
336+static struct nft_table *nft_table_lookup_byhandle(const struct net *net,
337+ const struct nlattr *nla,
338+ u8 genmask)
339+{
340+ struct nft_table *table;
341+
342+ list_for_each_entry(table, &net->nft.tables, list) {
343+ if (be64_to_cpu(nla_get_be64(nla)) == table->handle &&
396344 nft_active_genmask(table, genmask))
397345 return table;
398346 }
399347 return NULL;
400348 }
401349
402−static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi,
350+static struct nft_table *nf_tables_table_lookup(const struct net *net,
403351 const struct nlattr *nla,
404− u8 genmask)
352+ u8 family, u8 genmask)
405353 {
406354 struct nft_table *table;
407355
408356 if (nla == NULL)
409357 return ERR_PTR(-EINVAL);
410358
411− table = nft_table_lookup(afi, nla, genmask);
359+ table = nft_table_lookup(net, nla, family, genmask);
360+ if (table != NULL)
361+ return table;
362+
363+ return ERR_PTR(-ENOENT);
364+}
365+
366+static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net,
367+ const struct nlattr *nla,
368+ u8 genmask)
369+{
370+ struct nft_table *table;
371+
372+ if (nla == NULL)
373+ return ERR_PTR(-EINVAL);
374+
375+ table = nft_table_lookup_byhandle(net, nla, genmask);
412376 if (table != NULL)
413377 return table;
414378
@@ -423,7 +387,7 @@ static inline u64 nf_tables_alloc_handle(struct nft_table *table) · 8 unmodified lines
423387 static const struct nf_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX];
424388
425389 static const struct nf_chain_type *
426−__nf_tables_chain_type_lookup(int family, const struct nlattr *nla)
390+__nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)
427391 {
428392 int i;
429393
@@ -436,22 +400,20 @@ __nf_tables_chain_type_lookup(int family, const struct nlattr *nla) · 6 unmodified lines
436400 }
437401
438402 static const struct nf_chain_type *
439−nf_tables_chain_type_lookup(const struct nft_af_info *afi,
440− const struct nlattr *nla,
441− bool autoload)
403+nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)
442404 {
443405 const struct nf_chain_type *type;
444406
445− type = __nf_tables_chain_type_lookup(afi->family, nla);
407+ type = __nf_tables_chain_type_lookup(nla, family);
446408 if (type != NULL)
447409 return type;
448410 #ifdef CONFIG_MODULES
449411 if (autoload) {
450412 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
451− request_module("nft-chain-%u-%.*s", afi->family,
413+ request_module("nft-chain-%u-%.*s", family,
452414 nla_len(nla), (const char *)nla_data(nla));
453415 nfnl_lock(NFNL_SUBSYS_NFTABLES);
454− type = __nf_tables_chain_type_lookup(afi->family, nla);
416+ type = __nf_tables_chain_type_lookup(nla, family);
455417 if (type != NULL)
456418 return ERR_PTR(-EAGAIN);
457419 }
@@ -463,6 +425,7 @@ static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { · 5 unmodified lines
463425 [NFTA_TABLE_NAME] = { .type = NLA_STRING,
464426 .len = NFT_TABLE_MAXNAMELEN - 1 },
465427 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 },
428+ [NFTA_TABLE_HANDLE] = { .type = NLA_U64 },
466429 };
467430
468431 static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
@@ -484,7 +447,9 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, · 15 unmodified lines
484447
485448 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
486449 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
487− nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)))
450+ nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) ||
451+ nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle),
452+ NFTA_TABLE_PAD))
488453 goto nla_put_failure;
489454
490455 nlmsg_end(skb, nlh);
@@ -509,7 +474,7 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event) · 18 unmodified lines
509474 goto err;
510475
511476 err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq,
512− event, 0, ctx->afi->family, ctx->table);
477+ event, 0, ctx->family, ctx->table);
513478 if (err < 0) {
514479 kfree_skb(skb);
515480 goto err;
@@ -526,7 +491,6 @@ static int nf_tables_dump_tables(struct sk_buff *skb, · 10 unmodified lines
526491 struct netlink_callback *cb)
527492 {
528493 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
529− const struct nft_af_info *afi;
530494 const struct nft_table *table;
531495 unsigned int idx = 0, s_idx = cb->args[0];
532496 struct net *net = sock_net(skb->sk);
@@ -535,30 +499,27 @@ static int nf_tables_dump_tables(struct sk_buff *skb, · 2 unmodified lines
535499 rcu_read_lock();
536500 cb->seq = net->nft.base_seq;
537501
538− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
539− if (family != NFPROTO_UNSPEC && family != afi->family)
502+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
503+ if (family != NFPROTO_UNSPEC && family != table->family)
540504 continue;
541505
542− list_for_each_entry_rcu(table, &afi->tables, list) {
543− if (idx < s_idx)
544− goto cont;
545− if (idx > s_idx)
546− memset(&cb->args[1], 0,
547− sizeof(cb->args) - sizeof(cb->args[0]));
548− if (!nft_is_active(net, table))
549− continue;
550− if (nf_tables_fill_table_info(skb, net,
551− NETLINK_CB(cb->skb).portid,
552− cb->nlh->nlmsg_seq,
553− NFT_MSG_NEWTABLE,
554− NLM_F_MULTI,
555− afi->family, table) < 0)
556− goto done;
557−
558− nl_dump_check_consistent(cb, nlmsg_hdr(skb));
506+ if (idx < s_idx)
507+ goto cont;
508+ if (idx > s_idx)
509+ memset(&cb->args[1], 0,
510+ sizeof(cb->args) - sizeof(cb->args[0]));
511+ if (!nft_is_active(net, table))
512+ continue;
513+ if (nf_tables_fill_table_info(skb, net,
514+ NETLINK_CB(cb->skb).portid,
515+ cb->nlh->nlmsg_seq,
516+ NFT_MSG_NEWTABLE, NLM_F_MULTI,
517+ table->family, table) < 0)
518+ goto done;
519+
520+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
559521 cont:
560− idx++;
561− }
522+ idx++;
562523 }
563524 done:
564525 rcu_read_unlock();
@@ -573,7 +534,6 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk, · 8 unmodified lines
573534 {
574535 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
575536 u8 genmask = nft_genmask_cur(net);
576− const struct nft_af_info *afi;
577537 const struct nft_table *table;
578538 struct sk_buff *skb2;
579539 int family = nfmsg->nfgen_family;
@@ -586,11 +546,8 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk, · 6 unmodified lines
586546 return netlink_dump_start(nlsk, skb, nlh, &c);
587547 }
588548
589− afi = nf_tables_afinfo_lookup(net, family, false);
590− if (IS_ERR(afi))
591− return PTR_ERR(afi);
592−
593− table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
549+ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family,
550+ genmask);
594551 if (IS_ERR(table))
595552 return PTR_ERR(table);
596553
@@ -611,10 +568,7 @@ err: · 14 unmodified lines
611568 return err;
612569 }
613570
614−static void _nf_tables_table_disable(struct net *net,
615− const struct nft_af_info *afi,
616− struct nft_table *table,
617− u32 cnt)
571+static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt)
618572 {
619573 struct nft_chain *chain;
620574 u32 i = 0;
@@ -632,9 +586,7 @@ static void _nf_tables_table_disable(struct net *net, · 11 unmodified lines
632586 }
633587 }
634588
635−static int nf_tables_table_enable(struct net *net,
636− const struct nft_af_info *afi,
637− struct nft_table *table)
589+static int nf_tables_table_enable(struct net *net, struct nft_table *table)
638590 {
639591 struct nft_chain *chain;
640592 int err, i = 0;
@@ -654,15 +606,13 @@ static int nf_tables_table_enable(struct net *net, · 13 unmodified lines
654606 return 0;
655607 err:
656608 if (i)
657− _nf_tables_table_disable(net, afi, table, i);
609+ nft_table_disable(net, table, i);
658610 return err;
659611 }
660612
661−static void nf_tables_table_disable(struct net *net,
662− const struct nft_af_info *afi,
663− struct nft_table *table)
613+static void nf_tables_table_disable(struct net *net, struct nft_table *table)
664614 {
665− _nf_tables_table_disable(net, afi, table, 0);
615+ nft_table_disable(net, table, 0);
666616 }
667617
668618 static int nf_tables_updtable(struct nft_ctx *ctx)
@@ -691,7 +641,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx) · 22 unmodified lines
691641 nft_trans_table_enable(trans) = false;
692642 } else if (!(flags & NFT_TABLE_F_DORMANT) &&
693643 ctx->table->flags & NFT_TABLE_F_DORMANT) {
694− ret = nf_tables_table_enable(ctx->net, ctx->afi, ctx->table);
644+ ret = nf_tables_table_enable(ctx->net, ctx->table);
695645 if (ret >= 0) {
696646 ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
697647 nft_trans_table_enable(trans) = true;
@@ -716,19 +666,14 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, · 18 unmodified lines
716666 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
717667 u8 genmask = nft_genmask_next(net);
718668 const struct nlattr *name;
719− struct nft_af_info *afi;
720669 struct nft_table *table;
721670 int family = nfmsg->nfgen_family;
722671 u32 flags = 0;
723672 struct nft_ctx ctx;
724673 int err;
725674
726− afi = nf_tables_afinfo_lookup(net, family, true);
727− if (IS_ERR(afi))
728− return PTR_ERR(afi);
729−
730675 name = nla[NFTA_TABLE_NAME];
731− table = nf_tables_table_lookup(afi, name, genmask);
676+ table = nf_tables_table_lookup(net, name, family, genmask);
732677 if (IS_ERR(table)) {
733678 if (PTR_ERR(table) != -ENOENT)
734679 return PTR_ERR(table);
@@ -738,7 +683,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, · 3 unmodified lines
738683 if (nlh->nlmsg_flags & NLM_F_REPLACE)
739684 return -EOPNOTSUPP;
740685
741− nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
686+ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
742687 return nf_tables_updtable(&ctx);
743688 }
744689
@@ -748,39 +693,35 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, · 3 unmodified lines
748693 return -EINVAL;
749694 }
750695
751− err = -EAFNOSUPPORT;
752− if (!try_module_get(afi->owner))
753− goto err1;
754−
755696 err = -ENOMEM;
756697 table = kzalloc(sizeof(*table), GFP_KERNEL);
757698 if (table == NULL)
758− goto err2;
699+ goto err_kzalloc;
759700
760701 table->name = nla_strdup(name, GFP_KERNEL);
761702 if (table->name == NULL)
762− goto err3;
703+ goto err_strdup;
763704
764705 INIT_LIST_HEAD(&table->chains);
765706 INIT_LIST_HEAD(&table->sets);
766707 INIT_LIST_HEAD(&table->objects);
767708 INIT_LIST_HEAD(&table->flowtables);
709+ table->family = family;
768710 table->flags = flags;
711+ table->handle = ++table_handle;
769712
770− nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
713+ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
771714 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
772715 if (err < 0)
773− goto err4;
716+ goto err_trans;
774717
775− list_add_tail_rcu(&table->list, &afi->tables);
718+ list_add_tail_rcu(&table->list, &net->nft.tables);
776719 return 0;
777−err4:
720+err_trans:
778721 kfree(table->name);
779−err3:
722+err_strdup:
780723 kfree(table);
781−err2:
782− module_put(afi->owner);
783−err1:
724+err_kzalloc:
784725 return err;
785726 }
786727
@@ -846,30 +787,28 @@ out: · 59 unmodified lines
846787
847788 static int nft_flush(struct nft_ctx *ctx, int family)
848789 {
849− struct nft_af_info *afi;
850790 struct nft_table *table, *nt;
851791 const struct nlattr * const *nla = ctx->nla;
852792 int err = 0;
853793
854− list_for_each_entry(afi, &ctx->net->nft.af_info, list) {
855− if (family != AF_UNSPEC && afi->family != family)
794+ list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) {
795+ if (family != AF_UNSPEC && table->family != family)
856796 continue;
857797
858− ctx->afi = afi;
859− list_for_each_entry_safe(table, nt, &afi->tables, list) {
860− if (!nft_is_active_next(ctx->net, table))
861− continue;
798+ ctx->family = table->family;
862799
863− if (nla[NFTA_TABLE_NAME] &&
864− nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
865− continue;
800+ if (!nft_is_active_next(ctx->net, table))
801+ continue;
866802
867− ctx->table = table;
803+ if (nla[NFTA_TABLE_NAME] &&
804+ nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
805+ continue;
868806
869− err = nft_flush_table(ctx);
870− if (err < 0)
871− goto out;
872− }
807+ ctx->table = table;
808+
809+ err = nft_flush_table(ctx);
810+ if (err < 0)
811+ goto out;
873812 }
874813 out:
875814 return err;
@@ -882,20 +821,23 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk, · 6 unmodified lines
882821 {
883822 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
884823 u8 genmask = nft_genmask_next(net);
885− struct nft_af_info *afi;
886824 struct nft_table *table;
887825 int family = nfmsg->nfgen_family;
888826 struct nft_ctx ctx;
889827
890− nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla);
891− if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL)
828+ nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla);
829+ if (family == AF_UNSPEC ||
830+ (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE]))
892831 return nft_flush(&ctx, family);
893832
894− afi = nf_tables_afinfo_lookup(net, family, false);
895− if (IS_ERR(afi))
896− return PTR_ERR(afi);
833+ if (nla[NFTA_TABLE_HANDLE])
834+ table = nf_tables_table_lookup_byhandle(net,
835+ nla[NFTA_TABLE_HANDLE],
836+ genmask);
837+ else
838+ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME],
839+ family, genmask);
897840
898− table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
899841 if (IS_ERR(table))
900842 return PTR_ERR(table);
901843
@@ -903,7 +845,7 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk, · 1 unmodified line
903845 table->use > 0)
904846 return -EBUSY;
905847
906− ctx.afi = afi;
848+ ctx.family = family;
907849 ctx.table = table;
908850
909851 return nft_flush_table(&ctx);
@@ -915,7 +857,6 @@ static void nf_tables_table_destroy(struct nft_ctx *ctx) · 5 unmodified lines
915857
916858 kfree(ctx->table->name);
917859 kfree(ctx->table);
918− module_put(ctx->afi->owner);
919860 }
920861
921862 int nft_register_chain_type(const struct nf_chain_type *ctype)
@@ -1116,7 +1057,7 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event) · 194 unmodified lines
11161057 goto err;
11171058
11181059 err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq,
1119− event, 0, ctx->afi->family, ctx->table,
1060+ event, 0, ctx->family, ctx->table,
11201061 ctx->chain);
11211062 if (err < 0) {
11221063 kfree_skb(skb);
@@ -1134,7 +1075,6 @@ static int nf_tables_dump_chains(struct sk_buff *skb, · 11 unmodified lines
11341075 struct netlink_callback *cb)
11351076 {
11361077 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
1137− const struct nft_af_info *afi;
11381078 const struct nft_table *table;
11391079 const struct nft_chain *chain;
11401080 unsigned int idx = 0, s_idx = cb->args[0];
@@ -1144,31 +1084,30 @@ static int nf_tables_dump_chains(struct sk_buff *skb, · 3 unmodified lines
11441084 rcu_read_lock();
11451085 cb->seq = net->nft.base_seq;
11461086
1147− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
1148− if (family != NFPROTO_UNSPEC && family != afi->family)
1087+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
1088+ if (family != NFPROTO_UNSPEC && family != table->family)
11491089 continue;
11501090
1151− list_for_each_entry_rcu(table, &afi->tables, list) {
1152− list_for_each_entry_rcu(chain, &table->chains, list) {
1153− if (idx < s_idx)
1154− goto cont;
1155− if (idx > s_idx)
1156− memset(&cb->args[1], 0,
1157− sizeof(cb->args) - sizeof(cb->args[0]));
1158− if (!nft_is_active(net, chain))
1159− continue;
1160− if (nf_tables_fill_chain_info(skb, net,
1161− NETLINK_CB(cb->skb).portid,
1162− cb->nlh->nlmsg_seq,
1163− NFT_MSG_NEWCHAIN,
1164− NLM_F_MULTI,
1165− afi->family, table, chain) < 0)
1166− goto done;
1091+ list_for_each_entry_rcu(chain, &table->chains, list) {
1092+ if (idx < s_idx)
1093+ goto cont;
1094+ if (idx > s_idx)
1095+ memset(&cb->args[1], 0,
1096+ sizeof(cb->args) - sizeof(cb->args[0]));
1097+ if (!nft_is_active(net, chain))
1098+ continue;
1099+ if (nf_tables_fill_chain_info(skb, net,
1100+ NETLINK_CB(cb->skb).portid,
1101+ cb->nlh->nlmsg_seq,
1102+ NFT_MSG_NEWCHAIN,
1103+ NLM_F_MULTI,
1104+ table->family, table,
1105+ chain) < 0)
1106+ goto done;
11671107
1168− nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1108+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
11691109 cont:
1170− idx++;
1171− }
1110+ idx++;
11721111 }
11731112 }
11741113 done:
@@ -1184,7 +1123,6 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk, · 9 unmodified lines
11841123 {
11851124 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
11861125 u8 genmask = nft_genmask_cur(net);
1187− const struct nft_af_info *afi;
11881126 const struct nft_table *table;
11891127 const struct nft_chain *chain;
11901128 struct sk_buff *skb2;
@@ -1198,11 +1136,8 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk, · 7 unmodified lines
11981136 return netlink_dump_start(nlsk, skb, nlh, &c);
11991137 }
12001138
1201− afi = nf_tables_afinfo_lookup(net, family, false);
1202− if (IS_ERR(afi))
1203− return PTR_ERR(afi);
1204−
1205− table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
1139+ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family,
1140+ genmask);
12061141 if (IS_ERR(table))
12071142 return PTR_ERR(table);
12081143
@@ -1310,8 +1245,8 @@ struct nft_chain_hook { · 101 unmodified lines
13101245
13111246 static int nft_chain_parse_hook(struct net *net,
13121247 const struct nlattr * const nla[],
1313− struct nft_af_info *afi,
1314− struct nft_chain_hook *hook, bool create)
1248+ struct nft_chain_hook *hook, u8 family,
1249+ bool create)
13151250 {
13161251 struct nlattr *ha[NFTA_HOOK_MAX + 1];
13171252 const struct nf_chain_type *type;
@@ -1328,15 +1263,12 @@ static int nft_chain_parse_hook(struct net *net, · 10 unmodified lines
13281263 return -EINVAL;
13291264
13301265 hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
1331− if (hook->num >= afi->nhooks)
1332− return -EINVAL;
1333−
13341266 hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
13351267
1336− type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT];
1268+ type = chain_type[family][NFT_CHAIN_T_DEFAULT];
13371269 if (nla[NFTA_CHAIN_TYPE]) {
1338− type = nf_tables_chain_type_lookup(afi, nla[NFTA_CHAIN_TYPE],
1339− create);
1270+ type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE],
1271+ family, create);
13401272 if (IS_ERR(type))
13411273 return PTR_ERR(type);
13421274 }
@@ -1353,7 +1285,7 @@ static int nft_chain_parse_hook(struct net *net, · 10 unmodified lines
13531285 hook->type = type;
13541286
13551287 hook->dev = NULL;
1356− if (afi->flags & NFT_AF_NEEDS_DEV) {
1288+ if (family == NFPROTO_NETDEV) {
13571289 char ifname[IFNAMSIZ];
13581290
13591291 if (!ha[NFTA_HOOK_DEV]) {
@@ -1388,7 +1320,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 28 unmodified lines
13881320 {
13891321 const struct nlattr * const *nla = ctx->nla;
13901322 struct nft_table *table = ctx->table;
1391− struct nft_af_info *afi = ctx->afi;
13921323 struct nft_base_chain *basechain;
13931324 struct nft_stats __percpu *stats;
13941325 struct net *net = ctx->net;
@@ -1402,7 +1333,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, · 7 unmodified lines
14021333 struct nft_chain_hook hook;
14031334 struct nf_hook_ops *ops;
14041335
1405− err = nft_chain_parse_hook(net, nla, afi, &hook, create);
1336+ err = nft_chain_parse_hook(net, nla, &hook, family, create);
14061337 if (err < 0)
14071338 return err;
14081339
@@ -1495,7 +1426,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, · 86 unmodified lines
14951426 if (!nft_is_base_chain(chain))
14961427 return -EBUSY;
14971428
1498− err = nft_chain_parse_hook(ctx->net, nla, ctx->afi, &hook,
1429+ err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
14991430 create);
15001431 if (err < 0)
15011432 return err;
@@ -1574,7 +1505,6 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 72 unmodified lines
15741505 const struct nlattr * uninitialized_var(name);
15751506 u8 genmask = nft_genmask_next(net);
15761507 int family = nfmsg->nfgen_family;
1577− struct nft_af_info *afi;
15781508 struct nft_table *table;
15791509 struct nft_chain *chain;
15801510 u8 policy = NF_ACCEPT;
@@ -1584,11 +1514,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 3 unmodified lines
15841514
15851515 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
15861516
1587− afi = nf_tables_afinfo_lookup(net, family, true);
1588− if (IS_ERR(afi))
1589− return PTR_ERR(afi);
1590−
1591− table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
1517+ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family,
1518+ genmask);
15921519 if (IS_ERR(table))
15931520 return PTR_ERR(table);
15941521
@@ -1628,7 +1555,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, · 33 unmodified lines
16281555 }
16291556 }
16301557
1631− nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
1558+ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
16321559
16331560 if (chain != NULL) {
16341561 if (nlh->nlmsg_flags & NLM_F_EXCL)
@@ -1649,24 +1576,26 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, · 14 unmodified lines
16491576 {
16501577 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
16511578 u8 genmask = nft_genmask_next(net);
1652− struct nft_af_info *afi;
16531579 struct nft_table *table;
16541580 struct nft_chain *chain;
16551581 struct nft_rule *rule;
16561582 int family = nfmsg->nfgen_family;
16571583 struct nft_ctx ctx;
1584+ u64 handle;
16581585 u32 use;
16591586 int err;
16601587
1661− afi = nf_tables_afinfo_lookup(net, family, false);
1662− if (IS_ERR(afi))
1663− return PTR_ERR(afi);
1664−
1665− table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
1588+ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family,
1589+ genmask);
16661590 if (IS_ERR(table))
16671591 return PTR_ERR(table);
16681592
1669− chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
1593+ if (nla[NFTA_CHAIN_HANDLE]) {
1594+ handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
1595+ chain = nf_tables_chain_lookup_byhandle(table, handle, genmask);
1596+ } else {
1597+ chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
1598+ }
16701599 if (IS_ERR(chain))
16711600 return PTR_ERR(chain);
16721601
@@ -1674,7 +1603,7 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, · 1 unmodified line
16741603 chain->use > 0)
16751604 return -EBUSY;
16761605
1677− nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
1606+ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
16781607
16791608 use = chain->use;
16801609 list_for_each_entry(rule, &chain->rules, list) {
@@ -1839,7 +1768,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx, · 158 unmodified lines
18391768 if (err < 0)
18401769 return err;
18411770
1842− type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]);
1771+ type = nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]);
18431772 if (IS_ERR(type))
18441773 return PTR_ERR(type);
18451774
@@ -2062,7 +1991,7 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx, · 216 unmodified lines
20621991 goto err;
20631992
20641993 err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
2065− event, 0, ctx->afi->family, ctx->table,
1994+ event, 0, ctx->family, ctx->table,
20661995 ctx->chain, rule);
20671996 if (err < 0) {
20681997 kfree_skb(skb);
@@ -2086,7 +2015,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb, · 17 unmodified lines
20862015 {
20872016 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
20882017 const struct nft_rule_dump_ctx *ctx = cb->data;
2089− const struct nft_af_info *afi;
20902018 const struct nft_table *table;
20912019 const struct nft_chain *chain;
20922020 const struct nft_rule *rule;
@@ -2097,39 +2025,37 @@ static int nf_tables_dump_rules(struct sk_buff *skb, · 4 unmodified lines
20972025 rcu_read_lock();
20982026 cb->seq = net->nft.base_seq;
20992027
2100− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
2101− if (family != NFPROTO_UNSPEC && family != afi->family)
2028+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
2029+ if (family != NFPROTO_UNSPEC && family != table->family)
21022030 continue;
21032031
2104− list_for_each_entry_rcu(table, &afi->tables, list) {
2105− if (ctx && ctx->table &&
2106− strcmp(ctx->table, table->name) != 0)
2032+ if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
2033+ continue;
2034+
2035+ list_for_each_entry_rcu(chain, &table->chains, list) {
2036+ if (ctx && ctx->chain &&
2037+ strcmp(ctx->chain, chain->name) != 0)
21072038 continue;
21082039
2109− list_for_each_entry_rcu(chain, &table->chains, list) {
2110− if (ctx && ctx->chain &&
2111− strcmp(ctx->chain, chain->name) != 0)
2112− continue;
2113−
2114− list_for_each_entry_rcu(rule, &chain->rules, list) {
2115− if (!nft_is_active(net, rule))
2116− goto cont;
2117− if (idx < s_idx)
2118− goto cont;
2119− if (idx > s_idx)
2120− memset(&cb->args[1], 0,
2121− sizeof(cb->args) - sizeof(cb->args[0]));
2122− if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid,
2123− cb->nlh->nlmsg_seq,
2124− NFT_MSG_NEWRULE,
2125− NLM_F_MULTI | NLM_F_APPEND,
2126− afi->family, table, chain, rule) < 0)
2127− goto done;
2128−
2129− nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2040+ list_for_each_entry_rcu(rule, &chain->rules, list) {
2041+ if (!nft_is_active(net, rule))
2042+ goto cont;
2043+ if (idx < s_idx)
2044+ goto cont;
2045+ if (idx > s_idx)
2046+ memset(&cb->args[1], 0,
2047+ sizeof(cb->args) - sizeof(cb->args[0]));
2048+ if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid,
2049+ cb->nlh->nlmsg_seq,
2050+ NFT_MSG_NEWRULE,
2051+ NLM_F_MULTI | NLM_F_APPEND,
2052+ table->family,
2053+ table, chain, rule) < 0)
2054+ goto done;
2055+
2056+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
21302057 cont:
2131− idx++;
2132− }
2058+ idx++;
21332059 }
21342060 }
21352061 }
@@ -2159,7 +2085,6 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, · 23 unmodified lines
21592085 {
21602086 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
21612087 u8 genmask = nft_genmask_cur(net);
2162− const struct nft_af_info *afi;
21632088 const struct nft_table *table;
21642089 const struct nft_chain *chain;
21652090 const struct nft_rule *rule;
@@ -2203,11 +2128,8 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, · 37 unmodified lines
22032128 return netlink_dump_start(nlsk, skb, nlh, &c);
22042129 }
22052130
2206− afi = nf_tables_afinfo_lookup(net, family, false);
2207− if (IS_ERR(afi))
2208− return PTR_ERR(afi);
2209−
2210− table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
2131+ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family,
2132+ genmask);
22112133 if (IS_ERR(table))
22122134 return PTR_ERR(table);
22132135
@@ -2264,7 +2186,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, · 50 unmodified lines
22642186 {
22652187 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
22662188 u8 genmask = nft_genmask_next(net);
2267− struct nft_af_info *afi;
2189+ int family = nfmsg->nfgen_family;
22682190 struct nft_table *table;
22692191 struct nft_chain *chain;
22702192 struct nft_rule *rule, *old_rule = NULL;
@@ -2280,11 +2202,8 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, · 9 unmodified lines
22802202
22812203 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
22822204
2283− afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
2284− if (IS_ERR(afi))
2285− return PTR_ERR(afi);
2286−
2287− table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
2205+ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family,
2206+ genmask);
22882207 if (IS_ERR(table))
22892208 return PTR_ERR(table);
22902209
@@ -2323,7 +2242,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, · 32 unmodified lines
23232242 return PTR_ERR(old_rule);
23242243 }
23252244
2326− nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
2245+ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
23272246
23282247 n = 0;
23292248 size = 0;
@@ -2447,18 +2366,14 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, · 117 unmodified lines
24472366 {
24482367 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
24492368 u8 genmask = nft_genmask_next(net);
2450− struct nft_af_info *afi;
24512369 struct nft_table *table;
24522370 struct nft_chain *chain = NULL;
24532371 struct nft_rule *rule;
24542372 int family = nfmsg->nfgen_family, err = 0;
24552373 struct nft_ctx ctx;
24562374
2457− afi = nf_tables_afinfo_lookup(net, family, false);
2458− if (IS_ERR(afi))
2459− return PTR_ERR(afi);
2460−
2461− table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
2375+ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family,
2376+ genmask);
24622377 if (IS_ERR(table))
24632378 return PTR_ERR(table);
24642379
@@ -2469,7 +2384,7 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, · 4 unmodified lines
24692384 return PTR_ERR(chain);
24702385 }
24712386
2472− nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
2387+ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
24732388
24742389 if (chain) {
24752390 if (nla[NFTA_RULE_HANDLE]) {
@@ -2636,6 +2551,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = { · 160 unmodified lines
26362551 [NFTA_SET_USERDATA] = { .type = NLA_BINARY,
26372552 .len = NFT_USERDATA_MAXLEN },
26382553 [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 },
2554+ [NFTA_SET_HANDLE] = { .type = NLA_U64 },
26392555 };
26402556
26412557 static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
@@ -2649,26 +2565,17 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net, · 7 unmodified lines
26492565 u8 genmask)
26502566 {
26512567 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2652− struct nft_af_info *afi = NULL;
2568+ int family = nfmsg->nfgen_family;
26532569 struct nft_table *table = NULL;
26542570
2655− if (nfmsg->nfgen_family != NFPROTO_UNSPEC) {
2656− afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
2657− if (IS_ERR(afi))
2658− return PTR_ERR(afi);
2659− }
2660−
26612571 if (nla[NFTA_SET_TABLE] != NULL) {
2662− if (afi == NULL)
2663− return -EAFNOSUPPORT;
2664−
2665− table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE],
2666− genmask);
2572+ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE],
2573+ family, genmask);
26672574 if (IS_ERR(table))
26682575 return PTR_ERR(table);
26692576 }
26702577
2671− nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
2578+ nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
26722579 return 0;
26732580 }
26742581
@@ -2688,6 +2595,22 @@ static struct nft_set *nf_tables_set_lookup(const struct nft_table *table, · 13 unmodified lines
26882595 return ERR_PTR(-ENOENT);
26892596 }
26902597
2598+static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table,
2599+ const struct nlattr *nla, u8 genmask)
2600+{
2601+ struct nft_set *set;
2602+
2603+ if (nla == NULL)
2604+ return ERR_PTR(-EINVAL);
2605+
2606+ list_for_each_entry(set, &table->sets, list) {
2607+ if (be64_to_cpu(nla_get_be64(nla)) == set->handle &&
2608+ nft_active_genmask(set, genmask))
2609+ return set;
2610+ }
2611+ return ERR_PTR(-ENOENT);
2612+}
2613+
26912614 static struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
26922615 const struct nlattr *nla,
26932616 u8 genmask)
@@ -2795,7 +2718,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, · 101 unmodified lines
27952718 goto nla_put_failure;
27962719
27972720 nfmsg = nlmsg_data(nlh);
2798− nfmsg->nfgen_family = ctx->afi->family;
2721+ nfmsg->nfgen_family = ctx->family;
27992722 nfmsg->version = NFNETLINK_V0;
28002723 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
28012724
@@ -2803,6 +2726,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, · 1 unmodified line
28032726 goto nla_put_failure;
28042727 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
28052728 goto nla_put_failure;
2729+ if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle),
2730+ NFTA_SET_PAD))
2731+ goto nla_put_failure;
28062732 if (set->flags != 0)
28072733 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags)))
28082734 goto nla_put_failure;
@@ -2887,10 +2813,8 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) · 78 unmodified lines
28872813 {
28882814 const struct nft_set *set;
28892815 unsigned int idx, s_idx = cb->args[0];
2890− struct nft_af_info *afi;
28912816 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
28922817 struct net *net = sock_net(skb->sk);
2893− int cur_family = cb->args[3];
28942818 struct nft_ctx *ctx = cb->data, ctx_set;
28952819
28962820 if (cb->args[1])
@@ -2899,51 +2823,44 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) · 2 unmodified lines
28992823 rcu_read_lock();
29002824 cb->seq = net->nft.base_seq;
29012825
2902− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
2903− if (ctx->afi && ctx->afi != afi)
2826+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
2827+ if (ctx->family != NFPROTO_UNSPEC &&
2828+ ctx->family != table->family)
29042829 continue;
29052830
2906− if (cur_family) {
2907− if (afi->family != cur_family)
2831+ if (ctx->table && ctx->table != table)
2832+ continue;
2833+
2834+ if (cur_table) {
2835+ if (cur_table != table)
29082836 continue;
29092837
2910− cur_family = 0;
2838+ cur_table = NULL;
29112839 }
2912− list_for_each_entry_rcu(table, &afi->tables, list) {
2913− if (ctx->table && ctx->table != table)
2914− continue;
2840+ idx = 0;
2841+ list_for_each_entry_rcu(set, &table->sets, list) {
2842+ if (idx < s_idx)
2843+ goto cont;
2844+ if (!nft_is_active(net, set))
2845+ goto cont;
29152846
2916− if (cur_table) {
2917− if (cur_table != table)
2918− continue;
2847+ ctx_set = *ctx;
2848+ ctx_set.table = table;
2849+ ctx_set.family = table->family;
29192850
2920− cur_table = NULL;
2851+ if (nf_tables_fill_set(skb, &ctx_set, set,
2852+ NFT_MSG_NEWSET,
2853+ NLM_F_MULTI) < 0) {
2854+ cb->args[0] = idx;
2855+ cb->args[2] = (unsigned long) table;
2856+ goto done;
29212857 }
2922− idx = 0;
2923− list_for_each_entry_rcu(set, &table->sets, list) {
2924− if (idx < s_idx)
2925− goto cont;
2926− if (!nft_is_active(net, set))
2927− goto cont;
2928−
2929− ctx_set = *ctx;
2930− ctx_set.table = table;
2931− ctx_set.afi = afi;
2932− if (nf_tables_fill_set(skb, &ctx_set, set,
2933− NFT_MSG_NEWSET,
2934− NLM_F_MULTI) < 0) {
2935− cb->args[0] = idx;
2936− cb->args[2] = (unsigned long) table;
2937− cb->args[3] = afi->family;
2938− goto done;
2939− }
2940− nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2858+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
29412859 cont:
2942− idx++;
2943− }
2944− if (s_idx)
2945− s_idx = 0;
2860+ idx++;
29462861 }
2862+ if (s_idx)
2863+ s_idx = 0;
29472864 }
29482865 cb->args[1] = 1;
29492866 done:
@@ -3041,8 +2958,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 91 unmodified lines
30412958 {
30422959 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
30432960 u8 genmask = nft_genmask_next(net);
2961+ int family = nfmsg->nfgen_family;
30442962 const struct nft_set_ops *ops;
3045− struct nft_af_info *afi;
30462963 struct nft_table *table;
30472964 struct nft_set *set;
30482965 struct nft_ctx ctx;
@@ -3149,15 +3066,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 100 unmodified lines
31493066
31503067 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
31513068
3152− afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
3153− if (IS_ERR(afi))
3154− return PTR_ERR(afi);
3155−
3156− table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask);
3069+ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], family,
3070+ genmask);
31573071 if (IS_ERR(table))
31583072 return PTR_ERR(table);
31593073
3160− nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
3074+ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
31613075
31623076 set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask);
31633077 if (IS_ERR(set)) {
@@ -3223,6 +3137,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 59 unmodified lines
32233137 set->udata = udata;
32243138 set->timeout = timeout;
32253139 set->gc_int = gc_int;
3140+ set->handle = nf_tables_alloc_handle(table);
32263141
32273142 err = ops->init(set, &desc, nla);
32283143 if (err < 0)
@@ -3280,7 +3195,10 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk, · 51 unmodified lines
32803195 if (err < 0)
32813196 return err;
32823197
3283− set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
3198+ if (nla[NFTA_SET_HANDLE])
3199+ set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask);
3200+ else
3201+ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
32843202 if (IS_ERR(set))
32853203 return PTR_ERR(set);
32863204
@@ -3415,19 +3333,15 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net, · 128 unmodified lines
34153333 u8 genmask)
34163334 {
34173335 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
3418− struct nft_af_info *afi;
3336+ int family = nfmsg->nfgen_family;
34193337 struct nft_table *table;
34203338
3421− afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
3422− if (IS_ERR(afi))
3423− return PTR_ERR(afi);
3424−
3425− table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE],
3426− genmask);
3339+ table = nf_tables_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE],
3340+ family, genmask);
34273341 if (IS_ERR(table))
34283342 return PTR_ERR(table);
34293343
3430− nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
3344+ nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
34313345 return 0;
34323346 }
34333347
@@ -3532,7 +3446,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) · 98 unmodified lines
35323446 {
35333447 struct nft_set_dump_ctx *dump_ctx = cb->data;
35343448 struct net *net = sock_net(skb->sk);
3535− struct nft_af_info *afi;
35363449 struct nft_table *table;
35373450 struct nft_set *set;
35383451 struct nft_set_dump_args args;
@@ -3544,21 +3457,19 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) · 5 unmodified lines
35443457 int event;
35453458
35463459 rcu_read_lock();
3547− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
3548− if (afi != dump_ctx->ctx.afi)
3460+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
3461+ if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
3462+ dump_ctx->ctx.family != table->family)
35493463 continue;
35503464
3551− list_for_each_entry_rcu(table, &afi->tables, list) {
3552− if (table != dump_ctx->ctx.table)
3553− continue;
3465+ if (table != dump_ctx->ctx.table)
3466+ continue;
35543467
3555− list_for_each_entry_rcu(set, &table->sets, list) {
3556− if (set == dump_ctx->set) {
3557− set_found = true;
3558− break;
3559− }
3468+ list_for_each_entry_rcu(set, &table->sets, list) {
3469+ if (set == dump_ctx->set) {
3470+ set_found = true;
3471+ break;
35603472 }
3561− break;
35623473 }
35633474 break;
35643475 }
@@ -3578,7 +3489,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) · 13 unmodified lines
35783489 goto nla_put_failure;
35793490
35803491 nfmsg = nlmsg_data(nlh);
3581− nfmsg->nfgen_family = afi->family;
3492+ nfmsg->nfgen_family = table->family;
35823493 nfmsg->version = NFNETLINK_V0;
35833494 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
35843495
@@ -3641,7 +3552,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb, · 56 unmodified lines
36413552 goto nla_put_failure;
36423553
36433554 nfmsg = nlmsg_data(nlh);
3644− nfmsg->nfgen_family = ctx->afi->family;
3555+ nfmsg->nfgen_family = ctx->family;
36453556 nfmsg->version = NFNETLINK_V0;
36463557 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
36473558
@@ -3998,7 +3909,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 350 unmodified lines
39983909 list_for_each_entry(binding, &set->bindings, list) {
39993910 struct nft_ctx bind_ctx = {
40003911 .net = ctx->net,
4001− .afi = ctx->afi,
3912+ .family = ctx->family,
40023913 .table = ctx->table,
40033914 .chain = (struct nft_chain *)binding->chain,
40043915 };
@@ -4417,6 +4328,21 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table, · 412 unmodified lines
44174328 }
44184329 EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
44194330
4331+struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table,
4332+ const struct nlattr *nla,
4333+ u32 objtype, u8 genmask)
4334+{
4335+ struct nft_object *obj;
4336+
4337+ list_for_each_entry(obj, &table->objects, list) {
4338+ if (be64_to_cpu(nla_get_be64(nla)) == obj->handle &&
4339+ objtype == obj->ops->type->type &&
4340+ nft_active_genmask(obj, genmask))
4341+ return obj;
4342+ }
4343+ return ERR_PTR(-ENOENT);
4344+}
4345+
44204346 static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
44214347 [NFTA_OBJ_TABLE] = { .type = NLA_STRING,
44224348 .len = NFT_TABLE_MAXNAMELEN - 1 },
@@ -4424,6 +4350,7 @@ static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { · 1 unmodified line
44244350 .len = NFT_OBJ_MAXNAMELEN - 1 },
44254351 [NFTA_OBJ_TYPE] = { .type = NLA_U32 },
44264352 [NFTA_OBJ_DATA] = { .type = NLA_NESTED },
4353+ [NFTA_OBJ_HANDLE] = { .type = NLA_U64},
44274354 };
44284355
44294356 static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
@@ -4529,7 +4456,6 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk, · 99 unmodified lines
45294456 const struct nft_object_type *type;
45304457 u8 genmask = nft_genmask_next(net);
45314458 int family = nfmsg->nfgen_family;
4532− struct nft_af_info *afi;
45334459 struct nft_table *table;
45344460 struct nft_object *obj;
45354461 struct nft_ctx ctx;
@@ -4541,11 +4467,8 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk, · 5 unmodified lines
45414467 !nla[NFTA_OBJ_DATA])
45424468 return -EINVAL;
45434469
4544− afi = nf_tables_afinfo_lookup(net, family, true);
4545− if (IS_ERR(afi))
4546− return PTR_ERR(afi);
4547−
4548− table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4470+ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
4471+ genmask);
45494472 if (IS_ERR(table))
45504473 return PTR_ERR(table);
45514474
@@ -4563,7 +4486,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk, · 11 unmodified lines
45634486 return 0;
45644487 }
45654488
4566− nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
4489+ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
45674490
45684491 type = nft_obj_type_get(objtype);
45694492 if (IS_ERR(type))
@@ -4575,6 +4498,8 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk, · 5 unmodified lines
45754498 goto err1;
45764499 }
45774500 obj->table = table;
4501+ obj->handle = nf_tables_alloc_handle(table);
4502+
45784503 obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
45794504 if (!obj->name) {
45804505 err = -ENOMEM;
@@ -4621,7 +4546,9 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net, · 40 unmodified lines
46214546 nla_put_string(skb, NFTA_OBJ_NAME, obj->name) ||
46224547 nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) ||
46234548 nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
4624− nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset))
4549+ nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) ||
4550+ nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle),
4551+ NFTA_OBJ_PAD))
46254552 goto nla_put_failure;
46264553
46274554 nlmsg_end(skb, nlh);
@@ -4640,7 +4567,6 @@ struct nft_obj_filter { · 12 unmodified lines
46404567 static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
46414568 {
46424569 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
4643− const struct nft_af_info *afi;
46444570 const struct nft_table *table;
46454571 unsigned int idx = 0, s_idx = cb->args[0];
46464572 struct nft_obj_filter *filter = cb->data;
@@ -4655,38 +4581,37 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) · 8 unmodified lines
46554581 rcu_read_lock();
46564582 cb->seq = net->nft.base_seq;
46574583
4658− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
4659− if (family != NFPROTO_UNSPEC && family != afi->family)
4584+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
4585+ if (family != NFPROTO_UNSPEC && family != table->family)
46604586 continue;
46614587
4662− list_for_each_entry_rcu(table, &afi->tables, list) {
4663− list_for_each_entry_rcu(obj, &table->objects, list) {
4664− if (!nft_is_active(net, obj))
4665− goto cont;
4666− if (idx < s_idx)
4667− goto cont;
4668− if (idx > s_idx)
4669− memset(&cb->args[1], 0,
4670− sizeof(cb->args) - sizeof(cb->args[0]));
4671− if (filter && filter->table[0] &&
4672− strcmp(filter->table, table->name))
4673− goto cont;
4674− if (filter &&
4675− filter->type != NFT_OBJECT_UNSPEC &&
4676− obj->ops->type->type != filter->type)
4677− goto cont;
4588+ list_for_each_entry_rcu(obj, &table->objects, list) {
4589+ if (!nft_is_active(net, obj))
4590+ goto cont;
4591+ if (idx < s_idx)
4592+ goto cont;
4593+ if (idx > s_idx)
4594+ memset(&cb->args[1], 0,
4595+ sizeof(cb->args) - sizeof(cb->args[0]));
4596+ if (filter && filter->table[0] &&
4597+ strcmp(filter->table, table->name))
4598+ goto cont;
4599+ if (filter &&
4600+ filter->type != NFT_OBJECT_UNSPEC &&
4601+ obj->ops->type->type != filter->type)
4602+ goto cont;
46784603
4679− if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
4680− cb->nlh->nlmsg_seq,
4681− NFT_MSG_NEWOBJ,
4682− NLM_F_MULTI | NLM_F_APPEND,
4683− afi->family, table, obj, reset) < 0)
4684− goto done;
4604+ if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
4605+ cb->nlh->nlmsg_seq,
4606+ NFT_MSG_NEWOBJ,
4607+ NLM_F_MULTI | NLM_F_APPEND,
4608+ table->family, table,
4609+ obj, reset) < 0)
4610+ goto done;
46854611
4686− nl_dump_check_consistent(cb, nlmsg_hdr(skb));
4612+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
46874613 cont:
4688− idx++;
4689− }
4614+ idx++;
46904615 }
46914616 }
46924617 done:
@@ -4738,7 +4663,6 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk, · 45 unmodified lines
47384663 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
47394664 u8 genmask = nft_genmask_cur(net);
47404665 int family = nfmsg->nfgen_family;
4741− const struct nft_af_info *afi;
47424666 const struct nft_table *table;
47434667 struct nft_object *obj;
47444668 struct sk_buff *skb2;
@@ -4769,11 +4693,8 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk, · 24 unmodified lines
47694693 !nla[NFTA_OBJ_TYPE])
47704694 return -EINVAL;
47714695
4772− afi = nf_tables_afinfo_lookup(net, family, false);
4773− if (IS_ERR(afi))
4774− return PTR_ERR(afi);
4775−
4776− table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4696+ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
4697+ genmask);
47774698 if (IS_ERR(table))
47784699 return PTR_ERR(table);
47794700
@@ -4819,32 +4740,33 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk, · 39 unmodified lines
48194740 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
48204741 u8 genmask = nft_genmask_next(net);
48214742 int family = nfmsg->nfgen_family;
4822− struct nft_af_info *afi;
48234743 struct nft_table *table;
48244744 struct nft_object *obj;
48254745 struct nft_ctx ctx;
48264746 u32 objtype;
48274747
48284748 if (!nla[NFTA_OBJ_TYPE] ||
4829− !nla[NFTA_OBJ_NAME])
4749+ (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE]))
48304750 return -EINVAL;
48314751
4832− afi = nf_tables_afinfo_lookup(net, family, true);
4833− if (IS_ERR(afi))
4834− return PTR_ERR(afi);
4835−
4836− table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4752+ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
4753+ genmask);
48374754 if (IS_ERR(table))
48384755 return PTR_ERR(table);
48394756
48404757 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4841− obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
4758+ if (nla[NFTA_OBJ_HANDLE])
4759+ obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE],
4760+ objtype, genmask);
4761+ else
4762+ obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME],
4763+ objtype, genmask);
48424764 if (IS_ERR(obj))
48434765 return PTR_ERR(obj);
48444766 if (obj->use > 0)
48454767 return -EBUSY;
48464768
4847− nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
4769+ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
48484770
48494771 return nft_delobj(&ctx, obj);
48504772 }
@@ -4882,7 +4804,7 @@ static void nf_tables_obj_notify(const struct nft_ctx *ctx, · 31 unmodified lines
48824804 struct nft_object *obj, int event)
48834805 {
48844806 nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
4885− ctx->afi->family, ctx->report, GFP_KERNEL);
4807+ ctx->family, ctx->report, GFP_KERNEL);
48864808 }
48874809
48884810 /*
@@ -4910,6 +4832,7 @@ static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = { · 21 unmodified lines
49104832 [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING,
49114833 .len = NFT_NAME_MAXLEN - 1 },
49124834 [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED },
4835+ [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 },
49134836 };
49144837
49154838 struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table,
@@ -4927,6 +4850,20 @@ struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, · 11 unmodified lines
49274850 }
49284851 EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup);
49294852
4853+struct nft_flowtable *
4854+nf_tables_flowtable_lookup_byhandle(const struct nft_table *table,
4855+ const struct nlattr *nla, u8 genmask)
4856+{
4857+ struct nft_flowtable *flowtable;
4858+
4859+ list_for_each_entry(flowtable, &table->flowtables, list) {
4860+ if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle &&
4861+ nft_active_genmask(flowtable, genmask))
4862+ return flowtable;
4863+ }
4864+ return ERR_PTR(-ENOENT);
4865+}
4866+
49304867 #define NFT_FLOWTABLE_DEVICE_MAX 8
49314868
49324869 static int nf_tables_parse_devices(const struct nft_ctx *ctx,
@@ -4993,7 +4930,7 @@ static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx, · 60 unmodified lines
49934930 return -EINVAL;
49944931
49954932 hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM]));
4996− if (hooknum >= ctx->afi->nhooks)
4933+ if (hooknum != NF_NETDEV_INGRESS)
49974934 return -EINVAL;
49984935
49994936 priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY]));
@@ -5009,6 +4946,8 @@ static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx, · 9 unmodified lines
50094946 goto err1;
50104947 }
50114948
4949+ flowtable->hooknum = hooknum;
4950+ flowtable->priority = priority;
50124951 flowtable->ops = ops;
50134952 flowtable->ops_len = n;
50144953
@@ -5029,33 +4968,31 @@ err1: · 14 unmodified lines
50294968 return err;
50304969 }
50314970
5032−static const struct nf_flowtable_type *
5033−__nft_flowtable_type_get(const struct nft_af_info *afi)
4971+static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)
50344972 {
50354973 const struct nf_flowtable_type *type;
50364974
50374975 list_for_each_entry(type, &nf_tables_flowtables, list) {
5038− if (afi->family == type->family)
4976+ if (family == type->family)
50394977 return type;
50404978 }
50414979 return NULL;
50424980 }
50434981
5044−static const struct nf_flowtable_type *
5045−nft_flowtable_type_get(const struct nft_af_info *afi)
4982+static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)
50464983 {
50474984 const struct nf_flowtable_type *type;
50484985
5049− type = __nft_flowtable_type_get(afi);
4986+ type = __nft_flowtable_type_get(family);
50504987 if (type != NULL && try_module_get(type->owner))
50514988 return type;
50524989
50534990 #ifdef CONFIG_MODULES
50544991 if (type == NULL) {
50554992 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
5056− request_module("nf-flowtable-%u", afi->family);
4993+ request_module("nf-flowtable-%u", family);
50574994 nfnl_lock(NFNL_SUBSYS_NFTABLES);
5058− if (__nft_flowtable_type_get(afi))
4995+ if (__nft_flowtable_type_get(family))
50594996 return ERR_PTR(-EAGAIN);
50604997 }
50614998 #endif
@@ -5067,15 +5004,12 @@ void nft_flow_table_iterate(struct net *net, · 5 unmodified lines
50675004 void *data)
50685005 {
50695006 struct nft_flowtable *flowtable;
5070− const struct nft_af_info *afi;
50715007 const struct nft_table *table;
50725008
50735009 rcu_read_lock();
5074− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
5075− list_for_each_entry_rcu(table, &afi->tables, list) {
5076− list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
5077− iter(&flowtable->data, data);
5078− }
5010+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
5011+ list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
5012+ iter(&flowtable->data, data);
50795013 }
50805014 }
50815015 rcu_read_unlock();
@@ -5106,7 +5040,6 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, · 24 unmodified lines
51065040 u8 genmask = nft_genmask_next(net);
51075041 int family = nfmsg->nfgen_family;
51085042 struct nft_flowtable *flowtable;
5109− struct nft_af_info *afi;
51105043 struct nft_table *table;
51115044 struct nft_ctx ctx;
51125045 int err, i, k;
@@ -5116,11 +5049,8 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, · 3 unmodified lines
51165049 !nla[NFTA_FLOWTABLE_HOOK])
51175050 return -EINVAL;
51185051
5119− afi = nf_tables_afinfo_lookup(net, family, true);
5120− if (IS_ERR(afi))
5121− return PTR_ERR(afi);
5122−
5123− table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask);
5052+ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE],
5053+ family, genmask);
51245054 if (IS_ERR(table))
51255055 return PTR_ERR(table);
51265056
@@ -5137,20 +5067,22 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, · 10 unmodified lines
51375067 return 0;
51385068 }
51395069
5140− nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
5070+ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
51415071
51425072 flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL);
51435073 if (!flowtable)
51445074 return -ENOMEM;
51455075
51465076 flowtable->table = table;
5077+ flowtable->handle = nf_tables_alloc_handle(table);
5078+
51475079 flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL);
51485080 if (!flowtable->name) {
51495081 err = -ENOMEM;
51505082 goto err1;
51515083 }
51525084
5153− type = nft_flowtable_type_get(afi);
5085+ type = nft_flowtable_type_get(family);
51545086 if (IS_ERR(type)) {
51555087 err = PTR_ERR(type);
51565088 goto err2;
@@ -5210,26 +5142,28 @@ static int nf_tables_delflowtable(struct net *net, struct sock *nlsk, · 53 unmodified lines
52105142 u8 genmask = nft_genmask_next(net);
52115143 int family = nfmsg->nfgen_family;
52125144 struct nft_flowtable *flowtable;
5213− struct nft_af_info *afi;
52145145 struct nft_table *table;
52155146 struct nft_ctx ctx;
52165147
5217− afi = nf_tables_afinfo_lookup(net, family, true);
5218− if (IS_ERR(afi))
5219− return PTR_ERR(afi);
5220−
5221− table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask);
5148+ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE],
5149+ family, genmask);
52225150 if (IS_ERR(table))
52235151 return PTR_ERR(table);
52245152
5225− flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
5226− genmask);
5153+ if (nla[NFTA_FLOWTABLE_HANDLE])
5154+ flowtable = nf_tables_flowtable_lookup_byhandle(table,
5155+ nla[NFTA_FLOWTABLE_HANDLE],
5156+ genmask);
5157+ else
5158+ flowtable = nf_tables_flowtable_lookup(table,
5159+ nla[NFTA_FLOWTABLE_NAME],
5160+ genmask);
52275161 if (IS_ERR(flowtable))
52285162 return PTR_ERR(flowtable);
52295163 if (flowtable->use > 0)
52305164 return -EBUSY;
52315165
5232− nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
5166+ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
52335167
52345168 return nft_delflowtable(&ctx, flowtable);
52355169 }
@@ -5256,7 +5190,9 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, · 20 unmodified lines
52565190
52575191 if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) ||
52585192 nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) ||
5259− nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)))
5193+ nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) ||
5194+ nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle),
5195+ NFTA_FLOWTABLE_PAD))
52605196 goto nla_put_failure;
52615197
52625198 nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK);
@@ -5298,40 +5234,37 @@ static int nf_tables_dump_flowtable(struct sk_buff *skb, · 35 unmodified lines
52985234 struct net *net = sock_net(skb->sk);
52995235 int family = nfmsg->nfgen_family;
53005236 struct nft_flowtable *flowtable;
5301− const struct nft_af_info *afi;
53025237 const struct nft_table *table;
53035238
53045239 rcu_read_lock();
53055240 cb->seq = net->nft.base_seq;
53065241
5307− list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
5308− if (family != NFPROTO_UNSPEC && family != afi->family)
5242+ list_for_each_entry_rcu(table, &net->nft.tables, list) {
5243+ if (family != NFPROTO_UNSPEC && family != table->family)
53095244 continue;
53105245
5311− list_for_each_entry_rcu(table, &afi->tables, list) {
5312− list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
5313− if (!nft_is_active(net, flowtable))
5314− goto cont;
5315− if (idx < s_idx)
5316− goto cont;
5317− if (idx > s_idx)
5318− memset(&cb->args[1], 0,
5319− sizeof(cb->args) - sizeof(cb->args[0]));
5320− if (filter && filter->table[0] &&
5321− strcmp(filter->table, table->name))
5322− goto cont;
5246+ list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
5247+ if (!nft_is_active(net, flowtable))
5248+ goto cont;
5249+ if (idx < s_idx)
5250+ goto cont;
5251+ if (idx > s_idx)
5252+ memset(&cb->args[1], 0,
5253+ sizeof(cb->args) - sizeof(cb->args[0]));
5254+ if (filter && filter->table[0] &&
5255+ strcmp(filter->table, table->name))
5256+ goto cont;
53235257
5324− if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid,
5325− cb->nlh->nlmsg_seq,
5326− NFT_MSG_NEWFLOWTABLE,
5327− NLM_F_MULTI | NLM_F_APPEND,
5328− afi->family, flowtable) < 0)
5329− goto done;
5258+ if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid,
5259+ cb->nlh->nlmsg_seq,
5260+ NFT_MSG_NEWFLOWTABLE,
5261+ NLM_F_MULTI | NLM_F_APPEND,
5262+ table->family, flowtable) < 0)
5263+ goto done;
53305264
5331− nl_dump_check_consistent(cb, nlmsg_hdr(skb));
5265+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
53325266 cont:
5333− idx++;
5334− }
5267+ idx++;
53355268 }
53365269 }
53375270 done:
@@ -5384,7 +5317,6 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk, · 46 unmodified lines
53845317 u8 genmask = nft_genmask_cur(net);
53855318 int family = nfmsg->nfgen_family;
53865319 struct nft_flowtable *flowtable;
5387− const struct nft_af_info *afi;
53885320 const struct nft_table *table;
53895321 struct sk_buff *skb2;
53905322 int err;
@@ -5410,17 +5342,14 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk, · 19 unmodified lines
54105342 if (!nla[NFTA_FLOWTABLE_NAME])
54115343 return -EINVAL;
54125344
5413− afi = nf_tables_afinfo_lookup(net, family, false);
5414− if (IS_ERR(afi))
5415− return PTR_ERR(afi);
5416−
5417− table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask);
5345+ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE],
5346+ family, genmask);
54185347 if (IS_ERR(table))
54195348 return PTR_ERR(table);
54205349
54215350 flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
54225351 genmask);
5423− if (IS_ERR(table))
5352+ if (IS_ERR(flowtable))
54245353 return PTR_ERR(flowtable);
54255354
54265355 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
@@ -5457,7 +5386,7 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx, · 30 unmodified lines
54575386
54585387 err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid,
54595388 ctx->seq, event, 0,
5460− ctx->afi->family, flowtable);
5389+ ctx->family, flowtable);
54615390 if (err < 0) {
54625391 kfree_skb(skb);
54635392 goto err;
@@ -5535,17 +5464,14 @@ static int nf_tables_flowtable_event(struct notifier_block *this, · 71 unmodified lines
55355464 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
55365465 struct nft_flowtable *flowtable;
55375466 struct nft_table *table;
5538− struct nft_af_info *afi;
55395467
55405468 if (event != NETDEV_UNREGISTER)
55415469 return 0;
55425470
55435471 nfnl_lock(NFNL_SUBSYS_NFTABLES);
5544− list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) {
5545− list_for_each_entry(table, &afi->tables, list) {
5546− list_for_each_entry(flowtable, &table->flowtables, list) {
5547− nft_flowtable_event(event, dev, flowtable);
5548− }
5472+ list_for_each_entry(table, &dev_net(dev)->nft.tables, list) {
5473+ list_for_each_entry(flowtable, &table->flowtables, list) {
5474+ nft_flowtable_event(event, dev, flowtable);
55495475 }
55505476 }
55515477 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
@@ -5798,7 +5724,6 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) · 246 unmodified lines
57985724 if (nft_trans_table_update(trans)) {
57995725 if (!nft_trans_table_enable(trans)) {
58005726 nf_tables_table_disable(net,
5801− trans->ctx.afi,
58025727 trans->ctx.table);
58035728 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
58045729 }
@@ -5960,7 +5885,6 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) · 155 unmodified lines
59605885 if (nft_trans_table_update(trans)) {
59615886 if (nft_trans_table_enable(trans)) {
59625887 nf_tables_table_disable(net,
5963− trans->ctx.afi,
59645888 trans->ctx.table);
59655889 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
59665890 }
@@ -6563,20 +6487,6 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, · 596 unmodified lines
65636487 }
65646488 EXPORT_SYMBOL_GPL(nft_data_dump);
65656489
6566−static int __net_init nf_tables_init_net(struct net *net)
6567−{
6568− INIT_LIST_HEAD(&net->nft.af_info);
6569− INIT_LIST_HEAD(&net->nft.commit_list);
6570− net->nft.base_seq = 1;
6571− return 0;
6572−}
6573−
6574−static void __net_exit nf_tables_exit_net(struct net *net)
6575−{
6576− WARN_ON_ONCE(!list_empty(&net->nft.af_info));
6577− WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
6578−}
6579−
65806490 int __nft_release_basechain(struct nft_ctx *ctx)
65816491 {
65826492 struct nft_rule *rule, *nr;
@@ -6597,8 +6507,7 @@ int __nft_release_basechain(struct nft_ctx *ctx) · 14 unmodified lines
65976507 }
65986508 EXPORT_SYMBOL_GPL(__nft_release_basechain);
65996509
6600−/* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */
6601−static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
6510+static void __nft_release_tables(struct net *net)
66026511 {
66036512 struct nft_flowtable *flowtable, *nf;
66046513 struct nft_table *table, *nt;
@@ -6608,10 +6517,11 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) · 3 unmodified lines
66086517 struct nft_set *set, *ns;
66096518 struct nft_ctx ctx = {
66106519 .net = net,
6611− .afi = afi,
66126520 };
66136521
6614− list_for_each_entry_safe(table, nt, &afi->tables, list) {
6522+ list_for_each_entry_safe(table, nt, &net->nft.tables, list) {
6523+ ctx.family = table->family;
6524+
66156525 list_for_each_entry(chain, &table->chains, list)
66166526 nf_tables_unregister_hook(net, table, chain);
66176527 list_for_each_entry(flowtable, &table->flowtables, list)
@@ -6652,6 +6562,21 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) · 34 unmodified lines
66526562 }
66536563 }
66546564
6565+static int __net_init nf_tables_init_net(struct net *net)
6566+{
6567+ INIT_LIST_HEAD(&net->nft.tables);
6568+ INIT_LIST_HEAD(&net->nft.commit_list);
6569+ net->nft.base_seq = 1;
6570+ return 0;
6571+}
6572+
6573+static void __net_exit nf_tables_exit_net(struct net *net)
6574+{
6575+ __nft_release_tables(net);
6576+ WARN_ON_ONCE(!list_empty(&net->nft.tables));
6577+ WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
6578+}
6579+
66556580 static struct pernet_operations nf_tables_net_ops = {
66566581 .init = nf_tables_init_net,
66576582 .exit = nf_tables_exit_net,
@@ -6678,7 +6603,6 @@ static int __init nf_tables_module_init(void) · 20 unmodified lines
66786603
66796604 register_netdevice_notifier(&nf_tables_flowtable_notifier);
66806605
6681− pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n");
66826606 return register_pernet_subsys(&nf_tables_net_ops);
66836607 err3:
66846608 nf_tables_core_module_exit();
net/netfilter/nf_tables_inet.c+2−47
@@ -38,40 +38,6 @@ static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb, · 37 unmodified lines
3838 return nft_do_chain(&pkt, priv);
3939 }
4040
41−static struct nft_af_info nft_af_inet __read_mostly = {
42− .family = NFPROTO_INET,
43− .nhooks = NF_INET_NUMHOOKS,
44− .owner = THIS_MODULE,
45−};
46−
47−static int __net_init nf_tables_inet_init_net(struct net *net)
48−{
49− net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
50− if (net->nft.inet == NULL)
51− return -ENOMEM;
52− memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet));
53−
54− if (nft_register_afinfo(net, net->nft.inet) < 0)
55− goto err;
56−
57− return 0;
58−
59−err:
60− kfree(net->nft.inet);
61− return -ENOMEM;
62−}
63−
64−static void __net_exit nf_tables_inet_exit_net(struct net *net)
65−{
66− nft_unregister_afinfo(net, net->nft.inet);
67− kfree(net->nft.inet);
68−}
69−
70−static struct pernet_operations nf_tables_inet_net_ops = {
71− .init = nf_tables_inet_init_net,
72− .exit = nf_tables_inet_exit_net,
73−};
74−
7541 static const struct nf_chain_type filter_inet = {
7642 .name = "filter",
7743 .type = NFT_CHAIN_T_DEFAULT,
@@ -93,22 +59,11 @@ static const struct nf_chain_type filter_inet = { · 15 unmodified lines
9359
9460 static int __init nf_tables_inet_init(void)
9561 {
96− int ret;
97−
98− ret = nft_register_chain_type(&filter_inet);
99− if (ret < 0)
100− return ret;
101−
102− ret = register_pernet_subsys(&nf_tables_inet_net_ops);
103− if (ret < 0)
104− nft_unregister_chain_type(&filter_inet);
105−
106− return ret;
62+ return nft_register_chain_type(&filter_inet);
10763 }
10864
10965 static void __exit nf_tables_inet_exit(void)
11066 {
111− unregister_pernet_subsys(&nf_tables_inet_net_ops);
11267 nft_unregister_chain_type(&filter_inet);
11368 }
11469
@@ -117,4 +72,4 @@ module_exit(nf_tables_inet_exit); · 2 unmodified lines
11772
11873 MODULE_LICENSE("GPL");
11974 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
120−MODULE_ALIAS_NFT_FAMILY(1);
75+MODULE_ALIAS_NFT_CHAIN(1, "filter");
net/netfilter/nf_tables_netdev.c+13−57
@@ -38,41 +38,6 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb, · 37 unmodified lines
3838 return nft_do_chain(&pkt, priv);
3939 }
4040
41−static struct nft_af_info nft_af_netdev __read_mostly = {
42− .family = NFPROTO_NETDEV,
43− .nhooks = NF_NETDEV_NUMHOOKS,
44− .owner = THIS_MODULE,
45− .flags = NFT_AF_NEEDS_DEV,
46−};
47−
48−static int nf_tables_netdev_init_net(struct net *net)
49−{
50− net->nft.netdev = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
51− if (net->nft.netdev == NULL)
52− return -ENOMEM;
53−
54− memcpy(net->nft.netdev, &nft_af_netdev, sizeof(nft_af_netdev));
55−
56− if (nft_register_afinfo(net, net->nft.netdev) < 0)
57− goto err;
58−
59− return 0;
60−err:
61− kfree(net->nft.netdev);
62− return -ENOMEM;
63−}
64−
65−static void nf_tables_netdev_exit_net(struct net *net)
66−{
67− nft_unregister_afinfo(net, net->nft.netdev);
68− kfree(net->nft.netdev);
69−}
70−
71−static struct pernet_operations nf_tables_netdev_net_ops = {
72− .init = nf_tables_netdev_init_net,
73− .exit = nf_tables_netdev_exit_net,
74−};
75−
7641 static const struct nf_chain_type nft_filter_chain_netdev = {
7742 .name = "filter",
7843 .type = NFT_CHAIN_T_DEFAULT,
@@ -109,7 +74,6 @@ static int nf_tables_netdev_event(struct notifier_block *this, · 30 unmodified lines
10974 unsigned long event, void *ptr)
11075 {
11176 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
112− struct nft_af_info *afi;
11377 struct nft_table *table;
11478 struct nft_chain *chain, *nr;
11579 struct nft_ctx ctx = {
@@ -121,20 +85,18 @@ static int nf_tables_netdev_event(struct notifier_block *this, · 5 unmodified lines
12185 return NOTIFY_DONE;
12286
12387 nfnl_lock(NFNL_SUBSYS_NFTABLES);
124− list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) {
125− ctx.afi = afi;
126− if (afi->family != NFPROTO_NETDEV)
88+ list_for_each_entry(table, &ctx.net->nft.tables, list) {
89+ if (table->family != NFPROTO_NETDEV)
12790 continue;
12891
129− list_for_each_entry(table, &afi->tables, list) {
130− ctx.table = table;
131− list_for_each_entry_safe(chain, nr, &table->chains, list) {
132− if (!nft_is_base_chain(chain))
133− continue;
92+ ctx.family = table->family;
93+ ctx.table = table;
94+ list_for_each_entry_safe(chain, nr, &table->chains, list) {
95+ if (!nft_is_base_chain(chain))
96+ continue;
13497
135− ctx.chain = chain;
136− nft_netdev_event(event, dev, &ctx);
137− }
98+ ctx.chain = chain;
99+ nft_netdev_event(event, dev, &ctx);
138100 }
139101 }
140102 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
@@ -154,27 +116,21 @@ static int __init nf_tables_netdev_init(void) · 13 unmodified lines
154116 if (ret)
155117 return ret;
156118
157− ret = register_pernet_subsys(&nf_tables_netdev_net_ops);
158− if (ret)
159− goto err1;
160−
161119 ret = register_netdevice_notifier(&nf_tables_netdev_notifier);
162120 if (ret)
163− goto err2;
121+ goto err_register_netdevice_notifier;
164122
165123 return 0;
166124
167−err2:
168− unregister_pernet_subsys(&nf_tables_netdev_net_ops);
169−err1:
125+err_register_netdevice_notifier:
170126 nft_unregister_chain_type(&nft_filter_chain_netdev);
127+
171128 return ret;
172129 }
173130
174131 static void __exit nf_tables_netdev_exit(void)
175132 {
176133 unregister_netdevice_notifier(&nf_tables_netdev_notifier);
177− unregister_pernet_subsys(&nf_tables_netdev_net_ops);
178134 nft_unregister_chain_type(&nft_filter_chain_netdev);
179135 }
180136
@@ -183,4 +139,4 @@ module_exit(nf_tables_netdev_exit); · 2 unmodified lines
183139
184140 MODULE_LICENSE("GPL");
185141 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
186−MODULE_ALIAS_NFT_FAMILY(5); /* NFPROTO_NETDEV */
142+MODULE_ALIAS_NFT_CHAIN(5, "filter"); /* NFPROTO_NETDEV */
net/netfilter/nfnetlink.c+0−4
@@ -37,8 +37,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); · 36 unmodified lines
3737 rcu_dereference_protected(table[(id)].subsys, \
3838 lockdep_nfnl_is_held((id)))
3939
40−static char __initdata nfversion[] = "0.30";
41−
4240 static struct {
4341 struct mutex mutex;
4442 const struct nfnetlink_subsystem __rcu *subsys;
@@ -580,13 +578,11 @@ static int __init nfnetlink_init(void) · 535 unmodified lines
580578 for (i=0; i<NFNL_SUBSYS_COUNT; i++)
581579 mutex_init(&table[i].mutex);
582580
583− pr_info("Netfilter messages via NETLINK v%s.\n", nfversion);
584581 return register_pernet_subsys(&nfnetlink_net_ops);
585582 }
586583
587584 static void __exit nfnetlink_exit(void)
588585 {
589− pr_info("Removing netfilter NETLINK layer.\n");
590586 unregister_pernet_subsys(&nfnetlink_net_ops);
591587 }
592588 module_init(nfnetlink_init);
net/netfilter/nfnetlink_acct.c+0−2
@@ -527,7 +527,6 @@ static int __init nfnl_acct_init(void) · 526 unmodified lines
527527 goto err_out;
528528 }
529529
530− pr_info("nfnl_acct: registering with nfnetlink.\n");
531530 ret = nfnetlink_subsys_register(&nfnl_acct_subsys);
532531 if (ret < 0) {
533532 pr_err("nfnl_acct_init: cannot register with nfnetlink.\n");
@@ -543,7 +542,6 @@ err_out: · 9 unmodified lines
543542
544543 static void __exit nfnl_acct_exit(void)
545544 {
546− pr_info("nfnl_acct: unregistering from nfnetlink.\n");
547545 nfnetlink_subsys_unregister(&nfnl_acct_subsys);
548546 unregister_pernet_subsys(&nfnl_acct_ops);
549547 }
net/netfilter/nfnetlink_cttimeout.c+0−2
@@ -615,8 +615,6 @@ err_out: · 614 unmodified lines
615615
616616 static void __exit cttimeout_exit(void)
617617 {
618− pr_info("cttimeout: unregistering from nfnetlink.\n");
619−
620618 nfnetlink_subsys_unregister(&cttimeout_subsys);
621619
622620 unregister_pernet_subsys(&cttimeout_ops);
net/netfilter/nfnetlink_log.c+0−1
@@ -1054,7 +1054,6 @@ static int nful_open(struct inode *inode, struct file *file) · 1053 unmodified lines
10541054 }
10551055
10561056 static const struct file_operations nful_file_ops = {
1057− .owner = THIS_MODULE,
10581057 .open = nful_open,
10591058 .read = seq_read,
10601059 .llseek = seq_lseek,
net/netfilter/nfnetlink_queue.c+0−1
@@ -1477,7 +1477,6 @@ static int nfqnl_open(struct inode *inode, struct file *file) · 1476 unmodified lines
14771477 }
14781478
14791479 static const struct file_operations nfqnl_file_ops = {
1480− .owner = THIS_MODULE,
14811480 .open = nfqnl_open,
14821481 .read = seq_read,
14831482 .llseek = seq_lseek,
net/netfilter/nft_compat.c+8−10
@@ -144,7 +144,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, · 143 unmodified lines
144144 {
145145 par->net = ctx->net;
146146 par->table = ctx->table->name;
147− switch (ctx->afi->family) {
147+ switch (ctx->family) {
148148 case AF_INET:
149149 entry->e4.ip.proto = proto;
150150 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
@@ -175,7 +175,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, · 24 unmodified lines
175175 } else {
176176 par->hook_mask = 0;
177177 }
178− par->family = ctx->afi->family;
178+ par->family = ctx->family;
179179 par->nft_compat = true;
180180 }
181181
@@ -267,7 +267,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) · 85 unmodified lines
267267 par.net = ctx->net;
268268 par.target = target;
269269 par.targinfo = info;
270− par.family = ctx->afi->family;
270+ par.family = ctx->family;
271271 if (par.target->destroy != NULL)
272272 par.target->destroy(&par);
273273
@@ -358,7 +358,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, · 84 unmodified lines
358358 {
359359 par->net = ctx->net;
360360 par->table = ctx->table->name;
361− switch (ctx->afi->family) {
361+ switch (ctx->family) {
362362 case AF_INET:
363363 entry->e4.ip.proto = proto;
364364 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
@@ -389,7 +389,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, · 24 unmodified lines
389389 } else {
390390 par->hook_mask = 0;
391391 }
392− par->family = ctx->afi->family;
392+ par->family = ctx->family;
393393 par->nft_compat = true;
394394 }
395395
@@ -446,7 +446,7 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) · 50 unmodified lines
446446 par.net = ctx->net;
447447 par.match = match;
448448 par.matchinfo = info;
449− par.family = ctx->afi->family;
449+ par.family = ctx->family;
450450 if (par.match->destroy != NULL)
451451 par.match->destroy(&par);
452452
@@ -648,7 +648,7 @@ nft_match_select_ops(const struct nft_ctx *ctx, · 195 unmodified lines
648648
649649 mt_name = nla_data(tb[NFTA_MATCH_NAME]);
650650 rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
651− family = ctx->afi->family;
651+ family = ctx->family;
652652
653653 /* Re-use the existing match if it's already loaded. */
654654 list_for_each_entry(nft_match, &nft_match_list, head) {
@@ -733,7 +733,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, · 78 unmodified lines
733733
734734 tg_name = nla_data(tb[NFTA_TARGET_NAME]);
735735 rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV]));
736− family = ctx->afi->family;
736+ family = ctx->family;
737737
738738 /* Re-use the existing target if it's already loaded. */
739739 list_for_each_entry(nft_target, &nft_target_list, head) {
@@ -812,8 +812,6 @@ static int __init nft_compat_module_init(void) · 72 unmodified lines
812812 goto err_target;
813813 }
814814
815− pr_info("nf_tables_compat: (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>\n");
816−
817815 return ret;
818816
819817 err_target:
net/netfilter/nft_ct.c+8−8
@@ -405,7 +405,7 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, · 404 unmodified lines
405405 if (tb[NFTA_CT_DIRECTION] == NULL)
406406 return -EINVAL;
407407
408− switch (ctx->afi->family) {
408+ switch (ctx->family) {
409409 case NFPROTO_IPV4:
410410 len = FIELD_SIZEOF(struct nf_conntrack_tuple,
411411 src.u3.ip);
@@ -456,7 +456,7 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, · 44 unmodified lines
456456 if (err < 0)
457457 return err;
458458
459− err = nf_ct_netns_get(ctx->net, ctx->afi->family);
459+ err = nf_ct_netns_get(ctx->net, ctx->family);
460460 if (err < 0)
461461 return err;
462462
@@ -550,7 +550,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx, · 87 unmodified lines
550550 if (err < 0)
551551 goto err1;
552552
553− err = nf_ct_netns_get(ctx->net, ctx->afi->family);
553+ err = nf_ct_netns_get(ctx->net, ctx->family);
554554 if (err < 0)
555555 goto err1;
556556
@@ -564,7 +564,7 @@ err1: · 7 unmodified lines
564564 static void nft_ct_get_destroy(const struct nft_ctx *ctx,
565565 const struct nft_expr *expr)
566566 {
567− nf_ct_netns_put(ctx->net, ctx->afi->family);
567+ nf_ct_netns_put(ctx->net, ctx->family);
568568 }
569569
570570 static void nft_ct_set_destroy(const struct nft_ctx *ctx,
@@ -573,7 +573,7 @@ static void nft_ct_set_destroy(const struct nft_ctx *ctx, · 2 unmodified lines
573573 struct nft_ct *priv = nft_expr_priv(expr);
574574
575575 __nft_ct_set_destroy(ctx, priv);
576− nf_ct_netns_put(ctx->net, ctx->afi->family);
576+ nf_ct_netns_put(ctx->net, ctx->family);
577577 }
578578
579579 static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -734,7 +734,7 @@ static int nft_ct_helper_obj_init(const struct nft_ctx *ctx, · 154 unmodified lines
734734 struct nft_ct_helper_obj *priv = nft_obj_data(obj);
735735 struct nf_conntrack_helper *help4, *help6;
736736 char name[NF_CT_HELPER_NAME_LEN];
737− int family = ctx->afi->family;
737+ int family = ctx->family;
738738
739739 if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO])
740740 return -EINVAL;
@@ -753,14 +753,14 @@ static int nft_ct_helper_obj_init(const struct nft_ctx *ctx, · 12 unmodified lines
753753
754754 switch (family) {
755755 case NFPROTO_IPV4:
756− if (ctx->afi->family == NFPROTO_IPV6)
756+ if (ctx->family == NFPROTO_IPV6)
757757 return -EINVAL;
758758
759759 help4 = nf_conntrack_helper_try_module_get(name, family,
760760 priv->l4proto);
761761 break;
762762 case NFPROTO_IPV6:
763− if (ctx->afi->family == NFPROTO_IPV4)
763+ if (ctx->family == NFPROTO_IPV4)
764764 return -EINVAL;
765765
766766 help6 = nf_conntrack_helper_try_module_get(name, family,
net/netfilter/nft_dynset.c+1−1
@@ -164,7 +164,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, · 163 unmodified lines
164164 }
165165
166166 priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]);
167− err = nft_validate_register_load(priv->sreg_key, set->klen);;
167+ err = nft_validate_register_load(priv->sreg_key, set->klen);
168168 if (err < 0)
169169 return err;
170170
net/netfilter/nft_flow_offload.c+2−2
@@ -151,7 +151,7 @@ static int nft_flow_offload_init(const struct nft_ctx *ctx, · 150 unmodified lines
151151 priv->flowtable = flowtable;
152152 flowtable->use++;
153153
154− return nf_ct_netns_get(ctx->net, ctx->afi->family);
154+ return nf_ct_netns_get(ctx->net, ctx->family);
155155 }
156156
157157 static void nft_flow_offload_destroy(const struct nft_ctx *ctx,
@@ -160,7 +160,7 @@ static void nft_flow_offload_destroy(const struct nft_ctx *ctx, · 2 unmodified lines
160160 struct nft_flow_offload *priv = nft_expr_priv(expr);
161161
162162 priv->flowtable->use--;
163− nf_ct_netns_put(ctx->net, ctx->afi->family);
163+ nf_ct_netns_put(ctx->net, ctx->family);
164164 }
165165
166166 static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr)
net/netfilter/nft_log.c+2−2
@@ -112,7 +112,7 @@ static int nft_log_init(const struct nft_ctx *ctx, · 111 unmodified lines
112112 break;
113113 }
114114
115− err = nf_logger_find_get(ctx->afi->family, li->type);
115+ err = nf_logger_find_get(ctx->family, li->type);
116116 if (err < 0)
117117 goto err1;
118118
@@ -133,7 +133,7 @@ static void nft_log_destroy(const struct nft_ctx *ctx, · 14 unmodified lines
133133 if (priv->prefix != nft_log_null_prefix)
134134 kfree(priv->prefix);
135135
136− nf_logger_put(ctx->afi->family, li->type);
136+ nf_logger_put(ctx->family, li->type);
137137 }
138138
139139 static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr)
net/netfilter/nft_masq.c+1−1
@@ -73,7 +73,7 @@ int nft_masq_init(const struct nft_ctx *ctx, · 72 unmodified lines
7373 }
7474 }
7575
76− return nf_ct_netns_get(ctx->net, ctx->afi->family);
76+ return nf_ct_netns_get(ctx->net, ctx->family);
7777 }
7878 EXPORT_SYMBOL_GPL(nft_masq_init);
7979
net/netfilter/nft_meta.c+2−2
@@ -339,7 +339,7 @@ static int nft_meta_get_validate(const struct nft_ctx *ctx, · 338 unmodified lines
339339 if (priv->key != NFT_META_SECPATH)
340340 return 0;
341341
342− switch (ctx->afi->family) {
342+ switch (ctx->family) {
343343 case NFPROTO_NETDEV:
344344 hooks = 1 << NF_NETDEV_INGRESS;
345345 break;
@@ -370,7 +370,7 @@ int nft_meta_set_validate(const struct nft_ctx *ctx, · 24 unmodified lines
370370 if (priv->key != NFT_META_PKTTYPE)
371371 return 0;
372372
373− switch (ctx->afi->family) {
373+ switch (ctx->family) {
374374 case NFPROTO_BRIDGE:
375375 hooks = 1 << NF_BR_PRE_ROUTING;
376376 break;
net/netfilter/nft_nat.c+1−1
@@ -142,7 +142,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, · 141 unmodified lines
142142 return -EINVAL;
143143
144144 family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY]));
145− if (family != ctx->afi->family)
145+ if (family != ctx->family)
146146 return -EOPNOTSUPP;
147147
148148 switch (family) {
net/netfilter/nft_redir.c+1−1
@@ -75,7 +75,7 @@ int nft_redir_init(const struct nft_ctx *ctx, · 74 unmodified lines
7575 return -EINVAL;
7676 }
7777
78− return nf_ct_netns_get(ctx->net, ctx->afi->family);
78+ return nf_ct_netns_get(ctx->net, ctx->family);
7979 }
8080 EXPORT_SYMBOL_GPL(nft_redir_init);
8181
net/netfilter/x_tables.c+2−5
@@ -1082,10 +1082,10 @@ struct xt_table *xt_request_find_table_lock(struct net *net, u_int8_t af, · 1081 unmodified lines
10821082 {
10831083 struct xt_table *t = xt_find_table_lock(net, af, name);
10841084
1085−#ifdef CONFIG_MODULE
1085+#ifdef CONFIG_MODULES
10861086 if (IS_ERR(t)) {
10871087 int err = request_module("%stable_%s", xt_prefix[af], name);
1088− if (err)
1088+ if (err < 0)
10891089 return ERR_PTR(err);
10901090 t = xt_find_table_lock(net, af, name);
10911091 }
@@ -1362,7 +1362,6 @@ static int xt_table_open(struct inode *inode, struct file *file) · 270 unmodified lines
13621362 }
13631363
13641364 static const struct file_operations xt_table_ops = {
1365− .owner = THIS_MODULE,
13661365 .open = xt_table_open,
13671366 .read = seq_read,
13681367 .llseek = seq_lseek,
@@ -1498,7 +1497,6 @@ static int xt_match_open(struct inode *inode, struct file *file) · 129 unmodified lines
14981497 }
14991498
15001499 static const struct file_operations xt_match_ops = {
1501− .owner = THIS_MODULE,
15021500 .open = xt_match_open,
15031501 .read = seq_read,
15041502 .llseek = seq_lseek,
@@ -1551,7 +1549,6 @@ static int xt_target_open(struct inode *inode, struct file *file) · 46 unmodified lines
15511549 }
15521550
15531551 static const struct file_operations xt_target_ops = {
1554− .owner = THIS_MODULE,
15551552 .open = xt_target_open,
15561553 .read = seq_read,
15571554 .llseek = seq_lseek,
net/netfilter/xt_hashlimit.c+1−4
@@ -353,7 +353,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg, · 352 unmodified lines
353353 static bool select_all(const struct xt_hashlimit_htable *ht,
354354 const struct dsthash_ent *he)
355355 {
356− return 1;
356+ return true;
357357 }
358358
359359 static bool select_gc(const struct xt_hashlimit_htable *ht,
@@ -1266,7 +1266,6 @@ static int dl_proc_open(struct inode *inode, struct file *file) · 906 unmodified lines
12661266 }
12671267
12681268 static const struct file_operations dl_file_ops_v2 = {
1269− .owner = THIS_MODULE,
12701269 .open = dl_proc_open_v2,
12711270 .read = seq_read,
12721271 .llseek = seq_lseek,
@@ -1274,7 +1273,6 @@ static const struct file_operations dl_file_ops_v2 = { · 1 unmodified line
12741273 };
12751274
12761275 static const struct file_operations dl_file_ops_v1 = {
1277− .owner = THIS_MODULE,
12781276 .open = dl_proc_open_v1,
12791277 .read = seq_read,
12801278 .llseek = seq_lseek,
@@ -1282,7 +1280,6 @@ static const struct file_operations dl_file_ops_v1 = { · 1 unmodified line
12821280 };
12831281
12841282 static const struct file_operations dl_file_ops = {
1285− .owner = THIS_MODULE,
12861283 .open = dl_proc_open,
12871284 .read = seq_read,
12881285 .llseek = seq_lseek,
net/netfilter/xt_ipcomp.c+1−1
@@ -58,7 +58,7 @@ static bool comp_mt(const struct sk_buff *skb, struct xt_action_param *par) · 57 unmodified lines
5858 */
5959 pr_debug("Dropping evil IPComp tinygram.\n");
6060 par->hotdrop = true;
61− return 0;
61+ return false;
6262 }
6363
6464 return spi_match(compinfo->spis[0], compinfo->spis[1],

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t