aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-01-21 11:35:34 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-21 11:35:34 -0500
commitcbcbeedbfd76e45c3f522043bb7c6fb287779a9c (patch)
treed691fe7e3291b9a8bb1cd8b655a61d92250e5b83
parentea9722e2650db8f0a0d9ef2e391c95285ef991cd (diff)
parente55311665286ab2744295575948c2b08dc001bf3 (diff)
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. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netfilter/nf_tables.h48
-rw-r--r--include/net/netns/nftables.h8
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h10
-rw-r--r--include/uapi/linux/netfilter_ipv4.h1
-rw-r--r--include/uapi/linux/netfilter_ipv6.h1
-rw-r--r--include/uapi/linux/netfilter_ipv6/ip6t_srh.h57
-rw-r--r--net/bridge/netfilter/ebtables.c2
-rw-r--r--net/bridge/netfilter/nf_tables_bridge.c54
-rw-r--r--net/ipv4/netfilter/Kconfig5
-rw-r--r--net/ipv4/netfilter/Makefile6
-rw-r--r--net/ipv4/netfilter/arp_tables.c1
-rw-r--r--net/ipv4/netfilter/ip_tables.c1
-rw-r--r--net/ipv4/netfilter/iptable_raw.c31
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.asn1177
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c1286
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic_main.c235
-rw-r--r--net/ipv4/netfilter/nf_tables_arp.c49
-rw-r--r--net/ipv4/netfilter/nf_tables_ipv4.c49
-rw-r--r--net/ipv6/netfilter/Kconfig12
-rw-r--r--net/ipv6/netfilter/Makefile1
-rw-r--r--net/ipv6/netfilter/ip6_tables.c1
-rw-r--r--net/ipv6/netfilter/ip6t_srh.c161
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c31
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c15
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c3
-rw-r--r--net/ipv6/netfilter/nf_flow_table_ipv6.c1
-rw-r--r--net/ipv6/netfilter/nf_tables_ipv6.c49
-rw-r--r--net/netfilter/Kconfig6
-rw-r--r--net/netfilter/core.c6
-rw-r--r--net/netfilter/ipset/ip_set_core.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_app.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c3
-rw-r--r--net/netfilter/nf_conncount.c2
-rw-r--r--net/netfilter/nf_conntrack_core.c6
-rw-r--r--net/netfilter/nf_conntrack_expect.c1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c5
-rw-r--r--net/netfilter/nf_conntrack_standalone.c2
-rw-r--r--net/netfilter/nf_log.c1
-rw-r--r--net/netfilter/nf_queue.c2
-rw-r--r--net/netfilter/nf_synproxy_core.c1
-rw-r--r--net/netfilter/nf_tables_api.c932
-rw-r--r--net/netfilter/nf_tables_inet.c49
-rw-r--r--net/netfilter/nf_tables_netdev.c70
-rw-r--r--net/netfilter/nfnetlink.c4
-rw-r--r--net/netfilter/nfnetlink_acct.c2
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c2
-rw-r--r--net/netfilter/nfnetlink_log.c1
-rw-r--r--net/netfilter/nfnetlink_queue.c1
-rw-r--r--net/netfilter/nft_compat.c18
-rw-r--r--net/netfilter/nft_ct.c16
-rw-r--r--net/netfilter/nft_dynset.c2
-rw-r--r--net/netfilter/nft_flow_offload.c4
-rw-r--r--net/netfilter/nft_log.c4
-rw-r--r--net/netfilter/nft_masq.c2
-rw-r--r--net/netfilter/nft_meta.c4
-rw-r--r--net/netfilter/nft_nat.c2
-rw-r--r--net/netfilter/nft_redir.c2
-rw-r--r--net/netfilter/x_tables.c7
-rw-r--r--net/netfilter/xt_hashlimit.c5
-rw-r--r--net/netfilter/xt_ipcomp.c2
62 files changed, 1241 insertions, 2226 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index dd238950df81..663b015dace5 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -143,22 +143,22 @@ static inline void nft_data_debug(const struct nft_data *data)
143 * struct nft_ctx - nf_tables rule/set context 143 * struct nft_ctx - nf_tables rule/set context
144 * 144 *
145 * @net: net namespace 145 * @net: net namespace
146 * @afi: address family info
147 * @table: the table the chain is contained in 146 * @table: the table the chain is contained in
148 * @chain: the chain the rule is contained in 147 * @chain: the chain the rule is contained in
149 * @nla: netlink attributes 148 * @nla: netlink attributes
150 * @portid: netlink portID of the original message 149 * @portid: netlink portID of the original message
151 * @seq: netlink sequence number 150 * @seq: netlink sequence number
151 * @family: protocol family
152 * @report: notify via unicast netlink message 152 * @report: notify via unicast netlink message
153 */ 153 */
154struct nft_ctx { 154struct nft_ctx {
155 struct net *net; 155 struct net *net;
156 struct nft_af_info *afi;
157 struct nft_table *table; 156 struct nft_table *table;
158 struct nft_chain *chain; 157 struct nft_chain *chain;
159 const struct nlattr * const *nla; 158 const struct nlattr * const *nla;
160 u32 portid; 159 u32 portid;
161 u32 seq; 160 u32 seq;
161 u8 family;
162 bool report; 162 bool report;
163}; 163};
164 164
@@ -374,6 +374,7 @@ void nft_unregister_set(struct nft_set_type *type);
374 * @list: table set list node 374 * @list: table set list node
375 * @bindings: list of set bindings 375 * @bindings: list of set bindings
376 * @name: name of the set 376 * @name: name of the set
377 * @handle: unique handle of the set
377 * @ktype: key type (numeric type defined by userspace, not used in the kernel) 378 * @ktype: key type (numeric type defined by userspace, not used in the kernel)
378 * @dtype: data type (verdict or numeric type defined by userspace) 379 * @dtype: data type (verdict or numeric type defined by userspace)
379 * @objtype: object type (see NFT_OBJECT_* definitions) 380 * @objtype: object type (see NFT_OBJECT_* definitions)
@@ -396,6 +397,7 @@ struct nft_set {
396 struct list_head list; 397 struct list_head list;
397 struct list_head bindings; 398 struct list_head bindings;
398 char *name; 399 char *name;
400 u64 handle;
399 u32 ktype; 401 u32 ktype;
400 u32 dtype; 402 u32 dtype;
401 u32 objtype; 403 u32 objtype;
@@ -946,9 +948,11 @@ unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv);
946 * @objects: stateful objects in the table 948 * @objects: stateful objects in the table
947 * @flowtables: flow tables in the table 949 * @flowtables: flow tables in the table
948 * @hgenerator: handle generator state 950 * @hgenerator: handle generator state
951 * @handle: table handle
949 * @use: number of chain references to this table 952 * @use: number of chain references to this table
950 * @flags: table flag (see enum nft_table_flags) 953 * @flags: table flag (see enum nft_table_flags)
951 * @genmask: generation mask 954 * @genmask: generation mask
955 * @afinfo: address family info
952 * @name: name of the table 956 * @name: name of the table
953 */ 957 */
954struct nft_table { 958struct nft_table {
@@ -958,38 +962,14 @@ struct nft_table {
958 struct list_head objects; 962 struct list_head objects;
959 struct list_head flowtables; 963 struct list_head flowtables;
960 u64 hgenerator; 964 u64 hgenerator;
965 u64 handle;
961 u32 use; 966 u32 use;
962 u16 flags:14, 967 u16 family:6,
968 flags:8,
963 genmask:2; 969 genmask:2;
964 char *name; 970 char *name;
965}; 971};
966 972
967enum 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 */
981struct 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
990int nft_register_afinfo(struct net *, struct nft_af_info *);
991void nft_unregister_afinfo(struct net *, struct nft_af_info *);
992
993int nft_register_chain_type(const struct nf_chain_type *); 973int nft_register_chain_type(const struct nf_chain_type *);
994void nft_unregister_chain_type(const struct nf_chain_type *); 974void nft_unregister_chain_type(const struct nf_chain_type *);
995 975
@@ -1007,9 +987,9 @@ int nft_verdict_dump(struct sk_buff *skb, int type,
1007 * @name: name of this stateful object 987 * @name: name of this stateful object
1008 * @genmask: generation mask 988 * @genmask: generation mask
1009 * @use: number of references to this stateful object 989 * @use: number of references to this stateful object
1010 * @data: object data, layout depends on type 990 * @handle: unique object handle
1011 * @ops: object operations 991 * @ops: object operations
1012 * @data: pointer to object data 992 * @data: object data, layout depends on type
1013 */ 993 */
1014struct nft_object { 994struct nft_object {
1015 struct list_head list; 995 struct list_head list;
@@ -1017,6 +997,7 @@ struct nft_object {
1017 struct nft_table *table; 997 struct nft_table *table;
1018 u32 genmask:2, 998 u32 genmask:2,
1019 use:30; 999 use:30;
1000 u64 handle;
1020 /* runtime data below here */ 1001 /* runtime data below here */
1021 const struct nft_object_ops *ops ____cacheline_aligned; 1002 const struct nft_object_ops *ops ____cacheline_aligned;
1022 unsigned char data[] 1003 unsigned char data[]
@@ -1098,6 +1079,7 @@ void nft_unregister_obj(struct nft_object_type *obj_type);
1098 * @ops_len: number of hooks in array 1079 * @ops_len: number of hooks in array
1099 * @genmask: generation mask 1080 * @genmask: generation mask
1100 * @use: number of references to this flow table 1081 * @use: number of references to this flow table
1082 * @handle: unique object handle
1101 * @data: rhashtable and garbage collector 1083 * @data: rhashtable and garbage collector
1102 * @ops: array of hooks 1084 * @ops: array of hooks
1103 */ 1085 */
@@ -1110,6 +1092,7 @@ struct nft_flowtable {
1110 int ops_len; 1092 int ops_len;
1111 u32 genmask:2, 1093 u32 genmask:2,
1112 use:30; 1094 use:30;
1095 u64 handle;
1113 /* runtime data below here */ 1096 /* runtime data below here */
1114 struct nf_hook_ops *ops ____cacheline_aligned; 1097 struct nf_hook_ops *ops ____cacheline_aligned;
1115 struct nf_flowtable data; 1098 struct nf_flowtable data;
@@ -1154,9 +1137,6 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt,
1154 1137
1155void nft_trace_notify(struct nft_traceinfo *info); 1138void nft_trace_notify(struct nft_traceinfo *info);
1156 1139
1157#define MODULE_ALIAS_NFT_FAMILY(family) \
1158 MODULE_ALIAS("nft-afinfo-" __stringify(family))
1159
1160#define MODULE_ALIAS_NFT_CHAIN(family, name) \ 1140#define MODULE_ALIAS_NFT_CHAIN(family, name) \
1161 MODULE_ALIAS("nft-chain-" __stringify(family) "-" name) 1141 MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
1162 1142
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
index 4109b5f3010f..48134353411d 100644
--- a/include/net/netns/nftables.h
+++ b/include/net/netns/nftables.h
@@ -7,14 +7,8 @@
7struct nft_af_info; 7struct nft_af_info;
8 8
9struct netns_nftables { 9struct netns_nftables {
10 struct list_head af_info; 10 struct list_head tables;
11 struct list_head commit_list; 11 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;
18 unsigned int base_seq; 12 unsigned int base_seq;
19 u8 gencursor; 13 u8 gencursor;
20}; 14};
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 53e8dd2a3a03..66dceee0ae30 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -174,6 +174,8 @@ enum nft_table_attributes {
174 NFTA_TABLE_NAME, 174 NFTA_TABLE_NAME,
175 NFTA_TABLE_FLAGS, 175 NFTA_TABLE_FLAGS,
176 NFTA_TABLE_USE, 176 NFTA_TABLE_USE,
177 NFTA_TABLE_HANDLE,
178 NFTA_TABLE_PAD,
177 __NFTA_TABLE_MAX 179 __NFTA_TABLE_MAX
178}; 180};
179#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) 181#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
@@ -317,6 +319,7 @@ enum nft_set_desc_attributes {
317 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) 319 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
318 * @NFTA_SET_USERDATA: user data (NLA_BINARY) 320 * @NFTA_SET_USERDATA: user data (NLA_BINARY)
319 * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) 321 * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
322 * @NFTA_SET_HANDLE: set handle (NLA_U64)
320 */ 323 */
321enum nft_set_attributes { 324enum nft_set_attributes {
322 NFTA_SET_UNSPEC, 325 NFTA_SET_UNSPEC,
@@ -335,6 +338,7 @@ enum nft_set_attributes {
335 NFTA_SET_USERDATA, 338 NFTA_SET_USERDATA,
336 NFTA_SET_PAD, 339 NFTA_SET_PAD,
337 NFTA_SET_OBJ_TYPE, 340 NFTA_SET_OBJ_TYPE,
341 NFTA_SET_HANDLE,
338 __NFTA_SET_MAX 342 __NFTA_SET_MAX
339}; 343};
340#define NFTA_SET_MAX (__NFTA_SET_MAX - 1) 344#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -1314,6 +1318,7 @@ enum nft_ct_helper_attributes {
1314 * @NFTA_OBJ_TYPE: stateful object type (NLA_U32) 1318 * @NFTA_OBJ_TYPE: stateful object type (NLA_U32)
1315 * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) 1319 * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
1316 * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) 1320 * @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
1321 * @NFTA_OBJ_HANDLE: object handle (NLA_U64)
1317 */ 1322 */
1318enum nft_object_attributes { 1323enum nft_object_attributes {
1319 NFTA_OBJ_UNSPEC, 1324 NFTA_OBJ_UNSPEC,
@@ -1322,6 +1327,8 @@ enum nft_object_attributes {
1322 NFTA_OBJ_TYPE, 1327 NFTA_OBJ_TYPE,
1323 NFTA_OBJ_DATA, 1328 NFTA_OBJ_DATA,
1324 NFTA_OBJ_USE, 1329 NFTA_OBJ_USE,
1330 NFTA_OBJ_HANDLE,
1331 NFTA_OBJ_PAD,
1325 __NFTA_OBJ_MAX 1332 __NFTA_OBJ_MAX
1326}; 1333};
1327#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) 1334#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
@@ -1333,6 +1340,7 @@ enum nft_object_attributes {
1333 * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) 1340 * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING)
1334 * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) 1341 * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
1335 * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) 1342 * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
1343 * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
1336 */ 1344 */
1337enum nft_flowtable_attributes { 1345enum nft_flowtable_attributes {
1338 NFTA_FLOWTABLE_UNSPEC, 1346 NFTA_FLOWTABLE_UNSPEC,
@@ -1340,6 +1348,8 @@ enum nft_flowtable_attributes {
1340 NFTA_FLOWTABLE_NAME, 1348 NFTA_FLOWTABLE_NAME,
1341 NFTA_FLOWTABLE_HOOK, 1349 NFTA_FLOWTABLE_HOOK,
1342 NFTA_FLOWTABLE_USE, 1350 NFTA_FLOWTABLE_USE,
1351 NFTA_FLOWTABLE_HANDLE,
1352 NFTA_FLOWTABLE_PAD,
1343 __NFTA_FLOWTABLE_MAX 1353 __NFTA_FLOWTABLE_MAX
1344}; 1354};
1345#define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) 1355#define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1)
diff --git a/include/uapi/linux/netfilter_ipv4.h b/include/uapi/linux/netfilter_ipv4.h
index e6b1a84f5dd3..c3b060775e13 100644
--- a/include/uapi/linux/netfilter_ipv4.h
+++ b/include/uapi/linux/netfilter_ipv4.h
@@ -57,6 +57,7 @@
57 57
58enum nf_ip_hook_priorities { 58enum nf_ip_hook_priorities {
59 NF_IP_PRI_FIRST = INT_MIN, 59 NF_IP_PRI_FIRST = INT_MIN,
60 NF_IP_PRI_RAW_BEFORE_DEFRAG = -450,
60 NF_IP_PRI_CONNTRACK_DEFRAG = -400, 61 NF_IP_PRI_CONNTRACK_DEFRAG = -400,
61 NF_IP_PRI_RAW = -300, 62 NF_IP_PRI_RAW = -300,
62 NF_IP_PRI_SELINUX_FIRST = -225, 63 NF_IP_PRI_SELINUX_FIRST = -225,
diff --git a/include/uapi/linux/netfilter_ipv6.h b/include/uapi/linux/netfilter_ipv6.h
index 2f9724611cc2..dc624fd24d25 100644
--- a/include/uapi/linux/netfilter_ipv6.h
+++ b/include/uapi/linux/netfilter_ipv6.h
@@ -62,6 +62,7 @@
62 62
63enum nf_ip6_hook_priorities { 63enum nf_ip6_hook_priorities {
64 NF_IP6_PRI_FIRST = INT_MIN, 64 NF_IP6_PRI_FIRST = INT_MIN,
65 NF_IP6_PRI_RAW_BEFORE_DEFRAG = -450,
65 NF_IP6_PRI_CONNTRACK_DEFRAG = -400, 66 NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
66 NF_IP6_PRI_RAW = -300, 67 NF_IP6_PRI_RAW = -300,
67 NF_IP6_PRI_SELINUX_FIRST = -225, 68 NF_IP6_PRI_SELINUX_FIRST = -225,
diff --git a/include/uapi/linux/netfilter_ipv6/ip6t_srh.h b/include/uapi/linux/netfilter_ipv6/ip6t_srh.h
new file mode 100644
index 000000000000..f3cc0ef514a7
--- /dev/null
+++ b/include/uapi/linux/netfilter_ipv6/ip6t_srh.h
@@ -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
47struct 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*/
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 37817d25b63d..02c4b409d317 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -2445,7 +2445,6 @@ static int __init ebtables_init(void)
2445 return ret; 2445 return ret;
2446 } 2446 }
2447 2447
2448 printk(KERN_INFO "Ebtables v2.0 registered\n");
2449 return 0; 2448 return 0;
2450} 2449}
2451 2450
@@ -2453,7 +2452,6 @@ static void __exit ebtables_fini(void)
2453{ 2452{
2454 nf_unregister_sockopt(&ebt_sockopts); 2453 nf_unregister_sockopt(&ebt_sockopts);
2455 xt_unregister_target(&ebt_standard_target); 2454 xt_unregister_target(&ebt_standard_target);
2456 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
2457} 2455}
2458 2456
2459EXPORT_SYMBOL(ebt_register_table); 2457EXPORT_SYMBOL(ebt_register_table);
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index 86774b5c3b73..5160cf614176 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -42,40 +42,6 @@ nft_do_chain_bridge(void *priv,
42 return nft_do_chain(&pkt, priv); 42 return nft_do_chain(&pkt, priv);
43} 43}
44 44
45static struct nft_af_info nft_af_bridge __read_mostly = {
46 .family = NFPROTO_BRIDGE,
47 .nhooks = NF_BR_NUMHOOKS,
48 .owner = THIS_MODULE,
49};
50
51static 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;
63err:
64 kfree(net->nft.bridge);
65 return -ENOMEM;
66}
67
68static 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
74static struct pernet_operations nf_tables_bridge_net_ops = {
75 .init = nf_tables_bridge_init_net,
76 .exit = nf_tables_bridge_exit_net,
77};
78
79static const struct nf_chain_type filter_bridge = { 45static const struct nf_chain_type filter_bridge = {
80 .name = "filter", 46 .name = "filter",
81 .type = NFT_CHAIN_T_DEFAULT, 47 .type = NFT_CHAIN_T_DEFAULT,
@@ -97,27 +63,11 @@ static const struct nf_chain_type filter_bridge = {
97 63
98static int __init nf_tables_bridge_init(void) 64static int __init nf_tables_bridge_init(void)
99{ 65{
100 int ret; 66 return nft_register_chain_type(&filter_bridge);
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
112err_register_subsys:
113 nft_unregister_chain_type(&filter_bridge);
114
115 return ret;
116} 67}
117 68
118static void __exit nf_tables_bridge_exit(void) 69static void __exit nf_tables_bridge_exit(void)
119{ 70{
120 unregister_pernet_subsys(&nf_tables_bridge_net_ops);
121 nft_unregister_chain_type(&filter_bridge); 71 nft_unregister_chain_type(&filter_bridge);
122} 72}
123 73
@@ -126,4 +76,4 @@ module_exit(nf_tables_bridge_exit);
126 76
127MODULE_LICENSE("GPL"); 77MODULE_LICENSE("GPL");
128MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 78MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
129MODULE_ALIAS_NFT_FAMILY(AF_BRIDGE); 79MODULE_ALIAS_NFT_CHAIN(AF_BRIDGE, "filter");
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 7d5d444964aa..5f52236780b4 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -79,8 +79,9 @@ config NF_TABLES_ARP
79endif # NF_TABLES 79endif # NF_TABLES
80 80
81config NF_FLOW_TABLE_IPV4 81config NF_FLOW_TABLE_IPV4
82 select NF_FLOW_TABLE
83 tristate "Netfilter flow table IPv4 module" 82 tristate "Netfilter flow table IPv4 module"
83 depends on NF_CONNTRACK && NF_TABLES
84 select NF_FLOW_TABLE
84 help 85 help
85 This option adds the flow table IPv4 support. 86 This option adds the flow table IPv4 support.
86 87
@@ -157,6 +158,7 @@ config NF_NAT_SNMP_BASIC
157 depends on NF_CONNTRACK_SNMP 158 depends on NF_CONNTRACK_SNMP
158 depends on NETFILTER_ADVANCED 159 depends on NETFILTER_ADVANCED
159 default NF_NAT && NF_CONNTRACK_SNMP 160 default NF_NAT && NF_CONNTRACK_SNMP
161 select ASN1
160 ---help--- 162 ---help---
161 163
162 This module implements an Application Layer Gateway (ALG) for 164 This module implements an Application Layer Gateway (ALG) for
@@ -342,6 +344,7 @@ config IP_NF_TARGET_CLUSTERIP
342 depends on NF_CONNTRACK_IPV4 344 depends on NF_CONNTRACK_IPV4
343 depends on NETFILTER_ADVANCED 345 depends on NETFILTER_ADVANCED
344 select NF_CONNTRACK_MARK 346 select NF_CONNTRACK_MARK
347 select NETFILTER_FAMILY_ARP
345 help 348 help
346 The CLUSTERIP target allows you to build load-balancing clusters of 349 The CLUSTERIP target allows you to build load-balancing clusters of
347 network servers without having a dedicated load-balancing 350 network servers without having a dedicated load-balancing
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 8bb1f0c7a375..2dad20eefd26 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -27,9 +27,15 @@ obj-$(CONFIG_NF_REJECT_IPV4) += nf_reject_ipv4.o
27# NAT helpers (nf_conntrack) 27# NAT helpers (nf_conntrack)
28obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 28obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
29obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o 29obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
30
31nf_nat_snmp_basic-y := nf_nat_snmp_basic-asn1.o nf_nat_snmp_basic_main.o
32nf_nat_snmp_basic-y : nf_nat_snmp_basic-asn1.h nf_nat_snmp_basic-asn1.c
30obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o 33obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
34clean-files := nf_nat_snmp_basic-asn1.c nf_nat_snmp_basic-asn1.h
35
31obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o 36obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o
32 37
38
33# NAT protocols (nf_nat) 39# NAT protocols (nf_nat)
34obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o 40obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
35 41
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index bf8a5340f15e..5f7c0d643fb3 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1656,7 +1656,6 @@ static int __init arp_tables_init(void)
1656 if (ret < 0) 1656 if (ret < 0)
1657 goto err4; 1657 goto err4;
1658 1658
1659 pr_info("arp_tables: (C) 2002 David S. Miller\n");
1660 return 0; 1659 return 0;
1661 1660
1662err4: 1661err4:
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 0b975aa2d363..1f534aec22f0 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1939,7 +1939,6 @@ static int __init ip_tables_init(void)
1939 if (ret < 0) 1939 if (ret < 0)
1940 goto err5; 1940 goto err5;
1941 1941
1942 pr_info("(C) 2000-2006 Netfilter Core Team\n");
1943 return 0; 1942 return 0;
1944 1943
1945err5: 1944err5:
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index a869d1fea7d9..960625aabf04 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 4 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5 */ 5 */
6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
6#include <linux/module.h> 7#include <linux/module.h>
7#include <linux/netfilter_ipv4/ip_tables.h> 8#include <linux/netfilter_ipv4/ip_tables.h>
8#include <linux/slab.h> 9#include <linux/slab.h>
@@ -12,6 +13,10 @@
12 13
13static int __net_init iptable_raw_table_init(struct net *net); 14static int __net_init iptable_raw_table_init(struct net *net);
14 15
16static bool raw_before_defrag __read_mostly;
17MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
18module_param(raw_before_defrag, bool, 0000);
19
15static const struct xt_table packet_raw = { 20static const struct xt_table packet_raw = {
16 .name = "raw", 21 .name = "raw",
17 .valid_hooks = RAW_VALID_HOOKS, 22 .valid_hooks = RAW_VALID_HOOKS,
@@ -21,6 +26,15 @@ static const struct xt_table packet_raw = {
21 .table_init = iptable_raw_table_init, 26 .table_init = iptable_raw_table_init,
22}; 27};
23 28
29static 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
24/* The work comes in here from netfilter.c. */ 38/* The work comes in here from netfilter.c. */
25static unsigned int 39static unsigned int
26iptable_raw_hook(void *priv, struct sk_buff *skb, 40iptable_raw_hook(void *priv, struct sk_buff *skb,
@@ -34,15 +48,19 @@ static struct nf_hook_ops *rawtable_ops __read_mostly;
34static int __net_init iptable_raw_table_init(struct net *net) 48static int __net_init iptable_raw_table_init(struct net *net)
35{ 49{
36 struct ipt_replace *repl; 50 struct ipt_replace *repl;
51 const struct xt_table *table = &packet_raw;
37 int ret; 52 int ret;
38 53
54 if (raw_before_defrag)
55 table = &packet_raw_before_defrag;
56
39 if (net->ipv4.iptable_raw) 57 if (net->ipv4.iptable_raw)
40 return 0; 58 return 0;
41 59
42 repl = ipt_alloc_initial_table(&packet_raw); 60 repl = ipt_alloc_initial_table(table);
43 if (repl == NULL) 61 if (repl == NULL)
44 return -ENOMEM; 62 return -ENOMEM;
45 ret = ipt_register_table(net, &packet_raw, repl, rawtable_ops, 63 ret = ipt_register_table(net, table, repl, rawtable_ops,
46 &net->ipv4.iptable_raw); 64 &net->ipv4.iptable_raw);
47 kfree(repl); 65 kfree(repl);
48 return ret; 66 return ret;
@@ -63,8 +81,15 @@ static struct pernet_operations iptable_raw_net_ops = {
63static int __init iptable_raw_init(void) 81static int __init iptable_raw_init(void)
64{ 82{
65 int ret; 83 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 }
66 91
67 rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook); 92 rawtable_ops = xt_hook_ops_alloc(table, iptable_raw_hook);
68 if (IS_ERR(rawtable_ops)) 93 if (IS_ERR(rawtable_ops))
69 return PTR_ERR(rawtable_ops); 94 return PTR_ERR(rawtable_ops);
70 95
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index 37fe1616ca0b..a0d3ad60a411 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -78,6 +78,8 @@ static unsigned int ipv4_conntrack_defrag(void *priv,
78 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb))) 78 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb)))
79 return NF_ACCEPT; 79 return NF_ACCEPT;
80#endif 80#endif
81 if (skb->_nfct == IP_CT_UNTRACKED)
82 return NF_ACCEPT;
81#endif 83#endif
82 /* Gather fragments. */ 84 /* Gather fragments. */
83 if (ip_is_fragment(ip_hdr(skb))) { 85 if (ip_is_fragment(ip_hdr(skb))) {
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.asn1 b/net/ipv4/netfilter/nf_nat_snmp_basic.asn1
new file mode 100644
index 000000000000..24b73268f362
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.asn1
@@ -0,0 +1,177 @@
1Message ::=
2 SEQUENCE {
3 version
4 INTEGER ({snmp_version}),
5
6 community
7 OCTET STRING,
8
9 pdu
10 PDUs
11 }
12
13
14ObjectName ::=
15 OBJECT IDENTIFIER
16
17ObjectSyntax ::=
18 CHOICE {
19 simple
20 SimpleSyntax,
21
22 application-wide
23 ApplicationSyntax
24 }
25
26SimpleSyntax ::=
27 CHOICE {
28 integer-value
29 INTEGER,
30
31 string-value
32 OCTET STRING,
33
34 objectID-value
35 OBJECT IDENTIFIER
36 }
37
38ApplicationSyntax ::=
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
59IpAddress ::=
60 [APPLICATION 0]
61 IMPLICIT OCTET STRING OPTIONAL ({snmp_helper})
62
63Counter32 ::=
64 [APPLICATION 1]
65 IMPLICIT INTEGER OPTIONAL
66
67Unsigned32 ::=
68 [APPLICATION 2]
69 IMPLICIT INTEGER OPTIONAL
70
71Gauge32 ::= Unsigned32 OPTIONAL
72
73TimeTicks ::=
74 [APPLICATION 3]
75 IMPLICIT INTEGER OPTIONAL
76
77Opaque ::=
78 [APPLICATION 4]
79 IMPLICIT OCTET STRING OPTIONAL
80
81Counter64 ::=
82 [APPLICATION 6]
83 IMPLICIT INTEGER OPTIONAL
84
85PDUs ::=
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
112GetRequest-PDU ::=
113 [0] IMPLICIT PDU OPTIONAL
114
115GetNextRequest-PDU ::=
116 [1] IMPLICIT PDU OPTIONAL
117
118Response-PDU ::=
119 [2] IMPLICIT PDU OPTIONAL
120
121SetRequest-PDU ::=
122 [3] IMPLICIT PDU OPTIONAL
123
124-- [4] is obsolete
125
126GetBulkRequest-PDU ::=
127 [5] IMPLICIT PDU OPTIONAL
128
129InformRequest-PDU ::=
130 [6] IMPLICIT PDU OPTIONAL
131
132SNMPv2-Trap-PDU ::=
133 [7] IMPLICIT PDU OPTIONAL
134
135Report-PDU ::=
136 [8] IMPLICIT PDU OPTIONAL
137
138PDU ::=
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
154VarBind ::=
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
177VarBindList ::= SEQUENCE OF VarBind
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
deleted file mode 100644
index d5b1e0b3f687..000000000000
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ /dev/null
@@ -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
60MODULE_LICENSE("GPL");
61MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
62MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
63MODULE_ALIAS("ip_nat_snmp_basic");
64
65#define SNMP_PORT 161
66#define SNMP_TRAP_PORT 162
67#define NOCT1(n) (*(u8 *)(n))
68
69static int debug;
70static 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 */
77struct 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 */
135struct 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 */
146struct asn1_octstr
147{
148 unsigned char *data;
149 unsigned int len;
150};
151
152static 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
162static 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
172static 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
188static 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
209static 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
246static 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
272static 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
302static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc)
303{
304 ctx->pointer = eoc;
305 return 1;
306}
307
308static 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
336static 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
365static 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
394static 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
419static 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
436static 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
574union 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
582struct 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
591struct snmp_request
592{
593 unsigned long id;
594 unsigned int error_status;
595 unsigned int error_index;
596};
597
598struct 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
621static inline void mangle_address(unsigned char *begin,
622 unsigned char *addr,
623 const struct oct1_map *map,
624 __sum16 *check);
625struct snmp_cnv
626{
627 unsigned int class;
628 unsigned int tag;
629 int syntax;
630};
631
632static 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
653static 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
671static 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
830static unsigned char noinline_for_stack
831snmp_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 */
870static 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 */
897static 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
923static unsigned char noinline_for_stack
924snmp_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
986err_addr_free:
987 kfree((unsigned long *)trap->ip_address);
988
989err_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 */
1005static 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 */
1169static 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 */
1207static 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
1247static const struct nf_conntrack_expect_policy snmp_exp_policy = {
1248 .max_expected = 0,
1249 .timeout = 180,
1250};
1251
1252static 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
1268static 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
1276static 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
1283module_init(nf_nat_snmp_basic_init);
1284module_exit(nf_nat_snmp_basic_fini);
1285
1286module_param(debug, int, 0600);
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic_main.c b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
new file mode 100644
index 000000000000..b6e277093e7e
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c
@@ -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
59MODULE_LICENSE("GPL");
60MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
61MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
62MODULE_ALIAS("ip_nat_snmp_basic");
63
64#define SNMP_PORT 161
65#define SNMP_TRAP_PORT 162
66
67static DEFINE_SPINLOCK(snmp_lock);
68
69struct snmp_ctx {
70 unsigned char *begin;
71 __sum16 *check;
72 __be32 from;
73 __be32 to;
74};
75
76static 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
104int 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
112int 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
130static 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 */
164static 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
204static const struct nf_conntrack_expect_policy snmp_exp_policy = {
205 .max_expected = 0,
206 .timeout = 180,
207};
208
209static 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
219static 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
227static 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
234module_init(nf_nat_snmp_basic_init);
235module_exit(nf_nat_snmp_basic_fini);
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c
index f84c17763f6f..036c074736b0 100644
--- a/net/ipv4/netfilter/nf_tables_arp.c
+++ b/net/ipv4/netfilter/nf_tables_arp.c
@@ -27,40 +27,6 @@ nft_do_chain_arp(void *priv,
27 return nft_do_chain(&pkt, priv); 27 return nft_do_chain(&pkt, priv);
28} 28}
29 29
30static struct nft_af_info nft_af_arp __read_mostly = {
31 .family = NFPROTO_ARP,
32 .nhooks = NF_ARP_NUMHOOKS,
33 .owner = THIS_MODULE,
34};
35
36static 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;
48err:
49 kfree(net->nft.arp);
50 return -ENOMEM;
51}
52
53static 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
59static struct pernet_operations nf_tables_arp_net_ops = {
60 .init = nf_tables_arp_init_net,
61 .exit = nf_tables_arp_exit_net,
62};
63
64static const struct nf_chain_type filter_arp = { 30static const struct nf_chain_type filter_arp = {
65 .name = "filter", 31 .name = "filter",
66 .type = NFT_CHAIN_T_DEFAULT, 32 .type = NFT_CHAIN_T_DEFAULT,
@@ -76,22 +42,11 @@ static const struct nf_chain_type filter_arp = {
76 42
77static int __init nf_tables_arp_init(void) 43static int __init nf_tables_arp_init(void)
78{ 44{
79 int ret; 45 return nft_register_chain_type(&filter_arp);
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;
90} 46}
91 47
92static void __exit nf_tables_arp_exit(void) 48static void __exit nf_tables_arp_exit(void)
93{ 49{
94 unregister_pernet_subsys(&nf_tables_arp_net_ops);
95 nft_unregister_chain_type(&filter_arp); 50 nft_unregister_chain_type(&filter_arp);
96} 51}
97 52
@@ -100,4 +55,4 @@ module_exit(nf_tables_arp_exit);
100 55
101MODULE_LICENSE("GPL"); 56MODULE_LICENSE("GPL");
102MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 57MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
103MODULE_ALIAS_NFT_FAMILY(3); /* NFPROTO_ARP */ 58MODULE_ALIAS_NFT_CHAIN(3, "filter"); /* NFPROTO_ARP */
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index f4675253f1e6..96f955496d5f 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -30,40 +30,6 @@ static unsigned int nft_do_chain_ipv4(void *priv,
30 return nft_do_chain(&pkt, priv); 30 return nft_do_chain(&pkt, priv);
31} 31}
32 32
33static struct nft_af_info nft_af_ipv4 __read_mostly = {
34 .family = NFPROTO_IPV4,
35 .nhooks = NF_INET_NUMHOOKS,
36 .owner = THIS_MODULE,
37};
38
39static 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;
51err:
52 kfree(net->nft.ipv4);
53 return -ENOMEM;
54}
55
56static 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
62static struct pernet_operations nf_tables_ipv4_net_ops = {
63 .init = nf_tables_ipv4_init_net,
64 .exit = nf_tables_ipv4_exit_net,
65};
66
67static const struct nf_chain_type filter_ipv4 = { 33static const struct nf_chain_type filter_ipv4 = {
68 .name = "filter", 34 .name = "filter",
69 .type = NFT_CHAIN_T_DEFAULT, 35 .type = NFT_CHAIN_T_DEFAULT,
@@ -85,22 +51,11 @@ static const struct nf_chain_type filter_ipv4 = {
85 51
86static int __init nf_tables_ipv4_init(void) 52static int __init nf_tables_ipv4_init(void)
87{ 53{
88 int ret; 54 return nft_register_chain_type(&filter_ipv4);
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;
99} 55}
100 56
101static void __exit nf_tables_ipv4_exit(void) 57static void __exit nf_tables_ipv4_exit(void)
102{ 58{
103 unregister_pernet_subsys(&nf_tables_ipv4_net_ops);
104 nft_unregister_chain_type(&filter_ipv4); 59 nft_unregister_chain_type(&filter_ipv4);
105} 60}
106 61
@@ -109,4 +64,4 @@ module_exit(nf_tables_ipv4_exit);
109 64
110MODULE_LICENSE("GPL"); 65MODULE_LICENSE("GPL");
111MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 66MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
112MODULE_ALIAS_NFT_FAMILY(AF_INET); 67MODULE_ALIAS_NFT_CHAIN(AF_INET, "filter");
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 806e95375ec8..4a634b7a2c80 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -72,8 +72,9 @@ endif # NF_TABLES_IPV6
72endif # NF_TABLES 72endif # NF_TABLES
73 73
74config NF_FLOW_TABLE_IPV6 74config NF_FLOW_TABLE_IPV6
75 select NF_FLOW_TABLE
76 tristate "Netfilter flow table IPv6 module" 75 tristate "Netfilter flow table IPv6 module"
76 depends on NF_CONNTRACK && NF_TABLES
77 select NF_FLOW_TABLE
77 help 78 help
78 This option adds the flow table IPv6 support. 79 This option adds the flow table IPv6 support.
79 80
@@ -240,6 +241,15 @@ config IP6_NF_MATCH_RT
240 241
241 To compile it as a module, choose M here. If unsure, say N. 242 To compile it as a module, choose M here. If unsure, say N.
242 243
244config 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
243# The targets 253# The targets
244config IP6_NF_TARGET_HL 254config IP6_NF_TARGET_HL
245 tristate '"HL" hoplimit target support' 255 tristate '"HL" hoplimit target support'
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 95611c4b39b0..d984057b8395 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
57obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o 57obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
58obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o 58obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
59obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 59obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
60obj-$(CONFIG_IP6_NF_MATCH_SRH) += ip6t_srh.o
60 61
61# targets 62# targets
62obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o 63obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 6ebbef2dfb60..37fa76ee5130 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1952,7 +1952,6 @@ static int __init ip6_tables_init(void)
1952 if (ret < 0) 1952 if (ret < 0)
1953 goto err5; 1953 goto err5;
1954 1954
1955 pr_info("(C) 2000-2006 Netfilter Core Team\n");
1956 return 0; 1955 return 0;
1957 1956
1958err5: 1957err5:
diff --git a/net/ipv6/netfilter/ip6t_srh.c b/net/ipv6/netfilter/ip6t_srh.c
new file mode 100644
index 000000000000..9642164107ce
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_srh.c
@@ -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
28static 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
120static 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
137static 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
146static int __init srh_mt6_init(void)
147{
148 return xt_register_match(&srh_mt6_reg);
149}
150
151static void __exit srh_mt6_exit(void)
152{
153 xt_unregister_match(&srh_mt6_reg);
154}
155
156module_init(srh_mt6_init);
157module_exit(srh_mt6_exit);
158
159MODULE_LICENSE("GPL");
160MODULE_DESCRIPTION("Xtables: IPv6 Segment Routing Header match");
161MODULE_AUTHOR("Ahmed Abdelsalam <amsalam20@gmail.com>");
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index d4bc56443dc1..710fa0806c37 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 4 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5 */ 5 */
6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
6#include <linux/module.h> 7#include <linux/module.h>
7#include <linux/netfilter_ipv6/ip6_tables.h> 8#include <linux/netfilter_ipv6/ip6_tables.h>
8#include <linux/slab.h> 9#include <linux/slab.h>
@@ -11,6 +12,10 @@
11 12
12static int __net_init ip6table_raw_table_init(struct net *net); 13static int __net_init ip6table_raw_table_init(struct net *net);
13 14
15static bool raw_before_defrag __read_mostly;
16MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
17module_param(raw_before_defrag, bool, 0000);
18
14static const struct xt_table packet_raw = { 19static const struct xt_table packet_raw = {
15 .name = "raw", 20 .name = "raw",
16 .valid_hooks = RAW_VALID_HOOKS, 21 .valid_hooks = RAW_VALID_HOOKS,
@@ -20,6 +25,15 @@ static const struct xt_table packet_raw = {
20 .table_init = ip6table_raw_table_init, 25 .table_init = ip6table_raw_table_init,
21}; 26};
22 27
28static 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
23/* The work comes in here from netfilter.c. */ 37/* The work comes in here from netfilter.c. */
24static unsigned int 38static unsigned int
25ip6table_raw_hook(void *priv, struct sk_buff *skb, 39ip6table_raw_hook(void *priv, struct sk_buff *skb,
@@ -33,15 +47,19 @@ static struct nf_hook_ops *rawtable_ops __read_mostly;
33static int __net_init ip6table_raw_table_init(struct net *net) 47static int __net_init ip6table_raw_table_init(struct net *net)
34{ 48{
35 struct ip6t_replace *repl; 49 struct ip6t_replace *repl;
50 const struct xt_table *table = &packet_raw;
36 int ret; 51 int ret;
37 52
53 if (raw_before_defrag)
54 table = &packet_raw_before_defrag;
55
38 if (net->ipv6.ip6table_raw) 56 if (net->ipv6.ip6table_raw)
39 return 0; 57 return 0;
40 58
41 repl = ip6t_alloc_initial_table(&packet_raw); 59 repl = ip6t_alloc_initial_table(table);
42 if (repl == NULL) 60 if (repl == NULL)
43 return -ENOMEM; 61 return -ENOMEM;
44 ret = ip6t_register_table(net, &packet_raw, repl, rawtable_ops, 62 ret = ip6t_register_table(net, table, repl, rawtable_ops,
45 &net->ipv6.ip6table_raw); 63 &net->ipv6.ip6table_raw);
46 kfree(repl); 64 kfree(repl);
47 return ret; 65 return ret;
@@ -62,9 +80,16 @@ static struct pernet_operations ip6table_raw_net_ops = {
62static int __init ip6table_raw_init(void) 80static int __init ip6table_raw_init(void)
63{ 81{
64 int ret; 82 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 }
65 90
66 /* Register hooks */ 91 /* 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);
68 if (IS_ERR(rawtable_ops)) 93 if (IS_ERR(rawtable_ops))
69 return PTR_ERR(rawtable_ops); 94 return PTR_ERR(rawtable_ops);
70 95
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 977d8900cfd1..ce53dcfda88a 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -231,7 +231,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb,
231 231
232 if ((unsigned int)end > IPV6_MAXPLEN) { 232 if ((unsigned int)end > IPV6_MAXPLEN) {
233 pr_debug("offset is too large.\n"); 233 pr_debug("offset is too large.\n");
234 return -1; 234 return -EINVAL;
235 } 235 }
236 236
237 ecn = ip6_frag_ecn(ipv6_hdr(skb)); 237 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,
264 * this case. -DaveM 264 * this case. -DaveM
265 */ 265 */
266 pr_debug("end of fragment not rounded to 8 bytes.\n"); 266 pr_debug("end of fragment not rounded to 8 bytes.\n");
267 return -1; 267 return -EPROTO;
268 } 268 }
269 if (end > fq->q.len) { 269 if (end > fq->q.len) {
270 /* Some bits beyond end -> corruption. */ 270 /* Some bits beyond end -> corruption. */
@@ -358,7 +358,7 @@ found:
358discard_fq: 358discard_fq:
359 inet_frag_kill(&fq->q, &nf_frags); 359 inet_frag_kill(&fq->q, &nf_frags);
360err: 360err:
361 return -1; 361 return -EINVAL;
362} 362}
363 363
364/* 364/*
@@ -567,6 +567,7 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
567 567
568int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) 568int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
569{ 569{
570 u16 savethdr = skb->transport_header;
570 struct net_device *dev = skb->dev; 571 struct net_device *dev = skb->dev;
571 int fhoff, nhoff, ret; 572 int fhoff, nhoff, ret;
572 struct frag_hdr *fhdr; 573 struct frag_hdr *fhdr;
@@ -600,8 +601,12 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
600 601
601 spin_lock_bh(&fq->q.lock); 602 spin_lock_bh(&fq->q.lock);
602 603
603 if (nf_ct_frag6_queue(fq, skb, fhdr, nhoff) < 0) { 604 ret = nf_ct_frag6_queue(fq, skb, fhdr, nhoff);
604 ret = -EINVAL; 605 if (ret < 0) {
606 if (ret == -EPROTO) {
607 skb->transport_header = savethdr;
608 ret = 0;
609 }
605 goto out_unlock; 610 goto out_unlock;
606 } 611 }
607 612
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index b326da59257f..c87b48359e8f 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -63,6 +63,9 @@ static unsigned int ipv6_defrag(void *priv,
63 /* Previously seen (loopback)? */ 63 /* Previously seen (loopback)? */
64 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb))) 64 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb)))
65 return NF_ACCEPT; 65 return NF_ACCEPT;
66
67 if (skb->_nfct == IP_CT_UNTRACKED)
68 return NF_ACCEPT;
66#endif 69#endif
67 70
68 err = nf_ct_frag6_gather(state->net, skb, 71 err = nf_ct_frag6_gather(state->net, skb,
diff --git a/net/ipv6/netfilter/nf_flow_table_ipv6.c b/net/ipv6/netfilter/nf_flow_table_ipv6.c
index 0c3b9d32f64f..fff21602875a 100644
--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c
+++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c
@@ -5,7 +5,6 @@
5#include <linux/rhashtable.h> 5#include <linux/rhashtable.h>
6#include <linux/ipv6.h> 6#include <linux/ipv6.h>
7#include <linux/netdevice.h> 7#include <linux/netdevice.h>
8#include <linux/ipv6.h>
9#include <net/ipv6.h> 8#include <net/ipv6.h>
10#include <net/ip6_route.h> 9#include <net/ip6_route.h>
11#include <net/neighbour.h> 10#include <net/neighbour.h>
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c
index 9cd45b964123..17e03589331c 100644
--- a/net/ipv6/netfilter/nf_tables_ipv6.c
+++ b/net/ipv6/netfilter/nf_tables_ipv6.c
@@ -28,40 +28,6 @@ static unsigned int nft_do_chain_ipv6(void *priv,
28 return nft_do_chain(&pkt, priv); 28 return nft_do_chain(&pkt, priv);
29} 29}
30 30
31static struct nft_af_info nft_af_ipv6 __read_mostly = {
32 .family = NFPROTO_IPV6,
33 .nhooks = NF_INET_NUMHOOKS,
34 .owner = THIS_MODULE,
35};
36
37static 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;
49err:
50 kfree(net->nft.ipv6);
51 return -ENOMEM;
52}
53
54static 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
60static struct pernet_operations nf_tables_ipv6_net_ops = {
61 .init = nf_tables_ipv6_init_net,
62 .exit = nf_tables_ipv6_exit_net,
63};
64
65static const struct nf_chain_type filter_ipv6 = { 31static const struct nf_chain_type filter_ipv6 = {
66 .name = "filter", 32 .name = "filter",
67 .type = NFT_CHAIN_T_DEFAULT, 33 .type = NFT_CHAIN_T_DEFAULT,
@@ -83,22 +49,11 @@ static const struct nf_chain_type filter_ipv6 = {
83 49
84static int __init nf_tables_ipv6_init(void) 50static int __init nf_tables_ipv6_init(void)
85{ 51{
86 int ret; 52 return nft_register_chain_type(&filter_ipv6);
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;
97} 53}
98 54
99static void __exit nf_tables_ipv6_exit(void) 55static void __exit nf_tables_ipv6_exit(void)
100{ 56{
101 unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
102 nft_unregister_chain_type(&filter_ipv6); 57 nft_unregister_chain_type(&filter_ipv6);
103} 58}
104 59
@@ -107,4 +62,4 @@ module_exit(nf_tables_ipv6_exit);
107 62
108MODULE_LICENSE("GPL"); 63MODULE_LICENSE("GPL");
109MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 64MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
110MODULE_ALIAS_NFT_FAMILY(AF_INET6); 65MODULE_ALIAS_NFT_CHAIN(AF_INET6, "filter");
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 0ee0fcf3abbf..9019fa98003d 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -506,7 +506,7 @@ config NFT_CT
506 connection tracking information such as the flow state. 506 connection tracking information such as the flow state.
507 507
508config NFT_FLOW_OFFLOAD 508config NFT_FLOW_OFFLOAD
509 depends on NF_CONNTRACK 509 depends on NF_CONNTRACK && NF_FLOW_TABLE
510 tristate "Netfilter nf_tables hardware flow offload module" 510 tristate "Netfilter nf_tables hardware flow offload module"
511 help 511 help
512 This option adds the "flow_offload" expression that you can use to 512 This option adds the "flow_offload" expression that you can use to
@@ -665,8 +665,9 @@ endif # NF_TABLES_NETDEV
665endif # NF_TABLES 665endif # NF_TABLES
666 666
667config NF_FLOW_TABLE_INET 667config NF_FLOW_TABLE_INET
668 select NF_FLOW_TABLE
669 tristate "Netfilter flow table mixed IPv4/IPv6 module" 668 tristate "Netfilter flow table mixed IPv4/IPv6 module"
669 depends on NF_FLOW_TABLE_IPV4 && NF_FLOW_TABLE_IPV6
670 select NF_FLOW_TABLE
670 help 671 help
671 This option adds the flow table mixed IPv4/IPv6 support. 672 This option adds the flow table mixed IPv4/IPv6 support.
672 673
@@ -674,6 +675,7 @@ config NF_FLOW_TABLE_INET
674 675
675config NF_FLOW_TABLE 676config NF_FLOW_TABLE
676 tristate "Netfilter flow table module" 677 tristate "Netfilter flow table module"
678 depends on NF_CONNTRACK && NF_TABLES
677 help 679 help
678 This option adds the flow table core infrastructure. 680 This option adds the flow table core infrastructure.
679 681
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 997dd387d259..0f6b8172fb9a 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -140,7 +140,7 @@ nf_hook_entries_grow(const struct nf_hook_entries *old,
140 140
141 if (reg->nat_hook && orig_ops[i]->nat_hook) { 141 if (reg->nat_hook && orig_ops[i]->nat_hook) {
142 kvfree(new); 142 kvfree(new);
143 return ERR_PTR(-EEXIST); 143 return ERR_PTR(-EBUSY);
144 } 144 }
145 145
146 if (inserted || reg->priority > orig_ops[i]->priority) { 146 if (inserted || reg->priority > orig_ops[i]->priority) {
@@ -377,8 +377,8 @@ static void nf_remove_net_hook(struct nf_hook_entries *old,
377 } 377 }
378} 378}
379 379
380void __nf_unregister_net_hook(struct net *net, int pf, 380static void __nf_unregister_net_hook(struct net *net, int pf,
381 const struct nf_hook_ops *reg) 381 const struct nf_hook_ops *reg)
382{ 382{
383 struct nf_hook_entries __rcu **pp; 383 struct nf_hook_entries __rcu **pp;
384 struct nf_hook_entries *p; 384 struct nf_hook_entries *p;
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 728bf31bb386..975a85a48d39 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -2122,7 +2122,6 @@ ip_set_init(void)
2122 return ret; 2122 return ret;
2123 } 2123 }
2124 2124
2125 pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL);
2126 return 0; 2125 return 0;
2127} 2126}
2128 2127
@@ -2138,3 +2137,5 @@ ip_set_fini(void)
2138 2137
2139module_init(ip_set_init); 2138module_init(ip_set_init);
2140module_exit(ip_set_fini); 2139module_exit(ip_set_fini);
2140
2141MODULE_DESCRIPTION("ip_set: protocol " __stringify(IPSET_PROTOCOL));
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 299edc6add5a..1c98c907bc63 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -595,7 +595,6 @@ static int ip_vs_app_open(struct inode *inode, struct file *file)
595} 595}
596 596
597static const struct file_operations ip_vs_app_fops = { 597static const struct file_operations ip_vs_app_fops = {
598 .owner = THIS_MODULE,
599 .open = ip_vs_app_open, 598 .open = ip_vs_app_open,
600 .read = seq_read, 599 .read = seq_read,
601 .llseek = seq_lseek, 600 .llseek = seq_lseek,
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index f489b8db2406..370abbf6f421 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1143,7 +1143,6 @@ static int ip_vs_conn_open(struct inode *inode, struct file *file)
1143} 1143}
1144 1144
1145static const struct file_operations ip_vs_conn_fops = { 1145static const struct file_operations ip_vs_conn_fops = {
1146 .owner = THIS_MODULE,
1147 .open = ip_vs_conn_open, 1146 .open = ip_vs_conn_open,
1148 .read = seq_read, 1147 .read = seq_read,
1149 .llseek = seq_lseek, 1148 .llseek = seq_lseek,
@@ -1221,7 +1220,6 @@ static int ip_vs_conn_sync_open(struct inode *inode, struct file *file)
1221} 1220}
1222 1221
1223static const struct file_operations ip_vs_conn_sync_fops = { 1222static const struct file_operations ip_vs_conn_sync_fops = {
1224 .owner = THIS_MODULE,
1225 .open = ip_vs_conn_sync_open, 1223 .open = ip_vs_conn_sync_open,
1226 .read = seq_read, 1224 .read = seq_read,
1227 .llseek = seq_lseek, 1225 .llseek = seq_lseek,
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index fff213eacf2a..5ebde4b15810 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2116,7 +2116,6 @@ static int ip_vs_info_open(struct inode *inode, struct file *file)
2116} 2116}
2117 2117
2118static const struct file_operations ip_vs_info_fops = { 2118static const struct file_operations ip_vs_info_fops = {
2119 .owner = THIS_MODULE,
2120 .open = ip_vs_info_open, 2119 .open = ip_vs_info_open,
2121 .read = seq_read, 2120 .read = seq_read,
2122 .llseek = seq_lseek, 2121 .llseek = seq_lseek,
@@ -2161,7 +2160,6 @@ static int ip_vs_stats_seq_open(struct inode *inode, struct file *file)
2161} 2160}
2162 2161
2163static const struct file_operations ip_vs_stats_fops = { 2162static const struct file_operations ip_vs_stats_fops = {
2164 .owner = THIS_MODULE,
2165 .open = ip_vs_stats_seq_open, 2163 .open = ip_vs_stats_seq_open,
2166 .read = seq_read, 2164 .read = seq_read,
2167 .llseek = seq_lseek, 2165 .llseek = seq_lseek,
@@ -2230,7 +2228,6 @@ static int ip_vs_stats_percpu_seq_open(struct inode *inode, struct file *file)
2230} 2228}
2231 2229
2232static const struct file_operations ip_vs_stats_percpu_fops = { 2230static const struct file_operations ip_vs_stats_percpu_fops = {
2233 .owner = THIS_MODULE,
2234 .open = ip_vs_stats_percpu_seq_open, 2231 .open = ip_vs_stats_percpu_seq_open,
2235 .read = seq_read, 2232 .read = seq_read,
2236 .llseek = seq_lseek, 2233 .llseek = seq_lseek,
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index a95518261168..6d65389e308f 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -71,7 +71,7 @@ static inline bool already_closed(const struct nf_conn *conn)
71 return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT || 71 return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT ||
72 conn->proto.tcp.state == TCP_CONNTRACK_CLOSE; 72 conn->proto.tcp.state == TCP_CONNTRACK_CLOSE;
73 else 73 else
74 return 0; 74 return false;
75} 75}
76 76
77static int key_diff(const u32 *a, const u32 *b, unsigned int klen) 77static int key_diff(const u32 *a, const u32 *b, unsigned int klen)
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 6a64d528d076..3d72a0842c01 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -58,8 +58,6 @@
58 58
59#include "nf_internals.h" 59#include "nf_internals.h"
60 60
61#define NF_CONNTRACK_VERSION "0.5.0"
62
63int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, 61int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
64 enum nf_nat_manip_type manip, 62 enum nf_nat_manip_type manip,
65 const struct nlattr *attr) __read_mostly; 63 const struct nlattr *attr) __read_mostly;
@@ -2068,10 +2066,6 @@ int nf_conntrack_init_start(void)
2068 if (!nf_conntrack_cachep) 2066 if (!nf_conntrack_cachep)
2069 goto err_cachep; 2067 goto err_cachep;
2070 2068
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
2075 ret = nf_conntrack_expect_init(); 2069 ret = nf_conntrack_expect_init();
2076 if (ret < 0) 2070 if (ret < 0)
2077 goto err_expect; 2071 goto err_expect;
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index d6748a8a79c5..8ef21d9f9a00 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -649,7 +649,6 @@ static int exp_open(struct inode *inode, struct file *file)
649} 649}
650 650
651static const struct file_operations exp_file_ops = { 651static const struct file_operations exp_file_ops = {
652 .owner = THIS_MODULE,
653 .open = exp_open, 652 .open = exp_open,
654 .read = seq_read, 653 .read = seq_read,
655 .llseek = seq_lseek, 654 .llseek = seq_lseek,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 7c7921a53b13..dd177ebee9aa 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -57,8 +57,6 @@
57 57
58MODULE_LICENSE("GPL"); 58MODULE_LICENSE("GPL");
59 59
60static char __initdata version[] = "0.93";
61
62static int ctnetlink_dump_tuples_proto(struct sk_buff *skb, 60static int ctnetlink_dump_tuples_proto(struct sk_buff *skb,
63 const struct nf_conntrack_tuple *tuple, 61 const struct nf_conntrack_tuple *tuple,
64 const struct nf_conntrack_l4proto *l4proto) 62 const struct nf_conntrack_l4proto *l4proto)
@@ -3425,7 +3423,6 @@ static int __init ctnetlink_init(void)
3425{ 3423{
3426 int ret; 3424 int ret;
3427 3425
3428 pr_info("ctnetlink v%s: registering with nfnetlink.\n", version);
3429 ret = nfnetlink_subsys_register(&ctnl_subsys); 3426 ret = nfnetlink_subsys_register(&ctnl_subsys);
3430 if (ret < 0) { 3427 if (ret < 0) {
3431 pr_err("ctnetlink_init: cannot register with nfnetlink.\n"); 3428 pr_err("ctnetlink_init: cannot register with nfnetlink.\n");
@@ -3459,8 +3456,6 @@ err_out:
3459 3456
3460static void __exit ctnetlink_exit(void) 3457static void __exit ctnetlink_exit(void)
3461{ 3458{
3462 pr_info("ctnetlink: unregistering from nfnetlink.\n");
3463
3464 unregister_pernet_subsys(&ctnetlink_net_ops); 3459 unregister_pernet_subsys(&ctnetlink_net_ops);
3465 nfnetlink_subsys_unregister(&ctnl_exp_subsys); 3460 nfnetlink_subsys_unregister(&ctnl_exp_subsys);
3466 nfnetlink_subsys_unregister(&ctnl_subsys); 3461 nfnetlink_subsys_unregister(&ctnl_subsys);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 46d32baad095..9123fdec5e14 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -382,7 +382,6 @@ static int ct_open(struct inode *inode, struct file *file)
382} 382}
383 383
384static const struct file_operations ct_file_ops = { 384static const struct file_operations ct_file_ops = {
385 .owner = THIS_MODULE,
386 .open = ct_open, 385 .open = ct_open,
387 .read = seq_read, 386 .read = seq_read,
388 .llseek = seq_lseek, 387 .llseek = seq_lseek,
@@ -475,7 +474,6 @@ static int ct_cpu_seq_open(struct inode *inode, struct file *file)
475} 474}
476 475
477static const struct file_operations ct_cpu_seq_fops = { 476static const struct file_operations ct_cpu_seq_fops = {
478 .owner = THIS_MODULE,
479 .open = ct_cpu_seq_open, 477 .open = ct_cpu_seq_open,
480 .read = seq_read, 478 .read = seq_read,
481 .llseek = seq_lseek, 479 .llseek = seq_lseek,
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 8bb152a7cca4..c2c1b16b7538 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -402,7 +402,6 @@ static int nflog_open(struct inode *inode, struct file *file)
402} 402}
403 403
404static const struct file_operations nflog_file_ops = { 404static const struct file_operations nflog_file_ops = {
405 .owner = THIS_MODULE,
406 .open = nflog_open, 405 .open = nflog_open,
407 .read = seq_read, 406 .read = seq_read,
408 .llseek = seq_lseek, 407 .llseek = seq_lseek,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 7f55af5f3d1a..d67a96a25a68 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -15,8 +15,6 @@
15#include <linux/netfilter_bridge.h> 15#include <linux/netfilter_bridge.h>
16#include <linux/seq_file.h> 16#include <linux/seq_file.h>
17#include <linux/rcupdate.h> 17#include <linux/rcupdate.h>
18#include <linux/netfilter_ipv4.h>
19#include <linux/netfilter_ipv6.h>
20#include <net/protocol.h> 18#include <net/protocol.h>
21#include <net/netfilter/nf_queue.h> 19#include <net/netfilter/nf_queue.h>
22#include <net/dst.h> 20#include <net/dst.h>
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
index 49bd8bb16b18..92139a087260 100644
--- a/net/netfilter/nf_synproxy_core.c
+++ b/net/netfilter/nf_synproxy_core.c
@@ -317,7 +317,6 @@ static int synproxy_cpu_seq_open(struct inode *inode, struct file *file)
317} 317}
318 318
319static const struct file_operations synproxy_cpu_seq_fops = { 319static const struct file_operations synproxy_cpu_seq_fops = {
320 .owner = THIS_MODULE,
321 .open = synproxy_cpu_seq_open, 320 .open = synproxy_cpu_seq_open,
322 .read = seq_read, 321 .read = seq_read,
323 .llseek = seq_lseek, 322 .llseek = seq_lseek,
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 336b81689ac9..0791813a1e7d 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -26,86 +26,19 @@
26static LIST_HEAD(nf_tables_expressions); 26static LIST_HEAD(nf_tables_expressions);
27static LIST_HEAD(nf_tables_objects); 27static LIST_HEAD(nf_tables_objects);
28static LIST_HEAD(nf_tables_flowtables); 28static LIST_HEAD(nf_tables_flowtables);
29 29static u64 table_handle;
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 */
38int 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}
46EXPORT_SYMBOL_GPL(nft_register_afinfo);
47
48static 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 */
57void 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}
64EXPORT_SYMBOL_GPL(nft_unregister_afinfo);
65
66static 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
77static struct nft_af_info *
78nf_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}
97 30
98static void nft_ctx_init(struct nft_ctx *ctx, 31static void nft_ctx_init(struct nft_ctx *ctx,
99 struct net *net, 32 struct net *net,
100 const struct sk_buff *skb, 33 const struct sk_buff *skb,
101 const struct nlmsghdr *nlh, 34 const struct nlmsghdr *nlh,
102 struct nft_af_info *afi, 35 u8 family,
103 struct nft_table *table, 36 struct nft_table *table,
104 struct nft_chain *chain, 37 struct nft_chain *chain,
105 const struct nlattr * const *nla) 38 const struct nlattr * const *nla)
106{ 39{
107 ctx->net = net; 40 ctx->net = net;
108 ctx->afi = afi; 41 ctx->family = family;
109 ctx->table = table; 42 ctx->table = table;
110 ctx->chain = chain; 43 ctx->chain = chain;
111 ctx->nla = nla; 44 ctx->nla = nla;
@@ -385,30 +318,61 @@ static int nft_delflowtable(struct nft_ctx *ctx,
385 * Tables 318 * Tables
386 */ 319 */
387 320
388static struct nft_table *nft_table_lookup(const struct nft_af_info *afi, 321static struct nft_table *nft_table_lookup(const struct net *net,
389 const struct nlattr *nla, 322 const struct nlattr *nla,
390 u8 genmask) 323 u8 family, u8 genmask)
391{ 324{
392 struct nft_table *table; 325 struct nft_table *table;
393 326
394 list_for_each_entry(table, &afi->tables, list) { 327 list_for_each_entry(table, &net->nft.tables, list) {
395 if (!nla_strcmp(nla, table->name) && 328 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
336static 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 &&
396 nft_active_genmask(table, genmask)) 344 nft_active_genmask(table, genmask))
397 return table; 345 return table;
398 } 346 }
399 return NULL; 347 return NULL;
400} 348}
401 349
402static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi, 350static struct nft_table *nf_tables_table_lookup(const struct net *net,
403 const struct nlattr *nla, 351 const struct nlattr *nla,
404 u8 genmask) 352 u8 family, u8 genmask)
405{ 353{
406 struct nft_table *table; 354 struct nft_table *table;
407 355
408 if (nla == NULL) 356 if (nla == NULL)
409 return ERR_PTR(-EINVAL); 357 return ERR_PTR(-EINVAL);
410 358
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
366static 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);
412 if (table != NULL) 376 if (table != NULL)
413 return table; 377 return table;
414 378
@@ -423,7 +387,7 @@ static inline u64 nf_tables_alloc_handle(struct nft_table *table)
423static const struct nf_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX]; 387static const struct nf_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX];
424 388
425static const struct nf_chain_type * 389static 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)
427{ 391{
428 int i; 392 int i;
429 393
@@ -436,22 +400,20 @@ __nf_tables_chain_type_lookup(int family, const struct nlattr *nla)
436} 400}
437 401
438static const struct nf_chain_type * 402static const struct nf_chain_type *
439nf_tables_chain_type_lookup(const struct nft_af_info *afi, 403nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)
440 const struct nlattr *nla,
441 bool autoload)
442{ 404{
443 const struct nf_chain_type *type; 405 const struct nf_chain_type *type;
444 406
445 type = __nf_tables_chain_type_lookup(afi->family, nla); 407 type = __nf_tables_chain_type_lookup(nla, family);
446 if (type != NULL) 408 if (type != NULL)
447 return type; 409 return type;
448#ifdef CONFIG_MODULES 410#ifdef CONFIG_MODULES
449 if (autoload) { 411 if (autoload) {
450 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 412 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
451 request_module("nft-chain-%u-%.*s", afi->family, 413 request_module("nft-chain-%u-%.*s", family,
452 nla_len(nla), (const char *)nla_data(nla)); 414 nla_len(nla), (const char *)nla_data(nla));
453 nfnl_lock(NFNL_SUBSYS_NFTABLES); 415 nfnl_lock(NFNL_SUBSYS_NFTABLES);
454 type = __nf_tables_chain_type_lookup(afi->family, nla); 416 type = __nf_tables_chain_type_lookup(nla, family);
455 if (type != NULL) 417 if (type != NULL)
456 return ERR_PTR(-EAGAIN); 418 return ERR_PTR(-EAGAIN);
457 } 419 }
@@ -463,6 +425,7 @@ static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = {
463 [NFTA_TABLE_NAME] = { .type = NLA_STRING, 425 [NFTA_TABLE_NAME] = { .type = NLA_STRING,
464 .len = NFT_TABLE_MAXNAMELEN - 1 }, 426 .len = NFT_TABLE_MAXNAMELEN - 1 },
465 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, 427 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 },
428 [NFTA_TABLE_HANDLE] = { .type = NLA_U64 },
466}; 429};
467 430
468static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, 431static 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,
484 447
485 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || 448 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
486 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || 449 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))
488 goto nla_put_failure; 453 goto nla_put_failure;
489 454
490 nlmsg_end(skb, nlh); 455 nlmsg_end(skb, nlh);
@@ -509,7 +474,7 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
509 goto err; 474 goto err;
510 475
511 err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq, 476 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);
513 if (err < 0) { 478 if (err < 0) {
514 kfree_skb(skb); 479 kfree_skb(skb);
515 goto err; 480 goto err;
@@ -526,7 +491,6 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
526 struct netlink_callback *cb) 491 struct netlink_callback *cb)
527{ 492{
528 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 493 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
529 const struct nft_af_info *afi;
530 const struct nft_table *table; 494 const struct nft_table *table;
531 unsigned int idx = 0, s_idx = cb->args[0]; 495 unsigned int idx = 0, s_idx = cb->args[0];
532 struct net *net = sock_net(skb->sk); 496 struct net *net = sock_net(skb->sk);
@@ -535,30 +499,27 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
535 rcu_read_lock(); 499 rcu_read_lock();
536 cb->seq = net->nft.base_seq; 500 cb->seq = net->nft.base_seq;
537 501
538 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 502 list_for_each_entry_rcu(table, &net->nft.tables, list) {
539 if (family != NFPROTO_UNSPEC && family != afi->family) 503 if (family != NFPROTO_UNSPEC && family != table->family)
540 continue; 504 continue;
541 505
542 list_for_each_entry_rcu(table, &afi->tables, list) { 506 if (idx < s_idx)
543 if (idx < s_idx) 507 goto cont;
544 goto cont; 508 if (idx > s_idx)
545 if (idx > s_idx) 509 memset(&cb->args[1], 0,
546 memset(&cb->args[1], 0, 510 sizeof(cb->args) - sizeof(cb->args[0]));
547 sizeof(cb->args) - sizeof(cb->args[0])); 511 if (!nft_is_active(net, table))
548 if (!nft_is_active(net, table)) 512 continue;
549 continue; 513 if (nf_tables_fill_table_info(skb, net,
550 if (nf_tables_fill_table_info(skb, net, 514 NETLINK_CB(cb->skb).portid,
551 NETLINK_CB(cb->skb).portid, 515 cb->nlh->nlmsg_seq,
552 cb->nlh->nlmsg_seq, 516 NFT_MSG_NEWTABLE, NLM_F_MULTI,
553 NFT_MSG_NEWTABLE, 517 table->family, table) < 0)
554 NLM_F_MULTI, 518 goto done;
555 afi->family, table) < 0) 519
556 goto done; 520 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
557
558 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
559cont: 521cont:
560 idx++; 522 idx++;
561 }
562 } 523 }
563done: 524done:
564 rcu_read_unlock(); 525 rcu_read_unlock();
@@ -573,7 +534,6 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,
573{ 534{
574 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 535 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
575 u8 genmask = nft_genmask_cur(net); 536 u8 genmask = nft_genmask_cur(net);
576 const struct nft_af_info *afi;
577 const struct nft_table *table; 537 const struct nft_table *table;
578 struct sk_buff *skb2; 538 struct sk_buff *skb2;
579 int family = nfmsg->nfgen_family; 539 int family = nfmsg->nfgen_family;
@@ -586,11 +546,8 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,
586 return netlink_dump_start(nlsk, skb, nlh, &c); 546 return netlink_dump_start(nlsk, skb, nlh, &c);
587 } 547 }
588 548
589 afi = nf_tables_afinfo_lookup(net, family, false); 549 table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family,
590 if (IS_ERR(afi)) 550 genmask);
591 return PTR_ERR(afi);
592
593 table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
594 if (IS_ERR(table)) 551 if (IS_ERR(table))
595 return PTR_ERR(table); 552 return PTR_ERR(table);
596 553
@@ -611,10 +568,7 @@ err:
611 return err; 568 return err;
612} 569}
613 570
614static void _nf_tables_table_disable(struct net *net, 571static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt)
615 const struct nft_af_info *afi,
616 struct nft_table *table,
617 u32 cnt)
618{ 572{
619 struct nft_chain *chain; 573 struct nft_chain *chain;
620 u32 i = 0; 574 u32 i = 0;
@@ -632,9 +586,7 @@ static void _nf_tables_table_disable(struct net *net,
632 } 586 }
633} 587}
634 588
635static int nf_tables_table_enable(struct net *net, 589static int nf_tables_table_enable(struct net *net, struct nft_table *table)
636 const struct nft_af_info *afi,
637 struct nft_table *table)
638{ 590{
639 struct nft_chain *chain; 591 struct nft_chain *chain;
640 int err, i = 0; 592 int err, i = 0;
@@ -654,15 +606,13 @@ static int nf_tables_table_enable(struct net *net,
654 return 0; 606 return 0;
655err: 607err:
656 if (i) 608 if (i)
657 _nf_tables_table_disable(net, afi, table, i); 609 nft_table_disable(net, table, i);
658 return err; 610 return err;
659} 611}
660 612
661static void nf_tables_table_disable(struct net *net, 613static void nf_tables_table_disable(struct net *net, struct nft_table *table)
662 const struct nft_af_info *afi,
663 struct nft_table *table)
664{ 614{
665 _nf_tables_table_disable(net, afi, table, 0); 615 nft_table_disable(net, table, 0);
666} 616}
667 617
668static int nf_tables_updtable(struct nft_ctx *ctx) 618static int nf_tables_updtable(struct nft_ctx *ctx)
@@ -691,7 +641,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
691 nft_trans_table_enable(trans) = false; 641 nft_trans_table_enable(trans) = false;
692 } else if (!(flags & NFT_TABLE_F_DORMANT) && 642 } else if (!(flags & NFT_TABLE_F_DORMANT) &&
693 ctx->table->flags & NFT_TABLE_F_DORMANT) { 643 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);
695 if (ret >= 0) { 645 if (ret >= 0) {
696 ctx->table->flags &= ~NFT_TABLE_F_DORMANT; 646 ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
697 nft_trans_table_enable(trans) = true; 647 nft_trans_table_enable(trans) = true;
@@ -716,19 +666,14 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
716 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 666 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
717 u8 genmask = nft_genmask_next(net); 667 u8 genmask = nft_genmask_next(net);
718 const struct nlattr *name; 668 const struct nlattr *name;
719 struct nft_af_info *afi;
720 struct nft_table *table; 669 struct nft_table *table;
721 int family = nfmsg->nfgen_family; 670 int family = nfmsg->nfgen_family;
722 u32 flags = 0; 671 u32 flags = 0;
723 struct nft_ctx ctx; 672 struct nft_ctx ctx;
724 int err; 673 int err;
725 674
726 afi = nf_tables_afinfo_lookup(net, family, true);
727 if (IS_ERR(afi))
728 return PTR_ERR(afi);
729
730 name = nla[NFTA_TABLE_NAME]; 675 name = nla[NFTA_TABLE_NAME];
731 table = nf_tables_table_lookup(afi, name, genmask); 676 table = nf_tables_table_lookup(net, name, family, genmask);
732 if (IS_ERR(table)) { 677 if (IS_ERR(table)) {
733 if (PTR_ERR(table) != -ENOENT) 678 if (PTR_ERR(table) != -ENOENT)
734 return PTR_ERR(table); 679 return PTR_ERR(table);
@@ -738,7 +683,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
738 if (nlh->nlmsg_flags & NLM_F_REPLACE) 683 if (nlh->nlmsg_flags & NLM_F_REPLACE)
739 return -EOPNOTSUPP; 684 return -EOPNOTSUPP;
740 685
741 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 686 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
742 return nf_tables_updtable(&ctx); 687 return nf_tables_updtable(&ctx);
743 } 688 }
744 689
@@ -748,39 +693,35 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
748 return -EINVAL; 693 return -EINVAL;
749 } 694 }
750 695
751 err = -EAFNOSUPPORT;
752 if (!try_module_get(afi->owner))
753 goto err1;
754
755 err = -ENOMEM; 696 err = -ENOMEM;
756 table = kzalloc(sizeof(*table), GFP_KERNEL); 697 table = kzalloc(sizeof(*table), GFP_KERNEL);
757 if (table == NULL) 698 if (table == NULL)
758 goto err2; 699 goto err_kzalloc;
759 700
760 table->name = nla_strdup(name, GFP_KERNEL); 701 table->name = nla_strdup(name, GFP_KERNEL);
761 if (table->name == NULL) 702 if (table->name == NULL)
762 goto err3; 703 goto err_strdup;
763 704
764 INIT_LIST_HEAD(&table->chains); 705 INIT_LIST_HEAD(&table->chains);
765 INIT_LIST_HEAD(&table->sets); 706 INIT_LIST_HEAD(&table->sets);
766 INIT_LIST_HEAD(&table->objects); 707 INIT_LIST_HEAD(&table->objects);
767 INIT_LIST_HEAD(&table->flowtables); 708 INIT_LIST_HEAD(&table->flowtables);
709 table->family = family;
768 table->flags = flags; 710 table->flags = flags;
711 table->handle = ++table_handle;
769 712
770 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 713 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
771 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); 714 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
772 if (err < 0) 715 if (err < 0)
773 goto err4; 716 goto err_trans;
774 717
775 list_add_tail_rcu(&table->list, &afi->tables); 718 list_add_tail_rcu(&table->list, &net->nft.tables);
776 return 0; 719 return 0;
777err4: 720err_trans:
778 kfree(table->name); 721 kfree(table->name);
779err3: 722err_strdup:
780 kfree(table); 723 kfree(table);
781err2: 724err_kzalloc:
782 module_put(afi->owner);
783err1:
784 return err; 725 return err;
785} 726}
786 727
@@ -846,30 +787,28 @@ out:
846 787
847static int nft_flush(struct nft_ctx *ctx, int family) 788static int nft_flush(struct nft_ctx *ctx, int family)
848{ 789{
849 struct nft_af_info *afi;
850 struct nft_table *table, *nt; 790 struct nft_table *table, *nt;
851 const struct nlattr * const *nla = ctx->nla; 791 const struct nlattr * const *nla = ctx->nla;
852 int err = 0; 792 int err = 0;
853 793
854 list_for_each_entry(afi, &ctx->net->nft.af_info, list) { 794 list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) {
855 if (family != AF_UNSPEC && afi->family != family) 795 if (family != AF_UNSPEC && table->family != family)
856 continue; 796 continue;
857 797
858 ctx->afi = afi; 798 ctx->family = table->family;
859 list_for_each_entry_safe(table, nt, &afi->tables, list) {
860 if (!nft_is_active_next(ctx->net, table))
861 continue;
862 799
863 if (nla[NFTA_TABLE_NAME] && 800 if (!nft_is_active_next(ctx->net, table))
864 nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) 801 continue;
865 continue;
866 802
867 ctx->table = table; 803 if (nla[NFTA_TABLE_NAME] &&
804 nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
805 continue;
868 806
869 err = nft_flush_table(ctx); 807 ctx->table = table;
870 if (err < 0) 808
871 goto out; 809 err = nft_flush_table(ctx);
872 } 810 if (err < 0)
811 goto out;
873 } 812 }
874out: 813out:
875 return err; 814 return err;
@@ -882,20 +821,23 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk,
882{ 821{
883 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 822 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
884 u8 genmask = nft_genmask_next(net); 823 u8 genmask = nft_genmask_next(net);
885 struct nft_af_info *afi;
886 struct nft_table *table; 824 struct nft_table *table;
887 int family = nfmsg->nfgen_family; 825 int family = nfmsg->nfgen_family;
888 struct nft_ctx ctx; 826 struct nft_ctx ctx;
889 827
890 nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla); 828 nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla);
891 if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) 829 if (family == AF_UNSPEC ||
830 (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE]))
892 return nft_flush(&ctx, family); 831 return nft_flush(&ctx, family);
893 832
894 afi = nf_tables_afinfo_lookup(net, family, false); 833 if (nla[NFTA_TABLE_HANDLE])
895 if (IS_ERR(afi)) 834 table = nf_tables_table_lookup_byhandle(net,
896 return PTR_ERR(afi); 835 nla[NFTA_TABLE_HANDLE],
836 genmask);
837 else
838 table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME],
839 family, genmask);
897 840
898 table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
899 if (IS_ERR(table)) 841 if (IS_ERR(table))
900 return PTR_ERR(table); 842 return PTR_ERR(table);
901 843
@@ -903,7 +845,7 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk,
903 table->use > 0) 845 table->use > 0)
904 return -EBUSY; 846 return -EBUSY;
905 847
906 ctx.afi = afi; 848 ctx.family = family;
907 ctx.table = table; 849 ctx.table = table;
908 850
909 return nft_flush_table(&ctx); 851 return nft_flush_table(&ctx);
@@ -915,7 +857,6 @@ static void nf_tables_table_destroy(struct nft_ctx *ctx)
915 857
916 kfree(ctx->table->name); 858 kfree(ctx->table->name);
917 kfree(ctx->table); 859 kfree(ctx->table);
918 module_put(ctx->afi->owner);
919} 860}
920 861
921int nft_register_chain_type(const struct nf_chain_type *ctype) 862int 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)
1116 goto err; 1057 goto err;
1117 1058
1118 err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq, 1059 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,
1120 ctx->chain); 1061 ctx->chain);
1121 if (err < 0) { 1062 if (err < 0) {
1122 kfree_skb(skb); 1063 kfree_skb(skb);
@@ -1134,7 +1075,6 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
1134 struct netlink_callback *cb) 1075 struct netlink_callback *cb)
1135{ 1076{
1136 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 1077 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
1137 const struct nft_af_info *afi;
1138 const struct nft_table *table; 1078 const struct nft_table *table;
1139 const struct nft_chain *chain; 1079 const struct nft_chain *chain;
1140 unsigned int idx = 0, s_idx = cb->args[0]; 1080 unsigned int idx = 0, s_idx = cb->args[0];
@@ -1144,31 +1084,30 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
1144 rcu_read_lock(); 1084 rcu_read_lock();
1145 cb->seq = net->nft.base_seq; 1085 cb->seq = net->nft.base_seq;
1146 1086
1147 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 1087 list_for_each_entry_rcu(table, &net->nft.tables, list) {
1148 if (family != NFPROTO_UNSPEC && family != afi->family) 1088 if (family != NFPROTO_UNSPEC && family != table->family)
1149 continue; 1089 continue;
1150 1090
1151 list_for_each_entry_rcu(table, &afi->tables, list) { 1091 list_for_each_entry_rcu(chain, &table->chains, list) {
1152 list_for_each_entry_rcu(chain, &table->chains, list) { 1092 if (idx < s_idx)
1153 if (idx < s_idx) 1093 goto cont;
1154 goto cont; 1094 if (idx > s_idx)
1155 if (idx > s_idx) 1095 memset(&cb->args[1], 0,
1156 memset(&cb->args[1], 0, 1096 sizeof(cb->args) - sizeof(cb->args[0]));
1157 sizeof(cb->args) - sizeof(cb->args[0])); 1097 if (!nft_is_active(net, chain))
1158 if (!nft_is_active(net, chain)) 1098 continue;
1159 continue; 1099 if (nf_tables_fill_chain_info(skb, net,
1160 if (nf_tables_fill_chain_info(skb, net, 1100 NETLINK_CB(cb->skb).portid,
1161 NETLINK_CB(cb->skb).portid, 1101 cb->nlh->nlmsg_seq,
1162 cb->nlh->nlmsg_seq, 1102 NFT_MSG_NEWCHAIN,
1163 NFT_MSG_NEWCHAIN, 1103 NLM_F_MULTI,
1164 NLM_F_MULTI, 1104 table->family, table,
1165 afi->family, table, chain) < 0) 1105 chain) < 0)
1166 goto done; 1106 goto done;
1167 1107
1168 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1108 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
1169cont: 1109cont:
1170 idx++; 1110 idx++;
1171 }
1172 } 1111 }
1173 } 1112 }
1174done: 1113done:
@@ -1184,7 +1123,6 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
1184{ 1123{
1185 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1124 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1186 u8 genmask = nft_genmask_cur(net); 1125 u8 genmask = nft_genmask_cur(net);
1187 const struct nft_af_info *afi;
1188 const struct nft_table *table; 1126 const struct nft_table *table;
1189 const struct nft_chain *chain; 1127 const struct nft_chain *chain;
1190 struct sk_buff *skb2; 1128 struct sk_buff *skb2;
@@ -1198,11 +1136,8 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
1198 return netlink_dump_start(nlsk, skb, nlh, &c); 1136 return netlink_dump_start(nlsk, skb, nlh, &c);
1199 } 1137 }
1200 1138
1201 afi = nf_tables_afinfo_lookup(net, family, false); 1139 table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family,
1202 if (IS_ERR(afi)) 1140 genmask);
1203 return PTR_ERR(afi);
1204
1205 table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
1206 if (IS_ERR(table)) 1141 if (IS_ERR(table))
1207 return PTR_ERR(table); 1142 return PTR_ERR(table);
1208 1143
@@ -1310,8 +1245,8 @@ struct nft_chain_hook {
1310 1245
1311static int nft_chain_parse_hook(struct net *net, 1246static int nft_chain_parse_hook(struct net *net,
1312 const struct nlattr * const nla[], 1247 const struct nlattr * const nla[],
1313 struct nft_af_info *afi, 1248 struct nft_chain_hook *hook, u8 family,
1314 struct nft_chain_hook *hook, bool create) 1249 bool create)
1315{ 1250{
1316 struct nlattr *ha[NFTA_HOOK_MAX + 1]; 1251 struct nlattr *ha[NFTA_HOOK_MAX + 1];
1317 const struct nf_chain_type *type; 1252 const struct nf_chain_type *type;
@@ -1328,15 +1263,12 @@ static int nft_chain_parse_hook(struct net *net,
1328 return -EINVAL; 1263 return -EINVAL;
1329 1264
1330 hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); 1265 hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
1331 if (hook->num >= afi->nhooks)
1332 return -EINVAL;
1333
1334 hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); 1266 hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
1335 1267
1336 type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; 1268 type = chain_type[family][NFT_CHAIN_T_DEFAULT];
1337 if (nla[NFTA_CHAIN_TYPE]) { 1269 if (nla[NFTA_CHAIN_TYPE]) {
1338 type = nf_tables_chain_type_lookup(afi, nla[NFTA_CHAIN_TYPE], 1270 type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE],
1339 create); 1271 family, create);
1340 if (IS_ERR(type)) 1272 if (IS_ERR(type))
1341 return PTR_ERR(type); 1273 return PTR_ERR(type);
1342 } 1274 }
@@ -1353,7 +1285,7 @@ static int nft_chain_parse_hook(struct net *net,
1353 hook->type = type; 1285 hook->type = type;
1354 1286
1355 hook->dev = NULL; 1287 hook->dev = NULL;
1356 if (afi->flags & NFT_AF_NEEDS_DEV) { 1288 if (family == NFPROTO_NETDEV) {
1357 char ifname[IFNAMSIZ]; 1289 char ifname[IFNAMSIZ];
1358 1290
1359 if (!ha[NFTA_HOOK_DEV]) { 1291 if (!ha[NFTA_HOOK_DEV]) {
@@ -1388,7 +1320,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
1388{ 1320{
1389 const struct nlattr * const *nla = ctx->nla; 1321 const struct nlattr * const *nla = ctx->nla;
1390 struct nft_table *table = ctx->table; 1322 struct nft_table *table = ctx->table;
1391 struct nft_af_info *afi = ctx->afi;
1392 struct nft_base_chain *basechain; 1323 struct nft_base_chain *basechain;
1393 struct nft_stats __percpu *stats; 1324 struct nft_stats __percpu *stats;
1394 struct net *net = ctx->net; 1325 struct net *net = ctx->net;
@@ -1402,7 +1333,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
1402 struct nft_chain_hook hook; 1333 struct nft_chain_hook hook;
1403 struct nf_hook_ops *ops; 1334 struct nf_hook_ops *ops;
1404 1335
1405 err = nft_chain_parse_hook(net, nla, afi, &hook, create); 1336 err = nft_chain_parse_hook(net, nla, &hook, family, create);
1406 if (err < 0) 1337 if (err < 0)
1407 return err; 1338 return err;
1408 1339
@@ -1495,7 +1426,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
1495 if (!nft_is_base_chain(chain)) 1426 if (!nft_is_base_chain(chain))
1496 return -EBUSY; 1427 return -EBUSY;
1497 1428
1498 err = nft_chain_parse_hook(ctx->net, nla, ctx->afi, &hook, 1429 err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
1499 create); 1430 create);
1500 if (err < 0) 1431 if (err < 0)
1501 return err; 1432 return err;
@@ -1574,7 +1505,6 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1574 const struct nlattr * uninitialized_var(name); 1505 const struct nlattr * uninitialized_var(name);
1575 u8 genmask = nft_genmask_next(net); 1506 u8 genmask = nft_genmask_next(net);
1576 int family = nfmsg->nfgen_family; 1507 int family = nfmsg->nfgen_family;
1577 struct nft_af_info *afi;
1578 struct nft_table *table; 1508 struct nft_table *table;
1579 struct nft_chain *chain; 1509 struct nft_chain *chain;
1580 u8 policy = NF_ACCEPT; 1510 u8 policy = NF_ACCEPT;
@@ -1584,11 +1514,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1584 1514
1585 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 1515 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
1586 1516
1587 afi = nf_tables_afinfo_lookup(net, family, true); 1517 table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family,
1588 if (IS_ERR(afi)) 1518 genmask);
1589 return PTR_ERR(afi);
1590
1591 table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
1592 if (IS_ERR(table)) 1519 if (IS_ERR(table))
1593 return PTR_ERR(table); 1520 return PTR_ERR(table);
1594 1521
@@ -1628,7 +1555,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1628 } 1555 }
1629 } 1556 }
1630 1557
1631 nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 1558 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
1632 1559
1633 if (chain != NULL) { 1560 if (chain != NULL) {
1634 if (nlh->nlmsg_flags & NLM_F_EXCL) 1561 if (nlh->nlmsg_flags & NLM_F_EXCL)
@@ -1649,24 +1576,26 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
1649{ 1576{
1650 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1577 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1651 u8 genmask = nft_genmask_next(net); 1578 u8 genmask = nft_genmask_next(net);
1652 struct nft_af_info *afi;
1653 struct nft_table *table; 1579 struct nft_table *table;
1654 struct nft_chain *chain; 1580 struct nft_chain *chain;
1655 struct nft_rule *rule; 1581 struct nft_rule *rule;
1656 int family = nfmsg->nfgen_family; 1582 int family = nfmsg->nfgen_family;
1657 struct nft_ctx ctx; 1583 struct nft_ctx ctx;
1584 u64 handle;
1658 u32 use; 1585 u32 use;
1659 int err; 1586 int err;
1660 1587
1661 afi = nf_tables_afinfo_lookup(net, family, false); 1588 table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family,
1662 if (IS_ERR(afi)) 1589 genmask);
1663 return PTR_ERR(afi);
1664
1665 table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
1666 if (IS_ERR(table)) 1590 if (IS_ERR(table))
1667 return PTR_ERR(table); 1591 return PTR_ERR(table);
1668 1592
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 }
1670 if (IS_ERR(chain)) 1599 if (IS_ERR(chain))
1671 return PTR_ERR(chain); 1600 return PTR_ERR(chain);
1672 1601
@@ -1674,7 +1603,7 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
1674 chain->use > 0) 1603 chain->use > 0)
1675 return -EBUSY; 1604 return -EBUSY;
1676 1605
1677 nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 1606 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
1678 1607
1679 use = chain->use; 1608 use = chain->use;
1680 list_for_each_entry(rule, &chain->rules, list) { 1609 list_for_each_entry(rule, &chain->rules, list) {
@@ -1839,7 +1768,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
1839 if (err < 0) 1768 if (err < 0)
1840 return err; 1769 return err;
1841 1770
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]);
1843 if (IS_ERR(type)) 1772 if (IS_ERR(type))
1844 return PTR_ERR(type); 1773 return PTR_ERR(type);
1845 1774
@@ -2062,7 +1991,7 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
2062 goto err; 1991 goto err;
2063 1992
2064 err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq, 1993 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,
2066 ctx->chain, rule); 1995 ctx->chain, rule);
2067 if (err < 0) { 1996 if (err < 0) {
2068 kfree_skb(skb); 1997 kfree_skb(skb);
@@ -2086,7 +2015,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
2086{ 2015{
2087 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 2016 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
2088 const struct nft_rule_dump_ctx *ctx = cb->data; 2017 const struct nft_rule_dump_ctx *ctx = cb->data;
2089 const struct nft_af_info *afi;
2090 const struct nft_table *table; 2018 const struct nft_table *table;
2091 const struct nft_chain *chain; 2019 const struct nft_chain *chain;
2092 const struct nft_rule *rule; 2020 const struct nft_rule *rule;
@@ -2097,39 +2025,37 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
2097 rcu_read_lock(); 2025 rcu_read_lock();
2098 cb->seq = net->nft.base_seq; 2026 cb->seq = net->nft.base_seq;
2099 2027
2100 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 2028 list_for_each_entry_rcu(table, &net->nft.tables, list) {
2101 if (family != NFPROTO_UNSPEC && family != afi->family) 2029 if (family != NFPROTO_UNSPEC && family != table->family)
2102 continue; 2030 continue;
2103 2031
2104 list_for_each_entry_rcu(table, &afi->tables, list) { 2032 if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
2105 if (ctx && ctx->table && 2033 continue;
2106 strcmp(ctx->table, table->name) != 0) 2034
2035 list_for_each_entry_rcu(chain, &table->chains, list) {
2036 if (ctx && ctx->chain &&
2037 strcmp(ctx->chain, chain->name) != 0)
2107 continue; 2038 continue;
2108 2039
2109 list_for_each_entry_rcu(chain, &table->chains, list) { 2040 list_for_each_entry_rcu(rule, &chain->rules, list) {
2110 if (ctx && ctx->chain && 2041 if (!nft_is_active(net, rule))
2111 strcmp(ctx->chain, chain->name) != 0) 2042 goto cont;
2112 continue; 2043 if (idx < s_idx)
2113 2044 goto cont;
2114 list_for_each_entry_rcu(rule, &chain->rules, list) { 2045 if (idx > s_idx)
2115 if (!nft_is_active(net, rule)) 2046 memset(&cb->args[1], 0,
2116 goto cont; 2047 sizeof(cb->args) - sizeof(cb->args[0]));
2117 if (idx < s_idx) 2048 if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid,
2118 goto cont; 2049 cb->nlh->nlmsg_seq,
2119 if (idx > s_idx) 2050 NFT_MSG_NEWRULE,
2120 memset(&cb->args[1], 0, 2051 NLM_F_MULTI | NLM_F_APPEND,
2121 sizeof(cb->args) - sizeof(cb->args[0])); 2052 table->family,
2122 if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid, 2053 table, chain, rule) < 0)
2123 cb->nlh->nlmsg_seq, 2054 goto done;
2124 NFT_MSG_NEWRULE, 2055
2125 NLM_F_MULTI | NLM_F_APPEND, 2056 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2126 afi->family, table, chain, rule) < 0)
2127 goto done;
2128
2129 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2130cont: 2057cont:
2131 idx++; 2058 idx++;
2132 }
2133 } 2059 }
2134 } 2060 }
2135 } 2061 }
@@ -2159,7 +2085,6 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
2159{ 2085{
2160 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2086 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2161 u8 genmask = nft_genmask_cur(net); 2087 u8 genmask = nft_genmask_cur(net);
2162 const struct nft_af_info *afi;
2163 const struct nft_table *table; 2088 const struct nft_table *table;
2164 const struct nft_chain *chain; 2089 const struct nft_chain *chain;
2165 const struct nft_rule *rule; 2090 const struct nft_rule *rule;
@@ -2203,11 +2128,8 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
2203 return netlink_dump_start(nlsk, skb, nlh, &c); 2128 return netlink_dump_start(nlsk, skb, nlh, &c);
2204 } 2129 }
2205 2130
2206 afi = nf_tables_afinfo_lookup(net, family, false); 2131 table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family,
2207 if (IS_ERR(afi)) 2132 genmask);
2208 return PTR_ERR(afi);
2209
2210 table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
2211 if (IS_ERR(table)) 2133 if (IS_ERR(table))
2212 return PTR_ERR(table); 2134 return PTR_ERR(table);
2213 2135
@@ -2264,7 +2186,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2264{ 2186{
2265 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2187 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2266 u8 genmask = nft_genmask_next(net); 2188 u8 genmask = nft_genmask_next(net);
2267 struct nft_af_info *afi; 2189 int family = nfmsg->nfgen_family;
2268 struct nft_table *table; 2190 struct nft_table *table;
2269 struct nft_chain *chain; 2191 struct nft_chain *chain;
2270 struct nft_rule *rule, *old_rule = NULL; 2192 struct nft_rule *rule, *old_rule = NULL;
@@ -2280,11 +2202,8 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2280 2202
2281 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 2203 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
2282 2204
2283 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); 2205 table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family,
2284 if (IS_ERR(afi)) 2206 genmask);
2285 return PTR_ERR(afi);
2286
2287 table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
2288 if (IS_ERR(table)) 2207 if (IS_ERR(table))
2289 return PTR_ERR(table); 2208 return PTR_ERR(table);
2290 2209
@@ -2323,7 +2242,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2323 return PTR_ERR(old_rule); 2242 return PTR_ERR(old_rule);
2324 } 2243 }
2325 2244
2326 nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 2245 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
2327 2246
2328 n = 0; 2247 n = 0;
2329 size = 0; 2248 size = 0;
@@ -2447,18 +2366,14 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
2447{ 2366{
2448 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2367 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2449 u8 genmask = nft_genmask_next(net); 2368 u8 genmask = nft_genmask_next(net);
2450 struct nft_af_info *afi;
2451 struct nft_table *table; 2369 struct nft_table *table;
2452 struct nft_chain *chain = NULL; 2370 struct nft_chain *chain = NULL;
2453 struct nft_rule *rule; 2371 struct nft_rule *rule;
2454 int family = nfmsg->nfgen_family, err = 0; 2372 int family = nfmsg->nfgen_family, err = 0;
2455 struct nft_ctx ctx; 2373 struct nft_ctx ctx;
2456 2374
2457 afi = nf_tables_afinfo_lookup(net, family, false); 2375 table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family,
2458 if (IS_ERR(afi)) 2376 genmask);
2459 return PTR_ERR(afi);
2460
2461 table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
2462 if (IS_ERR(table)) 2377 if (IS_ERR(table))
2463 return PTR_ERR(table); 2378 return PTR_ERR(table);
2464 2379
@@ -2469,7 +2384,7 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
2469 return PTR_ERR(chain); 2384 return PTR_ERR(chain);
2470 } 2385 }
2471 2386
2472 nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 2387 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
2473 2388
2474 if (chain) { 2389 if (chain) {
2475 if (nla[NFTA_RULE_HANDLE]) { 2390 if (nla[NFTA_RULE_HANDLE]) {
@@ -2636,6 +2551,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
2636 [NFTA_SET_USERDATA] = { .type = NLA_BINARY, 2551 [NFTA_SET_USERDATA] = { .type = NLA_BINARY,
2637 .len = NFT_USERDATA_MAXLEN }, 2552 .len = NFT_USERDATA_MAXLEN },
2638 [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, 2553 [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 },
2554 [NFTA_SET_HANDLE] = { .type = NLA_U64 },
2639}; 2555};
2640 2556
2641static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { 2557static 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,
2649 u8 genmask) 2565 u8 genmask)
2650{ 2566{
2651 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2567 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2652 struct nft_af_info *afi = NULL; 2568 int family = nfmsg->nfgen_family;
2653 struct nft_table *table = NULL; 2569 struct nft_table *table = NULL;
2654 2570
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
2661 if (nla[NFTA_SET_TABLE] != NULL) { 2571 if (nla[NFTA_SET_TABLE] != NULL) {
2662 if (afi == NULL) 2572 table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE],
2663 return -EAFNOSUPPORT; 2573 family, genmask);
2664
2665 table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE],
2666 genmask);
2667 if (IS_ERR(table)) 2574 if (IS_ERR(table))
2668 return PTR_ERR(table); 2575 return PTR_ERR(table);
2669 } 2576 }
2670 2577
2671 nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); 2578 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
2672 return 0; 2579 return 0;
2673} 2580}
2674 2581
@@ -2688,6 +2595,22 @@ static struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
2688 return ERR_PTR(-ENOENT); 2595 return ERR_PTR(-ENOENT);
2689} 2596}
2690 2597
2598static 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
2691static struct nft_set *nf_tables_set_lookup_byid(const struct net *net, 2614static struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
2692 const struct nlattr *nla, 2615 const struct nlattr *nla,
2693 u8 genmask) 2616 u8 genmask)
@@ -2795,7 +2718,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2795 goto nla_put_failure; 2718 goto nla_put_failure;
2796 2719
2797 nfmsg = nlmsg_data(nlh); 2720 nfmsg = nlmsg_data(nlh);
2798 nfmsg->nfgen_family = ctx->afi->family; 2721 nfmsg->nfgen_family = ctx->family;
2799 nfmsg->version = NFNETLINK_V0; 2722 nfmsg->version = NFNETLINK_V0;
2800 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); 2723 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
2801 2724
@@ -2803,6 +2726,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2803 goto nla_put_failure; 2726 goto nla_put_failure;
2804 if (nla_put_string(skb, NFTA_SET_NAME, set->name)) 2727 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
2805 goto nla_put_failure; 2728 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;
2806 if (set->flags != 0) 2732 if (set->flags != 0)
2807 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) 2733 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags)))
2808 goto nla_put_failure; 2734 goto nla_put_failure;
@@ -2887,10 +2813,8 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
2887{ 2813{
2888 const struct nft_set *set; 2814 const struct nft_set *set;
2889 unsigned int idx, s_idx = cb->args[0]; 2815 unsigned int idx, s_idx = cb->args[0];
2890 struct nft_af_info *afi;
2891 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; 2816 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
2892 struct net *net = sock_net(skb->sk); 2817 struct net *net = sock_net(skb->sk);
2893 int cur_family = cb->args[3];
2894 struct nft_ctx *ctx = cb->data, ctx_set; 2818 struct nft_ctx *ctx = cb->data, ctx_set;
2895 2819
2896 if (cb->args[1]) 2820 if (cb->args[1])
@@ -2899,51 +2823,44 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
2899 rcu_read_lock(); 2823 rcu_read_lock();
2900 cb->seq = net->nft.base_seq; 2824 cb->seq = net->nft.base_seq;
2901 2825
2902 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 2826 list_for_each_entry_rcu(table, &net->nft.tables, list) {
2903 if (ctx->afi && ctx->afi != afi) 2827 if (ctx->family != NFPROTO_UNSPEC &&
2828 ctx->family != table->family)
2904 continue; 2829 continue;
2905 2830
2906 if (cur_family) { 2831 if (ctx->table && ctx->table != table)
2907 if (afi->family != cur_family) 2832 continue;
2833
2834 if (cur_table) {
2835 if (cur_table != table)
2908 continue; 2836 continue;
2909 2837
2910 cur_family = 0; 2838 cur_table = NULL;
2911 } 2839 }
2912 list_for_each_entry_rcu(table, &afi->tables, list) { 2840 idx = 0;
2913 if (ctx->table && ctx->table != table) 2841 list_for_each_entry_rcu(set, &table->sets, list) {
2914 continue; 2842 if (idx < s_idx)
2843 goto cont;
2844 if (!nft_is_active(net, set))
2845 goto cont;
2915 2846
2916 if (cur_table) { 2847 ctx_set = *ctx;
2917 if (cur_table != table) 2848 ctx_set.table = table;
2918 continue; 2849 ctx_set.family = table->family;
2919 2850
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;
2921 } 2857 }
2922 idx = 0; 2858 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
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));
2941cont: 2859cont:
2942 idx++; 2860 idx++;
2943 }
2944 if (s_idx)
2945 s_idx = 0;
2946 } 2861 }
2862 if (s_idx)
2863 s_idx = 0;
2947 } 2864 }
2948 cb->args[1] = 1; 2865 cb->args[1] = 1;
2949done: 2866done:
@@ -3041,8 +2958,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
3041{ 2958{
3042 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2959 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
3043 u8 genmask = nft_genmask_next(net); 2960 u8 genmask = nft_genmask_next(net);
2961 int family = nfmsg->nfgen_family;
3044 const struct nft_set_ops *ops; 2962 const struct nft_set_ops *ops;
3045 struct nft_af_info *afi;
3046 struct nft_table *table; 2963 struct nft_table *table;
3047 struct nft_set *set; 2964 struct nft_set *set;
3048 struct nft_ctx ctx; 2965 struct nft_ctx ctx;
@@ -3149,15 +3066,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
3149 3066
3150 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 3067 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
3151 3068
3152 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); 3069 table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], family,
3153 if (IS_ERR(afi)) 3070 genmask);
3154 return PTR_ERR(afi);
3155
3156 table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask);
3157 if (IS_ERR(table)) 3071 if (IS_ERR(table))
3158 return PTR_ERR(table); 3072 return PTR_ERR(table);
3159 3073
3160 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 3074 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
3161 3075
3162 set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask); 3076 set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask);
3163 if (IS_ERR(set)) { 3077 if (IS_ERR(set)) {
@@ -3223,6 +3137,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
3223 set->udata = udata; 3137 set->udata = udata;
3224 set->timeout = timeout; 3138 set->timeout = timeout;
3225 set->gc_int = gc_int; 3139 set->gc_int = gc_int;
3140 set->handle = nf_tables_alloc_handle(table);
3226 3141
3227 err = ops->init(set, &desc, nla); 3142 err = ops->init(set, &desc, nla);
3228 if (err < 0) 3143 if (err < 0)
@@ -3280,7 +3195,10 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
3280 if (err < 0) 3195 if (err < 0)
3281 return err; 3196 return err;
3282 3197
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);
3284 if (IS_ERR(set)) 3202 if (IS_ERR(set))
3285 return PTR_ERR(set); 3203 return PTR_ERR(set);
3286 3204
@@ -3415,19 +3333,15 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
3415 u8 genmask) 3333 u8 genmask)
3416{ 3334{
3417 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 3335 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
3418 struct nft_af_info *afi; 3336 int family = nfmsg->nfgen_family;
3419 struct nft_table *table; 3337 struct nft_table *table;
3420 3338
3421 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); 3339 table = nf_tables_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE],
3422 if (IS_ERR(afi)) 3340 family, genmask);
3423 return PTR_ERR(afi);
3424
3425 table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE],
3426 genmask);
3427 if (IS_ERR(table)) 3341 if (IS_ERR(table))
3428 return PTR_ERR(table); 3342 return PTR_ERR(table);
3429 3343
3430 nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); 3344 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
3431 return 0; 3345 return 0;
3432} 3346}
3433 3347
@@ -3532,7 +3446,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3532{ 3446{
3533 struct nft_set_dump_ctx *dump_ctx = cb->data; 3447 struct nft_set_dump_ctx *dump_ctx = cb->data;
3534 struct net *net = sock_net(skb->sk); 3448 struct net *net = sock_net(skb->sk);
3535 struct nft_af_info *afi;
3536 struct nft_table *table; 3449 struct nft_table *table;
3537 struct nft_set *set; 3450 struct nft_set *set;
3538 struct nft_set_dump_args args; 3451 struct nft_set_dump_args args;
@@ -3544,21 +3457,19 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3544 int event; 3457 int event;
3545 3458
3546 rcu_read_lock(); 3459 rcu_read_lock();
3547 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 3460 list_for_each_entry_rcu(table, &net->nft.tables, list) {
3548 if (afi != dump_ctx->ctx.afi) 3461 if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
3462 dump_ctx->ctx.family != table->family)
3549 continue; 3463 continue;
3550 3464
3551 list_for_each_entry_rcu(table, &afi->tables, list) { 3465 if (table != dump_ctx->ctx.table)
3552 if (table != dump_ctx->ctx.table) 3466 continue;
3553 continue;
3554 3467
3555 list_for_each_entry_rcu(set, &table->sets, list) { 3468 list_for_each_entry_rcu(set, &table->sets, list) {
3556 if (set == dump_ctx->set) { 3469 if (set == dump_ctx->set) {
3557 set_found = true; 3470 set_found = true;
3558 break; 3471 break;
3559 }
3560 } 3472 }
3561 break;
3562 } 3473 }
3563 break; 3474 break;
3564 } 3475 }
@@ -3578,7 +3489,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3578 goto nla_put_failure; 3489 goto nla_put_failure;
3579 3490
3580 nfmsg = nlmsg_data(nlh); 3491 nfmsg = nlmsg_data(nlh);
3581 nfmsg->nfgen_family = afi->family; 3492 nfmsg->nfgen_family = table->family;
3582 nfmsg->version = NFNETLINK_V0; 3493 nfmsg->version = NFNETLINK_V0;
3583 nfmsg->res_id = htons(net->nft.base_seq & 0xffff); 3494 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
3584 3495
@@ -3641,7 +3552,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
3641 goto nla_put_failure; 3552 goto nla_put_failure;
3642 3553
3643 nfmsg = nlmsg_data(nlh); 3554 nfmsg = nlmsg_data(nlh);
3644 nfmsg->nfgen_family = ctx->afi->family; 3555 nfmsg->nfgen_family = ctx->family;
3645 nfmsg->version = NFNETLINK_V0; 3556 nfmsg->version = NFNETLINK_V0;
3646 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); 3557 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
3647 3558
@@ -3998,7 +3909,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3998 list_for_each_entry(binding, &set->bindings, list) { 3909 list_for_each_entry(binding, &set->bindings, list) {
3999 struct nft_ctx bind_ctx = { 3910 struct nft_ctx bind_ctx = {
4000 .net = ctx->net, 3911 .net = ctx->net,
4001 .afi = ctx->afi, 3912 .family = ctx->family,
4002 .table = ctx->table, 3913 .table = ctx->table,
4003 .chain = (struct nft_chain *)binding->chain, 3914 .chain = (struct nft_chain *)binding->chain,
4004 }; 3915 };
@@ -4417,6 +4328,21 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
4417} 4328}
4418EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); 4329EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
4419 4330
4331struct 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
4420static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { 4346static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
4421 [NFTA_OBJ_TABLE] = { .type = NLA_STRING, 4347 [NFTA_OBJ_TABLE] = { .type = NLA_STRING,
4422 .len = NFT_TABLE_MAXNAMELEN - 1 }, 4348 .len = NFT_TABLE_MAXNAMELEN - 1 },
@@ -4424,6 +4350,7 @@ static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
4424 .len = NFT_OBJ_MAXNAMELEN - 1 }, 4350 .len = NFT_OBJ_MAXNAMELEN - 1 },
4425 [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, 4351 [NFTA_OBJ_TYPE] = { .type = NLA_U32 },
4426 [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, 4352 [NFTA_OBJ_DATA] = { .type = NLA_NESTED },
4353 [NFTA_OBJ_HANDLE] = { .type = NLA_U64},
4427}; 4354};
4428 4355
4429static struct nft_object *nft_obj_init(const struct nft_ctx *ctx, 4356static 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,
4529 const struct nft_object_type *type; 4456 const struct nft_object_type *type;
4530 u8 genmask = nft_genmask_next(net); 4457 u8 genmask = nft_genmask_next(net);
4531 int family = nfmsg->nfgen_family; 4458 int family = nfmsg->nfgen_family;
4532 struct nft_af_info *afi;
4533 struct nft_table *table; 4459 struct nft_table *table;
4534 struct nft_object *obj; 4460 struct nft_object *obj;
4535 struct nft_ctx ctx; 4461 struct nft_ctx ctx;
@@ -4541,11 +4467,8 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
4541 !nla[NFTA_OBJ_DATA]) 4467 !nla[NFTA_OBJ_DATA])
4542 return -EINVAL; 4468 return -EINVAL;
4543 4469
4544 afi = nf_tables_afinfo_lookup(net, family, true); 4470 table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
4545 if (IS_ERR(afi)) 4471 genmask);
4546 return PTR_ERR(afi);
4547
4548 table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4549 if (IS_ERR(table)) 4472 if (IS_ERR(table))
4550 return PTR_ERR(table); 4473 return PTR_ERR(table);
4551 4474
@@ -4563,7 +4486,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
4563 return 0; 4486 return 0;
4564 } 4487 }
4565 4488
4566 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 4489 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
4567 4490
4568 type = nft_obj_type_get(objtype); 4491 type = nft_obj_type_get(objtype);
4569 if (IS_ERR(type)) 4492 if (IS_ERR(type))
@@ -4575,6 +4498,8 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
4575 goto err1; 4498 goto err1;
4576 } 4499 }
4577 obj->table = table; 4500 obj->table = table;
4501 obj->handle = nf_tables_alloc_handle(table);
4502
4578 obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); 4503 obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
4579 if (!obj->name) { 4504 if (!obj->name) {
4580 err = -ENOMEM; 4505 err = -ENOMEM;
@@ -4621,7 +4546,9 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
4621 nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || 4546 nla_put_string(skb, NFTA_OBJ_NAME, obj->name) ||
4622 nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || 4547 nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) ||
4623 nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || 4548 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))
4625 goto nla_put_failure; 4552 goto nla_put_failure;
4626 4553
4627 nlmsg_end(skb, nlh); 4554 nlmsg_end(skb, nlh);
@@ -4640,7 +4567,6 @@ struct nft_obj_filter {
4640static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) 4567static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
4641{ 4568{
4642 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 4569 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
4643 const struct nft_af_info *afi;
4644 const struct nft_table *table; 4570 const struct nft_table *table;
4645 unsigned int idx = 0, s_idx = cb->args[0]; 4571 unsigned int idx = 0, s_idx = cb->args[0];
4646 struct nft_obj_filter *filter = cb->data; 4572 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)
4655 rcu_read_lock(); 4581 rcu_read_lock();
4656 cb->seq = net->nft.base_seq; 4582 cb->seq = net->nft.base_seq;
4657 4583
4658 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 4584 list_for_each_entry_rcu(table, &net->nft.tables, list) {
4659 if (family != NFPROTO_UNSPEC && family != afi->family) 4585 if (family != NFPROTO_UNSPEC && family != table->family)
4660 continue; 4586 continue;
4661 4587
4662 list_for_each_entry_rcu(table, &afi->tables, list) { 4588 list_for_each_entry_rcu(obj, &table->objects, list) {
4663 list_for_each_entry_rcu(obj, &table->objects, list) { 4589 if (!nft_is_active(net, obj))
4664 if (!nft_is_active(net, obj)) 4590 goto cont;
4665 goto cont; 4591 if (idx < s_idx)
4666 if (idx < s_idx) 4592 goto cont;
4667 goto cont; 4593 if (idx > s_idx)
4668 if (idx > s_idx) 4594 memset(&cb->args[1], 0,
4669 memset(&cb->args[1], 0, 4595 sizeof(cb->args) - sizeof(cb->args[0]));
4670 sizeof(cb->args) - sizeof(cb->args[0])); 4596 if (filter && filter->table[0] &&
4671 if (filter && filter->table[0] && 4597 strcmp(filter->table, table->name))
4672 strcmp(filter->table, table->name)) 4598 goto cont;
4673 goto cont; 4599 if (filter &&
4674 if (filter && 4600 filter->type != NFT_OBJECT_UNSPEC &&
4675 filter->type != NFT_OBJECT_UNSPEC && 4601 obj->ops->type->type != filter->type)
4676 obj->ops->type->type != filter->type) 4602 goto cont;
4677 goto cont;
4678 4603
4679 if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, 4604 if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
4680 cb->nlh->nlmsg_seq, 4605 cb->nlh->nlmsg_seq,
4681 NFT_MSG_NEWOBJ, 4606 NFT_MSG_NEWOBJ,
4682 NLM_F_MULTI | NLM_F_APPEND, 4607 NLM_F_MULTI | NLM_F_APPEND,
4683 afi->family, table, obj, reset) < 0) 4608 table->family, table,
4684 goto done; 4609 obj, reset) < 0)
4610 goto done;
4685 4611
4686 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 4612 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
4687cont: 4613cont:
4688 idx++; 4614 idx++;
4689 }
4690 } 4615 }
4691 } 4616 }
4692done: 4617done:
@@ -4738,7 +4663,6 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
4738 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4663 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4739 u8 genmask = nft_genmask_cur(net); 4664 u8 genmask = nft_genmask_cur(net);
4740 int family = nfmsg->nfgen_family; 4665 int family = nfmsg->nfgen_family;
4741 const struct nft_af_info *afi;
4742 const struct nft_table *table; 4666 const struct nft_table *table;
4743 struct nft_object *obj; 4667 struct nft_object *obj;
4744 struct sk_buff *skb2; 4668 struct sk_buff *skb2;
@@ -4769,11 +4693,8 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
4769 !nla[NFTA_OBJ_TYPE]) 4693 !nla[NFTA_OBJ_TYPE])
4770 return -EINVAL; 4694 return -EINVAL;
4771 4695
4772 afi = nf_tables_afinfo_lookup(net, family, false); 4696 table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
4773 if (IS_ERR(afi)) 4697 genmask);
4774 return PTR_ERR(afi);
4775
4776 table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4777 if (IS_ERR(table)) 4698 if (IS_ERR(table))
4778 return PTR_ERR(table); 4699 return PTR_ERR(table);
4779 4700
@@ -4819,32 +4740,33 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,
4819 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4740 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4820 u8 genmask = nft_genmask_next(net); 4741 u8 genmask = nft_genmask_next(net);
4821 int family = nfmsg->nfgen_family; 4742 int family = nfmsg->nfgen_family;
4822 struct nft_af_info *afi;
4823 struct nft_table *table; 4743 struct nft_table *table;
4824 struct nft_object *obj; 4744 struct nft_object *obj;
4825 struct nft_ctx ctx; 4745 struct nft_ctx ctx;
4826 u32 objtype; 4746 u32 objtype;
4827 4747
4828 if (!nla[NFTA_OBJ_TYPE] || 4748 if (!nla[NFTA_OBJ_TYPE] ||
4829 !nla[NFTA_OBJ_NAME]) 4749 (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE]))
4830 return -EINVAL; 4750 return -EINVAL;
4831 4751
4832 afi = nf_tables_afinfo_lookup(net, family, true); 4752 table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
4833 if (IS_ERR(afi)) 4753 genmask);
4834 return PTR_ERR(afi);
4835
4836 table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4837 if (IS_ERR(table)) 4754 if (IS_ERR(table))
4838 return PTR_ERR(table); 4755 return PTR_ERR(table);
4839 4756
4840 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4757 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);
4842 if (IS_ERR(obj)) 4764 if (IS_ERR(obj))
4843 return PTR_ERR(obj); 4765 return PTR_ERR(obj);
4844 if (obj->use > 0) 4766 if (obj->use > 0)
4845 return -EBUSY; 4767 return -EBUSY;
4846 4768
4847 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 4769 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
4848 4770
4849 return nft_delobj(&ctx, obj); 4771 return nft_delobj(&ctx, obj);
4850} 4772}
@@ -4882,7 +4804,7 @@ static void nf_tables_obj_notify(const struct nft_ctx *ctx,
4882 struct nft_object *obj, int event) 4804 struct nft_object *obj, int event)
4883{ 4805{
4884 nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, 4806 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);
4886} 4808}
4887 4809
4888/* 4810/*
@@ -4910,6 +4832,7 @@ static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = {
4910 [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, 4832 [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING,
4911 .len = NFT_NAME_MAXLEN - 1 }, 4833 .len = NFT_NAME_MAXLEN - 1 },
4912 [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, 4834 [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED },
4835 [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 },
4913}; 4836};
4914 4837
4915struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, 4838struct 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,
4927} 4850}
4928EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); 4851EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup);
4929 4852
4853struct nft_flowtable *
4854nf_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
4930#define NFT_FLOWTABLE_DEVICE_MAX 8 4867#define NFT_FLOWTABLE_DEVICE_MAX 8
4931 4868
4932static int nf_tables_parse_devices(const struct nft_ctx *ctx, 4869static 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,
4993 return -EINVAL; 4930 return -EINVAL;
4994 4931
4995 hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM])); 4932 hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM]));
4996 if (hooknum >= ctx->afi->nhooks) 4933 if (hooknum != NF_NETDEV_INGRESS)
4997 return -EINVAL; 4934 return -EINVAL;
4998 4935
4999 priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY])); 4936 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,
5009 goto err1; 4946 goto err1;
5010 } 4947 }
5011 4948
4949 flowtable->hooknum = hooknum;
4950 flowtable->priority = priority;
5012 flowtable->ops = ops; 4951 flowtable->ops = ops;
5013 flowtable->ops_len = n; 4952 flowtable->ops_len = n;
5014 4953
@@ -5029,33 +4968,31 @@ err1:
5029 return err; 4968 return err;
5030} 4969}
5031 4970
5032static const struct nf_flowtable_type * 4971static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)
5033__nft_flowtable_type_get(const struct nft_af_info *afi)
5034{ 4972{
5035 const struct nf_flowtable_type *type; 4973 const struct nf_flowtable_type *type;
5036 4974
5037 list_for_each_entry(type, &nf_tables_flowtables, list) { 4975 list_for_each_entry(type, &nf_tables_flowtables, list) {
5038 if (afi->family == type->family) 4976 if (family == type->family)
5039 return type; 4977 return type;
5040 } 4978 }
5041 return NULL; 4979 return NULL;
5042} 4980}
5043 4981
5044static const struct nf_flowtable_type * 4982static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)
5045nft_flowtable_type_get(const struct nft_af_info *afi)
5046{ 4983{
5047 const struct nf_flowtable_type *type; 4984 const struct nf_flowtable_type *type;
5048 4985
5049 type = __nft_flowtable_type_get(afi); 4986 type = __nft_flowtable_type_get(family);
5050 if (type != NULL && try_module_get(type->owner)) 4987 if (type != NULL && try_module_get(type->owner))
5051 return type; 4988 return type;
5052 4989
5053#ifdef CONFIG_MODULES 4990#ifdef CONFIG_MODULES
5054 if (type == NULL) { 4991 if (type == NULL) {
5055 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 4992 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
5056 request_module("nf-flowtable-%u", afi->family); 4993 request_module("nf-flowtable-%u", family);
5057 nfnl_lock(NFNL_SUBSYS_NFTABLES); 4994 nfnl_lock(NFNL_SUBSYS_NFTABLES);
5058 if (__nft_flowtable_type_get(afi)) 4995 if (__nft_flowtable_type_get(family))
5059 return ERR_PTR(-EAGAIN); 4996 return ERR_PTR(-EAGAIN);
5060 } 4997 }
5061#endif 4998#endif
@@ -5067,15 +5004,12 @@ void nft_flow_table_iterate(struct net *net,
5067 void *data) 5004 void *data)
5068{ 5005{
5069 struct nft_flowtable *flowtable; 5006 struct nft_flowtable *flowtable;
5070 const struct nft_af_info *afi;
5071 const struct nft_table *table; 5007 const struct nft_table *table;
5072 5008
5073 rcu_read_lock(); 5009 rcu_read_lock();
5074 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 5010 list_for_each_entry_rcu(table, &net->nft.tables, list) {
5075 list_for_each_entry_rcu(table, &afi->tables, list) { 5011 list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
5076 list_for_each_entry_rcu(flowtable, &table->flowtables, list) { 5012 iter(&flowtable->data, data);
5077 iter(&flowtable->data, data);
5078 }
5079 } 5013 }
5080 } 5014 }
5081 rcu_read_unlock(); 5015 rcu_read_unlock();
@@ -5106,7 +5040,6 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
5106 u8 genmask = nft_genmask_next(net); 5040 u8 genmask = nft_genmask_next(net);
5107 int family = nfmsg->nfgen_family; 5041 int family = nfmsg->nfgen_family;
5108 struct nft_flowtable *flowtable; 5042 struct nft_flowtable *flowtable;
5109 struct nft_af_info *afi;
5110 struct nft_table *table; 5043 struct nft_table *table;
5111 struct nft_ctx ctx; 5044 struct nft_ctx ctx;
5112 int err, i, k; 5045 int err, i, k;
@@ -5116,11 +5049,8 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
5116 !nla[NFTA_FLOWTABLE_HOOK]) 5049 !nla[NFTA_FLOWTABLE_HOOK])
5117 return -EINVAL; 5050 return -EINVAL;
5118 5051
5119 afi = nf_tables_afinfo_lookup(net, family, true); 5052 table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE],
5120 if (IS_ERR(afi)) 5053 family, genmask);
5121 return PTR_ERR(afi);
5122
5123 table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask);
5124 if (IS_ERR(table)) 5054 if (IS_ERR(table))
5125 return PTR_ERR(table); 5055 return PTR_ERR(table);
5126 5056
@@ -5137,20 +5067,22 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
5137 return 0; 5067 return 0;
5138 } 5068 }
5139 5069
5140 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 5070 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
5141 5071
5142 flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); 5072 flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL);
5143 if (!flowtable) 5073 if (!flowtable)
5144 return -ENOMEM; 5074 return -ENOMEM;
5145 5075
5146 flowtable->table = table; 5076 flowtable->table = table;
5077 flowtable->handle = nf_tables_alloc_handle(table);
5078
5147 flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); 5079 flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL);
5148 if (!flowtable->name) { 5080 if (!flowtable->name) {
5149 err = -ENOMEM; 5081 err = -ENOMEM;
5150 goto err1; 5082 goto err1;
5151 } 5083 }
5152 5084
5153 type = nft_flowtable_type_get(afi); 5085 type = nft_flowtable_type_get(family);
5154 if (IS_ERR(type)) { 5086 if (IS_ERR(type)) {
5155 err = PTR_ERR(type); 5087 err = PTR_ERR(type);
5156 goto err2; 5088 goto err2;
@@ -5210,26 +5142,28 @@ static int nf_tables_delflowtable(struct net *net, struct sock *nlsk,
5210 u8 genmask = nft_genmask_next(net); 5142 u8 genmask = nft_genmask_next(net);
5211 int family = nfmsg->nfgen_family; 5143 int family = nfmsg->nfgen_family;
5212 struct nft_flowtable *flowtable; 5144 struct nft_flowtable *flowtable;
5213 struct nft_af_info *afi;
5214 struct nft_table *table; 5145 struct nft_table *table;
5215 struct nft_ctx ctx; 5146 struct nft_ctx ctx;
5216 5147
5217 afi = nf_tables_afinfo_lookup(net, family, true); 5148 table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE],
5218 if (IS_ERR(afi)) 5149 family, genmask);
5219 return PTR_ERR(afi);
5220
5221 table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask);
5222 if (IS_ERR(table)) 5150 if (IS_ERR(table))
5223 return PTR_ERR(table); 5151 return PTR_ERR(table);
5224 5152
5225 flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], 5153 if (nla[NFTA_FLOWTABLE_HANDLE])
5226 genmask); 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);
5227 if (IS_ERR(flowtable)) 5161 if (IS_ERR(flowtable))
5228 return PTR_ERR(flowtable); 5162 return PTR_ERR(flowtable);
5229 if (flowtable->use > 0) 5163 if (flowtable->use > 0)
5230 return -EBUSY; 5164 return -EBUSY;
5231 5165
5232 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 5166 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
5233 5167
5234 return nft_delflowtable(&ctx, flowtable); 5168 return nft_delflowtable(&ctx, flowtable);
5235} 5169}
@@ -5256,7 +5190,9 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
5256 5190
5257 if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || 5191 if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) ||
5258 nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || 5192 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))
5260 goto nla_put_failure; 5196 goto nla_put_failure;
5261 5197
5262 nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); 5198 nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK);
@@ -5298,40 +5234,37 @@ static int nf_tables_dump_flowtable(struct sk_buff *skb,
5298 struct net *net = sock_net(skb->sk); 5234 struct net *net = sock_net(skb->sk);
5299 int family = nfmsg->nfgen_family; 5235 int family = nfmsg->nfgen_family;
5300 struct nft_flowtable *flowtable; 5236 struct nft_flowtable *flowtable;
5301 const struct nft_af_info *afi;
5302 const struct nft_table *table; 5237 const struct nft_table *table;
5303 5238
5304 rcu_read_lock(); 5239 rcu_read_lock();
5305 cb->seq = net->nft.base_seq; 5240 cb->seq = net->nft.base_seq;
5306 5241
5307 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 5242 list_for_each_entry_rcu(table, &net->nft.tables, list) {
5308 if (family != NFPROTO_UNSPEC && family != afi->family) 5243 if (family != NFPROTO_UNSPEC && family != table->family)
5309 continue; 5244 continue;
5310 5245
5311 list_for_each_entry_rcu(table, &afi->tables, list) { 5246 list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
5312 list_for_each_entry_rcu(flowtable, &table->flowtables, list) { 5247 if (!nft_is_active(net, flowtable))
5313 if (!nft_is_active(net, flowtable)) 5248 goto cont;
5314 goto cont; 5249 if (idx < s_idx)
5315 if (idx < s_idx) 5250 goto cont;
5316 goto cont; 5251 if (idx > s_idx)
5317 if (idx > s_idx) 5252 memset(&cb->args[1], 0,
5318 memset(&cb->args[1], 0, 5253 sizeof(cb->args) - sizeof(cb->args[0]));
5319 sizeof(cb->args) - sizeof(cb->args[0])); 5254 if (filter && filter->table[0] &&
5320 if (filter && filter->table[0] && 5255 strcmp(filter->table, table->name))
5321 strcmp(filter->table, table->name)) 5256 goto cont;
5322 goto cont;
5323 5257
5324 if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, 5258 if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid,
5325 cb->nlh->nlmsg_seq, 5259 cb->nlh->nlmsg_seq,
5326 NFT_MSG_NEWFLOWTABLE, 5260 NFT_MSG_NEWFLOWTABLE,
5327 NLM_F_MULTI | NLM_F_APPEND, 5261 NLM_F_MULTI | NLM_F_APPEND,
5328 afi->family, flowtable) < 0) 5262 table->family, flowtable) < 0)
5329 goto done; 5263 goto done;
5330 5264
5331 nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 5265 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
5332cont: 5266cont:
5333 idx++; 5267 idx++;
5334 }
5335 } 5268 }
5336 } 5269 }
5337done: 5270done:
@@ -5384,7 +5317,6 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
5384 u8 genmask = nft_genmask_cur(net); 5317 u8 genmask = nft_genmask_cur(net);
5385 int family = nfmsg->nfgen_family; 5318 int family = nfmsg->nfgen_family;
5386 struct nft_flowtable *flowtable; 5319 struct nft_flowtable *flowtable;
5387 const struct nft_af_info *afi;
5388 const struct nft_table *table; 5320 const struct nft_table *table;
5389 struct sk_buff *skb2; 5321 struct sk_buff *skb2;
5390 int err; 5322 int err;
@@ -5410,17 +5342,14 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
5410 if (!nla[NFTA_FLOWTABLE_NAME]) 5342 if (!nla[NFTA_FLOWTABLE_NAME])
5411 return -EINVAL; 5343 return -EINVAL;
5412 5344
5413 afi = nf_tables_afinfo_lookup(net, family, false); 5345 table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE],
5414 if (IS_ERR(afi)) 5346 family, genmask);
5415 return PTR_ERR(afi);
5416
5417 table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask);
5418 if (IS_ERR(table)) 5347 if (IS_ERR(table))
5419 return PTR_ERR(table); 5348 return PTR_ERR(table);
5420 5349
5421 flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], 5350 flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
5422 genmask); 5351 genmask);
5423 if (IS_ERR(table)) 5352 if (IS_ERR(flowtable))
5424 return PTR_ERR(flowtable); 5353 return PTR_ERR(flowtable);
5425 5354
5426 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 5355 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
@@ -5457,7 +5386,7 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
5457 5386
5458 err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid, 5387 err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid,
5459 ctx->seq, event, 0, 5388 ctx->seq, event, 0,
5460 ctx->afi->family, flowtable); 5389 ctx->family, flowtable);
5461 if (err < 0) { 5390 if (err < 0) {
5462 kfree_skb(skb); 5391 kfree_skb(skb);
5463 goto err; 5392 goto err;
@@ -5535,17 +5464,14 @@ static int nf_tables_flowtable_event(struct notifier_block *this,
5535 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 5464 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
5536 struct nft_flowtable *flowtable; 5465 struct nft_flowtable *flowtable;
5537 struct nft_table *table; 5466 struct nft_table *table;
5538 struct nft_af_info *afi;
5539 5467
5540 if (event != NETDEV_UNREGISTER) 5468 if (event != NETDEV_UNREGISTER)
5541 return 0; 5469 return 0;
5542 5470
5543 nfnl_lock(NFNL_SUBSYS_NFTABLES); 5471 nfnl_lock(NFNL_SUBSYS_NFTABLES);
5544 list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { 5472 list_for_each_entry(table, &dev_net(dev)->nft.tables, list) {
5545 list_for_each_entry(table, &afi->tables, list) { 5473 list_for_each_entry(flowtable, &table->flowtables, list) {
5546 list_for_each_entry(flowtable, &table->flowtables, list) { 5474 nft_flowtable_event(event, dev, flowtable);
5547 nft_flowtable_event(event, dev, flowtable);
5548 }
5549 } 5475 }
5550 } 5476 }
5551 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 5477 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
@@ -5798,7 +5724,6 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
5798 if (nft_trans_table_update(trans)) { 5724 if (nft_trans_table_update(trans)) {
5799 if (!nft_trans_table_enable(trans)) { 5725 if (!nft_trans_table_enable(trans)) {
5800 nf_tables_table_disable(net, 5726 nf_tables_table_disable(net,
5801 trans->ctx.afi,
5802 trans->ctx.table); 5727 trans->ctx.table);
5803 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; 5728 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
5804 } 5729 }
@@ -5960,7 +5885,6 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
5960 if (nft_trans_table_update(trans)) { 5885 if (nft_trans_table_update(trans)) {
5961 if (nft_trans_table_enable(trans)) { 5886 if (nft_trans_table_enable(trans)) {
5962 nf_tables_table_disable(net, 5887 nf_tables_table_disable(net,
5963 trans->ctx.afi,
5964 trans->ctx.table); 5888 trans->ctx.table);
5965 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; 5889 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
5966 } 5890 }
@@ -6563,20 +6487,6 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
6563} 6487}
6564EXPORT_SYMBOL_GPL(nft_data_dump); 6488EXPORT_SYMBOL_GPL(nft_data_dump);
6565 6489
6566static 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
6574static 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
6580int __nft_release_basechain(struct nft_ctx *ctx) 6490int __nft_release_basechain(struct nft_ctx *ctx)
6581{ 6491{
6582 struct nft_rule *rule, *nr; 6492 struct nft_rule *rule, *nr;
@@ -6597,8 +6507,7 @@ int __nft_release_basechain(struct nft_ctx *ctx)
6597} 6507}
6598EXPORT_SYMBOL_GPL(__nft_release_basechain); 6508EXPORT_SYMBOL_GPL(__nft_release_basechain);
6599 6509
6600/* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */ 6510static void __nft_release_tables(struct net *net)
6601static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
6602{ 6511{
6603 struct nft_flowtable *flowtable, *nf; 6512 struct nft_flowtable *flowtable, *nf;
6604 struct nft_table *table, *nt; 6513 struct nft_table *table, *nt;
@@ -6608,10 +6517,11 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
6608 struct nft_set *set, *ns; 6517 struct nft_set *set, *ns;
6609 struct nft_ctx ctx = { 6518 struct nft_ctx ctx = {
6610 .net = net, 6519 .net = net,
6611 .afi = afi,
6612 }; 6520 };
6613 6521
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
6615 list_for_each_entry(chain, &table->chains, list) 6525 list_for_each_entry(chain, &table->chains, list)
6616 nf_tables_unregister_hook(net, table, chain); 6526 nf_tables_unregister_hook(net, table, chain);
6617 list_for_each_entry(flowtable, &table->flowtables, list) 6527 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)
6652 } 6562 }
6653} 6563}
6654 6564
6565static 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
6573static 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
6655static struct pernet_operations nf_tables_net_ops = { 6580static struct pernet_operations nf_tables_net_ops = {
6656 .init = nf_tables_init_net, 6581 .init = nf_tables_init_net,
6657 .exit = nf_tables_exit_net, 6582 .exit = nf_tables_exit_net,
@@ -6678,7 +6603,6 @@ static int __init nf_tables_module_init(void)
6678 6603
6679 register_netdevice_notifier(&nf_tables_flowtable_notifier); 6604 register_netdevice_notifier(&nf_tables_flowtable_notifier);
6680 6605
6681 pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n");
6682 return register_pernet_subsys(&nf_tables_net_ops); 6606 return register_pernet_subsys(&nf_tables_net_ops);
6683err3: 6607err3:
6684 nf_tables_core_module_exit(); 6608 nf_tables_core_module_exit();
diff --git a/net/netfilter/nf_tables_inet.c b/net/netfilter/nf_tables_inet.c
index 58b9be7480bb..e30c7da09d0d 100644
--- a/net/netfilter/nf_tables_inet.c
+++ b/net/netfilter/nf_tables_inet.c
@@ -38,40 +38,6 @@ static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb,
38 return nft_do_chain(&pkt, priv); 38 return nft_do_chain(&pkt, priv);
39} 39}
40 40
41static struct nft_af_info nft_af_inet __read_mostly = {
42 .family = NFPROTO_INET,
43 .nhooks = NF_INET_NUMHOOKS,
44 .owner = THIS_MODULE,
45};
46
47static 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
59err:
60 kfree(net->nft.inet);
61 return -ENOMEM;
62}
63
64static 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
70static struct pernet_operations nf_tables_inet_net_ops = {
71 .init = nf_tables_inet_init_net,
72 .exit = nf_tables_inet_exit_net,
73};
74
75static const struct nf_chain_type filter_inet = { 41static const struct nf_chain_type filter_inet = {
76 .name = "filter", 42 .name = "filter",
77 .type = NFT_CHAIN_T_DEFAULT, 43 .type = NFT_CHAIN_T_DEFAULT,
@@ -93,22 +59,11 @@ static const struct nf_chain_type filter_inet = {
93 59
94static int __init nf_tables_inet_init(void) 60static int __init nf_tables_inet_init(void)
95{ 61{
96 int ret; 62 return nft_register_chain_type(&filter_inet);
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;
107} 63}
108 64
109static void __exit nf_tables_inet_exit(void) 65static void __exit nf_tables_inet_exit(void)
110{ 66{
111 unregister_pernet_subsys(&nf_tables_inet_net_ops);
112 nft_unregister_chain_type(&filter_inet); 67 nft_unregister_chain_type(&filter_inet);
113} 68}
114 69
@@ -117,4 +72,4 @@ module_exit(nf_tables_inet_exit);
117 72
118MODULE_LICENSE("GPL"); 73MODULE_LICENSE("GPL");
119MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 74MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
120MODULE_ALIAS_NFT_FAMILY(1); 75MODULE_ALIAS_NFT_CHAIN(1, "filter");
diff --git a/net/netfilter/nf_tables_netdev.c b/net/netfilter/nf_tables_netdev.c
index 42f6f6d42a6d..4041fafca934 100644
--- a/net/netfilter/nf_tables_netdev.c
+++ b/net/netfilter/nf_tables_netdev.c
@@ -38,41 +38,6 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb,
38 return nft_do_chain(&pkt, priv); 38 return nft_do_chain(&pkt, priv);
39} 39}
40 40
41static 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
48static 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;
60err:
61 kfree(net->nft.netdev);
62 return -ENOMEM;
63}
64
65static 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
71static struct pernet_operations nf_tables_netdev_net_ops = {
72 .init = nf_tables_netdev_init_net,
73 .exit = nf_tables_netdev_exit_net,
74};
75
76static const struct nf_chain_type nft_filter_chain_netdev = { 41static const struct nf_chain_type nft_filter_chain_netdev = {
77 .name = "filter", 42 .name = "filter",
78 .type = NFT_CHAIN_T_DEFAULT, 43 .type = NFT_CHAIN_T_DEFAULT,
@@ -109,7 +74,6 @@ static int nf_tables_netdev_event(struct notifier_block *this,
109 unsigned long event, void *ptr) 74 unsigned long event, void *ptr)
110{ 75{
111 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 76 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
112 struct nft_af_info *afi;
113 struct nft_table *table; 77 struct nft_table *table;
114 struct nft_chain *chain, *nr; 78 struct nft_chain *chain, *nr;
115 struct nft_ctx ctx = { 79 struct nft_ctx ctx = {
@@ -121,20 +85,18 @@ static int nf_tables_netdev_event(struct notifier_block *this,
121 return NOTIFY_DONE; 85 return NOTIFY_DONE;
122 86
123 nfnl_lock(NFNL_SUBSYS_NFTABLES); 87 nfnl_lock(NFNL_SUBSYS_NFTABLES);
124 list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { 88 list_for_each_entry(table, &ctx.net->nft.tables, list) {
125 ctx.afi = afi; 89 if (table->family != NFPROTO_NETDEV)
126 if (afi->family != NFPROTO_NETDEV)
127 continue; 90 continue;
128 91
129 list_for_each_entry(table, &afi->tables, list) { 92 ctx.family = table->family;
130 ctx.table = table; 93 ctx.table = table;
131 list_for_each_entry_safe(chain, nr, &table->chains, list) { 94 list_for_each_entry_safe(chain, nr, &table->chains, list) {
132 if (!nft_is_base_chain(chain)) 95 if (!nft_is_base_chain(chain))
133 continue; 96 continue;
134 97
135 ctx.chain = chain; 98 ctx.chain = chain;
136 nft_netdev_event(event, dev, &ctx); 99 nft_netdev_event(event, dev, &ctx);
137 }
138 } 100 }
139 } 101 }
140 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 102 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
@@ -154,27 +116,21 @@ static int __init nf_tables_netdev_init(void)
154 if (ret) 116 if (ret)
155 return ret; 117 return ret;
156 118
157 ret = register_pernet_subsys(&nf_tables_netdev_net_ops);
158 if (ret)
159 goto err1;
160
161 ret = register_netdevice_notifier(&nf_tables_netdev_notifier); 119 ret = register_netdevice_notifier(&nf_tables_netdev_notifier);
162 if (ret) 120 if (ret)
163 goto err2; 121 goto err_register_netdevice_notifier;
164 122
165 return 0; 123 return 0;
166 124
167err2: 125err_register_netdevice_notifier:
168 unregister_pernet_subsys(&nf_tables_netdev_net_ops);
169err1:
170 nft_unregister_chain_type(&nft_filter_chain_netdev); 126 nft_unregister_chain_type(&nft_filter_chain_netdev);
127
171 return ret; 128 return ret;
172} 129}
173 130
174static void __exit nf_tables_netdev_exit(void) 131static void __exit nf_tables_netdev_exit(void)
175{ 132{
176 unregister_netdevice_notifier(&nf_tables_netdev_notifier); 133 unregister_netdevice_notifier(&nf_tables_netdev_notifier);
177 unregister_pernet_subsys(&nf_tables_netdev_net_ops);
178 nft_unregister_chain_type(&nft_filter_chain_netdev); 134 nft_unregister_chain_type(&nft_filter_chain_netdev);
179} 135}
180 136
@@ -183,4 +139,4 @@ module_exit(nf_tables_netdev_exit);
183 139
184MODULE_LICENSE("GPL"); 140MODULE_LICENSE("GPL");
185MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 141MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
186MODULE_ALIAS_NFT_FAMILY(5); /* NFPROTO_NETDEV */ 142MODULE_ALIAS_NFT_CHAIN(5, "filter"); /* NFPROTO_NETDEV */
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 733d3e4a30d8..03ead8a9e90c 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -37,8 +37,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
37 rcu_dereference_protected(table[(id)].subsys, \ 37 rcu_dereference_protected(table[(id)].subsys, \
38 lockdep_nfnl_is_held((id))) 38 lockdep_nfnl_is_held((id)))
39 39
40static char __initdata nfversion[] = "0.30";
41
42static struct { 40static struct {
43 struct mutex mutex; 41 struct mutex mutex;
44 const struct nfnetlink_subsystem __rcu *subsys; 42 const struct nfnetlink_subsystem __rcu *subsys;
@@ -580,13 +578,11 @@ static int __init nfnetlink_init(void)
580 for (i=0; i<NFNL_SUBSYS_COUNT; i++) 578 for (i=0; i<NFNL_SUBSYS_COUNT; i++)
581 mutex_init(&table[i].mutex); 579 mutex_init(&table[i].mutex);
582 580
583 pr_info("Netfilter messages via NETLINK v%s.\n", nfversion);
584 return register_pernet_subsys(&nfnetlink_net_ops); 581 return register_pernet_subsys(&nfnetlink_net_ops);
585} 582}
586 583
587static void __exit nfnetlink_exit(void) 584static void __exit nfnetlink_exit(void)
588{ 585{
589 pr_info("Removing netfilter NETLINK layer.\n");
590 unregister_pernet_subsys(&nfnetlink_net_ops); 586 unregister_pernet_subsys(&nfnetlink_net_ops);
591} 587}
592module_init(nfnetlink_init); 588module_init(nfnetlink_init);
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index c45e6d4358ab..88d427f9f9e6 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -527,7 +527,6 @@ static int __init nfnl_acct_init(void)
527 goto err_out; 527 goto err_out;
528 } 528 }
529 529
530 pr_info("nfnl_acct: registering with nfnetlink.\n");
531 ret = nfnetlink_subsys_register(&nfnl_acct_subsys); 530 ret = nfnetlink_subsys_register(&nfnl_acct_subsys);
532 if (ret < 0) { 531 if (ret < 0) {
533 pr_err("nfnl_acct_init: cannot register with nfnetlink.\n"); 532 pr_err("nfnl_acct_init: cannot register with nfnetlink.\n");
@@ -543,7 +542,6 @@ err_out:
543 542
544static void __exit nfnl_acct_exit(void) 543static void __exit nfnl_acct_exit(void)
545{ 544{
546 pr_info("nfnl_acct: unregistering from nfnetlink.\n");
547 nfnetlink_subsys_unregister(&nfnl_acct_subsys); 545 nfnetlink_subsys_unregister(&nfnl_acct_subsys);
548 unregister_pernet_subsys(&nfnl_acct_ops); 546 unregister_pernet_subsys(&nfnl_acct_ops);
549} 547}
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 32b1c0b44e79..95b04702a655 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -615,8 +615,6 @@ err_out:
615 615
616static void __exit cttimeout_exit(void) 616static void __exit cttimeout_exit(void)
617{ 617{
618 pr_info("cttimeout: unregistering from nfnetlink.\n");
619
620 nfnetlink_subsys_unregister(&cttimeout_subsys); 618 nfnetlink_subsys_unregister(&cttimeout_subsys);
621 619
622 unregister_pernet_subsys(&cttimeout_ops); 620 unregister_pernet_subsys(&cttimeout_ops);
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index e955bec0acc6..7b46aa4c478d 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1054,7 +1054,6 @@ static int nful_open(struct inode *inode, struct file *file)
1054} 1054}
1055 1055
1056static const struct file_operations nful_file_ops = { 1056static const struct file_operations nful_file_ops = {
1057 .owner = THIS_MODULE,
1058 .open = nful_open, 1057 .open = nful_open,
1059 .read = seq_read, 1058 .read = seq_read,
1060 .llseek = seq_lseek, 1059 .llseek = seq_lseek,
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 2db35f2d553d..8bba23160a68 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1477,7 +1477,6 @@ static int nfqnl_open(struct inode *inode, struct file *file)
1477} 1477}
1478 1478
1479static const struct file_operations nfqnl_file_ops = { 1479static const struct file_operations nfqnl_file_ops = {
1480 .owner = THIS_MODULE,
1481 .open = nfqnl_open, 1480 .open = nfqnl_open,
1482 .read = seq_read, 1481 .read = seq_read,
1483 .llseek = seq_lseek, 1482 .llseek = seq_lseek,
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index dcff0dc8d28b..8e23726b9081 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -144,7 +144,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
144{ 144{
145 par->net = ctx->net; 145 par->net = ctx->net;
146 par->table = ctx->table->name; 146 par->table = ctx->table->name;
147 switch (ctx->afi->family) { 147 switch (ctx->family) {
148 case AF_INET: 148 case AF_INET:
149 entry->e4.ip.proto = proto; 149 entry->e4.ip.proto = proto;
150 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; 150 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
@@ -175,7 +175,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
175 } else { 175 } else {
176 par->hook_mask = 0; 176 par->hook_mask = 0;
177 } 177 }
178 par->family = ctx->afi->family; 178 par->family = ctx->family;
179 par->nft_compat = true; 179 par->nft_compat = true;
180} 180}
181 181
@@ -267,7 +267,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
267 par.net = ctx->net; 267 par.net = ctx->net;
268 par.target = target; 268 par.target = target;
269 par.targinfo = info; 269 par.targinfo = info;
270 par.family = ctx->afi->family; 270 par.family = ctx->family;
271 if (par.target->destroy != NULL) 271 if (par.target->destroy != NULL)
272 par.target->destroy(&par); 272 par.target->destroy(&par);
273 273
@@ -358,7 +358,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
358{ 358{
359 par->net = ctx->net; 359 par->net = ctx->net;
360 par->table = ctx->table->name; 360 par->table = ctx->table->name;
361 switch (ctx->afi->family) { 361 switch (ctx->family) {
362 case AF_INET: 362 case AF_INET:
363 entry->e4.ip.proto = proto; 363 entry->e4.ip.proto = proto;
364 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; 364 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,
389 } else { 389 } else {
390 par->hook_mask = 0; 390 par->hook_mask = 0;
391 } 391 }
392 par->family = ctx->afi->family; 392 par->family = ctx->family;
393 par->nft_compat = true; 393 par->nft_compat = true;
394} 394}
395 395
@@ -446,7 +446,7 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
446 par.net = ctx->net; 446 par.net = ctx->net;
447 par.match = match; 447 par.match = match;
448 par.matchinfo = info; 448 par.matchinfo = info;
449 par.family = ctx->afi->family; 449 par.family = ctx->family;
450 if (par.match->destroy != NULL) 450 if (par.match->destroy != NULL)
451 par.match->destroy(&par); 451 par.match->destroy(&par);
452 452
@@ -648,7 +648,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
648 648
649 mt_name = nla_data(tb[NFTA_MATCH_NAME]); 649 mt_name = nla_data(tb[NFTA_MATCH_NAME]);
650 rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV])); 650 rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
651 family = ctx->afi->family; 651 family = ctx->family;
652 652
653 /* Re-use the existing match if it's already loaded. */ 653 /* Re-use the existing match if it's already loaded. */
654 list_for_each_entry(nft_match, &nft_match_list, head) { 654 list_for_each_entry(nft_match, &nft_match_list, head) {
@@ -733,7 +733,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
733 733
734 tg_name = nla_data(tb[NFTA_TARGET_NAME]); 734 tg_name = nla_data(tb[NFTA_TARGET_NAME]);
735 rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV])); 735 rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV]));
736 family = ctx->afi->family; 736 family = ctx->family;
737 737
738 /* Re-use the existing target if it's already loaded. */ 738 /* Re-use the existing target if it's already loaded. */
739 list_for_each_entry(nft_target, &nft_target_list, head) { 739 list_for_each_entry(nft_target, &nft_target_list, head) {
@@ -812,8 +812,6 @@ static int __init nft_compat_module_init(void)
812 goto err_target; 812 goto err_target;
813 } 813 }
814 814
815 pr_info("nf_tables_compat: (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>\n");
816
817 return ret; 815 return ret;
818 816
819err_target: 817err_target:
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 2647b895f4b0..6ab274b14484 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -405,7 +405,7 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
405 if (tb[NFTA_CT_DIRECTION] == NULL) 405 if (tb[NFTA_CT_DIRECTION] == NULL)
406 return -EINVAL; 406 return -EINVAL;
407 407
408 switch (ctx->afi->family) { 408 switch (ctx->family) {
409 case NFPROTO_IPV4: 409 case NFPROTO_IPV4:
410 len = FIELD_SIZEOF(struct nf_conntrack_tuple, 410 len = FIELD_SIZEOF(struct nf_conntrack_tuple,
411 src.u3.ip); 411 src.u3.ip);
@@ -456,7 +456,7 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
456 if (err < 0) 456 if (err < 0)
457 return err; 457 return err;
458 458
459 err = nf_ct_netns_get(ctx->net, ctx->afi->family); 459 err = nf_ct_netns_get(ctx->net, ctx->family);
460 if (err < 0) 460 if (err < 0)
461 return err; 461 return err;
462 462
@@ -550,7 +550,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
550 if (err < 0) 550 if (err < 0)
551 goto err1; 551 goto err1;
552 552
553 err = nf_ct_netns_get(ctx->net, ctx->afi->family); 553 err = nf_ct_netns_get(ctx->net, ctx->family);
554 if (err < 0) 554 if (err < 0)
555 goto err1; 555 goto err1;
556 556
@@ -564,7 +564,7 @@ err1:
564static void nft_ct_get_destroy(const struct nft_ctx *ctx, 564static void nft_ct_get_destroy(const struct nft_ctx *ctx,
565 const struct nft_expr *expr) 565 const struct nft_expr *expr)
566{ 566{
567 nf_ct_netns_put(ctx->net, ctx->afi->family); 567 nf_ct_netns_put(ctx->net, ctx->family);
568} 568}
569 569
570static void nft_ct_set_destroy(const struct nft_ctx *ctx, 570static 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,
573 struct nft_ct *priv = nft_expr_priv(expr); 573 struct nft_ct *priv = nft_expr_priv(expr);
574 574
575 __nft_ct_set_destroy(ctx, priv); 575 __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);
577} 577}
578 578
579static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) 579static 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,
734 struct nft_ct_helper_obj *priv = nft_obj_data(obj); 734 struct nft_ct_helper_obj *priv = nft_obj_data(obj);
735 struct nf_conntrack_helper *help4, *help6; 735 struct nf_conntrack_helper *help4, *help6;
736 char name[NF_CT_HELPER_NAME_LEN]; 736 char name[NF_CT_HELPER_NAME_LEN];
737 int family = ctx->afi->family; 737 int family = ctx->family;
738 738
739 if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO]) 739 if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO])
740 return -EINVAL; 740 return -EINVAL;
@@ -753,14 +753,14 @@ static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
753 753
754 switch (family) { 754 switch (family) {
755 case NFPROTO_IPV4: 755 case NFPROTO_IPV4:
756 if (ctx->afi->family == NFPROTO_IPV6) 756 if (ctx->family == NFPROTO_IPV6)
757 return -EINVAL; 757 return -EINVAL;
758 758
759 help4 = nf_conntrack_helper_try_module_get(name, family, 759 help4 = nf_conntrack_helper_try_module_get(name, family,
760 priv->l4proto); 760 priv->l4proto);
761 break; 761 break;
762 case NFPROTO_IPV6: 762 case NFPROTO_IPV6:
763 if (ctx->afi->family == NFPROTO_IPV4) 763 if (ctx->family == NFPROTO_IPV4)
764 return -EINVAL; 764 return -EINVAL;
765 765
766 help6 = nf_conntrack_helper_try_module_get(name, family, 766 help6 = nf_conntrack_helper_try_module_get(name, family,
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
index ec0fd78231d8..fc83e29d6634 100644
--- a/net/netfilter/nft_dynset.c
+++ b/net/netfilter/nft_dynset.c
@@ -164,7 +164,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
164 } 164 }
165 165
166 priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]); 166 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);
168 if (err < 0) 168 if (err < 0)
169 return err; 169 return err;
170 170
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index dd38785dfed9..4503b8dcf9c0 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -151,7 +151,7 @@ static int nft_flow_offload_init(const struct nft_ctx *ctx,
151 priv->flowtable = flowtable; 151 priv->flowtable = flowtable;
152 flowtable->use++; 152 flowtable->use++;
153 153
154 return nf_ct_netns_get(ctx->net, ctx->afi->family); 154 return nf_ct_netns_get(ctx->net, ctx->family);
155} 155}
156 156
157static void nft_flow_offload_destroy(const struct nft_ctx *ctx, 157static 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,
160 struct nft_flow_offload *priv = nft_expr_priv(expr); 160 struct nft_flow_offload *priv = nft_expr_priv(expr);
161 161
162 priv->flowtable->use--; 162 priv->flowtable->use--;
163 nf_ct_netns_put(ctx->net, ctx->afi->family); 163 nf_ct_netns_put(ctx->net, ctx->family);
164} 164}
165 165
166static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr) 166static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr)
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 6f6e64423643..a27be36dc0af 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -112,7 +112,7 @@ static int nft_log_init(const struct nft_ctx *ctx,
112 break; 112 break;
113 } 113 }
114 114
115 err = nf_logger_find_get(ctx->afi->family, li->type); 115 err = nf_logger_find_get(ctx->family, li->type);
116 if (err < 0) 116 if (err < 0)
117 goto err1; 117 goto err1;
118 118
@@ -133,7 +133,7 @@ static void nft_log_destroy(const struct nft_ctx *ctx,
133 if (priv->prefix != nft_log_null_prefix) 133 if (priv->prefix != nft_log_null_prefix)
134 kfree(priv->prefix); 134 kfree(priv->prefix);
135 135
136 nf_logger_put(ctx->afi->family, li->type); 136 nf_logger_put(ctx->family, li->type);
137} 137}
138 138
139static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) 139static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr)
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
index 6ac03d4266c9..9d8655bc1bea 100644
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -73,7 +73,7 @@ int nft_masq_init(const struct nft_ctx *ctx,
73 } 73 }
74 } 74 }
75 75
76 return nf_ct_netns_get(ctx->net, ctx->afi->family); 76 return nf_ct_netns_get(ctx->net, ctx->family);
77} 77}
78EXPORT_SYMBOL_GPL(nft_masq_init); 78EXPORT_SYMBOL_GPL(nft_masq_init);
79 79
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 1a91e676f13e..8fb91940e2e7 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -339,7 +339,7 @@ static int nft_meta_get_validate(const struct nft_ctx *ctx,
339 if (priv->key != NFT_META_SECPATH) 339 if (priv->key != NFT_META_SECPATH)
340 return 0; 340 return 0;
341 341
342 switch (ctx->afi->family) { 342 switch (ctx->family) {
343 case NFPROTO_NETDEV: 343 case NFPROTO_NETDEV:
344 hooks = 1 << NF_NETDEV_INGRESS; 344 hooks = 1 << NF_NETDEV_INGRESS;
345 break; 345 break;
@@ -370,7 +370,7 @@ int nft_meta_set_validate(const struct nft_ctx *ctx,
370 if (priv->key != NFT_META_PKTTYPE) 370 if (priv->key != NFT_META_PKTTYPE)
371 return 0; 371 return 0;
372 372
373 switch (ctx->afi->family) { 373 switch (ctx->family) {
374 case NFPROTO_BRIDGE: 374 case NFPROTO_BRIDGE:
375 hooks = 1 << NF_BR_PRE_ROUTING; 375 hooks = 1 << NF_BR_PRE_ROUTING;
376 break; 376 break;
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index ed548d06b6dd..1f36954c2ba9 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -142,7 +142,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
142 return -EINVAL; 142 return -EINVAL;
143 143
144 family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); 144 family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY]));
145 if (family != ctx->afi->family) 145 if (family != ctx->family)
146 return -EOPNOTSUPP; 146 return -EOPNOTSUPP;
147 147
148 switch (family) { 148 switch (family) {
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index 1e66538bf0ff..c64cbe78dee7 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -75,7 +75,7 @@ int nft_redir_init(const struct nft_ctx *ctx,
75 return -EINVAL; 75 return -EINVAL;
76 } 76 }
77 77
78 return nf_ct_netns_get(ctx->net, ctx->afi->family); 78 return nf_ct_netns_get(ctx->net, ctx->family);
79} 79}
80EXPORT_SYMBOL_GPL(nft_redir_init); 80EXPORT_SYMBOL_GPL(nft_redir_init);
81 81
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 10c19a3f4cbd..0b56bf05c169 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1082,10 +1082,10 @@ struct xt_table *xt_request_find_table_lock(struct net *net, u_int8_t af,
1082{ 1082{
1083 struct xt_table *t = xt_find_table_lock(net, af, name); 1083 struct xt_table *t = xt_find_table_lock(net, af, name);
1084 1084
1085#ifdef CONFIG_MODULE 1085#ifdef CONFIG_MODULES
1086 if (IS_ERR(t)) { 1086 if (IS_ERR(t)) {
1087 int err = request_module("%stable_%s", xt_prefix[af], name); 1087 int err = request_module("%stable_%s", xt_prefix[af], name);
1088 if (err) 1088 if (err < 0)
1089 return ERR_PTR(err); 1089 return ERR_PTR(err);
1090 t = xt_find_table_lock(net, af, name); 1090 t = xt_find_table_lock(net, af, name);
1091 } 1091 }
@@ -1362,7 +1362,6 @@ static int xt_table_open(struct inode *inode, struct file *file)
1362} 1362}
1363 1363
1364static const struct file_operations xt_table_ops = { 1364static const struct file_operations xt_table_ops = {
1365 .owner = THIS_MODULE,
1366 .open = xt_table_open, 1365 .open = xt_table_open,
1367 .read = seq_read, 1366 .read = seq_read,
1368 .llseek = seq_lseek, 1367 .llseek = seq_lseek,
@@ -1498,7 +1497,6 @@ static int xt_match_open(struct inode *inode, struct file *file)
1498} 1497}
1499 1498
1500static const struct file_operations xt_match_ops = { 1499static const struct file_operations xt_match_ops = {
1501 .owner = THIS_MODULE,
1502 .open = xt_match_open, 1500 .open = xt_match_open,
1503 .read = seq_read, 1501 .read = seq_read,
1504 .llseek = seq_lseek, 1502 .llseek = seq_lseek,
@@ -1551,7 +1549,6 @@ static int xt_target_open(struct inode *inode, struct file *file)
1551} 1549}
1552 1550
1553static const struct file_operations xt_target_ops = { 1551static const struct file_operations xt_target_ops = {
1554 .owner = THIS_MODULE,
1555 .open = xt_target_open, 1552 .open = xt_target_open,
1556 .read = seq_read, 1553 .read = seq_read,
1557 .llseek = seq_lseek, 1554 .llseek = seq_lseek,
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 5da8746f7b88..ca6847403ca2 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -353,7 +353,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
353static bool select_all(const struct xt_hashlimit_htable *ht, 353static bool select_all(const struct xt_hashlimit_htable *ht,
354 const struct dsthash_ent *he) 354 const struct dsthash_ent *he)
355{ 355{
356 return 1; 356 return true;
357} 357}
358 358
359static bool select_gc(const struct xt_hashlimit_htable *ht, 359static bool select_gc(const struct xt_hashlimit_htable *ht,
@@ -1266,7 +1266,6 @@ static int dl_proc_open(struct inode *inode, struct file *file)
1266} 1266}
1267 1267
1268static const struct file_operations dl_file_ops_v2 = { 1268static const struct file_operations dl_file_ops_v2 = {
1269 .owner = THIS_MODULE,
1270 .open = dl_proc_open_v2, 1269 .open = dl_proc_open_v2,
1271 .read = seq_read, 1270 .read = seq_read,
1272 .llseek = seq_lseek, 1271 .llseek = seq_lseek,
@@ -1274,7 +1273,6 @@ static const struct file_operations dl_file_ops_v2 = {
1274}; 1273};
1275 1274
1276static const struct file_operations dl_file_ops_v1 = { 1275static const struct file_operations dl_file_ops_v1 = {
1277 .owner = THIS_MODULE,
1278 .open = dl_proc_open_v1, 1276 .open = dl_proc_open_v1,
1279 .read = seq_read, 1277 .read = seq_read,
1280 .llseek = seq_lseek, 1278 .llseek = seq_lseek,
@@ -1282,7 +1280,6 @@ static const struct file_operations dl_file_ops_v1 = {
1282}; 1280};
1283 1281
1284static const struct file_operations dl_file_ops = { 1282static const struct file_operations dl_file_ops = {
1285 .owner = THIS_MODULE,
1286 .open = dl_proc_open, 1283 .open = dl_proc_open,
1287 .read = seq_read, 1284 .read = seq_read,
1288 .llseek = seq_lseek, 1285 .llseek = seq_lseek,
diff --git a/net/netfilter/xt_ipcomp.c b/net/netfilter/xt_ipcomp.c
index 000e70377f85..7ca64a50db04 100644
--- a/net/netfilter/xt_ipcomp.c
+++ b/net/netfilter/xt_ipcomp.c
@@ -58,7 +58,7 @@ static bool comp_mt(const struct sk_buff *skb, struct xt_action_param *par)
58 */ 58 */
59 pr_debug("Dropping evil IPComp tinygram.\n"); 59 pr_debug("Dropping evil IPComp tinygram.\n");
60 par->hotdrop = true; 60 par->hotdrop = true;
61 return 0; 61 return false;
62 } 62 }
63 63
64 return spi_match(compinfo->spis[0], compinfo->spis[1], 64 return spi_match(compinfo->spis[0], compinfo->spis[1],