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

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

Pablo Neira Ayuso says:

====================
Netfilter/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>

+1239 -2224
+14 -34
include/net/netfilter/nf_tables.h
··· 143 143 * struct nft_ctx - nf_tables rule/set context 144 144 * 145 145 * @net: net namespace 146 - * @afi: address family info 147 146 * @table: the table the chain is contained in 148 147 * @chain: the chain the rule is contained in 149 148 * @nla: netlink attributes 150 149 * @portid: netlink portID of the original message 151 150 * @seq: netlink sequence number 151 + * @family: protocol family 152 152 * @report: notify via unicast netlink message 153 153 */ 154 154 struct nft_ctx { 155 155 struct net *net; 156 - struct nft_af_info *afi; 157 156 struct nft_table *table; 158 157 struct nft_chain *chain; 159 158 const struct nlattr * const *nla; 160 159 u32 portid; 161 160 u32 seq; 161 + u8 family; 162 162 bool report; 163 163 }; 164 164 ··· 374 374 * @list: table set list node 375 375 * @bindings: list of set bindings 376 376 * @name: name of the set 377 + * @handle: unique handle of the set 377 378 * @ktype: key type (numeric type defined by userspace, not used in the kernel) 378 379 * @dtype: data type (verdict or numeric type defined by userspace) 379 380 * @objtype: object type (see NFT_OBJECT_* definitions) ··· 397 396 struct list_head list; 398 397 struct list_head bindings; 399 398 char *name; 399 + u64 handle; 400 400 u32 ktype; 401 401 u32 dtype; 402 402 u32 objtype; ··· 948 946 * @objects: stateful objects in the table 949 947 * @flowtables: flow tables in the table 950 948 * @hgenerator: handle generator state 949 + * @handle: table handle 951 950 * @use: number of chain references to this table 952 951 * @flags: table flag (see enum nft_table_flags) 953 952 * @genmask: generation mask 953 + * @afinfo: address family info 954 954 * @name: name of the table 955 955 */ 956 956 struct nft_table { ··· 962 958 struct list_head objects; 963 959 struct list_head flowtables; 964 960 u64 hgenerator; 961 + u64 handle; 965 962 u32 use; 966 - u16 flags:14, 963 + u16 family:6, 964 + flags:8, 967 965 genmask:2; 968 966 char *name; 969 967 }; 970 - 971 - enum nft_af_flags { 972 - NFT_AF_NEEDS_DEV = (1 << 0), 973 - }; 974 - 975 - /** 976 - * struct nft_af_info - nf_tables address family info 977 - * 978 - * @list: used internally 979 - * @family: address family 980 - * @nhooks: number of hooks in this family 981 - * @owner: module owner 982 - * @tables: used internally 983 - * @flags: family flags 984 - */ 985 - struct nft_af_info { 986 - struct list_head list; 987 - int family; 988 - unsigned int nhooks; 989 - struct module *owner; 990 - struct list_head tables; 991 - u32 flags; 992 - }; 993 - 994 - int nft_register_afinfo(struct net *, struct nft_af_info *); 995 - void nft_unregister_afinfo(struct net *, struct nft_af_info *); 996 968 997 969 int nft_register_chain_type(const struct nf_chain_type *); 998 970 void nft_unregister_chain_type(const struct nf_chain_type *); ··· 987 1007 * @name: name of this stateful object 988 1008 * @genmask: generation mask 989 1009 * @use: number of references to this stateful object 990 - * @data: object data, layout depends on type 1010 + * @handle: unique object handle 991 1011 * @ops: object operations 992 - * @data: pointer to object data 1012 + * @data: object data, layout depends on type 993 1013 */ 994 1014 struct nft_object { 995 1015 struct list_head list; ··· 997 1017 struct nft_table *table; 998 1018 u32 genmask:2, 999 1019 use:30; 1020 + u64 handle; 1000 1021 /* runtime data below here */ 1001 1022 const struct nft_object_ops *ops ____cacheline_aligned; 1002 1023 unsigned char data[] ··· 1079 1098 * @ops_len: number of hooks in array 1080 1099 * @genmask: generation mask 1081 1100 * @use: number of references to this flow table 1101 + * @handle: unique object handle 1082 1102 * @data: rhashtable and garbage collector 1083 1103 * @ops: array of hooks 1084 1104 */ ··· 1092 1110 int ops_len; 1093 1111 u32 genmask:2, 1094 1112 use:30; 1113 + u64 handle; 1095 1114 /* runtime data below here */ 1096 1115 struct nf_hook_ops *ops ____cacheline_aligned; 1097 1116 struct nf_flowtable data; ··· 1136 1153 const struct nft_chain *basechain); 1137 1154 1138 1155 void nft_trace_notify(struct nft_traceinfo *info); 1139 - 1140 - #define MODULE_ALIAS_NFT_FAMILY(family) \ 1141 - MODULE_ALIAS("nft-afinfo-" __stringify(family)) 1142 1156 1143 1157 #define MODULE_ALIAS_NFT_CHAIN(family, name) \ 1144 1158 MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
+1 -7
include/net/netns/nftables.h
··· 7 7 struct nft_af_info; 8 8 9 9 struct netns_nftables { 10 - struct list_head af_info; 10 + struct list_head tables; 11 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 12 unsigned int base_seq; 19 13 u8 gencursor; 20 14 };
+10
include/uapi/linux/netfilter/nf_tables.h
··· 174 174 NFTA_TABLE_NAME, 175 175 NFTA_TABLE_FLAGS, 176 176 NFTA_TABLE_USE, 177 + NFTA_TABLE_HANDLE, 178 + NFTA_TABLE_PAD, 177 179 __NFTA_TABLE_MAX 178 180 }; 179 181 #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) ··· 319 317 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) 320 318 * @NFTA_SET_USERDATA: user data (NLA_BINARY) 321 319 * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) 320 + * @NFTA_SET_HANDLE: set handle (NLA_U64) 322 321 */ 323 322 enum nft_set_attributes { 324 323 NFTA_SET_UNSPEC, ··· 338 335 NFTA_SET_USERDATA, 339 336 NFTA_SET_PAD, 340 337 NFTA_SET_OBJ_TYPE, 338 + NFTA_SET_HANDLE, 341 339 __NFTA_SET_MAX 342 340 }; 343 341 #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) ··· 1318 1314 * @NFTA_OBJ_TYPE: stateful object type (NLA_U32) 1319 1315 * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) 1320 1316 * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) 1317 + * @NFTA_OBJ_HANDLE: object handle (NLA_U64) 1321 1318 */ 1322 1319 enum nft_object_attributes { 1323 1320 NFTA_OBJ_UNSPEC, ··· 1327 1322 NFTA_OBJ_TYPE, 1328 1323 NFTA_OBJ_DATA, 1329 1324 NFTA_OBJ_USE, 1325 + NFTA_OBJ_HANDLE, 1326 + NFTA_OBJ_PAD, 1330 1327 __NFTA_OBJ_MAX 1331 1328 }; 1332 1329 #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) ··· 1340 1333 * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) 1341 1334 * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) 1342 1335 * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) 1336 + * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) 1343 1337 */ 1344 1338 enum nft_flowtable_attributes { 1345 1339 NFTA_FLOWTABLE_UNSPEC, ··· 1348 1340 NFTA_FLOWTABLE_NAME, 1349 1341 NFTA_FLOWTABLE_HOOK, 1350 1342 NFTA_FLOWTABLE_USE, 1343 + NFTA_FLOWTABLE_HANDLE, 1344 + NFTA_FLOWTABLE_PAD, 1351 1345 __NFTA_FLOWTABLE_MAX 1352 1346 }; 1353 1347 #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1)
+1
include/uapi/linux/netfilter_ipv4.h
··· 57 57 58 58 enum nf_ip_hook_priorities { 59 59 NF_IP_PRI_FIRST = INT_MIN, 60 + NF_IP_PRI_RAW_BEFORE_DEFRAG = -450, 60 61 NF_IP_PRI_CONNTRACK_DEFRAG = -400, 61 62 NF_IP_PRI_RAW = -300, 62 63 NF_IP_PRI_SELINUX_FIRST = -225,
+1
include/uapi/linux/netfilter_ipv6.h
··· 62 62 63 63 enum nf_ip6_hook_priorities { 64 64 NF_IP6_PRI_FIRST = INT_MIN, 65 + NF_IP6_PRI_RAW_BEFORE_DEFRAG = -450, 65 66 NF_IP6_PRI_CONNTRACK_DEFRAG = -400, 66 67 NF_IP6_PRI_RAW = -300, 67 68 NF_IP6_PRI_SELINUX_FIRST = -225,
+57
include/uapi/linux/netfilter_ipv6/ip6t_srh.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + #ifndef _IP6T_SRH_H 3 + #define _IP6T_SRH_H 4 + 5 + #include <linux/types.h> 6 + #include <linux/netfilter.h> 7 + 8 + /* Values for "mt_flags" field in struct ip6t_srh */ 9 + #define IP6T_SRH_NEXTHDR 0x0001 10 + #define IP6T_SRH_LEN_EQ 0x0002 11 + #define IP6T_SRH_LEN_GT 0x0004 12 + #define IP6T_SRH_LEN_LT 0x0008 13 + #define IP6T_SRH_SEGS_EQ 0x0010 14 + #define IP6T_SRH_SEGS_GT 0x0020 15 + #define IP6T_SRH_SEGS_LT 0x0040 16 + #define IP6T_SRH_LAST_EQ 0x0080 17 + #define IP6T_SRH_LAST_GT 0x0100 18 + #define IP6T_SRH_LAST_LT 0x0200 19 + #define IP6T_SRH_TAG 0x0400 20 + #define IP6T_SRH_MASK 0x07FF 21 + 22 + /* Values for "mt_invflags" field in struct ip6t_srh */ 23 + #define IP6T_SRH_INV_NEXTHDR 0x0001 24 + #define IP6T_SRH_INV_LEN_EQ 0x0002 25 + #define IP6T_SRH_INV_LEN_GT 0x0004 26 + #define IP6T_SRH_INV_LEN_LT 0x0008 27 + #define IP6T_SRH_INV_SEGS_EQ 0x0010 28 + #define IP6T_SRH_INV_SEGS_GT 0x0020 29 + #define IP6T_SRH_INV_SEGS_LT 0x0040 30 + #define IP6T_SRH_INV_LAST_EQ 0x0080 31 + #define IP6T_SRH_INV_LAST_GT 0x0100 32 + #define IP6T_SRH_INV_LAST_LT 0x0200 33 + #define IP6T_SRH_INV_TAG 0x0400 34 + #define IP6T_SRH_INV_MASK 0x07FF 35 + 36 + /** 37 + * struct ip6t_srh - SRH match options 38 + * @ next_hdr: Next header field of SRH 39 + * @ hdr_len: Extension header length field of SRH 40 + * @ segs_left: Segments left field of SRH 41 + * @ last_entry: Last entry field of SRH 42 + * @ tag: Tag field of SRH 43 + * @ mt_flags: match options 44 + * @ mt_invflags: Invert the sense of match options 45 + */ 46 + 47 + struct ip6t_srh { 48 + __u8 next_hdr; 49 + __u8 hdr_len; 50 + __u8 segs_left; 51 + __u8 last_entry; 52 + __u16 tag; 53 + __u16 mt_flags; 54 + __u16 mt_invflags; 55 + }; 56 + 57 + #endif /*_IP6T_SRH_H*/
-2
net/bridge/netfilter/ebtables.c
··· 2445 2445 return ret; 2446 2446 } 2447 2447 2448 - printk(KERN_INFO "Ebtables v2.0 registered\n"); 2449 2448 return 0; 2450 2449 } 2451 2450 ··· 2452 2453 { 2453 2454 nf_unregister_sockopt(&ebt_sockopts); 2454 2455 xt_unregister_target(&ebt_standard_target); 2455 - printk(KERN_INFO "Ebtables v2.0 unregistered\n"); 2456 2456 } 2457 2457 2458 2458 EXPORT_SYMBOL(ebt_register_table);
+2 -52
net/bridge/netfilter/nf_tables_bridge.c
··· 42 42 return nft_do_chain(&pkt, priv); 43 43 } 44 44 45 - static struct nft_af_info nft_af_bridge __read_mostly = { 46 - .family = NFPROTO_BRIDGE, 47 - .nhooks = NF_BR_NUMHOOKS, 48 - .owner = THIS_MODULE, 49 - }; 50 - 51 - static int nf_tables_bridge_init_net(struct net *net) 52 - { 53 - net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); 54 - if (net->nft.bridge == NULL) 55 - return -ENOMEM; 56 - 57 - memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge)); 58 - 59 - if (nft_register_afinfo(net, net->nft.bridge) < 0) 60 - goto err; 61 - 62 - return 0; 63 - err: 64 - kfree(net->nft.bridge); 65 - return -ENOMEM; 66 - } 67 - 68 - static void nf_tables_bridge_exit_net(struct net *net) 69 - { 70 - nft_unregister_afinfo(net, net->nft.bridge); 71 - kfree(net->nft.bridge); 72 - } 73 - 74 - static struct pernet_operations nf_tables_bridge_net_ops = { 75 - .init = nf_tables_bridge_init_net, 76 - .exit = nf_tables_bridge_exit_net, 77 - }; 78 - 79 45 static const struct nf_chain_type filter_bridge = { 80 46 .name = "filter", 81 47 .type = NFT_CHAIN_T_DEFAULT, ··· 63 97 64 98 static int __init nf_tables_bridge_init(void) 65 99 { 66 - int ret; 67 - 68 - ret = nft_register_chain_type(&filter_bridge); 69 - if (ret < 0) 70 - return ret; 71 - 72 - ret = register_pernet_subsys(&nf_tables_bridge_net_ops); 73 - if (ret < 0) 74 - goto err_register_subsys; 75 - 76 - return ret; 77 - 78 - err_register_subsys: 79 - nft_unregister_chain_type(&filter_bridge); 80 - 81 - return ret; 100 + return nft_register_chain_type(&filter_bridge); 82 101 } 83 102 84 103 static void __exit nf_tables_bridge_exit(void) 85 104 { 86 - unregister_pernet_subsys(&nf_tables_bridge_net_ops); 87 105 nft_unregister_chain_type(&filter_bridge); 88 106 } 89 107 ··· 76 126 77 127 MODULE_LICENSE("GPL"); 78 128 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 79 - MODULE_ALIAS_NFT_FAMILY(AF_BRIDGE); 129 + MODULE_ALIAS_NFT_CHAIN(AF_BRIDGE, "filter");
+4 -1
net/ipv4/netfilter/Kconfig
··· 79 79 endif # NF_TABLES 80 80 81 81 config NF_FLOW_TABLE_IPV4 82 - select NF_FLOW_TABLE 83 82 tristate "Netfilter flow table IPv4 module" 83 + depends on NF_CONNTRACK && NF_TABLES 84 + select NF_FLOW_TABLE 84 85 help 85 86 This option adds the flow table IPv4 support. 86 87 ··· 158 157 depends on NF_CONNTRACK_SNMP 159 158 depends on NETFILTER_ADVANCED 160 159 default NF_NAT && NF_CONNTRACK_SNMP 160 + select ASN1 161 161 ---help--- 162 162 163 163 This module implements an Application Layer Gateway (ALG) for ··· 344 342 depends on NF_CONNTRACK_IPV4 345 343 depends on NETFILTER_ADVANCED 346 344 select NF_CONNTRACK_MARK 345 + select NETFILTER_FAMILY_ARP 347 346 help 348 347 The CLUSTERIP target allows you to build load-balancing clusters of 349 348 network servers without having a dedicated load-balancing
+6
net/ipv4/netfilter/Makefile
··· 27 27 # NAT helpers (nf_conntrack) 28 28 obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 29 29 obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o 30 + 31 + nf_nat_snmp_basic-y := nf_nat_snmp_basic-asn1.o nf_nat_snmp_basic_main.o 32 + nf_nat_snmp_basic-y : nf_nat_snmp_basic-asn1.h nf_nat_snmp_basic-asn1.c 30 33 obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o 34 + clean-files := nf_nat_snmp_basic-asn1.c nf_nat_snmp_basic-asn1.h 35 + 31 36 obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o 37 + 32 38 33 39 # NAT protocols (nf_nat) 34 40 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
-1
net/ipv4/netfilter/arp_tables.c
··· 1656 1656 if (ret < 0) 1657 1657 goto err4; 1658 1658 1659 - pr_info("arp_tables: (C) 2002 David S. Miller\n"); 1660 1659 return 0; 1661 1660 1662 1661 err4:
-1
net/ipv4/netfilter/ip_tables.c
··· 1939 1939 if (ret < 0) 1940 1940 goto err5; 1941 1941 1942 - pr_info("(C) 2000-2006 Netfilter Core Team\n"); 1943 1942 return 0; 1944 1943 1945 1944 err5:
+28 -3
net/ipv4/netfilter/iptable_raw.c
··· 3 3 * 4 4 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 5 5 */ 6 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 6 7 #include <linux/module.h> 7 8 #include <linux/netfilter_ipv4/ip_tables.h> 8 9 #include <linux/slab.h> ··· 13 12 14 13 static int __net_init iptable_raw_table_init(struct net *net); 15 14 15 + static bool raw_before_defrag __read_mostly; 16 + MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag"); 17 + module_param(raw_before_defrag, bool, 0000); 18 + 16 19 static const struct xt_table packet_raw = { 17 20 .name = "raw", 18 21 .valid_hooks = RAW_VALID_HOOKS, 19 22 .me = THIS_MODULE, 20 23 .af = NFPROTO_IPV4, 21 24 .priority = NF_IP_PRI_RAW, 25 + .table_init = iptable_raw_table_init, 26 + }; 27 + 28 + static const struct xt_table packet_raw_before_defrag = { 29 + .name = "raw", 30 + .valid_hooks = RAW_VALID_HOOKS, 31 + .me = THIS_MODULE, 32 + .af = NFPROTO_IPV4, 33 + .priority = NF_IP_PRI_RAW_BEFORE_DEFRAG, 22 34 .table_init = iptable_raw_table_init, 23 35 }; 24 36 ··· 48 34 static int __net_init iptable_raw_table_init(struct net *net) 49 35 { 50 36 struct ipt_replace *repl; 37 + const struct xt_table *table = &packet_raw; 51 38 int ret; 39 + 40 + if (raw_before_defrag) 41 + table = &packet_raw_before_defrag; 52 42 53 43 if (net->ipv4.iptable_raw) 54 44 return 0; 55 45 56 - repl = ipt_alloc_initial_table(&packet_raw); 46 + repl = ipt_alloc_initial_table(table); 57 47 if (repl == NULL) 58 48 return -ENOMEM; 59 - ret = ipt_register_table(net, &packet_raw, repl, rawtable_ops, 49 + ret = ipt_register_table(net, table, repl, rawtable_ops, 60 50 &net->ipv4.iptable_raw); 61 51 kfree(repl); 62 52 return ret; ··· 81 63 static int __init iptable_raw_init(void) 82 64 { 83 65 int ret; 66 + const struct xt_table *table = &packet_raw; 84 67 85 - rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook); 68 + if (raw_before_defrag) { 69 + table = &packet_raw_before_defrag; 70 + 71 + pr_info("Enabling raw table before defrag\n"); 72 + } 73 + 74 + rawtable_ops = xt_hook_ops_alloc(table, iptable_raw_hook); 86 75 if (IS_ERR(rawtable_ops)) 87 76 return PTR_ERR(rawtable_ops); 88 77
+2
net/ipv4/netfilter/nf_defrag_ipv4.c
··· 78 78 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb))) 79 79 return NF_ACCEPT; 80 80 #endif 81 + if (skb->_nfct == IP_CT_UNTRACKED) 82 + return NF_ACCEPT; 81 83 #endif 82 84 /* Gather fragments. */ 83 85 if (ip_is_fragment(ip_hdr(skb))) {
+177
net/ipv4/netfilter/nf_nat_snmp_basic.asn1
··· 1 + Message ::= 2 + SEQUENCE { 3 + version 4 + INTEGER ({snmp_version}), 5 + 6 + community 7 + OCTET STRING, 8 + 9 + pdu 10 + PDUs 11 + } 12 + 13 + 14 + ObjectName ::= 15 + OBJECT IDENTIFIER 16 + 17 + ObjectSyntax ::= 18 + CHOICE { 19 + simple 20 + SimpleSyntax, 21 + 22 + application-wide 23 + ApplicationSyntax 24 + } 25 + 26 + SimpleSyntax ::= 27 + CHOICE { 28 + integer-value 29 + INTEGER, 30 + 31 + string-value 32 + OCTET STRING, 33 + 34 + objectID-value 35 + OBJECT IDENTIFIER 36 + } 37 + 38 + ApplicationSyntax ::= 39 + CHOICE { 40 + ipAddress-value 41 + IpAddress, 42 + 43 + counter-value 44 + Counter32, 45 + 46 + timeticks-value 47 + TimeTicks, 48 + 49 + arbitrary-value 50 + Opaque, 51 + 52 + big-counter-value 53 + Counter64, 54 + 55 + unsigned-integer-value 56 + Unsigned32 57 + } 58 + 59 + IpAddress ::= 60 + [APPLICATION 0] 61 + IMPLICIT OCTET STRING OPTIONAL ({snmp_helper}) 62 + 63 + Counter32 ::= 64 + [APPLICATION 1] 65 + IMPLICIT INTEGER OPTIONAL 66 + 67 + Unsigned32 ::= 68 + [APPLICATION 2] 69 + IMPLICIT INTEGER OPTIONAL 70 + 71 + Gauge32 ::= Unsigned32 OPTIONAL 72 + 73 + TimeTicks ::= 74 + [APPLICATION 3] 75 + IMPLICIT INTEGER OPTIONAL 76 + 77 + Opaque ::= 78 + [APPLICATION 4] 79 + IMPLICIT OCTET STRING OPTIONAL 80 + 81 + Counter64 ::= 82 + [APPLICATION 6] 83 + IMPLICIT INTEGER OPTIONAL 84 + 85 + PDUs ::= 86 + CHOICE { 87 + get-request 88 + GetRequest-PDU, 89 + 90 + get-next-request 91 + GetNextRequest-PDU, 92 + 93 + get-bulk-request 94 + GetBulkRequest-PDU, 95 + 96 + response 97 + Response-PDU, 98 + 99 + set-request 100 + SetRequest-PDU, 101 + 102 + inform-request 103 + InformRequest-PDU, 104 + 105 + snmpV2-trap 106 + SNMPv2-Trap-PDU, 107 + 108 + report 109 + Report-PDU 110 + } 111 + 112 + GetRequest-PDU ::= 113 + [0] IMPLICIT PDU OPTIONAL 114 + 115 + GetNextRequest-PDU ::= 116 + [1] IMPLICIT PDU OPTIONAL 117 + 118 + Response-PDU ::= 119 + [2] IMPLICIT PDU OPTIONAL 120 + 121 + SetRequest-PDU ::= 122 + [3] IMPLICIT PDU OPTIONAL 123 + 124 + -- [4] is obsolete 125 + 126 + GetBulkRequest-PDU ::= 127 + [5] IMPLICIT PDU OPTIONAL 128 + 129 + InformRequest-PDU ::= 130 + [6] IMPLICIT PDU OPTIONAL 131 + 132 + SNMPv2-Trap-PDU ::= 133 + [7] IMPLICIT PDU OPTIONAL 134 + 135 + Report-PDU ::= 136 + [8] IMPLICIT PDU OPTIONAL 137 + 138 + PDU ::= 139 + SEQUENCE { 140 + request-id 141 + INTEGER, 142 + 143 + error-status 144 + INTEGER, 145 + 146 + error-index 147 + INTEGER, 148 + 149 + variable-bindings 150 + VarBindList 151 + } 152 + 153 + 154 + VarBind ::= 155 + SEQUENCE { 156 + name 157 + ObjectName, 158 + 159 + CHOICE { 160 + value 161 + ObjectSyntax, 162 + 163 + unSpecified 164 + NULL, 165 + 166 + noSuchObject 167 + [0] IMPLICIT NULL, 168 + 169 + noSuchInstance 170 + [1] IMPLICIT NULL, 171 + 172 + endOfMibView 173 + [2] IMPLICIT NULL 174 + } 175 + } 176 + 177 + VarBindList ::= SEQUENCE OF VarBind
-1286
net/ipv4/netfilter/nf_nat_snmp_basic.c
··· 1 - /* 2 - * nf_nat_snmp_basic.c 3 - * 4 - * Basic SNMP Application Layer Gateway 5 - * 6 - * This IP NAT module is intended for use with SNMP network 7 - * discovery and monitoring applications where target networks use 8 - * conflicting private address realms. 9 - * 10 - * Static NAT is used to remap the networks from the view of the network 11 - * management system at the IP layer, and this module remaps some application 12 - * layer addresses to match. 13 - * 14 - * The simplest form of ALG is performed, where only tagged IP addresses 15 - * are modified. The module does not need to be MIB aware and only scans 16 - * messages at the ASN.1/BER level. 17 - * 18 - * Currently, only SNMPv1 and SNMPv2 are supported. 19 - * 20 - * More information on ALG and associated issues can be found in 21 - * RFC 2962 22 - * 23 - * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory 24 - * McLean & Jochen Friedrich, stripped down for use in the kernel. 25 - * 26 - * Copyright (c) 2000 RP Internet (www.rpi.net.au). 27 - * 28 - * This program is free software; you can redistribute it and/or modify 29 - * it under the terms of the GNU General Public License as published by 30 - * the Free Software Foundation; either version 2 of the License, or 31 - * (at your option) any later version. 32 - * This program is distributed in the hope that it will be useful, 33 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 34 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 35 - * GNU General Public License for more details. 36 - * You should have received a copy of the GNU General Public License 37 - * along with this program; if not, see <http://www.gnu.org/licenses/>. 38 - * 39 - * Author: James Morris <jmorris@intercode.com.au> 40 - * 41 - * Copyright (c) 2006-2010 Patrick McHardy <kaber@trash.net> 42 - */ 43 - #include <linux/module.h> 44 - #include <linux/moduleparam.h> 45 - #include <linux/types.h> 46 - #include <linux/kernel.h> 47 - #include <linux/slab.h> 48 - #include <linux/in.h> 49 - #include <linux/ip.h> 50 - #include <linux/udp.h> 51 - #include <net/checksum.h> 52 - #include <net/udp.h> 53 - 54 - #include <net/netfilter/nf_nat.h> 55 - #include <net/netfilter/nf_conntrack_expect.h> 56 - #include <net/netfilter/nf_conntrack_helper.h> 57 - #include <net/netfilter/nf_nat_helper.h> 58 - #include <linux/netfilter/nf_conntrack_snmp.h> 59 - 60 - MODULE_LICENSE("GPL"); 61 - MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); 62 - MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway"); 63 - MODULE_ALIAS("ip_nat_snmp_basic"); 64 - 65 - #define SNMP_PORT 161 66 - #define SNMP_TRAP_PORT 162 67 - #define NOCT1(n) (*(u8 *)(n)) 68 - 69 - static int debug; 70 - static DEFINE_SPINLOCK(snmp_lock); 71 - 72 - /* 73 - * Application layer address mapping mimics the NAT mapping, but 74 - * only for the first octet in this case (a more flexible system 75 - * can be implemented if needed). 76 - */ 77 - struct oct1_map 78 - { 79 - u_int8_t from; 80 - u_int8_t to; 81 - }; 82 - 83 - 84 - /***************************************************************************** 85 - * 86 - * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse) 87 - * 88 - *****************************************************************************/ 89 - 90 - /* Class */ 91 - #define ASN1_UNI 0 /* Universal */ 92 - #define ASN1_APL 1 /* Application */ 93 - #define ASN1_CTX 2 /* Context */ 94 - #define ASN1_PRV 3 /* Private */ 95 - 96 - /* Tag */ 97 - #define ASN1_EOC 0 /* End Of Contents */ 98 - #define ASN1_BOL 1 /* Boolean */ 99 - #define ASN1_INT 2 /* Integer */ 100 - #define ASN1_BTS 3 /* Bit String */ 101 - #define ASN1_OTS 4 /* Octet String */ 102 - #define ASN1_NUL 5 /* Null */ 103 - #define ASN1_OJI 6 /* Object Identifier */ 104 - #define ASN1_OJD 7 /* Object Description */ 105 - #define ASN1_EXT 8 /* External */ 106 - #define ASN1_SEQ 16 /* Sequence */ 107 - #define ASN1_SET 17 /* Set */ 108 - #define ASN1_NUMSTR 18 /* Numerical String */ 109 - #define ASN1_PRNSTR 19 /* Printable String */ 110 - #define ASN1_TEXSTR 20 /* Teletext String */ 111 - #define ASN1_VIDSTR 21 /* Video String */ 112 - #define ASN1_IA5STR 22 /* IA5 String */ 113 - #define ASN1_UNITIM 23 /* Universal Time */ 114 - #define ASN1_GENTIM 24 /* General Time */ 115 - #define ASN1_GRASTR 25 /* Graphical String */ 116 - #define ASN1_VISSTR 26 /* Visible String */ 117 - #define ASN1_GENSTR 27 /* General String */ 118 - 119 - /* Primitive / Constructed methods*/ 120 - #define ASN1_PRI 0 /* Primitive */ 121 - #define ASN1_CON 1 /* Constructed */ 122 - 123 - /* 124 - * Error codes. 125 - */ 126 - #define ASN1_ERR_NOERROR 0 127 - #define ASN1_ERR_DEC_EMPTY 2 128 - #define ASN1_ERR_DEC_EOC_MISMATCH 3 129 - #define ASN1_ERR_DEC_LENGTH_MISMATCH 4 130 - #define ASN1_ERR_DEC_BADVALUE 5 131 - 132 - /* 133 - * ASN.1 context. 134 - */ 135 - struct asn1_ctx 136 - { 137 - int error; /* Error condition */ 138 - unsigned char *pointer; /* Octet just to be decoded */ 139 - unsigned char *begin; /* First octet */ 140 - unsigned char *end; /* Octet after last octet */ 141 - }; 142 - 143 - /* 144 - * Octet string (not null terminated) 145 - */ 146 - struct asn1_octstr 147 - { 148 - unsigned char *data; 149 - unsigned int len; 150 - }; 151 - 152 - static void asn1_open(struct asn1_ctx *ctx, 153 - unsigned char *buf, 154 - unsigned int len) 155 - { 156 - ctx->begin = buf; 157 - ctx->end = buf + len; 158 - ctx->pointer = buf; 159 - ctx->error = ASN1_ERR_NOERROR; 160 - } 161 - 162 - static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) 163 - { 164 - if (ctx->pointer >= ctx->end) { 165 - ctx->error = ASN1_ERR_DEC_EMPTY; 166 - return 0; 167 - } 168 - *ch = *(ctx->pointer)++; 169 - return 1; 170 - } 171 - 172 - static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) 173 - { 174 - unsigned char ch; 175 - 176 - *tag = 0; 177 - 178 - do 179 - { 180 - if (!asn1_octet_decode(ctx, &ch)) 181 - return 0; 182 - *tag <<= 7; 183 - *tag |= ch & 0x7F; 184 - } while ((ch & 0x80) == 0x80); 185 - return 1; 186 - } 187 - 188 - static unsigned char asn1_id_decode(struct asn1_ctx *ctx, 189 - unsigned int *cls, 190 - unsigned int *con, 191 - unsigned int *tag) 192 - { 193 - unsigned char ch; 194 - 195 - if (!asn1_octet_decode(ctx, &ch)) 196 - return 0; 197 - 198 - *cls = (ch & 0xC0) >> 6; 199 - *con = (ch & 0x20) >> 5; 200 - *tag = (ch & 0x1F); 201 - 202 - if (*tag == 0x1F) { 203 - if (!asn1_tag_decode(ctx, tag)) 204 - return 0; 205 - } 206 - return 1; 207 - } 208 - 209 - static unsigned char asn1_length_decode(struct asn1_ctx *ctx, 210 - unsigned int *def, 211 - unsigned int *len) 212 - { 213 - unsigned char ch, cnt; 214 - 215 - if (!asn1_octet_decode(ctx, &ch)) 216 - return 0; 217 - 218 - if (ch == 0x80) 219 - *def = 0; 220 - else { 221 - *def = 1; 222 - 223 - if (ch < 0x80) 224 - *len = ch; 225 - else { 226 - cnt = ch & 0x7F; 227 - *len = 0; 228 - 229 - while (cnt > 0) { 230 - if (!asn1_octet_decode(ctx, &ch)) 231 - return 0; 232 - *len <<= 8; 233 - *len |= ch; 234 - cnt--; 235 - } 236 - } 237 - } 238 - 239 - /* don't trust len bigger than ctx buffer */ 240 - if (*len > ctx->end - ctx->pointer) 241 - return 0; 242 - 243 - return 1; 244 - } 245 - 246 - static unsigned char asn1_header_decode(struct asn1_ctx *ctx, 247 - unsigned char **eoc, 248 - unsigned int *cls, 249 - unsigned int *con, 250 - unsigned int *tag) 251 - { 252 - unsigned int def, len; 253 - 254 - if (!asn1_id_decode(ctx, cls, con, tag)) 255 - return 0; 256 - 257 - def = len = 0; 258 - if (!asn1_length_decode(ctx, &def, &len)) 259 - return 0; 260 - 261 - /* primitive shall be definite, indefinite shall be constructed */ 262 - if (*con == ASN1_PRI && !def) 263 - return 0; 264 - 265 - if (def) 266 - *eoc = ctx->pointer + len; 267 - else 268 - *eoc = NULL; 269 - return 1; 270 - } 271 - 272 - static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc) 273 - { 274 - unsigned char ch; 275 - 276 - if (eoc == NULL) { 277 - if (!asn1_octet_decode(ctx, &ch)) 278 - return 0; 279 - 280 - if (ch != 0x00) { 281 - ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; 282 - return 0; 283 - } 284 - 285 - if (!asn1_octet_decode(ctx, &ch)) 286 - return 0; 287 - 288 - if (ch != 0x00) { 289 - ctx->error = ASN1_ERR_DEC_EOC_MISMATCH; 290 - return 0; 291 - } 292 - return 1; 293 - } else { 294 - if (ctx->pointer != eoc) { 295 - ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH; 296 - return 0; 297 - } 298 - return 1; 299 - } 300 - } 301 - 302 - static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc) 303 - { 304 - ctx->pointer = eoc; 305 - return 1; 306 - } 307 - 308 - static unsigned char asn1_long_decode(struct asn1_ctx *ctx, 309 - unsigned char *eoc, 310 - long *integer) 311 - { 312 - unsigned char ch; 313 - unsigned int len; 314 - 315 - if (!asn1_octet_decode(ctx, &ch)) 316 - return 0; 317 - 318 - *integer = (signed char) ch; 319 - len = 1; 320 - 321 - while (ctx->pointer < eoc) { 322 - if (++len > sizeof (long)) { 323 - ctx->error = ASN1_ERR_DEC_BADVALUE; 324 - return 0; 325 - } 326 - 327 - if (!asn1_octet_decode(ctx, &ch)) 328 - return 0; 329 - 330 - *integer <<= 8; 331 - *integer |= ch; 332 - } 333 - return 1; 334 - } 335 - 336 - static unsigned char asn1_uint_decode(struct asn1_ctx *ctx, 337 - unsigned char *eoc, 338 - unsigned int *integer) 339 - { 340 - unsigned char ch; 341 - unsigned int len; 342 - 343 - if (!asn1_octet_decode(ctx, &ch)) 344 - return 0; 345 - 346 - *integer = ch; 347 - if (ch == 0) len = 0; 348 - else len = 1; 349 - 350 - while (ctx->pointer < eoc) { 351 - if (++len > sizeof (unsigned int)) { 352 - ctx->error = ASN1_ERR_DEC_BADVALUE; 353 - return 0; 354 - } 355 - 356 - if (!asn1_octet_decode(ctx, &ch)) 357 - return 0; 358 - 359 - *integer <<= 8; 360 - *integer |= ch; 361 - } 362 - return 1; 363 - } 364 - 365 - static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx, 366 - unsigned char *eoc, 367 - unsigned long *integer) 368 - { 369 - unsigned char ch; 370 - unsigned int len; 371 - 372 - if (!asn1_octet_decode(ctx, &ch)) 373 - return 0; 374 - 375 - *integer = ch; 376 - if (ch == 0) len = 0; 377 - else len = 1; 378 - 379 - while (ctx->pointer < eoc) { 380 - if (++len > sizeof (unsigned long)) { 381 - ctx->error = ASN1_ERR_DEC_BADVALUE; 382 - return 0; 383 - } 384 - 385 - if (!asn1_octet_decode(ctx, &ch)) 386 - return 0; 387 - 388 - *integer <<= 8; 389 - *integer |= ch; 390 - } 391 - return 1; 392 - } 393 - 394 - static unsigned char asn1_octets_decode(struct asn1_ctx *ctx, 395 - unsigned char *eoc, 396 - unsigned char **octets, 397 - unsigned int *len) 398 - { 399 - unsigned char *ptr; 400 - 401 - *len = 0; 402 - 403 - *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC); 404 - if (*octets == NULL) 405 - return 0; 406 - 407 - ptr = *octets; 408 - while (ctx->pointer < eoc) { 409 - if (!asn1_octet_decode(ctx, ptr++)) { 410 - kfree(*octets); 411 - *octets = NULL; 412 - return 0; 413 - } 414 - (*len)++; 415 - } 416 - return 1; 417 - } 418 - 419 - static unsigned char asn1_subid_decode(struct asn1_ctx *ctx, 420 - unsigned long *subid) 421 - { 422 - unsigned char ch; 423 - 424 - *subid = 0; 425 - 426 - do { 427 - if (!asn1_octet_decode(ctx, &ch)) 428 - return 0; 429 - 430 - *subid <<= 7; 431 - *subid |= ch & 0x7F; 432 - } while ((ch & 0x80) == 0x80); 433 - return 1; 434 - } 435 - 436 - static unsigned char asn1_oid_decode(struct asn1_ctx *ctx, 437 - unsigned char *eoc, 438 - unsigned long **oid, 439 - unsigned int *len) 440 - { 441 - unsigned long subid; 442 - unsigned long *optr; 443 - size_t size; 444 - 445 - size = eoc - ctx->pointer + 1; 446 - 447 - /* first subid actually encodes first two subids */ 448 - if (size < 2 || size > ULONG_MAX/sizeof(unsigned long)) 449 - return 0; 450 - 451 - *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); 452 - if (*oid == NULL) 453 - return 0; 454 - 455 - optr = *oid; 456 - 457 - if (!asn1_subid_decode(ctx, &subid)) { 458 - kfree(*oid); 459 - *oid = NULL; 460 - return 0; 461 - } 462 - 463 - if (subid < 40) { 464 - optr[0] = 0; 465 - optr[1] = subid; 466 - } else if (subid < 80) { 467 - optr[0] = 1; 468 - optr[1] = subid - 40; 469 - } else { 470 - optr[0] = 2; 471 - optr[1] = subid - 80; 472 - } 473 - 474 - *len = 2; 475 - optr += 2; 476 - 477 - while (ctx->pointer < eoc) { 478 - if (++(*len) > size) { 479 - ctx->error = ASN1_ERR_DEC_BADVALUE; 480 - kfree(*oid); 481 - *oid = NULL; 482 - return 0; 483 - } 484 - 485 - if (!asn1_subid_decode(ctx, optr++)) { 486 - kfree(*oid); 487 - *oid = NULL; 488 - return 0; 489 - } 490 - } 491 - return 1; 492 - } 493 - 494 - /***************************************************************************** 495 - * 496 - * SNMP decoding routines (gxsnmp author Dirk Wisse) 497 - * 498 - *****************************************************************************/ 499 - 500 - /* SNMP Versions */ 501 - #define SNMP_V1 0 502 - #define SNMP_V2C 1 503 - #define SNMP_V2 2 504 - #define SNMP_V3 3 505 - 506 - /* Default Sizes */ 507 - #define SNMP_SIZE_COMM 256 508 - #define SNMP_SIZE_OBJECTID 128 509 - #define SNMP_SIZE_BUFCHR 256 510 - #define SNMP_SIZE_BUFINT 128 511 - #define SNMP_SIZE_SMALLOBJECTID 16 512 - 513 - /* Requests */ 514 - #define SNMP_PDU_GET 0 515 - #define SNMP_PDU_NEXT 1 516 - #define SNMP_PDU_RESPONSE 2 517 - #define SNMP_PDU_SET 3 518 - #define SNMP_PDU_TRAP1 4 519 - #define SNMP_PDU_BULK 5 520 - #define SNMP_PDU_INFORM 6 521 - #define SNMP_PDU_TRAP2 7 522 - 523 - /* Errors */ 524 - #define SNMP_NOERROR 0 525 - #define SNMP_TOOBIG 1 526 - #define SNMP_NOSUCHNAME 2 527 - #define SNMP_BADVALUE 3 528 - #define SNMP_READONLY 4 529 - #define SNMP_GENERROR 5 530 - #define SNMP_NOACCESS 6 531 - #define SNMP_WRONGTYPE 7 532 - #define SNMP_WRONGLENGTH 8 533 - #define SNMP_WRONGENCODING 9 534 - #define SNMP_WRONGVALUE 10 535 - #define SNMP_NOCREATION 11 536 - #define SNMP_INCONSISTENTVALUE 12 537 - #define SNMP_RESOURCEUNAVAILABLE 13 538 - #define SNMP_COMMITFAILED 14 539 - #define SNMP_UNDOFAILED 15 540 - #define SNMP_AUTHORIZATIONERROR 16 541 - #define SNMP_NOTWRITABLE 17 542 - #define SNMP_INCONSISTENTNAME 18 543 - 544 - /* General SNMP V1 Traps */ 545 - #define SNMP_TRAP_COLDSTART 0 546 - #define SNMP_TRAP_WARMSTART 1 547 - #define SNMP_TRAP_LINKDOWN 2 548 - #define SNMP_TRAP_LINKUP 3 549 - #define SNMP_TRAP_AUTFAILURE 4 550 - #define SNMP_TRAP_EQPNEIGHBORLOSS 5 551 - #define SNMP_TRAP_ENTSPECIFIC 6 552 - 553 - /* SNMPv1 Types */ 554 - #define SNMP_NULL 0 555 - #define SNMP_INTEGER 1 /* l */ 556 - #define SNMP_OCTETSTR 2 /* c */ 557 - #define SNMP_DISPLAYSTR 2 /* c */ 558 - #define SNMP_OBJECTID 3 /* ul */ 559 - #define SNMP_IPADDR 4 /* uc */ 560 - #define SNMP_COUNTER 5 /* ul */ 561 - #define SNMP_GAUGE 6 /* ul */ 562 - #define SNMP_TIMETICKS 7 /* ul */ 563 - #define SNMP_OPAQUE 8 /* c */ 564 - 565 - /* Additional SNMPv2 Types */ 566 - #define SNMP_UINTEGER 5 /* ul */ 567 - #define SNMP_BITSTR 9 /* uc */ 568 - #define SNMP_NSAP 10 /* uc */ 569 - #define SNMP_COUNTER64 11 /* ul */ 570 - #define SNMP_NOSUCHOBJECT 12 571 - #define SNMP_NOSUCHINSTANCE 13 572 - #define SNMP_ENDOFMIBVIEW 14 573 - 574 - union snmp_syntax 575 - { 576 - unsigned char uc[0]; /* 8 bit unsigned */ 577 - char c[0]; /* 8 bit signed */ 578 - unsigned long ul[0]; /* 32 bit unsigned */ 579 - long l[0]; /* 32 bit signed */ 580 - }; 581 - 582 - struct snmp_object 583 - { 584 - unsigned long *id; 585 - unsigned int id_len; 586 - unsigned short type; 587 - unsigned int syntax_len; 588 - union snmp_syntax syntax; 589 - }; 590 - 591 - struct snmp_request 592 - { 593 - unsigned long id; 594 - unsigned int error_status; 595 - unsigned int error_index; 596 - }; 597 - 598 - struct snmp_v1_trap 599 - { 600 - unsigned long *id; 601 - unsigned int id_len; 602 - unsigned long ip_address; /* pointer */ 603 - unsigned int general; 604 - unsigned int specific; 605 - unsigned long time; 606 - }; 607 - 608 - /* SNMP types */ 609 - #define SNMP_IPA 0 610 - #define SNMP_CNT 1 611 - #define SNMP_GGE 2 612 - #define SNMP_TIT 3 613 - #define SNMP_OPQ 4 614 - #define SNMP_C64 6 615 - 616 - /* SNMP errors */ 617 - #define SERR_NSO 0 618 - #define SERR_NSI 1 619 - #define SERR_EOM 2 620 - 621 - static inline void mangle_address(unsigned char *begin, 622 - unsigned char *addr, 623 - const struct oct1_map *map, 624 - __sum16 *check); 625 - struct snmp_cnv 626 - { 627 - unsigned int class; 628 - unsigned int tag; 629 - int syntax; 630 - }; 631 - 632 - static const struct snmp_cnv snmp_conv[] = { 633 - {ASN1_UNI, ASN1_NUL, SNMP_NULL}, 634 - {ASN1_UNI, ASN1_INT, SNMP_INTEGER}, 635 - {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR}, 636 - {ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR}, 637 - {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID}, 638 - {ASN1_APL, SNMP_IPA, SNMP_IPADDR}, 639 - {ASN1_APL, SNMP_CNT, SNMP_COUNTER}, /* Counter32 */ 640 - {ASN1_APL, SNMP_GGE, SNMP_GAUGE}, /* Gauge32 == Unsigned32 */ 641 - {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS}, 642 - {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE}, 643 - 644 - /* SNMPv2 data types and errors */ 645 - {ASN1_UNI, ASN1_BTS, SNMP_BITSTR}, 646 - {ASN1_APL, SNMP_C64, SNMP_COUNTER64}, 647 - {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT}, 648 - {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE}, 649 - {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW}, 650 - {0, 0, -1} 651 - }; 652 - 653 - static unsigned char snmp_tag_cls2syntax(unsigned int tag, 654 - unsigned int cls, 655 - unsigned short *syntax) 656 - { 657 - const struct snmp_cnv *cnv; 658 - 659 - cnv = snmp_conv; 660 - 661 - while (cnv->syntax != -1) { 662 - if (cnv->tag == tag && cnv->class == cls) { 663 - *syntax = cnv->syntax; 664 - return 1; 665 - } 666 - cnv++; 667 - } 668 - return 0; 669 - } 670 - 671 - static unsigned char snmp_object_decode(struct asn1_ctx *ctx, 672 - struct snmp_object **obj) 673 - { 674 - unsigned int cls, con, tag, len, idlen; 675 - unsigned short type; 676 - unsigned char *eoc, *end, *p; 677 - unsigned long *lp, *id; 678 - unsigned long ul; 679 - long l; 680 - 681 - *obj = NULL; 682 - id = NULL; 683 - 684 - if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag)) 685 - return 0; 686 - 687 - if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) 688 - return 0; 689 - 690 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 691 - return 0; 692 - 693 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) 694 - return 0; 695 - 696 - if (!asn1_oid_decode(ctx, end, &id, &idlen)) 697 - return 0; 698 - 699 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) { 700 - kfree(id); 701 - return 0; 702 - } 703 - 704 - if (con != ASN1_PRI) { 705 - kfree(id); 706 - return 0; 707 - } 708 - 709 - type = 0; 710 - if (!snmp_tag_cls2syntax(tag, cls, &type)) { 711 - kfree(id); 712 - return 0; 713 - } 714 - 715 - l = 0; 716 - switch (type) { 717 - case SNMP_INTEGER: 718 - len = sizeof(long); 719 - if (!asn1_long_decode(ctx, end, &l)) { 720 - kfree(id); 721 - return 0; 722 - } 723 - *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); 724 - if (*obj == NULL) { 725 - kfree(id); 726 - return 0; 727 - } 728 - (*obj)->syntax.l[0] = l; 729 - break; 730 - case SNMP_OCTETSTR: 731 - case SNMP_OPAQUE: 732 - if (!asn1_octets_decode(ctx, end, &p, &len)) { 733 - kfree(id); 734 - return 0; 735 - } 736 - *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); 737 - if (*obj == NULL) { 738 - kfree(p); 739 - kfree(id); 740 - return 0; 741 - } 742 - memcpy((*obj)->syntax.c, p, len); 743 - kfree(p); 744 - break; 745 - case SNMP_NULL: 746 - case SNMP_NOSUCHOBJECT: 747 - case SNMP_NOSUCHINSTANCE: 748 - case SNMP_ENDOFMIBVIEW: 749 - len = 0; 750 - *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC); 751 - if (*obj == NULL) { 752 - kfree(id); 753 - return 0; 754 - } 755 - if (!asn1_null_decode(ctx, end)) { 756 - kfree(id); 757 - kfree(*obj); 758 - *obj = NULL; 759 - return 0; 760 - } 761 - break; 762 - case SNMP_OBJECTID: 763 - if (!asn1_oid_decode(ctx, end, &lp, &len)) { 764 - kfree(id); 765 - return 0; 766 - } 767 - len *= sizeof(unsigned long); 768 - *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); 769 - if (*obj == NULL) { 770 - kfree(lp); 771 - kfree(id); 772 - return 0; 773 - } 774 - memcpy((*obj)->syntax.ul, lp, len); 775 - kfree(lp); 776 - break; 777 - case SNMP_IPADDR: 778 - if (!asn1_octets_decode(ctx, end, &p, &len)) { 779 - kfree(id); 780 - return 0; 781 - } 782 - if (len != 4) { 783 - kfree(p); 784 - kfree(id); 785 - return 0; 786 - } 787 - *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); 788 - if (*obj == NULL) { 789 - kfree(p); 790 - kfree(id); 791 - return 0; 792 - } 793 - memcpy((*obj)->syntax.uc, p, len); 794 - kfree(p); 795 - break; 796 - case SNMP_COUNTER: 797 - case SNMP_GAUGE: 798 - case SNMP_TIMETICKS: 799 - len = sizeof(unsigned long); 800 - if (!asn1_ulong_decode(ctx, end, &ul)) { 801 - kfree(id); 802 - return 0; 803 - } 804 - *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); 805 - if (*obj == NULL) { 806 - kfree(id); 807 - return 0; 808 - } 809 - (*obj)->syntax.ul[0] = ul; 810 - break; 811 - default: 812 - kfree(id); 813 - return 0; 814 - } 815 - 816 - (*obj)->syntax_len = len; 817 - (*obj)->type = type; 818 - (*obj)->id = id; 819 - (*obj)->id_len = idlen; 820 - 821 - if (!asn1_eoc_decode(ctx, eoc)) { 822 - kfree(id); 823 - kfree(*obj); 824 - *obj = NULL; 825 - return 0; 826 - } 827 - return 1; 828 - } 829 - 830 - static unsigned char noinline_for_stack 831 - snmp_request_decode(struct asn1_ctx *ctx, struct snmp_request *request) 832 - { 833 - unsigned int cls, con, tag; 834 - unsigned char *end; 835 - 836 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 837 - return 0; 838 - 839 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) 840 - return 0; 841 - 842 - if (!asn1_ulong_decode(ctx, end, &request->id)) 843 - return 0; 844 - 845 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 846 - return 0; 847 - 848 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) 849 - return 0; 850 - 851 - if (!asn1_uint_decode(ctx, end, &request->error_status)) 852 - return 0; 853 - 854 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 855 - return 0; 856 - 857 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) 858 - return 0; 859 - 860 - if (!asn1_uint_decode(ctx, end, &request->error_index)) 861 - return 0; 862 - 863 - return 1; 864 - } 865 - 866 - /* 867 - * Fast checksum update for possibly oddly-aligned UDP byte, from the 868 - * code example in the draft. 869 - */ 870 - static void fast_csum(__sum16 *csum, 871 - const unsigned char *optr, 872 - const unsigned char *nptr, 873 - int offset) 874 - { 875 - unsigned char s[4]; 876 - 877 - if (offset & 1) { 878 - s[0] = ~0; 879 - s[1] = ~*optr; 880 - s[2] = 0; 881 - s[3] = *nptr; 882 - } else { 883 - s[0] = ~*optr; 884 - s[1] = ~0; 885 - s[2] = *nptr; 886 - s[3] = 0; 887 - } 888 - 889 - *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum))); 890 - } 891 - 892 - /* 893 - * Mangle IP address. 894 - * - begin points to the start of the snmp messgae 895 - * - addr points to the start of the address 896 - */ 897 - static inline void mangle_address(unsigned char *begin, 898 - unsigned char *addr, 899 - const struct oct1_map *map, 900 - __sum16 *check) 901 - { 902 - if (map->from == NOCT1(addr)) { 903 - u_int32_t old; 904 - 905 - if (debug) 906 - memcpy(&old, addr, sizeof(old)); 907 - 908 - *addr = map->to; 909 - 910 - /* Update UDP checksum if being used */ 911 - if (*check) { 912 - fast_csum(check, 913 - &map->from, &map->to, addr - begin); 914 - 915 - } 916 - 917 - if (debug) 918 - printk(KERN_DEBUG "bsalg: mapped %pI4 to %pI4\n", 919 - &old, addr); 920 - } 921 - } 922 - 923 - static unsigned char noinline_for_stack 924 - snmp_trap_decode(struct asn1_ctx *ctx, struct snmp_v1_trap *trap, 925 - const struct oct1_map *map, 926 - __sum16 *check) 927 - { 928 - unsigned int cls, con, tag, len; 929 - unsigned char *end; 930 - 931 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 932 - return 0; 933 - 934 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) 935 - return 0; 936 - 937 - if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len)) 938 - return 0; 939 - 940 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 941 - goto err_id_free; 942 - 943 - if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) || 944 - (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) 945 - goto err_id_free; 946 - 947 - if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len)) 948 - goto err_id_free; 949 - 950 - /* IPv4 only */ 951 - if (len != 4) 952 - goto err_addr_free; 953 - 954 - mangle_address(ctx->begin, ctx->pointer - 4, map, check); 955 - 956 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 957 - goto err_addr_free; 958 - 959 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) 960 - goto err_addr_free; 961 - 962 - if (!asn1_uint_decode(ctx, end, &trap->general)) 963 - goto err_addr_free; 964 - 965 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 966 - goto err_addr_free; 967 - 968 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) 969 - goto err_addr_free; 970 - 971 - if (!asn1_uint_decode(ctx, end, &trap->specific)) 972 - goto err_addr_free; 973 - 974 - if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) 975 - goto err_addr_free; 976 - 977 - if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) || 978 - (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) 979 - goto err_addr_free; 980 - 981 - if (!asn1_ulong_decode(ctx, end, &trap->time)) 982 - goto err_addr_free; 983 - 984 - return 1; 985 - 986 - err_addr_free: 987 - kfree((unsigned long *)trap->ip_address); 988 - 989 - err_id_free: 990 - kfree(trap->id); 991 - 992 - return 0; 993 - } 994 - 995 - /***************************************************************************** 996 - * 997 - * Misc. routines 998 - * 999 - *****************************************************************************/ 1000 - 1001 - /* 1002 - * Parse and mangle SNMP message according to mapping. 1003 - * (And this is the fucking 'basic' method). 1004 - */ 1005 - static int snmp_parse_mangle(unsigned char *msg, 1006 - u_int16_t len, 1007 - const struct oct1_map *map, 1008 - __sum16 *check) 1009 - { 1010 - unsigned char *eoc, *end; 1011 - unsigned int cls, con, tag, vers, pdutype; 1012 - struct asn1_ctx ctx; 1013 - struct asn1_octstr comm; 1014 - struct snmp_object *obj; 1015 - 1016 - if (debug > 1) 1017 - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 16, 1, 1018 - msg, len, 0); 1019 - 1020 - asn1_open(&ctx, msg, len); 1021 - 1022 - /* 1023 - * Start of SNMP message. 1024 - */ 1025 - if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag)) 1026 - return 0; 1027 - if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) 1028 - return 0; 1029 - 1030 - /* 1031 - * Version 1 or 2 handled. 1032 - */ 1033 - if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag)) 1034 - return 0; 1035 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) 1036 - return 0; 1037 - if (!asn1_uint_decode (&ctx, end, &vers)) 1038 - return 0; 1039 - if (debug > 1) 1040 - pr_debug("bsalg: snmp version: %u\n", vers + 1); 1041 - if (vers > 1) 1042 - return 1; 1043 - 1044 - /* 1045 - * Community. 1046 - */ 1047 - if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag)) 1048 - return 0; 1049 - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS) 1050 - return 0; 1051 - if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len)) 1052 - return 0; 1053 - if (debug > 1) { 1054 - unsigned int i; 1055 - 1056 - pr_debug("bsalg: community: "); 1057 - for (i = 0; i < comm.len; i++) 1058 - pr_cont("%c", comm.data[i]); 1059 - pr_cont("\n"); 1060 - } 1061 - kfree(comm.data); 1062 - 1063 - /* 1064 - * PDU type 1065 - */ 1066 - if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype)) 1067 - return 0; 1068 - if (cls != ASN1_CTX || con != ASN1_CON) 1069 - return 0; 1070 - if (debug > 1) { 1071 - static const unsigned char *const pdus[] = { 1072 - [SNMP_PDU_GET] = "get", 1073 - [SNMP_PDU_NEXT] = "get-next", 1074 - [SNMP_PDU_RESPONSE] = "response", 1075 - [SNMP_PDU_SET] = "set", 1076 - [SNMP_PDU_TRAP1] = "trapv1", 1077 - [SNMP_PDU_BULK] = "bulk", 1078 - [SNMP_PDU_INFORM] = "inform", 1079 - [SNMP_PDU_TRAP2] = "trapv2" 1080 - }; 1081 - 1082 - if (pdutype > SNMP_PDU_TRAP2) 1083 - pr_debug("bsalg: bad pdu type %u\n", pdutype); 1084 - else 1085 - pr_debug("bsalg: pdu: %s\n", pdus[pdutype]); 1086 - } 1087 - if (pdutype != SNMP_PDU_RESPONSE && 1088 - pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2) 1089 - return 1; 1090 - 1091 - /* 1092 - * Request header or v1 trap 1093 - */ 1094 - if (pdutype == SNMP_PDU_TRAP1) { 1095 - struct snmp_v1_trap trap; 1096 - unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check); 1097 - 1098 - if (ret) { 1099 - kfree(trap.id); 1100 - kfree((unsigned long *)trap.ip_address); 1101 - } else 1102 - return ret; 1103 - 1104 - } else { 1105 - struct snmp_request req; 1106 - 1107 - if (!snmp_request_decode(&ctx, &req)) 1108 - return 0; 1109 - 1110 - if (debug > 1) 1111 - pr_debug("bsalg: request: id=0x%lx error_status=%u " 1112 - "error_index=%u\n", req.id, req.error_status, 1113 - req.error_index); 1114 - } 1115 - 1116 - /* 1117 - * Loop through objects, look for IP addresses to mangle. 1118 - */ 1119 - if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag)) 1120 - return 0; 1121 - 1122 - if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) 1123 - return 0; 1124 - 1125 - while (!asn1_eoc_decode(&ctx, eoc)) { 1126 - unsigned int i; 1127 - 1128 - if (!snmp_object_decode(&ctx, &obj)) { 1129 - if (obj) { 1130 - kfree(obj->id); 1131 - kfree(obj); 1132 - } 1133 - return 0; 1134 - } 1135 - 1136 - if (debug > 1) { 1137 - pr_debug("bsalg: object: "); 1138 - for (i = 0; i < obj->id_len; i++) { 1139 - if (i > 0) 1140 - pr_cont("."); 1141 - pr_cont("%lu", obj->id[i]); 1142 - } 1143 - pr_cont(": type=%u\n", obj->type); 1144 - 1145 - } 1146 - 1147 - if (obj->type == SNMP_IPADDR) 1148 - mangle_address(ctx.begin, ctx.pointer - 4, map, check); 1149 - 1150 - kfree(obj->id); 1151 - kfree(obj); 1152 - } 1153 - 1154 - if (!asn1_eoc_decode(&ctx, eoc)) 1155 - return 0; 1156 - 1157 - return 1; 1158 - } 1159 - 1160 - /***************************************************************************** 1161 - * 1162 - * NAT routines. 1163 - * 1164 - *****************************************************************************/ 1165 - 1166 - /* 1167 - * SNMP translation routine. 1168 - */ 1169 - static int snmp_translate(struct nf_conn *ct, 1170 - enum ip_conntrack_info ctinfo, 1171 - struct sk_buff *skb) 1172 - { 1173 - struct iphdr *iph = ip_hdr(skb); 1174 - struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); 1175 - u_int16_t udplen = ntohs(udph->len); 1176 - u_int16_t paylen = udplen - sizeof(struct udphdr); 1177 - int dir = CTINFO2DIR(ctinfo); 1178 - struct oct1_map map; 1179 - 1180 - /* 1181 - * Determine mappping for application layer addresses based 1182 - * on NAT manipulations for the packet. 1183 - */ 1184 - if (dir == IP_CT_DIR_ORIGINAL) { 1185 - /* SNAT traps */ 1186 - map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip); 1187 - map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip); 1188 - } else { 1189 - /* DNAT replies */ 1190 - map.from = NOCT1(&ct->tuplehash[!dir].tuple.src.u3.ip); 1191 - map.to = NOCT1(&ct->tuplehash[dir].tuple.dst.u3.ip); 1192 - } 1193 - 1194 - if (map.from == map.to) 1195 - return NF_ACCEPT; 1196 - 1197 - if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr), 1198 - paylen, &map, &udph->check)) { 1199 - net_warn_ratelimited("bsalg: parser failed\n"); 1200 - return NF_DROP; 1201 - } 1202 - return NF_ACCEPT; 1203 - } 1204 - 1205 - /* We don't actually set up expectations, just adjust internal IP 1206 - * addresses if this is being NATted */ 1207 - static int help(struct sk_buff *skb, unsigned int protoff, 1208 - struct nf_conn *ct, 1209 - enum ip_conntrack_info ctinfo) 1210 - { 1211 - int dir = CTINFO2DIR(ctinfo); 1212 - unsigned int ret; 1213 - const struct iphdr *iph = ip_hdr(skb); 1214 - const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); 1215 - 1216 - /* SNMP replies and originating SNMP traps get mangled */ 1217 - if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY) 1218 - return NF_ACCEPT; 1219 - if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL) 1220 - return NF_ACCEPT; 1221 - 1222 - /* No NAT? */ 1223 - if (!(ct->status & IPS_NAT_MASK)) 1224 - return NF_ACCEPT; 1225 - 1226 - /* 1227 - * Make sure the packet length is ok. So far, we were only guaranteed 1228 - * to have a valid length IP header plus 8 bytes, which means we have 1229 - * enough room for a UDP header. Just verify the UDP length field so we 1230 - * can mess around with the payload. 1231 - */ 1232 - if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) { 1233 - net_warn_ratelimited("SNMP: dropping malformed packet src=%pI4 dst=%pI4\n", 1234 - &iph->saddr, &iph->daddr); 1235 - return NF_DROP; 1236 - } 1237 - 1238 - if (!skb_make_writable(skb, skb->len)) 1239 - return NF_DROP; 1240 - 1241 - spin_lock_bh(&snmp_lock); 1242 - ret = snmp_translate(ct, ctinfo, skb); 1243 - spin_unlock_bh(&snmp_lock); 1244 - return ret; 1245 - } 1246 - 1247 - static const struct nf_conntrack_expect_policy snmp_exp_policy = { 1248 - .max_expected = 0, 1249 - .timeout = 180, 1250 - }; 1251 - 1252 - static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { 1253 - .me = THIS_MODULE, 1254 - .help = help, 1255 - .expect_policy = &snmp_exp_policy, 1256 - .name = "snmp_trap", 1257 - .tuple.src.l3num = AF_INET, 1258 - .tuple.src.u.udp.port = cpu_to_be16(SNMP_TRAP_PORT), 1259 - .tuple.dst.protonum = IPPROTO_UDP, 1260 - }; 1261 - 1262 - /***************************************************************************** 1263 - * 1264 - * Module stuff. 1265 - * 1266 - *****************************************************************************/ 1267 - 1268 - static int __init nf_nat_snmp_basic_init(void) 1269 - { 1270 - BUG_ON(nf_nat_snmp_hook != NULL); 1271 - RCU_INIT_POINTER(nf_nat_snmp_hook, help); 1272 - 1273 - return nf_conntrack_helper_register(&snmp_trap_helper); 1274 - } 1275 - 1276 - static void __exit nf_nat_snmp_basic_fini(void) 1277 - { 1278 - RCU_INIT_POINTER(nf_nat_snmp_hook, NULL); 1279 - synchronize_rcu(); 1280 - nf_conntrack_helper_unregister(&snmp_trap_helper); 1281 - } 1282 - 1283 - module_init(nf_nat_snmp_basic_init); 1284 - module_exit(nf_nat_snmp_basic_fini); 1285 - 1286 - module_param(debug, int, 0600);
+235
net/ipv4/netfilter/nf_nat_snmp_basic_main.c
··· 1 + /* 2 + * nf_nat_snmp_basic.c 3 + * 4 + * Basic SNMP Application Layer Gateway 5 + * 6 + * This IP NAT module is intended for use with SNMP network 7 + * discovery and monitoring applications where target networks use 8 + * conflicting private address realms. 9 + * 10 + * Static NAT is used to remap the networks from the view of the network 11 + * management system at the IP layer, and this module remaps some application 12 + * layer addresses to match. 13 + * 14 + * The simplest form of ALG is performed, where only tagged IP addresses 15 + * are modified. The module does not need to be MIB aware and only scans 16 + * messages at the ASN.1/BER level. 17 + * 18 + * Currently, only SNMPv1 and SNMPv2 are supported. 19 + * 20 + * More information on ALG and associated issues can be found in 21 + * RFC 2962 22 + * 23 + * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory 24 + * McLean & Jochen Friedrich, stripped down for use in the kernel. 25 + * 26 + * Copyright (c) 2000 RP Internet (www.rpi.net.au). 27 + * 28 + * This program is free software; you can redistribute it and/or modify 29 + * it under the terms of the GNU General Public License as published by 30 + * the Free Software Foundation; either version 2 of the License, or 31 + * (at your option) any later version. 32 + * This program is distributed in the hope that it will be useful, 33 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 34 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 35 + * GNU General Public License for more details. 36 + * You should have received a copy of the GNU General Public License 37 + * along with this program; if not, see <http://www.gnu.org/licenses/>. 38 + * 39 + * Author: James Morris <jmorris@intercode.com.au> 40 + * 41 + * Copyright (c) 2006-2010 Patrick McHardy <kaber@trash.net> 42 + */ 43 + #include <linux/module.h> 44 + #include <linux/moduleparam.h> 45 + #include <linux/types.h> 46 + #include <linux/kernel.h> 47 + #include <linux/in.h> 48 + #include <linux/ip.h> 49 + #include <linux/udp.h> 50 + #include <net/checksum.h> 51 + #include <net/udp.h> 52 + 53 + #include <net/netfilter/nf_nat.h> 54 + #include <net/netfilter/nf_conntrack_expect.h> 55 + #include <net/netfilter/nf_conntrack_helper.h> 56 + #include <linux/netfilter/nf_conntrack_snmp.h> 57 + #include "nf_nat_snmp_basic-asn1.h" 58 + 59 + MODULE_LICENSE("GPL"); 60 + MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); 61 + MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway"); 62 + MODULE_ALIAS("ip_nat_snmp_basic"); 63 + 64 + #define SNMP_PORT 161 65 + #define SNMP_TRAP_PORT 162 66 + 67 + static DEFINE_SPINLOCK(snmp_lock); 68 + 69 + struct snmp_ctx { 70 + unsigned char *begin; 71 + __sum16 *check; 72 + __be32 from; 73 + __be32 to; 74 + }; 75 + 76 + static void fast_csum(struct snmp_ctx *ctx, unsigned char offset) 77 + { 78 + unsigned char s[12] = {0,}; 79 + int size; 80 + 81 + if (offset & 1) { 82 + memcpy(&s[1], &ctx->from, 4); 83 + memcpy(&s[7], &ctx->to, 4); 84 + s[0] = ~0; 85 + s[1] = ~s[1]; 86 + s[2] = ~s[2]; 87 + s[3] = ~s[3]; 88 + s[4] = ~s[4]; 89 + s[5] = ~0; 90 + size = 12; 91 + } else { 92 + memcpy(&s[0], &ctx->from, 4); 93 + memcpy(&s[4], &ctx->to, 4); 94 + s[0] = ~s[0]; 95 + s[1] = ~s[1]; 96 + s[2] = ~s[2]; 97 + s[3] = ~s[3]; 98 + size = 8; 99 + } 100 + *ctx->check = csum_fold(csum_partial(s, size, 101 + ~csum_unfold(*ctx->check))); 102 + } 103 + 104 + int snmp_version(void *context, size_t hdrlen, unsigned char tag, 105 + const void *data, size_t datalen) 106 + { 107 + if (*(unsigned char *)data > 1) 108 + return -ENOTSUPP; 109 + return 1; 110 + } 111 + 112 + int snmp_helper(void *context, size_t hdrlen, unsigned char tag, 113 + const void *data, size_t datalen) 114 + { 115 + struct snmp_ctx *ctx = (struct snmp_ctx *)context; 116 + __be32 *pdata = (__be32 *)data; 117 + 118 + if (*pdata == ctx->from) { 119 + pr_debug("%s: %pI4 to %pI4\n", __func__, 120 + (void *)&ctx->from, (void *)&ctx->to); 121 + 122 + if (*ctx->check) 123 + fast_csum(ctx, (unsigned char *)data - ctx->begin); 124 + *pdata = ctx->to; 125 + } 126 + 127 + return 1; 128 + } 129 + 130 + static int snmp_translate(struct nf_conn *ct, int dir, struct sk_buff *skb) 131 + { 132 + struct iphdr *iph = ip_hdr(skb); 133 + struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); 134 + u16 datalen = ntohs(udph->len) - sizeof(struct udphdr); 135 + char *data = (unsigned char *)udph + sizeof(struct udphdr); 136 + struct snmp_ctx ctx; 137 + int ret; 138 + 139 + if (dir == IP_CT_DIR_ORIGINAL) { 140 + ctx.from = ct->tuplehash[dir].tuple.src.u3.ip; 141 + ctx.to = ct->tuplehash[!dir].tuple.dst.u3.ip; 142 + } else { 143 + ctx.from = ct->tuplehash[!dir].tuple.src.u3.ip; 144 + ctx.to = ct->tuplehash[dir].tuple.dst.u3.ip; 145 + } 146 + 147 + if (ctx.from == ctx.to) 148 + return NF_ACCEPT; 149 + 150 + ctx.begin = (unsigned char *)udph + sizeof(struct udphdr); 151 + ctx.check = &udph->check; 152 + ret = asn1_ber_decoder(&nf_nat_snmp_basic_decoder, &ctx, data, datalen); 153 + if (ret < 0) { 154 + nf_ct_helper_log(skb, ct, "parser failed\n"); 155 + return NF_DROP; 156 + } 157 + 158 + return NF_ACCEPT; 159 + } 160 + 161 + /* We don't actually set up expectations, just adjust internal IP 162 + * addresses if this is being NATted 163 + */ 164 + static int help(struct sk_buff *skb, unsigned int protoff, 165 + struct nf_conn *ct, 166 + enum ip_conntrack_info ctinfo) 167 + { 168 + int dir = CTINFO2DIR(ctinfo); 169 + unsigned int ret; 170 + const struct iphdr *iph = ip_hdr(skb); 171 + const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl); 172 + 173 + /* SNMP replies and originating SNMP traps get mangled */ 174 + if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY) 175 + return NF_ACCEPT; 176 + if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL) 177 + return NF_ACCEPT; 178 + 179 + /* No NAT? */ 180 + if (!(ct->status & IPS_NAT_MASK)) 181 + return NF_ACCEPT; 182 + 183 + /* Make sure the packet length is ok. So far, we were only guaranteed 184 + * to have a valid length IP header plus 8 bytes, which means we have 185 + * enough room for a UDP header. Just verify the UDP length field so we 186 + * can mess around with the payload. 187 + */ 188 + if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) { 189 + nf_ct_helper_log(skb, ct, "dropping malformed packet\n"); 190 + return NF_DROP; 191 + } 192 + 193 + if (!skb_make_writable(skb, skb->len)) { 194 + nf_ct_helper_log(skb, ct, "cannot mangle packet"); 195 + return NF_DROP; 196 + } 197 + 198 + spin_lock_bh(&snmp_lock); 199 + ret = snmp_translate(ct, dir, skb); 200 + spin_unlock_bh(&snmp_lock); 201 + return ret; 202 + } 203 + 204 + static const struct nf_conntrack_expect_policy snmp_exp_policy = { 205 + .max_expected = 0, 206 + .timeout = 180, 207 + }; 208 + 209 + static struct nf_conntrack_helper snmp_trap_helper __read_mostly = { 210 + .me = THIS_MODULE, 211 + .help = help, 212 + .expect_policy = &snmp_exp_policy, 213 + .name = "snmp_trap", 214 + .tuple.src.l3num = AF_INET, 215 + .tuple.src.u.udp.port = cpu_to_be16(SNMP_TRAP_PORT), 216 + .tuple.dst.protonum = IPPROTO_UDP, 217 + }; 218 + 219 + static int __init nf_nat_snmp_basic_init(void) 220 + { 221 + BUG_ON(nf_nat_snmp_hook != NULL); 222 + RCU_INIT_POINTER(nf_nat_snmp_hook, help); 223 + 224 + return nf_conntrack_helper_register(&snmp_trap_helper); 225 + } 226 + 227 + static void __exit nf_nat_snmp_basic_fini(void) 228 + { 229 + RCU_INIT_POINTER(nf_nat_snmp_hook, NULL); 230 + synchronize_rcu(); 231 + nf_conntrack_helper_unregister(&snmp_trap_helper); 232 + } 233 + 234 + module_init(nf_nat_snmp_basic_init); 235 + module_exit(nf_nat_snmp_basic_fini);
+2 -47
net/ipv4/netfilter/nf_tables_arp.c
··· 27 27 return nft_do_chain(&pkt, priv); 28 28 } 29 29 30 - static struct nft_af_info nft_af_arp __read_mostly = { 31 - .family = NFPROTO_ARP, 32 - .nhooks = NF_ARP_NUMHOOKS, 33 - .owner = THIS_MODULE, 34 - }; 35 - 36 - static int nf_tables_arp_init_net(struct net *net) 37 - { 38 - net->nft.arp = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); 39 - if (net->nft.arp== NULL) 40 - return -ENOMEM; 41 - 42 - memcpy(net->nft.arp, &nft_af_arp, sizeof(nft_af_arp)); 43 - 44 - if (nft_register_afinfo(net, net->nft.arp) < 0) 45 - goto err; 46 - 47 - return 0; 48 - err: 49 - kfree(net->nft.arp); 50 - return -ENOMEM; 51 - } 52 - 53 - static void nf_tables_arp_exit_net(struct net *net) 54 - { 55 - nft_unregister_afinfo(net, net->nft.arp); 56 - kfree(net->nft.arp); 57 - } 58 - 59 - static struct pernet_operations nf_tables_arp_net_ops = { 60 - .init = nf_tables_arp_init_net, 61 - .exit = nf_tables_arp_exit_net, 62 - }; 63 - 64 30 static const struct nf_chain_type filter_arp = { 65 31 .name = "filter", 66 32 .type = NFT_CHAIN_T_DEFAULT, ··· 42 76 43 77 static int __init nf_tables_arp_init(void) 44 78 { 45 - int ret; 46 - 47 - ret = nft_register_chain_type(&filter_arp); 48 - if (ret < 0) 49 - return ret; 50 - 51 - ret = register_pernet_subsys(&nf_tables_arp_net_ops); 52 - if (ret < 0) 53 - nft_unregister_chain_type(&filter_arp); 54 - 55 - return ret; 79 + return nft_register_chain_type(&filter_arp); 56 80 } 57 81 58 82 static void __exit nf_tables_arp_exit(void) 59 83 { 60 - unregister_pernet_subsys(&nf_tables_arp_net_ops); 61 84 nft_unregister_chain_type(&filter_arp); 62 85 } 63 86 ··· 55 100 56 101 MODULE_LICENSE("GPL"); 57 102 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 58 - MODULE_ALIAS_NFT_FAMILY(3); /* NFPROTO_ARP */ 103 + MODULE_ALIAS_NFT_CHAIN(3, "filter"); /* NFPROTO_ARP */
+2 -47
net/ipv4/netfilter/nf_tables_ipv4.c
··· 30 30 return nft_do_chain(&pkt, priv); 31 31 } 32 32 33 - static struct nft_af_info nft_af_ipv4 __read_mostly = { 34 - .family = NFPROTO_IPV4, 35 - .nhooks = NF_INET_NUMHOOKS, 36 - .owner = THIS_MODULE, 37 - }; 38 - 39 - static int nf_tables_ipv4_init_net(struct net *net) 40 - { 41 - net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); 42 - if (net->nft.ipv4 == NULL) 43 - return -ENOMEM; 44 - 45 - memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4)); 46 - 47 - if (nft_register_afinfo(net, net->nft.ipv4) < 0) 48 - goto err; 49 - 50 - return 0; 51 - err: 52 - kfree(net->nft.ipv4); 53 - return -ENOMEM; 54 - } 55 - 56 - static void nf_tables_ipv4_exit_net(struct net *net) 57 - { 58 - nft_unregister_afinfo(net, net->nft.ipv4); 59 - kfree(net->nft.ipv4); 60 - } 61 - 62 - static struct pernet_operations nf_tables_ipv4_net_ops = { 63 - .init = nf_tables_ipv4_init_net, 64 - .exit = nf_tables_ipv4_exit_net, 65 - }; 66 - 67 33 static const struct nf_chain_type filter_ipv4 = { 68 34 .name = "filter", 69 35 .type = NFT_CHAIN_T_DEFAULT, ··· 51 85 52 86 static int __init nf_tables_ipv4_init(void) 53 87 { 54 - int ret; 55 - 56 - ret = nft_register_chain_type(&filter_ipv4); 57 - if (ret < 0) 58 - return ret; 59 - 60 - ret = register_pernet_subsys(&nf_tables_ipv4_net_ops); 61 - if (ret < 0) 62 - nft_unregister_chain_type(&filter_ipv4); 63 - 64 - return ret; 88 + return nft_register_chain_type(&filter_ipv4); 65 89 } 66 90 67 91 static void __exit nf_tables_ipv4_exit(void) 68 92 { 69 - unregister_pernet_subsys(&nf_tables_ipv4_net_ops); 70 93 nft_unregister_chain_type(&filter_ipv4); 71 94 } 72 95 ··· 64 109 65 110 MODULE_LICENSE("GPL"); 66 111 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 67 - MODULE_ALIAS_NFT_FAMILY(AF_INET); 112 + MODULE_ALIAS_NFT_CHAIN(AF_INET, "filter");
+11 -1
net/ipv6/netfilter/Kconfig
··· 72 72 endif # NF_TABLES 73 73 74 74 config NF_FLOW_TABLE_IPV6 75 - select NF_FLOW_TABLE 76 75 tristate "Netfilter flow table IPv6 module" 76 + depends on NF_CONNTRACK && NF_TABLES 77 + select NF_FLOW_TABLE 77 78 help 78 79 This option adds the flow table IPv6 support. 79 80 ··· 240 239 header of the packet. 241 240 242 241 To compile it as a module, choose M here. If unsure, say N. 242 + 243 + config IP6_NF_MATCH_SRH 244 + tristate '"srh" Segment Routing header match support' 245 + depends on NETFILTER_ADVANCED 246 + help 247 + srh matching allows you to match packets based on the segment 248 + routing header of the packet. 249 + 250 + To compile it as a module, choose M here. If unsure, say N. 243 251 244 252 # The targets 245 253 config IP6_NF_TARGET_HL
+1
net/ipv6/netfilter/Makefile
··· 57 57 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o 58 58 obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o 59 59 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 60 + obj-$(CONFIG_IP6_NF_MATCH_SRH) += ip6t_srh.o 60 61 61 62 # targets 62 63 obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
-1
net/ipv6/netfilter/ip6_tables.c
··· 1952 1952 if (ret < 0) 1953 1953 goto err5; 1954 1954 1955 - pr_info("(C) 2000-2006 Netfilter Core Team\n"); 1956 1955 return 0; 1957 1956 1958 1957 err5:
+161
net/ipv6/netfilter/ip6t_srh.c
··· 1 + /* Kernel module to match Segment Routing Header (SRH) parameters. */ 2 + 3 + /* Author: 4 + * Ahmed Abdelsalam <amsalam20@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 2 9 + * of the License, or (at your option) any later version. 10 + */ 11 + 12 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 + #include <linux/module.h> 14 + #include <linux/skbuff.h> 15 + #include <linux/ipv6.h> 16 + #include <linux/types.h> 17 + #include <net/ipv6.h> 18 + #include <net/seg6.h> 19 + 20 + #include <linux/netfilter/x_tables.h> 21 + #include <linux/netfilter_ipv6/ip6t_srh.h> 22 + #include <linux/netfilter_ipv6/ip6_tables.h> 23 + 24 + /* Test a struct->mt_invflags and a boolean for inequality */ 25 + #define NF_SRH_INVF(ptr, flag, boolean) \ 26 + ((boolean) ^ !!((ptr)->mt_invflags & (flag))) 27 + 28 + static bool srh_mt6(const struct sk_buff *skb, struct xt_action_param *par) 29 + { 30 + const struct ip6t_srh *srhinfo = par->matchinfo; 31 + struct ipv6_sr_hdr *srh; 32 + struct ipv6_sr_hdr _srh; 33 + int hdrlen, srhoff = 0; 34 + 35 + if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0) 36 + return false; 37 + srh = skb_header_pointer(skb, srhoff, sizeof(_srh), &_srh); 38 + if (!srh) 39 + return false; 40 + 41 + hdrlen = ipv6_optlen(srh); 42 + if (skb->len - srhoff < hdrlen) 43 + return false; 44 + 45 + if (srh->type != IPV6_SRCRT_TYPE_4) 46 + return false; 47 + 48 + if (srh->segments_left > srh->first_segment) 49 + return false; 50 + 51 + /* Next Header matching */ 52 + if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR) 53 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NEXTHDR, 54 + !(srh->nexthdr == srhinfo->next_hdr))) 55 + return false; 56 + 57 + /* Header Extension Length matching */ 58 + if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ) 59 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_EQ, 60 + !(srh->hdrlen == srhinfo->hdr_len))) 61 + return false; 62 + 63 + if (srhinfo->mt_flags & IP6T_SRH_LEN_GT) 64 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_GT, 65 + !(srh->hdrlen > srhinfo->hdr_len))) 66 + return false; 67 + 68 + if (srhinfo->mt_flags & IP6T_SRH_LEN_LT) 69 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_LT, 70 + !(srh->hdrlen < srhinfo->hdr_len))) 71 + return false; 72 + 73 + /* Segments Left matching */ 74 + if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ) 75 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_EQ, 76 + !(srh->segments_left == srhinfo->segs_left))) 77 + return false; 78 + 79 + if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT) 80 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_GT, 81 + !(srh->segments_left > srhinfo->segs_left))) 82 + return false; 83 + 84 + if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT) 85 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_LT, 86 + !(srh->segments_left < srhinfo->segs_left))) 87 + return false; 88 + 89 + /** 90 + * Last Entry matching 91 + * Last_Entry field was introduced in revision 6 of the SRH draft. 92 + * It was called First_Segment in the previous revision 93 + */ 94 + if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ) 95 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_EQ, 96 + !(srh->first_segment == srhinfo->last_entry))) 97 + return false; 98 + 99 + if (srhinfo->mt_flags & IP6T_SRH_LAST_GT) 100 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_GT, 101 + !(srh->first_segment > srhinfo->last_entry))) 102 + return false; 103 + 104 + if (srhinfo->mt_flags & IP6T_SRH_LAST_LT) 105 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_LT, 106 + !(srh->first_segment < srhinfo->last_entry))) 107 + return false; 108 + 109 + /** 110 + * Tag matchig 111 + * Tag field was introduced in revision 6 of the SRH draft. 112 + */ 113 + if (srhinfo->mt_flags & IP6T_SRH_TAG) 114 + if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_TAG, 115 + !(srh->tag == srhinfo->tag))) 116 + return false; 117 + return true; 118 + } 119 + 120 + static int srh_mt6_check(const struct xt_mtchk_param *par) 121 + { 122 + const struct ip6t_srh *srhinfo = par->matchinfo; 123 + 124 + if (srhinfo->mt_flags & ~IP6T_SRH_MASK) { 125 + pr_err("unknown srh match flags %X\n", srhinfo->mt_flags); 126 + return -EINVAL; 127 + } 128 + 129 + if (srhinfo->mt_invflags & ~IP6T_SRH_INV_MASK) { 130 + pr_err("unknown srh invflags %X\n", srhinfo->mt_invflags); 131 + return -EINVAL; 132 + } 133 + 134 + return 0; 135 + } 136 + 137 + static struct xt_match srh_mt6_reg __read_mostly = { 138 + .name = "srh", 139 + .family = NFPROTO_IPV6, 140 + .match = srh_mt6, 141 + .matchsize = sizeof(struct ip6t_srh), 142 + .checkentry = srh_mt6_check, 143 + .me = THIS_MODULE, 144 + }; 145 + 146 + static int __init srh_mt6_init(void) 147 + { 148 + return xt_register_match(&srh_mt6_reg); 149 + } 150 + 151 + static void __exit srh_mt6_exit(void) 152 + { 153 + xt_unregister_match(&srh_mt6_reg); 154 + } 155 + 156 + module_init(srh_mt6_init); 157 + module_exit(srh_mt6_exit); 158 + 159 + MODULE_LICENSE("GPL"); 160 + MODULE_DESCRIPTION("Xtables: IPv6 Segment Routing Header match"); 161 + MODULE_AUTHOR("Ahmed Abdelsalam <amsalam20@gmail.com>");
+28 -3
net/ipv6/netfilter/ip6table_raw.c
··· 3 3 * 4 4 * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 5 5 */ 6 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 6 7 #include <linux/module.h> 7 8 #include <linux/netfilter_ipv6/ip6_tables.h> 8 9 #include <linux/slab.h> ··· 12 11 13 12 static int __net_init ip6table_raw_table_init(struct net *net); 14 13 14 + static bool raw_before_defrag __read_mostly; 15 + MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag"); 16 + module_param(raw_before_defrag, bool, 0000); 17 + 15 18 static const struct xt_table packet_raw = { 16 19 .name = "raw", 17 20 .valid_hooks = RAW_VALID_HOOKS, 18 21 .me = THIS_MODULE, 19 22 .af = NFPROTO_IPV6, 20 23 .priority = NF_IP6_PRI_RAW, 24 + .table_init = ip6table_raw_table_init, 25 + }; 26 + 27 + static const struct xt_table packet_raw_before_defrag = { 28 + .name = "raw", 29 + .valid_hooks = RAW_VALID_HOOKS, 30 + .me = THIS_MODULE, 31 + .af = NFPROTO_IPV6, 32 + .priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG, 21 33 .table_init = ip6table_raw_table_init, 22 34 }; 23 35 ··· 47 33 static int __net_init ip6table_raw_table_init(struct net *net) 48 34 { 49 35 struct ip6t_replace *repl; 36 + const struct xt_table *table = &packet_raw; 50 37 int ret; 38 + 39 + if (raw_before_defrag) 40 + table = &packet_raw_before_defrag; 51 41 52 42 if (net->ipv6.ip6table_raw) 53 43 return 0; 54 44 55 - repl = ip6t_alloc_initial_table(&packet_raw); 45 + repl = ip6t_alloc_initial_table(table); 56 46 if (repl == NULL) 57 47 return -ENOMEM; 58 - ret = ip6t_register_table(net, &packet_raw, repl, rawtable_ops, 48 + ret = ip6t_register_table(net, table, repl, rawtable_ops, 59 49 &net->ipv6.ip6table_raw); 60 50 kfree(repl); 61 51 return ret; ··· 80 62 static int __init ip6table_raw_init(void) 81 63 { 82 64 int ret; 65 + const struct xt_table *table = &packet_raw; 66 + 67 + if (raw_before_defrag) { 68 + table = &packet_raw_before_defrag; 69 + 70 + pr_info("Enabling raw table before defrag\n"); 71 + } 83 72 84 73 /* Register hooks */ 85 - rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook); 74 + rawtable_ops = xt_hook_ops_alloc(table, ip6table_raw_hook); 86 75 if (IS_ERR(rawtable_ops)) 87 76 return PTR_ERR(rawtable_ops); 88 77
+10 -5
net/ipv6/netfilter/nf_conntrack_reasm.c
··· 231 231 232 232 if ((unsigned int)end > IPV6_MAXPLEN) { 233 233 pr_debug("offset is too large.\n"); 234 - return -1; 234 + return -EINVAL; 235 235 } 236 236 237 237 ecn = ip6_frag_ecn(ipv6_hdr(skb)); ··· 264 264 * this case. -DaveM 265 265 */ 266 266 pr_debug("end of fragment not rounded to 8 bytes.\n"); 267 - return -1; 267 + return -EPROTO; 268 268 } 269 269 if (end > fq->q.len) { 270 270 /* Some bits beyond end -> corruption. */ ··· 358 358 discard_fq: 359 359 inet_frag_kill(&fq->q, &nf_frags); 360 360 err: 361 - return -1; 361 + return -EINVAL; 362 362 } 363 363 364 364 /* ··· 567 567 568 568 int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) 569 569 { 570 + u16 savethdr = skb->transport_header; 570 571 struct net_device *dev = skb->dev; 571 572 int fhoff, nhoff, ret; 572 573 struct frag_hdr *fhdr; ··· 601 600 602 601 spin_lock_bh(&fq->q.lock); 603 602 604 - if (nf_ct_frag6_queue(fq, skb, fhdr, nhoff) < 0) { 605 - ret = -EINVAL; 603 + ret = nf_ct_frag6_queue(fq, skb, fhdr, nhoff); 604 + if (ret < 0) { 605 + if (ret == -EPROTO) { 606 + skb->transport_header = savethdr; 607 + ret = 0; 608 + } 606 609 goto out_unlock; 607 610 } 608 611
+3
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
··· 63 63 /* Previously seen (loopback)? */ 64 64 if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb))) 65 65 return NF_ACCEPT; 66 + 67 + if (skb->_nfct == IP_CT_UNTRACKED) 68 + return NF_ACCEPT; 66 69 #endif 67 70 68 71 err = nf_ct_frag6_gather(state->net, skb,
-1
net/ipv6/netfilter/nf_flow_table_ipv6.c
··· 5 5 #include <linux/rhashtable.h> 6 6 #include <linux/ipv6.h> 7 7 #include <linux/netdevice.h> 8 - #include <linux/ipv6.h> 9 8 #include <net/ipv6.h> 10 9 #include <net/ip6_route.h> 11 10 #include <net/neighbour.h>
+2 -47
net/ipv6/netfilter/nf_tables_ipv6.c
··· 28 28 return nft_do_chain(&pkt, priv); 29 29 } 30 30 31 - static struct nft_af_info nft_af_ipv6 __read_mostly = { 32 - .family = NFPROTO_IPV6, 33 - .nhooks = NF_INET_NUMHOOKS, 34 - .owner = THIS_MODULE, 35 - }; 36 - 37 - static int nf_tables_ipv6_init_net(struct net *net) 38 - { 39 - net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); 40 - if (net->nft.ipv6 == NULL) 41 - return -ENOMEM; 42 - 43 - memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6)); 44 - 45 - if (nft_register_afinfo(net, net->nft.ipv6) < 0) 46 - goto err; 47 - 48 - return 0; 49 - err: 50 - kfree(net->nft.ipv6); 51 - return -ENOMEM; 52 - } 53 - 54 - static void nf_tables_ipv6_exit_net(struct net *net) 55 - { 56 - nft_unregister_afinfo(net, net->nft.ipv6); 57 - kfree(net->nft.ipv6); 58 - } 59 - 60 - static struct pernet_operations nf_tables_ipv6_net_ops = { 61 - .init = nf_tables_ipv6_init_net, 62 - .exit = nf_tables_ipv6_exit_net, 63 - }; 64 - 65 31 static const struct nf_chain_type filter_ipv6 = { 66 32 .name = "filter", 67 33 .type = NFT_CHAIN_T_DEFAULT, ··· 49 83 50 84 static int __init nf_tables_ipv6_init(void) 51 85 { 52 - int ret; 53 - 54 - ret = nft_register_chain_type(&filter_ipv6); 55 - if (ret < 0) 56 - return ret; 57 - 58 - ret = register_pernet_subsys(&nf_tables_ipv6_net_ops); 59 - if (ret < 0) 60 - nft_unregister_chain_type(&filter_ipv6); 61 - 62 - return ret; 86 + return nft_register_chain_type(&filter_ipv6); 63 87 } 64 88 65 89 static void __exit nf_tables_ipv6_exit(void) 66 90 { 67 - unregister_pernet_subsys(&nf_tables_ipv6_net_ops); 68 91 nft_unregister_chain_type(&filter_ipv6); 69 92 } 70 93 ··· 62 107 63 108 MODULE_LICENSE("GPL"); 64 109 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 65 - MODULE_ALIAS_NFT_FAMILY(AF_INET6); 110 + MODULE_ALIAS_NFT_CHAIN(AF_INET6, "filter");
+4 -2
net/netfilter/Kconfig
··· 506 506 connection tracking information such as the flow state. 507 507 508 508 config NFT_FLOW_OFFLOAD 509 - depends on NF_CONNTRACK 509 + depends on NF_CONNTRACK && NF_FLOW_TABLE 510 510 tristate "Netfilter nf_tables hardware flow offload module" 511 511 help 512 512 This option adds the "flow_offload" expression that you can use to ··· 665 665 endif # NF_TABLES 666 666 667 667 config NF_FLOW_TABLE_INET 668 - select NF_FLOW_TABLE 669 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 671 help 671 672 This option adds the flow table mixed IPv4/IPv6 support. 672 673 ··· 675 674 676 675 config NF_FLOW_TABLE 677 676 tristate "Netfilter flow table module" 677 + depends on NF_CONNTRACK && NF_TABLES 678 678 help 679 679 This option adds the flow table core infrastructure. 680 680
+3 -3
net/netfilter/core.c
··· 140 140 141 141 if (reg->nat_hook && orig_ops[i]->nat_hook) { 142 142 kvfree(new); 143 - return ERR_PTR(-EEXIST); 143 + return ERR_PTR(-EBUSY); 144 144 } 145 145 146 146 if (inserted || reg->priority > orig_ops[i]->priority) { ··· 377 377 } 378 378 } 379 379 380 - void __nf_unregister_net_hook(struct net *net, int pf, 381 - const struct nf_hook_ops *reg) 380 + static void __nf_unregister_net_hook(struct net *net, int pf, 381 + const struct nf_hook_ops *reg) 382 382 { 383 383 struct nf_hook_entries __rcu **pp; 384 384 struct nf_hook_entries *p;
+2 -1
net/netfilter/ipset/ip_set_core.c
··· 2122 2122 return ret; 2123 2123 } 2124 2124 2125 - pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL); 2126 2125 return 0; 2127 2126 } 2128 2127 ··· 2137 2138 2138 2139 module_init(ip_set_init); 2139 2140 module_exit(ip_set_fini); 2141 + 2142 + MODULE_DESCRIPTION("ip_set: protocol " __stringify(IPSET_PROTOCOL));
-1
net/netfilter/ipvs/ip_vs_app.c
··· 595 595 } 596 596 597 597 static const struct file_operations ip_vs_app_fops = { 598 - .owner = THIS_MODULE, 599 598 .open = ip_vs_app_open, 600 599 .read = seq_read, 601 600 .llseek = seq_lseek,
-2
net/netfilter/ipvs/ip_vs_conn.c
··· 1143 1143 } 1144 1144 1145 1145 static const struct file_operations ip_vs_conn_fops = { 1146 - .owner = THIS_MODULE, 1147 1146 .open = ip_vs_conn_open, 1148 1147 .read = seq_read, 1149 1148 .llseek = seq_lseek, ··· 1220 1221 } 1221 1222 1222 1223 static const struct file_operations ip_vs_conn_sync_fops = { 1223 - .owner = THIS_MODULE, 1224 1224 .open = ip_vs_conn_sync_open, 1225 1225 .read = seq_read, 1226 1226 .llseek = seq_lseek,
-3
net/netfilter/ipvs/ip_vs_ctl.c
··· 2116 2116 } 2117 2117 2118 2118 static const struct file_operations ip_vs_info_fops = { 2119 - .owner = THIS_MODULE, 2120 2119 .open = ip_vs_info_open, 2121 2120 .read = seq_read, 2122 2121 .llseek = seq_lseek, ··· 2160 2161 } 2161 2162 2162 2163 static const struct file_operations ip_vs_stats_fops = { 2163 - .owner = THIS_MODULE, 2164 2164 .open = ip_vs_stats_seq_open, 2165 2165 .read = seq_read, 2166 2166 .llseek = seq_lseek, ··· 2228 2230 } 2229 2231 2230 2232 static const struct file_operations ip_vs_stats_percpu_fops = { 2231 - .owner = THIS_MODULE, 2232 2233 .open = ip_vs_stats_percpu_seq_open, 2233 2234 .read = seq_read, 2234 2235 .llseek = seq_lseek,
+1 -1
net/netfilter/nf_conncount.c
··· 71 71 return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT || 72 72 conn->proto.tcp.state == TCP_CONNTRACK_CLOSE; 73 73 else 74 - return 0; 74 + return false; 75 75 } 76 76 77 77 static int key_diff(const u32 *a, const u32 *b, unsigned int klen)
-6
net/netfilter/nf_conntrack_core.c
··· 58 58 59 59 #include "nf_internals.h" 60 60 61 - #define NF_CONNTRACK_VERSION "0.5.0" 62 - 63 61 int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, 64 62 enum nf_nat_manip_type manip, 65 63 const struct nlattr *attr) __read_mostly; ··· 2065 2067 SLAB_TYPESAFE_BY_RCU | SLAB_HWCACHE_ALIGN, NULL); 2066 2068 if (!nf_conntrack_cachep) 2067 2069 goto err_cachep; 2068 - 2069 - printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n", 2070 - NF_CONNTRACK_VERSION, nf_conntrack_htable_size, 2071 - nf_conntrack_max); 2072 2070 2073 2071 ret = nf_conntrack_expect_init(); 2074 2072 if (ret < 0)
-1
net/netfilter/nf_conntrack_expect.c
··· 649 649 } 650 650 651 651 static const struct file_operations exp_file_ops = { 652 - .owner = THIS_MODULE, 653 652 .open = exp_open, 654 653 .read = seq_read, 655 654 .llseek = seq_lseek,
-5
net/netfilter/nf_conntrack_netlink.c
··· 57 57 58 58 MODULE_LICENSE("GPL"); 59 59 60 - static char __initdata version[] = "0.93"; 61 - 62 60 static int ctnetlink_dump_tuples_proto(struct sk_buff *skb, 63 61 const struct nf_conntrack_tuple *tuple, 64 62 const struct nf_conntrack_l4proto *l4proto) ··· 3423 3425 { 3424 3426 int ret; 3425 3427 3426 - pr_info("ctnetlink v%s: registering with nfnetlink.\n", version); 3427 3428 ret = nfnetlink_subsys_register(&ctnl_subsys); 3428 3429 if (ret < 0) { 3429 3430 pr_err("ctnetlink_init: cannot register with nfnetlink.\n"); ··· 3456 3459 3457 3460 static void __exit ctnetlink_exit(void) 3458 3461 { 3459 - pr_info("ctnetlink: unregistering from nfnetlink.\n"); 3460 - 3461 3462 unregister_pernet_subsys(&ctnetlink_net_ops); 3462 3463 nfnetlink_subsys_unregister(&ctnl_exp_subsys); 3463 3464 nfnetlink_subsys_unregister(&ctnl_subsys);
-2
net/netfilter/nf_conntrack_standalone.c
··· 382 382 } 383 383 384 384 static const struct file_operations ct_file_ops = { 385 - .owner = THIS_MODULE, 386 385 .open = ct_open, 387 386 .read = seq_read, 388 387 .llseek = seq_lseek, ··· 474 475 } 475 476 476 477 static const struct file_operations ct_cpu_seq_fops = { 477 - .owner = THIS_MODULE, 478 478 .open = ct_cpu_seq_open, 479 479 .read = seq_read, 480 480 .llseek = seq_lseek,
-1
net/netfilter/nf_log.c
··· 402 402 } 403 403 404 404 static const struct file_operations nflog_file_ops = { 405 - .owner = THIS_MODULE, 406 405 .open = nflog_open, 407 406 .read = seq_read, 408 407 .llseek = seq_lseek,
-2
net/netfilter/nf_queue.c
··· 15 15 #include <linux/netfilter_bridge.h> 16 16 #include <linux/seq_file.h> 17 17 #include <linux/rcupdate.h> 18 - #include <linux/netfilter_ipv4.h> 19 - #include <linux/netfilter_ipv6.h> 20 18 #include <net/protocol.h> 21 19 #include <net/netfilter/nf_queue.h> 22 20 #include <net/dst.h>
-1
net/netfilter/nf_synproxy_core.c
··· 317 317 } 318 318 319 319 static const struct file_operations synproxy_cpu_seq_fops = { 320 - .owner = THIS_MODULE, 321 320 .open = synproxy_cpu_seq_open, 322 321 .read = seq_read, 323 322 .llseek = seq_lseek,
+426 -502
net/netfilter/nf_tables_api.c
··· 26 26 static LIST_HEAD(nf_tables_expressions); 27 27 static LIST_HEAD(nf_tables_objects); 28 28 static LIST_HEAD(nf_tables_flowtables); 29 - 30 - /** 31 - * nft_register_afinfo - register nf_tables address family info 32 - * 33 - * @afi: address family info to register 34 - * 35 - * Register the address family for use with nf_tables. Returns zero on 36 - * success or a negative errno code otherwise. 37 - */ 38 - int nft_register_afinfo(struct net *net, struct nft_af_info *afi) 39 - { 40 - INIT_LIST_HEAD(&afi->tables); 41 - nfnl_lock(NFNL_SUBSYS_NFTABLES); 42 - list_add_tail_rcu(&afi->list, &net->nft.af_info); 43 - nfnl_unlock(NFNL_SUBSYS_NFTABLES); 44 - return 0; 45 - } 46 - EXPORT_SYMBOL_GPL(nft_register_afinfo); 47 - 48 - static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi); 49 - 50 - /** 51 - * nft_unregister_afinfo - unregister nf_tables address family info 52 - * 53 - * @afi: address family info to unregister 54 - * 55 - * Unregister the address family for use with nf_tables. 56 - */ 57 - void nft_unregister_afinfo(struct net *net, struct nft_af_info *afi) 58 - { 59 - nfnl_lock(NFNL_SUBSYS_NFTABLES); 60 - __nft_release_afinfo(net, afi); 61 - list_del_rcu(&afi->list); 62 - nfnl_unlock(NFNL_SUBSYS_NFTABLES); 63 - } 64 - EXPORT_SYMBOL_GPL(nft_unregister_afinfo); 65 - 66 - static struct nft_af_info *nft_afinfo_lookup(struct net *net, int family) 67 - { 68 - struct nft_af_info *afi; 69 - 70 - list_for_each_entry(afi, &net->nft.af_info, list) { 71 - if (afi->family == family) 72 - return afi; 73 - } 74 - return NULL; 75 - } 76 - 77 - static struct nft_af_info * 78 - nf_tables_afinfo_lookup(struct net *net, int family, bool autoload) 79 - { 80 - struct nft_af_info *afi; 81 - 82 - afi = nft_afinfo_lookup(net, family); 83 - if (afi != NULL) 84 - return afi; 85 - #ifdef CONFIG_MODULES 86 - if (autoload) { 87 - nfnl_unlock(NFNL_SUBSYS_NFTABLES); 88 - request_module("nft-afinfo-%u", family); 89 - nfnl_lock(NFNL_SUBSYS_NFTABLES); 90 - afi = nft_afinfo_lookup(net, family); 91 - if (afi != NULL) 92 - return ERR_PTR(-EAGAIN); 93 - } 94 - #endif 95 - return ERR_PTR(-EAFNOSUPPORT); 96 - } 29 + static u64 table_handle; 97 30 98 31 static void nft_ctx_init(struct nft_ctx *ctx, 99 32 struct net *net, 100 33 const struct sk_buff *skb, 101 34 const struct nlmsghdr *nlh, 102 - struct nft_af_info *afi, 35 + u8 family, 103 36 struct nft_table *table, 104 37 struct nft_chain *chain, 105 38 const struct nlattr * const *nla) 106 39 { 107 40 ctx->net = net; 108 - ctx->afi = afi; 41 + ctx->family = family; 109 42 ctx->table = table; 110 43 ctx->chain = chain; 111 44 ctx->nla = nla; ··· 318 385 * Tables 319 386 */ 320 387 321 - static struct nft_table *nft_table_lookup(const struct nft_af_info *afi, 388 + static struct nft_table *nft_table_lookup(const struct net *net, 322 389 const struct nlattr *nla, 323 - u8 genmask) 390 + u8 family, u8 genmask) 324 391 { 325 392 struct nft_table *table; 326 393 327 - list_for_each_entry(table, &afi->tables, list) { 394 + list_for_each_entry(table, &net->nft.tables, list) { 328 395 if (!nla_strcmp(nla, table->name) && 396 + table->family == family && 329 397 nft_active_genmask(table, genmask)) 330 398 return table; 331 399 } 332 400 return NULL; 333 401 } 334 402 335 - static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi, 403 + static struct nft_table *nft_table_lookup_byhandle(const struct net *net, 404 + const struct nlattr *nla, 405 + u8 genmask) 406 + { 407 + struct nft_table *table; 408 + 409 + list_for_each_entry(table, &net->nft.tables, list) { 410 + if (be64_to_cpu(nla_get_be64(nla)) == table->handle && 411 + nft_active_genmask(table, genmask)) 412 + return table; 413 + } 414 + return NULL; 415 + } 416 + 417 + static struct nft_table *nf_tables_table_lookup(const struct net *net, 336 418 const struct nlattr *nla, 337 - u8 genmask) 419 + u8 family, u8 genmask) 338 420 { 339 421 struct nft_table *table; 340 422 341 423 if (nla == NULL) 342 424 return ERR_PTR(-EINVAL); 343 425 344 - table = nft_table_lookup(afi, nla, genmask); 426 + table = nft_table_lookup(net, nla, family, genmask); 427 + if (table != NULL) 428 + return table; 429 + 430 + return ERR_PTR(-ENOENT); 431 + } 432 + 433 + static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net, 434 + const struct nlattr *nla, 435 + u8 genmask) 436 + { 437 + struct nft_table *table; 438 + 439 + if (nla == NULL) 440 + return ERR_PTR(-EINVAL); 441 + 442 + table = nft_table_lookup_byhandle(net, nla, genmask); 345 443 if (table != NULL) 346 444 return table; 347 445 ··· 387 423 static const struct nf_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX]; 388 424 389 425 static const struct nf_chain_type * 390 - __nf_tables_chain_type_lookup(int family, const struct nlattr *nla) 426 + __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family) 391 427 { 392 428 int i; 393 429 ··· 400 436 } 401 437 402 438 static const struct nf_chain_type * 403 - nf_tables_chain_type_lookup(const struct nft_af_info *afi, 404 - const struct nlattr *nla, 405 - bool autoload) 439 + nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload) 406 440 { 407 441 const struct nf_chain_type *type; 408 442 409 - type = __nf_tables_chain_type_lookup(afi->family, nla); 443 + type = __nf_tables_chain_type_lookup(nla, family); 410 444 if (type != NULL) 411 445 return type; 412 446 #ifdef CONFIG_MODULES 413 447 if (autoload) { 414 448 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 415 - request_module("nft-chain-%u-%.*s", afi->family, 449 + request_module("nft-chain-%u-%.*s", family, 416 450 nla_len(nla), (const char *)nla_data(nla)); 417 451 nfnl_lock(NFNL_SUBSYS_NFTABLES); 418 - type = __nf_tables_chain_type_lookup(afi->family, nla); 452 + type = __nf_tables_chain_type_lookup(nla, family); 419 453 if (type != NULL) 420 454 return ERR_PTR(-EAGAIN); 421 455 } ··· 425 463 [NFTA_TABLE_NAME] = { .type = NLA_STRING, 426 464 .len = NFT_TABLE_MAXNAMELEN - 1 }, 427 465 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, 466 + [NFTA_TABLE_HANDLE] = { .type = NLA_U64 }, 428 467 }; 429 468 430 469 static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, ··· 447 484 448 485 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || 449 486 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || 450 - nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) 487 + nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) || 488 + nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle), 489 + NFTA_TABLE_PAD)) 451 490 goto nla_put_failure; 452 491 453 492 nlmsg_end(skb, nlh); ··· 474 509 goto err; 475 510 476 511 err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq, 477 - event, 0, ctx->afi->family, ctx->table); 512 + event, 0, ctx->family, ctx->table); 478 513 if (err < 0) { 479 514 kfree_skb(skb); 480 515 goto err; ··· 491 526 struct netlink_callback *cb) 492 527 { 493 528 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 494 - const struct nft_af_info *afi; 495 529 const struct nft_table *table; 496 530 unsigned int idx = 0, s_idx = cb->args[0]; 497 531 struct net *net = sock_net(skb->sk); ··· 499 535 rcu_read_lock(); 500 536 cb->seq = net->nft.base_seq; 501 537 502 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 503 - if (family != NFPROTO_UNSPEC && family != afi->family) 538 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 539 + if (family != NFPROTO_UNSPEC && family != table->family) 504 540 continue; 505 541 506 - list_for_each_entry_rcu(table, &afi->tables, list) { 507 - if (idx < s_idx) 508 - goto cont; 509 - if (idx > s_idx) 510 - memset(&cb->args[1], 0, 511 - sizeof(cb->args) - sizeof(cb->args[0])); 512 - if (!nft_is_active(net, table)) 513 - continue; 514 - if (nf_tables_fill_table_info(skb, net, 515 - NETLINK_CB(cb->skb).portid, 516 - cb->nlh->nlmsg_seq, 517 - NFT_MSG_NEWTABLE, 518 - NLM_F_MULTI, 519 - afi->family, table) < 0) 520 - goto done; 542 + if (idx < s_idx) 543 + goto cont; 544 + if (idx > s_idx) 545 + memset(&cb->args[1], 0, 546 + sizeof(cb->args) - sizeof(cb->args[0])); 547 + if (!nft_is_active(net, table)) 548 + continue; 549 + if (nf_tables_fill_table_info(skb, net, 550 + NETLINK_CB(cb->skb).portid, 551 + cb->nlh->nlmsg_seq, 552 + NFT_MSG_NEWTABLE, NLM_F_MULTI, 553 + table->family, table) < 0) 554 + goto done; 521 555 522 - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 556 + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 523 557 cont: 524 - idx++; 525 - } 558 + idx++; 526 559 } 527 560 done: 528 561 rcu_read_unlock(); ··· 534 573 { 535 574 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 536 575 u8 genmask = nft_genmask_cur(net); 537 - const struct nft_af_info *afi; 538 576 const struct nft_table *table; 539 577 struct sk_buff *skb2; 540 578 int family = nfmsg->nfgen_family; ··· 546 586 return netlink_dump_start(nlsk, skb, nlh, &c); 547 587 } 548 588 549 - afi = nf_tables_afinfo_lookup(net, family, false); 550 - if (IS_ERR(afi)) 551 - return PTR_ERR(afi); 552 - 553 - table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); 589 + table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, 590 + genmask); 554 591 if (IS_ERR(table)) 555 592 return PTR_ERR(table); 556 593 ··· 568 611 return err; 569 612 } 570 613 571 - static void _nf_tables_table_disable(struct net *net, 572 - const struct nft_af_info *afi, 573 - struct nft_table *table, 574 - u32 cnt) 614 + static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt) 575 615 { 576 616 struct nft_chain *chain; 577 617 u32 i = 0; ··· 586 632 } 587 633 } 588 634 589 - static int nf_tables_table_enable(struct net *net, 590 - const struct nft_af_info *afi, 591 - struct nft_table *table) 635 + static int nf_tables_table_enable(struct net *net, struct nft_table *table) 592 636 { 593 637 struct nft_chain *chain; 594 638 int err, i = 0; ··· 606 654 return 0; 607 655 err: 608 656 if (i) 609 - _nf_tables_table_disable(net, afi, table, i); 657 + nft_table_disable(net, table, i); 610 658 return err; 611 659 } 612 660 613 - static void nf_tables_table_disable(struct net *net, 614 - const struct nft_af_info *afi, 615 - struct nft_table *table) 661 + static void nf_tables_table_disable(struct net *net, struct nft_table *table) 616 662 { 617 - _nf_tables_table_disable(net, afi, table, 0); 663 + nft_table_disable(net, table, 0); 618 664 } 619 665 620 666 static int nf_tables_updtable(struct nft_ctx *ctx) ··· 641 691 nft_trans_table_enable(trans) = false; 642 692 } else if (!(flags & NFT_TABLE_F_DORMANT) && 643 693 ctx->table->flags & NFT_TABLE_F_DORMANT) { 644 - ret = nf_tables_table_enable(ctx->net, ctx->afi, ctx->table); 694 + ret = nf_tables_table_enable(ctx->net, ctx->table); 645 695 if (ret >= 0) { 646 696 ctx->table->flags &= ~NFT_TABLE_F_DORMANT; 647 697 nft_trans_table_enable(trans) = true; ··· 666 716 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 667 717 u8 genmask = nft_genmask_next(net); 668 718 const struct nlattr *name; 669 - struct nft_af_info *afi; 670 719 struct nft_table *table; 671 720 int family = nfmsg->nfgen_family; 672 721 u32 flags = 0; 673 722 struct nft_ctx ctx; 674 723 int err; 675 724 676 - afi = nf_tables_afinfo_lookup(net, family, true); 677 - if (IS_ERR(afi)) 678 - return PTR_ERR(afi); 679 - 680 725 name = nla[NFTA_TABLE_NAME]; 681 - table = nf_tables_table_lookup(afi, name, genmask); 726 + table = nf_tables_table_lookup(net, name, family, genmask); 682 727 if (IS_ERR(table)) { 683 728 if (PTR_ERR(table) != -ENOENT) 684 729 return PTR_ERR(table); ··· 683 738 if (nlh->nlmsg_flags & NLM_F_REPLACE) 684 739 return -EOPNOTSUPP; 685 740 686 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 741 + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 687 742 return nf_tables_updtable(&ctx); 688 743 } 689 744 ··· 693 748 return -EINVAL; 694 749 } 695 750 696 - err = -EAFNOSUPPORT; 697 - if (!try_module_get(afi->owner)) 698 - goto err1; 699 - 700 751 err = -ENOMEM; 701 752 table = kzalloc(sizeof(*table), GFP_KERNEL); 702 753 if (table == NULL) 703 - goto err2; 754 + goto err_kzalloc; 704 755 705 756 table->name = nla_strdup(name, GFP_KERNEL); 706 757 if (table->name == NULL) 707 - goto err3; 758 + goto err_strdup; 708 759 709 760 INIT_LIST_HEAD(&table->chains); 710 761 INIT_LIST_HEAD(&table->sets); 711 762 INIT_LIST_HEAD(&table->objects); 712 763 INIT_LIST_HEAD(&table->flowtables); 764 + table->family = family; 713 765 table->flags = flags; 766 + table->handle = ++table_handle; 714 767 715 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 768 + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 716 769 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); 717 770 if (err < 0) 718 - goto err4; 771 + goto err_trans; 719 772 720 - list_add_tail_rcu(&table->list, &afi->tables); 773 + list_add_tail_rcu(&table->list, &net->nft.tables); 721 774 return 0; 722 - err4: 775 + err_trans: 723 776 kfree(table->name); 724 - err3: 777 + err_strdup: 725 778 kfree(table); 726 - err2: 727 - module_put(afi->owner); 728 - err1: 779 + err_kzalloc: 729 780 return err; 730 781 } 731 782 ··· 787 846 788 847 static int nft_flush(struct nft_ctx *ctx, int family) 789 848 { 790 - struct nft_af_info *afi; 791 849 struct nft_table *table, *nt; 792 850 const struct nlattr * const *nla = ctx->nla; 793 851 int err = 0; 794 852 795 - list_for_each_entry(afi, &ctx->net->nft.af_info, list) { 796 - if (family != AF_UNSPEC && afi->family != family) 853 + list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) { 854 + if (family != AF_UNSPEC && table->family != family) 797 855 continue; 798 856 799 - ctx->afi = afi; 800 - list_for_each_entry_safe(table, nt, &afi->tables, list) { 801 - if (!nft_is_active_next(ctx->net, table)) 802 - continue; 857 + ctx->family = table->family; 803 858 804 - if (nla[NFTA_TABLE_NAME] && 805 - nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) 806 - continue; 859 + if (!nft_is_active_next(ctx->net, table)) 860 + continue; 807 861 808 - ctx->table = table; 862 + if (nla[NFTA_TABLE_NAME] && 863 + nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) 864 + continue; 809 865 810 - err = nft_flush_table(ctx); 811 - if (err < 0) 812 - goto out; 813 - } 866 + ctx->table = table; 867 + 868 + err = nft_flush_table(ctx); 869 + if (err < 0) 870 + goto out; 814 871 } 815 872 out: 816 873 return err; ··· 821 882 { 822 883 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 823 884 u8 genmask = nft_genmask_next(net); 824 - struct nft_af_info *afi; 825 885 struct nft_table *table; 826 886 int family = nfmsg->nfgen_family; 827 887 struct nft_ctx ctx; 828 888 829 - nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla); 830 - if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) 889 + nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); 890 + if (family == AF_UNSPEC || 891 + (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE])) 831 892 return nft_flush(&ctx, family); 832 893 833 - afi = nf_tables_afinfo_lookup(net, family, false); 834 - if (IS_ERR(afi)) 835 - return PTR_ERR(afi); 894 + if (nla[NFTA_TABLE_HANDLE]) 895 + table = nf_tables_table_lookup_byhandle(net, 896 + nla[NFTA_TABLE_HANDLE], 897 + genmask); 898 + else 899 + table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], 900 + family, genmask); 836 901 837 - table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); 838 902 if (IS_ERR(table)) 839 903 return PTR_ERR(table); 840 904 ··· 845 903 table->use > 0) 846 904 return -EBUSY; 847 905 848 - ctx.afi = afi; 906 + ctx.family = family; 849 907 ctx.table = table; 850 908 851 909 return nft_flush_table(&ctx); ··· 857 915 858 916 kfree(ctx->table->name); 859 917 kfree(ctx->table); 860 - module_put(ctx->afi->owner); 861 918 } 862 919 863 920 int nft_register_chain_type(const struct nf_chain_type *ctype) ··· 1057 1116 goto err; 1058 1117 1059 1118 err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq, 1060 - event, 0, ctx->afi->family, ctx->table, 1119 + event, 0, ctx->family, ctx->table, 1061 1120 ctx->chain); 1062 1121 if (err < 0) { 1063 1122 kfree_skb(skb); ··· 1075 1134 struct netlink_callback *cb) 1076 1135 { 1077 1136 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 1078 - const struct nft_af_info *afi; 1079 1137 const struct nft_table *table; 1080 1138 const struct nft_chain *chain; 1081 1139 unsigned int idx = 0, s_idx = cb->args[0]; ··· 1084 1144 rcu_read_lock(); 1085 1145 cb->seq = net->nft.base_seq; 1086 1146 1087 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 1088 - if (family != NFPROTO_UNSPEC && family != afi->family) 1147 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 1148 + if (family != NFPROTO_UNSPEC && family != table->family) 1089 1149 continue; 1090 1150 1091 - list_for_each_entry_rcu(table, &afi->tables, list) { 1092 - list_for_each_entry_rcu(chain, &table->chains, list) { 1093 - if (idx < s_idx) 1094 - goto cont; 1095 - if (idx > s_idx) 1096 - memset(&cb->args[1], 0, 1097 - sizeof(cb->args) - sizeof(cb->args[0])); 1098 - if (!nft_is_active(net, chain)) 1099 - continue; 1100 - if (nf_tables_fill_chain_info(skb, net, 1101 - NETLINK_CB(cb->skb).portid, 1102 - cb->nlh->nlmsg_seq, 1103 - NFT_MSG_NEWCHAIN, 1104 - NLM_F_MULTI, 1105 - afi->family, table, chain) < 0) 1106 - goto done; 1151 + list_for_each_entry_rcu(chain, &table->chains, list) { 1152 + if (idx < s_idx) 1153 + goto cont; 1154 + if (idx > s_idx) 1155 + memset(&cb->args[1], 0, 1156 + sizeof(cb->args) - sizeof(cb->args[0])); 1157 + if (!nft_is_active(net, chain)) 1158 + continue; 1159 + if (nf_tables_fill_chain_info(skb, net, 1160 + NETLINK_CB(cb->skb).portid, 1161 + cb->nlh->nlmsg_seq, 1162 + NFT_MSG_NEWCHAIN, 1163 + NLM_F_MULTI, 1164 + table->family, table, 1165 + chain) < 0) 1166 + goto done; 1107 1167 1108 - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1168 + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 1109 1169 cont: 1110 - idx++; 1111 - } 1170 + idx++; 1112 1171 } 1113 1172 } 1114 1173 done: ··· 1123 1184 { 1124 1185 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1125 1186 u8 genmask = nft_genmask_cur(net); 1126 - const struct nft_af_info *afi; 1127 1187 const struct nft_table *table; 1128 1188 const struct nft_chain *chain; 1129 1189 struct sk_buff *skb2; ··· 1136 1198 return netlink_dump_start(nlsk, skb, nlh, &c); 1137 1199 } 1138 1200 1139 - afi = nf_tables_afinfo_lookup(net, family, false); 1140 - if (IS_ERR(afi)) 1141 - return PTR_ERR(afi); 1142 - 1143 - table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); 1201 + table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, 1202 + genmask); 1144 1203 if (IS_ERR(table)) 1145 1204 return PTR_ERR(table); 1146 1205 ··· 1245 1310 1246 1311 static int nft_chain_parse_hook(struct net *net, 1247 1312 const struct nlattr * const nla[], 1248 - struct nft_af_info *afi, 1249 - struct nft_chain_hook *hook, bool create) 1313 + struct nft_chain_hook *hook, u8 family, 1314 + bool create) 1250 1315 { 1251 1316 struct nlattr *ha[NFTA_HOOK_MAX + 1]; 1252 1317 const struct nf_chain_type *type; ··· 1263 1328 return -EINVAL; 1264 1329 1265 1330 hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); 1266 - if (hook->num >= afi->nhooks) 1267 - return -EINVAL; 1268 - 1269 1331 hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); 1270 1332 1271 - type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; 1333 + type = chain_type[family][NFT_CHAIN_T_DEFAULT]; 1272 1334 if (nla[NFTA_CHAIN_TYPE]) { 1273 - type = nf_tables_chain_type_lookup(afi, nla[NFTA_CHAIN_TYPE], 1274 - create); 1335 + type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE], 1336 + family, create); 1275 1337 if (IS_ERR(type)) 1276 1338 return PTR_ERR(type); 1277 1339 } ··· 1285 1353 hook->type = type; 1286 1354 1287 1355 hook->dev = NULL; 1288 - if (afi->flags & NFT_AF_NEEDS_DEV) { 1356 + if (family == NFPROTO_NETDEV) { 1289 1357 char ifname[IFNAMSIZ]; 1290 1358 1291 1359 if (!ha[NFTA_HOOK_DEV]) { ··· 1320 1388 { 1321 1389 const struct nlattr * const *nla = ctx->nla; 1322 1390 struct nft_table *table = ctx->table; 1323 - struct nft_af_info *afi = ctx->afi; 1324 1391 struct nft_base_chain *basechain; 1325 1392 struct nft_stats __percpu *stats; 1326 1393 struct net *net = ctx->net; ··· 1333 1402 struct nft_chain_hook hook; 1334 1403 struct nf_hook_ops *ops; 1335 1404 1336 - err = nft_chain_parse_hook(net, nla, afi, &hook, create); 1405 + err = nft_chain_parse_hook(net, nla, &hook, family, create); 1337 1406 if (err < 0) 1338 1407 return err; 1339 1408 ··· 1426 1495 if (!nft_is_base_chain(chain)) 1427 1496 return -EBUSY; 1428 1497 1429 - err = nft_chain_parse_hook(ctx->net, nla, ctx->afi, &hook, 1498 + err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family, 1430 1499 create); 1431 1500 if (err < 0) 1432 1501 return err; ··· 1505 1574 const struct nlattr * uninitialized_var(name); 1506 1575 u8 genmask = nft_genmask_next(net); 1507 1576 int family = nfmsg->nfgen_family; 1508 - struct nft_af_info *afi; 1509 1577 struct nft_table *table; 1510 1578 struct nft_chain *chain; 1511 1579 u8 policy = NF_ACCEPT; ··· 1514 1584 1515 1585 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 1516 1586 1517 - afi = nf_tables_afinfo_lookup(net, family, true); 1518 - if (IS_ERR(afi)) 1519 - return PTR_ERR(afi); 1520 - 1521 - table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); 1587 + table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, 1588 + genmask); 1522 1589 if (IS_ERR(table)) 1523 1590 return PTR_ERR(table); 1524 1591 ··· 1555 1628 } 1556 1629 } 1557 1630 1558 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 1631 + nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); 1559 1632 1560 1633 if (chain != NULL) { 1561 1634 if (nlh->nlmsg_flags & NLM_F_EXCL) ··· 1576 1649 { 1577 1650 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1578 1651 u8 genmask = nft_genmask_next(net); 1579 - struct nft_af_info *afi; 1580 1652 struct nft_table *table; 1581 1653 struct nft_chain *chain; 1582 1654 struct nft_rule *rule; 1583 1655 int family = nfmsg->nfgen_family; 1584 1656 struct nft_ctx ctx; 1657 + u64 handle; 1585 1658 u32 use; 1586 1659 int err; 1587 1660 1588 - afi = nf_tables_afinfo_lookup(net, family, false); 1589 - if (IS_ERR(afi)) 1590 - return PTR_ERR(afi); 1591 - 1592 - table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); 1661 + table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, 1662 + genmask); 1593 1663 if (IS_ERR(table)) 1594 1664 return PTR_ERR(table); 1595 1665 1596 - chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); 1666 + if (nla[NFTA_CHAIN_HANDLE]) { 1667 + handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); 1668 + chain = nf_tables_chain_lookup_byhandle(table, handle, genmask); 1669 + } else { 1670 + chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); 1671 + } 1597 1672 if (IS_ERR(chain)) 1598 1673 return PTR_ERR(chain); 1599 1674 ··· 1603 1674 chain->use > 0) 1604 1675 return -EBUSY; 1605 1676 1606 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 1677 + nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); 1607 1678 1608 1679 use = chain->use; 1609 1680 list_for_each_entry(rule, &chain->rules, list) { ··· 1768 1839 if (err < 0) 1769 1840 return err; 1770 1841 1771 - type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]); 1842 + type = nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]); 1772 1843 if (IS_ERR(type)) 1773 1844 return PTR_ERR(type); 1774 1845 ··· 1991 2062 goto err; 1992 2063 1993 2064 err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq, 1994 - event, 0, ctx->afi->family, ctx->table, 2065 + event, 0, ctx->family, ctx->table, 1995 2066 ctx->chain, rule); 1996 2067 if (err < 0) { 1997 2068 kfree_skb(skb); ··· 2015 2086 { 2016 2087 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 2017 2088 const struct nft_rule_dump_ctx *ctx = cb->data; 2018 - const struct nft_af_info *afi; 2019 2089 const struct nft_table *table; 2020 2090 const struct nft_chain *chain; 2021 2091 const struct nft_rule *rule; ··· 2025 2097 rcu_read_lock(); 2026 2098 cb->seq = net->nft.base_seq; 2027 2099 2028 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 2029 - if (family != NFPROTO_UNSPEC && family != afi->family) 2100 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 2101 + if (family != NFPROTO_UNSPEC && family != table->family) 2030 2102 continue; 2031 2103 2032 - list_for_each_entry_rcu(table, &afi->tables, list) { 2033 - if (ctx && ctx->table && 2034 - strcmp(ctx->table, table->name) != 0) 2104 + if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0) 2105 + continue; 2106 + 2107 + list_for_each_entry_rcu(chain, &table->chains, list) { 2108 + if (ctx && ctx->chain && 2109 + strcmp(ctx->chain, chain->name) != 0) 2035 2110 continue; 2036 2111 2037 - list_for_each_entry_rcu(chain, &table->chains, list) { 2038 - if (ctx && ctx->chain && 2039 - strcmp(ctx->chain, chain->name) != 0) 2040 - continue; 2112 + list_for_each_entry_rcu(rule, &chain->rules, list) { 2113 + if (!nft_is_active(net, rule)) 2114 + goto cont; 2115 + if (idx < s_idx) 2116 + goto cont; 2117 + if (idx > s_idx) 2118 + memset(&cb->args[1], 0, 2119 + sizeof(cb->args) - sizeof(cb->args[0])); 2120 + if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid, 2121 + cb->nlh->nlmsg_seq, 2122 + NFT_MSG_NEWRULE, 2123 + NLM_F_MULTI | NLM_F_APPEND, 2124 + table->family, 2125 + table, chain, rule) < 0) 2126 + goto done; 2041 2127 2042 - list_for_each_entry_rcu(rule, &chain->rules, list) { 2043 - if (!nft_is_active(net, rule)) 2044 - goto cont; 2045 - if (idx < s_idx) 2046 - goto cont; 2047 - if (idx > s_idx) 2048 - memset(&cb->args[1], 0, 2049 - sizeof(cb->args) - sizeof(cb->args[0])); 2050 - if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid, 2051 - cb->nlh->nlmsg_seq, 2052 - NFT_MSG_NEWRULE, 2053 - NLM_F_MULTI | NLM_F_APPEND, 2054 - afi->family, table, chain, rule) < 0) 2055 - goto done; 2056 - 2057 - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 2128 + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 2058 2129 cont: 2059 - idx++; 2060 - } 2130 + idx++; 2061 2131 } 2062 2132 } 2063 2133 } ··· 2085 2159 { 2086 2160 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2087 2161 u8 genmask = nft_genmask_cur(net); 2088 - const struct nft_af_info *afi; 2089 2162 const struct nft_table *table; 2090 2163 const struct nft_chain *chain; 2091 2164 const struct nft_rule *rule; ··· 2128 2203 return netlink_dump_start(nlsk, skb, nlh, &c); 2129 2204 } 2130 2205 2131 - afi = nf_tables_afinfo_lookup(net, family, false); 2132 - if (IS_ERR(afi)) 2133 - return PTR_ERR(afi); 2134 - 2135 - table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); 2206 + table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, 2207 + genmask); 2136 2208 if (IS_ERR(table)) 2137 2209 return PTR_ERR(table); 2138 2210 ··· 2186 2264 { 2187 2265 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2188 2266 u8 genmask = nft_genmask_next(net); 2189 - struct nft_af_info *afi; 2267 + int family = nfmsg->nfgen_family; 2190 2268 struct nft_table *table; 2191 2269 struct nft_chain *chain; 2192 2270 struct nft_rule *rule, *old_rule = NULL; ··· 2202 2280 2203 2281 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 2204 2282 2205 - afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); 2206 - if (IS_ERR(afi)) 2207 - return PTR_ERR(afi); 2208 - 2209 - table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); 2283 + table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, 2284 + genmask); 2210 2285 if (IS_ERR(table)) 2211 2286 return PTR_ERR(table); 2212 2287 ··· 2242 2323 return PTR_ERR(old_rule); 2243 2324 } 2244 2325 2245 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 2326 + nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); 2246 2327 2247 2328 n = 0; 2248 2329 size = 0; ··· 2366 2447 { 2367 2448 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2368 2449 u8 genmask = nft_genmask_next(net); 2369 - struct nft_af_info *afi; 2370 2450 struct nft_table *table; 2371 2451 struct nft_chain *chain = NULL; 2372 2452 struct nft_rule *rule; 2373 2453 int family = nfmsg->nfgen_family, err = 0; 2374 2454 struct nft_ctx ctx; 2375 2455 2376 - afi = nf_tables_afinfo_lookup(net, family, false); 2377 - if (IS_ERR(afi)) 2378 - return PTR_ERR(afi); 2379 - 2380 - table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); 2456 + table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, 2457 + genmask); 2381 2458 if (IS_ERR(table)) 2382 2459 return PTR_ERR(table); 2383 2460 ··· 2384 2469 return PTR_ERR(chain); 2385 2470 } 2386 2471 2387 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); 2472 + nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); 2388 2473 2389 2474 if (chain) { 2390 2475 if (nla[NFTA_RULE_HANDLE]) { ··· 2551 2636 [NFTA_SET_USERDATA] = { .type = NLA_BINARY, 2552 2637 .len = NFT_USERDATA_MAXLEN }, 2553 2638 [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, 2639 + [NFTA_SET_HANDLE] = { .type = NLA_U64 }, 2554 2640 }; 2555 2641 2556 2642 static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { ··· 2565 2649 u8 genmask) 2566 2650 { 2567 2651 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2568 - struct nft_af_info *afi = NULL; 2652 + int family = nfmsg->nfgen_family; 2569 2653 struct nft_table *table = NULL; 2570 2654 2571 - if (nfmsg->nfgen_family != NFPROTO_UNSPEC) { 2572 - afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); 2573 - if (IS_ERR(afi)) 2574 - return PTR_ERR(afi); 2575 - } 2576 - 2577 2655 if (nla[NFTA_SET_TABLE] != NULL) { 2578 - if (afi == NULL) 2579 - return -EAFNOSUPPORT; 2580 - 2581 - table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], 2582 - genmask); 2656 + table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], 2657 + family, genmask); 2583 2658 if (IS_ERR(table)) 2584 2659 return PTR_ERR(table); 2585 2660 } 2586 2661 2587 - nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); 2662 + nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); 2588 2663 return 0; 2589 2664 } 2590 2665 ··· 2589 2682 2590 2683 list_for_each_entry(set, &table->sets, list) { 2591 2684 if (!nla_strcmp(nla, set->name) && 2685 + nft_active_genmask(set, genmask)) 2686 + return set; 2687 + } 2688 + return ERR_PTR(-ENOENT); 2689 + } 2690 + 2691 + static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table, 2692 + const struct nlattr *nla, u8 genmask) 2693 + { 2694 + struct nft_set *set; 2695 + 2696 + if (nla == NULL) 2697 + return ERR_PTR(-EINVAL); 2698 + 2699 + list_for_each_entry(set, &table->sets, list) { 2700 + if (be64_to_cpu(nla_get_be64(nla)) == set->handle && 2592 2701 nft_active_genmask(set, genmask)) 2593 2702 return set; 2594 2703 } ··· 2718 2795 goto nla_put_failure; 2719 2796 2720 2797 nfmsg = nlmsg_data(nlh); 2721 - nfmsg->nfgen_family = ctx->afi->family; 2798 + nfmsg->nfgen_family = ctx->family; 2722 2799 nfmsg->version = NFNETLINK_V0; 2723 2800 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); 2724 2801 2725 2802 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name)) 2726 2803 goto nla_put_failure; 2727 2804 if (nla_put_string(skb, NFTA_SET_NAME, set->name)) 2805 + goto nla_put_failure; 2806 + if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle), 2807 + NFTA_SET_PAD)) 2728 2808 goto nla_put_failure; 2729 2809 if (set->flags != 0) 2730 2810 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) ··· 2813 2887 { 2814 2888 const struct nft_set *set; 2815 2889 unsigned int idx, s_idx = cb->args[0]; 2816 - struct nft_af_info *afi; 2817 2890 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; 2818 2891 struct net *net = sock_net(skb->sk); 2819 - int cur_family = cb->args[3]; 2820 2892 struct nft_ctx *ctx = cb->data, ctx_set; 2821 2893 2822 2894 if (cb->args[1]) ··· 2823 2899 rcu_read_lock(); 2824 2900 cb->seq = net->nft.base_seq; 2825 2901 2826 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 2827 - if (ctx->afi && ctx->afi != afi) 2902 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 2903 + if (ctx->family != NFPROTO_UNSPEC && 2904 + ctx->family != table->family) 2828 2905 continue; 2829 2906 2830 - if (cur_family) { 2831 - if (afi->family != cur_family) 2907 + if (ctx->table && ctx->table != table) 2908 + continue; 2909 + 2910 + if (cur_table) { 2911 + if (cur_table != table) 2832 2912 continue; 2833 2913 2834 - cur_family = 0; 2914 + cur_table = NULL; 2835 2915 } 2836 - list_for_each_entry_rcu(table, &afi->tables, list) { 2837 - if (ctx->table && ctx->table != table) 2838 - continue; 2916 + idx = 0; 2917 + list_for_each_entry_rcu(set, &table->sets, list) { 2918 + if (idx < s_idx) 2919 + goto cont; 2920 + if (!nft_is_active(net, set)) 2921 + goto cont; 2839 2922 2840 - if (cur_table) { 2841 - if (cur_table != table) 2842 - continue; 2923 + ctx_set = *ctx; 2924 + ctx_set.table = table; 2925 + ctx_set.family = table->family; 2843 2926 2844 - cur_table = NULL; 2927 + if (nf_tables_fill_set(skb, &ctx_set, set, 2928 + NFT_MSG_NEWSET, 2929 + NLM_F_MULTI) < 0) { 2930 + cb->args[0] = idx; 2931 + cb->args[2] = (unsigned long) table; 2932 + goto done; 2845 2933 } 2846 - idx = 0; 2847 - list_for_each_entry_rcu(set, &table->sets, list) { 2848 - if (idx < s_idx) 2849 - goto cont; 2850 - if (!nft_is_active(net, set)) 2851 - goto cont; 2852 - 2853 - ctx_set = *ctx; 2854 - ctx_set.table = table; 2855 - ctx_set.afi = afi; 2856 - if (nf_tables_fill_set(skb, &ctx_set, set, 2857 - NFT_MSG_NEWSET, 2858 - NLM_F_MULTI) < 0) { 2859 - cb->args[0] = idx; 2860 - cb->args[2] = (unsigned long) table; 2861 - cb->args[3] = afi->family; 2862 - goto done; 2863 - } 2864 - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 2934 + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 2865 2935 cont: 2866 - idx++; 2867 - } 2868 - if (s_idx) 2869 - s_idx = 0; 2936 + idx++; 2870 2937 } 2938 + if (s_idx) 2939 + s_idx = 0; 2871 2940 } 2872 2941 cb->args[1] = 1; 2873 2942 done: ··· 2958 3041 { 2959 3042 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2960 3043 u8 genmask = nft_genmask_next(net); 3044 + int family = nfmsg->nfgen_family; 2961 3045 const struct nft_set_ops *ops; 2962 - struct nft_af_info *afi; 2963 3046 struct nft_table *table; 2964 3047 struct nft_set *set; 2965 3048 struct nft_ctx ctx; ··· 3066 3149 3067 3150 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 3068 3151 3069 - afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); 3070 - if (IS_ERR(afi)) 3071 - return PTR_ERR(afi); 3072 - 3073 - table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask); 3152 + table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], family, 3153 + genmask); 3074 3154 if (IS_ERR(table)) 3075 3155 return PTR_ERR(table); 3076 3156 3077 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 3157 + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 3078 3158 3079 3159 set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask); 3080 3160 if (IS_ERR(set)) { ··· 3137 3223 set->udata = udata; 3138 3224 set->timeout = timeout; 3139 3225 set->gc_int = gc_int; 3226 + set->handle = nf_tables_alloc_handle(table); 3140 3227 3141 3228 err = ops->init(set, &desc, nla); 3142 3229 if (err < 0) ··· 3195 3280 if (err < 0) 3196 3281 return err; 3197 3282 3198 - set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); 3283 + if (nla[NFTA_SET_HANDLE]) 3284 + set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask); 3285 + else 3286 + set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); 3199 3287 if (IS_ERR(set)) 3200 3288 return PTR_ERR(set); 3201 3289 ··· 3333 3415 u8 genmask) 3334 3416 { 3335 3417 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 3336 - struct nft_af_info *afi; 3418 + int family = nfmsg->nfgen_family; 3337 3419 struct nft_table *table; 3338 3420 3339 - afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); 3340 - if (IS_ERR(afi)) 3341 - return PTR_ERR(afi); 3342 - 3343 - table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE], 3344 - genmask); 3421 + table = nf_tables_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], 3422 + family, genmask); 3345 3423 if (IS_ERR(table)) 3346 3424 return PTR_ERR(table); 3347 3425 3348 - nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); 3426 + nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); 3349 3427 return 0; 3350 3428 } 3351 3429 ··· 3446 3532 { 3447 3533 struct nft_set_dump_ctx *dump_ctx = cb->data; 3448 3534 struct net *net = sock_net(skb->sk); 3449 - struct nft_af_info *afi; 3450 3535 struct nft_table *table; 3451 3536 struct nft_set *set; 3452 3537 struct nft_set_dump_args args; ··· 3457 3544 int event; 3458 3545 3459 3546 rcu_read_lock(); 3460 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 3461 - if (afi != dump_ctx->ctx.afi) 3547 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 3548 + if (dump_ctx->ctx.family != NFPROTO_UNSPEC && 3549 + dump_ctx->ctx.family != table->family) 3462 3550 continue; 3463 3551 3464 - list_for_each_entry_rcu(table, &afi->tables, list) { 3465 - if (table != dump_ctx->ctx.table) 3466 - continue; 3552 + if (table != dump_ctx->ctx.table) 3553 + continue; 3467 3554 3468 - list_for_each_entry_rcu(set, &table->sets, list) { 3469 - if (set == dump_ctx->set) { 3470 - set_found = true; 3471 - break; 3472 - } 3555 + list_for_each_entry_rcu(set, &table->sets, list) { 3556 + if (set == dump_ctx->set) { 3557 + set_found = true; 3558 + break; 3473 3559 } 3474 - break; 3475 3560 } 3476 3561 break; 3477 3562 } ··· 3489 3578 goto nla_put_failure; 3490 3579 3491 3580 nfmsg = nlmsg_data(nlh); 3492 - nfmsg->nfgen_family = afi->family; 3581 + nfmsg->nfgen_family = table->family; 3493 3582 nfmsg->version = NFNETLINK_V0; 3494 3583 nfmsg->res_id = htons(net->nft.base_seq & 0xffff); 3495 3584 ··· 3552 3641 goto nla_put_failure; 3553 3642 3554 3643 nfmsg = nlmsg_data(nlh); 3555 - nfmsg->nfgen_family = ctx->afi->family; 3644 + nfmsg->nfgen_family = ctx->family; 3556 3645 nfmsg->version = NFNETLINK_V0; 3557 3646 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); 3558 3647 ··· 3909 3998 list_for_each_entry(binding, &set->bindings, list) { 3910 3999 struct nft_ctx bind_ctx = { 3911 4000 .net = ctx->net, 3912 - .afi = ctx->afi, 4001 + .family = ctx->family, 3913 4002 .table = ctx->table, 3914 4003 .chain = (struct nft_chain *)binding->chain, 3915 4004 }; ··· 4328 4417 } 4329 4418 EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); 4330 4419 4420 + struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table, 4421 + const struct nlattr *nla, 4422 + u32 objtype, u8 genmask) 4423 + { 4424 + struct nft_object *obj; 4425 + 4426 + list_for_each_entry(obj, &table->objects, list) { 4427 + if (be64_to_cpu(nla_get_be64(nla)) == obj->handle && 4428 + objtype == obj->ops->type->type && 4429 + nft_active_genmask(obj, genmask)) 4430 + return obj; 4431 + } 4432 + return ERR_PTR(-ENOENT); 4433 + } 4434 + 4331 4435 static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { 4332 4436 [NFTA_OBJ_TABLE] = { .type = NLA_STRING, 4333 4437 .len = NFT_TABLE_MAXNAMELEN - 1 }, ··· 4350 4424 .len = NFT_OBJ_MAXNAMELEN - 1 }, 4351 4425 [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, 4352 4426 [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, 4427 + [NFTA_OBJ_HANDLE] = { .type = NLA_U64}, 4353 4428 }; 4354 4429 4355 4430 static struct nft_object *nft_obj_init(const struct nft_ctx *ctx, ··· 4456 4529 const struct nft_object_type *type; 4457 4530 u8 genmask = nft_genmask_next(net); 4458 4531 int family = nfmsg->nfgen_family; 4459 - struct nft_af_info *afi; 4460 4532 struct nft_table *table; 4461 4533 struct nft_object *obj; 4462 4534 struct nft_ctx ctx; ··· 4467 4541 !nla[NFTA_OBJ_DATA]) 4468 4542 return -EINVAL; 4469 4543 4470 - afi = nf_tables_afinfo_lookup(net, family, true); 4471 - if (IS_ERR(afi)) 4472 - return PTR_ERR(afi); 4473 - 4474 - table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); 4544 + table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, 4545 + genmask); 4475 4546 if (IS_ERR(table)) 4476 4547 return PTR_ERR(table); 4477 4548 ··· 4486 4563 return 0; 4487 4564 } 4488 4565 4489 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 4566 + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 4490 4567 4491 4568 type = nft_obj_type_get(objtype); 4492 4569 if (IS_ERR(type)) ··· 4498 4575 goto err1; 4499 4576 } 4500 4577 obj->table = table; 4578 + obj->handle = nf_tables_alloc_handle(table); 4579 + 4501 4580 obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); 4502 4581 if (!obj->name) { 4503 4582 err = -ENOMEM; ··· 4546 4621 nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || 4547 4622 nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || 4548 4623 nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || 4549 - nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) 4624 + nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) || 4625 + nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), 4626 + NFTA_OBJ_PAD)) 4550 4627 goto nla_put_failure; 4551 4628 4552 4629 nlmsg_end(skb, nlh); ··· 4567 4640 static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) 4568 4641 { 4569 4642 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 4570 - const struct nft_af_info *afi; 4571 4643 const struct nft_table *table; 4572 4644 unsigned int idx = 0, s_idx = cb->args[0]; 4573 4645 struct nft_obj_filter *filter = cb->data; ··· 4581 4655 rcu_read_lock(); 4582 4656 cb->seq = net->nft.base_seq; 4583 4657 4584 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 4585 - if (family != NFPROTO_UNSPEC && family != afi->family) 4658 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 4659 + if (family != NFPROTO_UNSPEC && family != table->family) 4586 4660 continue; 4587 4661 4588 - list_for_each_entry_rcu(table, &afi->tables, list) { 4589 - list_for_each_entry_rcu(obj, &table->objects, list) { 4590 - if (!nft_is_active(net, obj)) 4591 - goto cont; 4592 - if (idx < s_idx) 4593 - goto cont; 4594 - if (idx > s_idx) 4595 - memset(&cb->args[1], 0, 4596 - sizeof(cb->args) - sizeof(cb->args[0])); 4597 - if (filter && filter->table[0] && 4598 - strcmp(filter->table, table->name)) 4599 - goto cont; 4600 - if (filter && 4601 - filter->type != NFT_OBJECT_UNSPEC && 4602 - obj->ops->type->type != filter->type) 4603 - goto cont; 4662 + list_for_each_entry_rcu(obj, &table->objects, list) { 4663 + if (!nft_is_active(net, obj)) 4664 + goto cont; 4665 + if (idx < s_idx) 4666 + goto cont; 4667 + if (idx > s_idx) 4668 + memset(&cb->args[1], 0, 4669 + sizeof(cb->args) - sizeof(cb->args[0])); 4670 + if (filter && filter->table[0] && 4671 + strcmp(filter->table, table->name)) 4672 + goto cont; 4673 + if (filter && 4674 + filter->type != NFT_OBJECT_UNSPEC && 4675 + obj->ops->type->type != filter->type) 4676 + goto cont; 4604 4677 4605 - if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, 4606 - cb->nlh->nlmsg_seq, 4607 - NFT_MSG_NEWOBJ, 4608 - NLM_F_MULTI | NLM_F_APPEND, 4609 - afi->family, table, obj, reset) < 0) 4610 - goto done; 4678 + if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, 4679 + cb->nlh->nlmsg_seq, 4680 + NFT_MSG_NEWOBJ, 4681 + NLM_F_MULTI | NLM_F_APPEND, 4682 + table->family, table, 4683 + obj, reset) < 0) 4684 + goto done; 4611 4685 4612 - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 4686 + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 4613 4687 cont: 4614 - idx++; 4615 - } 4688 + idx++; 4616 4689 } 4617 4690 } 4618 4691 done: ··· 4663 4738 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4664 4739 u8 genmask = nft_genmask_cur(net); 4665 4740 int family = nfmsg->nfgen_family; 4666 - const struct nft_af_info *afi; 4667 4741 const struct nft_table *table; 4668 4742 struct nft_object *obj; 4669 4743 struct sk_buff *skb2; ··· 4693 4769 !nla[NFTA_OBJ_TYPE]) 4694 4770 return -EINVAL; 4695 4771 4696 - afi = nf_tables_afinfo_lookup(net, family, false); 4697 - if (IS_ERR(afi)) 4698 - return PTR_ERR(afi); 4699 - 4700 - table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); 4772 + table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, 4773 + genmask); 4701 4774 if (IS_ERR(table)) 4702 4775 return PTR_ERR(table); 4703 4776 ··· 4740 4819 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4741 4820 u8 genmask = nft_genmask_next(net); 4742 4821 int family = nfmsg->nfgen_family; 4743 - struct nft_af_info *afi; 4744 4822 struct nft_table *table; 4745 4823 struct nft_object *obj; 4746 4824 struct nft_ctx ctx; 4747 4825 u32 objtype; 4748 4826 4749 4827 if (!nla[NFTA_OBJ_TYPE] || 4750 - !nla[NFTA_OBJ_NAME]) 4828 + (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE])) 4751 4829 return -EINVAL; 4752 4830 4753 - afi = nf_tables_afinfo_lookup(net, family, true); 4754 - if (IS_ERR(afi)) 4755 - return PTR_ERR(afi); 4756 - 4757 - table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); 4831 + table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, 4832 + genmask); 4758 4833 if (IS_ERR(table)) 4759 4834 return PTR_ERR(table); 4760 4835 4761 4836 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4762 - obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); 4837 + if (nla[NFTA_OBJ_HANDLE]) 4838 + obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE], 4839 + objtype, genmask); 4840 + else 4841 + obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], 4842 + objtype, genmask); 4763 4843 if (IS_ERR(obj)) 4764 4844 return PTR_ERR(obj); 4765 4845 if (obj->use > 0) 4766 4846 return -EBUSY; 4767 4847 4768 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 4848 + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 4769 4849 4770 4850 return nft_delobj(&ctx, obj); 4771 4851 } ··· 4804 4882 struct nft_object *obj, int event) 4805 4883 { 4806 4884 nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, 4807 - ctx->afi->family, ctx->report, GFP_KERNEL); 4885 + ctx->family, ctx->report, GFP_KERNEL); 4808 4886 } 4809 4887 4810 4888 /* ··· 4832 4910 [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, 4833 4911 .len = NFT_NAME_MAXLEN - 1 }, 4834 4912 [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, 4913 + [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 }, 4835 4914 }; 4836 4915 4837 4916 struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, ··· 4849 4926 return ERR_PTR(-ENOENT); 4850 4927 } 4851 4928 EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); 4929 + 4930 + struct nft_flowtable * 4931 + nf_tables_flowtable_lookup_byhandle(const struct nft_table *table, 4932 + const struct nlattr *nla, u8 genmask) 4933 + { 4934 + struct nft_flowtable *flowtable; 4935 + 4936 + list_for_each_entry(flowtable, &table->flowtables, list) { 4937 + if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle && 4938 + nft_active_genmask(flowtable, genmask)) 4939 + return flowtable; 4940 + } 4941 + return ERR_PTR(-ENOENT); 4942 + } 4852 4943 4853 4944 #define NFT_FLOWTABLE_DEVICE_MAX 8 4854 4945 ··· 4930 4993 return -EINVAL; 4931 4994 4932 4995 hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM])); 4933 - if (hooknum >= ctx->afi->nhooks) 4996 + if (hooknum != NF_NETDEV_INGRESS) 4934 4997 return -EINVAL; 4935 4998 4936 4999 priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY])); ··· 4946 5009 goto err1; 4947 5010 } 4948 5011 5012 + flowtable->hooknum = hooknum; 5013 + flowtable->priority = priority; 4949 5014 flowtable->ops = ops; 4950 5015 flowtable->ops_len = n; 4951 5016 ··· 4968 5029 return err; 4969 5030 } 4970 5031 4971 - static const struct nf_flowtable_type * 4972 - __nft_flowtable_type_get(const struct nft_af_info *afi) 5032 + static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family) 4973 5033 { 4974 5034 const struct nf_flowtable_type *type; 4975 5035 4976 5036 list_for_each_entry(type, &nf_tables_flowtables, list) { 4977 - if (afi->family == type->family) 5037 + if (family == type->family) 4978 5038 return type; 4979 5039 } 4980 5040 return NULL; 4981 5041 } 4982 5042 4983 - static const struct nf_flowtable_type * 4984 - nft_flowtable_type_get(const struct nft_af_info *afi) 5043 + static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family) 4985 5044 { 4986 5045 const struct nf_flowtable_type *type; 4987 5046 4988 - type = __nft_flowtable_type_get(afi); 5047 + type = __nft_flowtable_type_get(family); 4989 5048 if (type != NULL && try_module_get(type->owner)) 4990 5049 return type; 4991 5050 4992 5051 #ifdef CONFIG_MODULES 4993 5052 if (type == NULL) { 4994 5053 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 4995 - request_module("nf-flowtable-%u", afi->family); 5054 + request_module("nf-flowtable-%u", family); 4996 5055 nfnl_lock(NFNL_SUBSYS_NFTABLES); 4997 - if (__nft_flowtable_type_get(afi)) 5056 + if (__nft_flowtable_type_get(family)) 4998 5057 return ERR_PTR(-EAGAIN); 4999 5058 } 5000 5059 #endif ··· 5004 5067 void *data) 5005 5068 { 5006 5069 struct nft_flowtable *flowtable; 5007 - const struct nft_af_info *afi; 5008 5070 const struct nft_table *table; 5009 5071 5010 5072 rcu_read_lock(); 5011 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 5012 - list_for_each_entry_rcu(table, &afi->tables, list) { 5013 - list_for_each_entry_rcu(flowtable, &table->flowtables, list) { 5014 - iter(&flowtable->data, data); 5015 - } 5073 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 5074 + list_for_each_entry_rcu(flowtable, &table->flowtables, list) { 5075 + iter(&flowtable->data, data); 5016 5076 } 5017 5077 } 5018 5078 rcu_read_unlock(); ··· 5040 5106 u8 genmask = nft_genmask_next(net); 5041 5107 int family = nfmsg->nfgen_family; 5042 5108 struct nft_flowtable *flowtable; 5043 - struct nft_af_info *afi; 5044 5109 struct nft_table *table; 5045 5110 struct nft_ctx ctx; 5046 5111 int err, i, k; ··· 5049 5116 !nla[NFTA_FLOWTABLE_HOOK]) 5050 5117 return -EINVAL; 5051 5118 5052 - afi = nf_tables_afinfo_lookup(net, family, true); 5053 - if (IS_ERR(afi)) 5054 - return PTR_ERR(afi); 5055 - 5056 - table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); 5119 + table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], 5120 + family, genmask); 5057 5121 if (IS_ERR(table)) 5058 5122 return PTR_ERR(table); 5059 5123 ··· 5067 5137 return 0; 5068 5138 } 5069 5139 5070 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 5140 + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 5071 5141 5072 5142 flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); 5073 5143 if (!flowtable) 5074 5144 return -ENOMEM; 5075 5145 5076 5146 flowtable->table = table; 5147 + flowtable->handle = nf_tables_alloc_handle(table); 5148 + 5077 5149 flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); 5078 5150 if (!flowtable->name) { 5079 5151 err = -ENOMEM; 5080 5152 goto err1; 5081 5153 } 5082 5154 5083 - type = nft_flowtable_type_get(afi); 5155 + type = nft_flowtable_type_get(family); 5084 5156 if (IS_ERR(type)) { 5085 5157 err = PTR_ERR(type); 5086 5158 goto err2; ··· 5142 5210 u8 genmask = nft_genmask_next(net); 5143 5211 int family = nfmsg->nfgen_family; 5144 5212 struct nft_flowtable *flowtable; 5145 - struct nft_af_info *afi; 5146 5213 struct nft_table *table; 5147 5214 struct nft_ctx ctx; 5148 5215 5149 - afi = nf_tables_afinfo_lookup(net, family, true); 5150 - if (IS_ERR(afi)) 5151 - return PTR_ERR(afi); 5152 - 5153 - table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); 5216 + table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], 5217 + family, genmask); 5154 5218 if (IS_ERR(table)) 5155 5219 return PTR_ERR(table); 5156 5220 5157 - flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], 5158 - genmask); 5221 + if (nla[NFTA_FLOWTABLE_HANDLE]) 5222 + flowtable = nf_tables_flowtable_lookup_byhandle(table, 5223 + nla[NFTA_FLOWTABLE_HANDLE], 5224 + genmask); 5225 + else 5226 + flowtable = nf_tables_flowtable_lookup(table, 5227 + nla[NFTA_FLOWTABLE_NAME], 5228 + genmask); 5159 5229 if (IS_ERR(flowtable)) 5160 5230 return PTR_ERR(flowtable); 5161 5231 if (flowtable->use > 0) 5162 5232 return -EBUSY; 5163 5233 5164 - nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 5234 + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); 5165 5235 5166 5236 return nft_delflowtable(&ctx, flowtable); 5167 5237 } ··· 5190 5256 5191 5257 if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || 5192 5258 nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || 5193 - nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) 5259 + nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || 5260 + nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), 5261 + NFTA_FLOWTABLE_PAD)) 5194 5262 goto nla_put_failure; 5195 5263 5196 5264 nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); ··· 5234 5298 struct net *net = sock_net(skb->sk); 5235 5299 int family = nfmsg->nfgen_family; 5236 5300 struct nft_flowtable *flowtable; 5237 - const struct nft_af_info *afi; 5238 5301 const struct nft_table *table; 5239 5302 5240 5303 rcu_read_lock(); 5241 5304 cb->seq = net->nft.base_seq; 5242 5305 5243 - list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 5244 - if (family != NFPROTO_UNSPEC && family != afi->family) 5306 + list_for_each_entry_rcu(table, &net->nft.tables, list) { 5307 + if (family != NFPROTO_UNSPEC && family != table->family) 5245 5308 continue; 5246 5309 5247 - list_for_each_entry_rcu(table, &afi->tables, list) { 5248 - list_for_each_entry_rcu(flowtable, &table->flowtables, list) { 5249 - if (!nft_is_active(net, flowtable)) 5250 - goto cont; 5251 - if (idx < s_idx) 5252 - goto cont; 5253 - if (idx > s_idx) 5254 - memset(&cb->args[1], 0, 5255 - sizeof(cb->args) - sizeof(cb->args[0])); 5256 - if (filter && filter->table[0] && 5257 - strcmp(filter->table, table->name)) 5258 - goto cont; 5310 + list_for_each_entry_rcu(flowtable, &table->flowtables, list) { 5311 + if (!nft_is_active(net, flowtable)) 5312 + goto cont; 5313 + if (idx < s_idx) 5314 + goto cont; 5315 + if (idx > s_idx) 5316 + memset(&cb->args[1], 0, 5317 + sizeof(cb->args) - sizeof(cb->args[0])); 5318 + if (filter && filter->table[0] && 5319 + strcmp(filter->table, table->name)) 5320 + goto cont; 5259 5321 5260 - if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, 5261 - cb->nlh->nlmsg_seq, 5262 - NFT_MSG_NEWFLOWTABLE, 5263 - NLM_F_MULTI | NLM_F_APPEND, 5264 - afi->family, flowtable) < 0) 5265 - goto done; 5322 + if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, 5323 + cb->nlh->nlmsg_seq, 5324 + NFT_MSG_NEWFLOWTABLE, 5325 + NLM_F_MULTI | NLM_F_APPEND, 5326 + table->family, flowtable) < 0) 5327 + goto done; 5266 5328 5267 - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 5329 + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 5268 5330 cont: 5269 - idx++; 5270 - } 5331 + idx++; 5271 5332 } 5272 5333 } 5273 5334 done: ··· 5317 5384 u8 genmask = nft_genmask_cur(net); 5318 5385 int family = nfmsg->nfgen_family; 5319 5386 struct nft_flowtable *flowtable; 5320 - const struct nft_af_info *afi; 5321 5387 const struct nft_table *table; 5322 5388 struct sk_buff *skb2; 5323 5389 int err; ··· 5342 5410 if (!nla[NFTA_FLOWTABLE_NAME]) 5343 5411 return -EINVAL; 5344 5412 5345 - afi = nf_tables_afinfo_lookup(net, family, false); 5346 - if (IS_ERR(afi)) 5347 - return PTR_ERR(afi); 5348 - 5349 - table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); 5413 + table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], 5414 + family, genmask); 5350 5415 if (IS_ERR(table)) 5351 5416 return PTR_ERR(table); 5352 5417 5353 5418 flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], 5354 5419 genmask); 5355 - if (IS_ERR(table)) 5420 + if (IS_ERR(flowtable)) 5356 5421 return PTR_ERR(flowtable); 5357 5422 5358 5423 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); ··· 5386 5457 5387 5458 err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid, 5388 5459 ctx->seq, event, 0, 5389 - ctx->afi->family, flowtable); 5460 + ctx->family, flowtable); 5390 5461 if (err < 0) { 5391 5462 kfree_skb(skb); 5392 5463 goto err; ··· 5464 5535 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 5465 5536 struct nft_flowtable *flowtable; 5466 5537 struct nft_table *table; 5467 - struct nft_af_info *afi; 5468 5538 5469 5539 if (event != NETDEV_UNREGISTER) 5470 5540 return 0; 5471 5541 5472 5542 nfnl_lock(NFNL_SUBSYS_NFTABLES); 5473 - list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { 5474 - list_for_each_entry(table, &afi->tables, list) { 5475 - list_for_each_entry(flowtable, &table->flowtables, list) { 5476 - nft_flowtable_event(event, dev, flowtable); 5477 - } 5543 + list_for_each_entry(table, &dev_net(dev)->nft.tables, list) { 5544 + list_for_each_entry(flowtable, &table->flowtables, list) { 5545 + nft_flowtable_event(event, dev, flowtable); 5478 5546 } 5479 5547 } 5480 5548 nfnl_unlock(NFNL_SUBSYS_NFTABLES); ··· 5724 5798 if (nft_trans_table_update(trans)) { 5725 5799 if (!nft_trans_table_enable(trans)) { 5726 5800 nf_tables_table_disable(net, 5727 - trans->ctx.afi, 5728 5801 trans->ctx.table); 5729 5802 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; 5730 5803 } ··· 5885 5960 if (nft_trans_table_update(trans)) { 5886 5961 if (nft_trans_table_enable(trans)) { 5887 5962 nf_tables_table_disable(net, 5888 - trans->ctx.afi, 5889 5963 trans->ctx.table); 5890 5964 trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; 5891 5965 } ··· 6487 6563 } 6488 6564 EXPORT_SYMBOL_GPL(nft_data_dump); 6489 6565 6490 - static int __net_init nf_tables_init_net(struct net *net) 6491 - { 6492 - INIT_LIST_HEAD(&net->nft.af_info); 6493 - INIT_LIST_HEAD(&net->nft.commit_list); 6494 - net->nft.base_seq = 1; 6495 - return 0; 6496 - } 6497 - 6498 - static void __net_exit nf_tables_exit_net(struct net *net) 6499 - { 6500 - WARN_ON_ONCE(!list_empty(&net->nft.af_info)); 6501 - WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); 6502 - } 6503 - 6504 6566 int __nft_release_basechain(struct nft_ctx *ctx) 6505 6567 { 6506 6568 struct nft_rule *rule, *nr; ··· 6507 6597 } 6508 6598 EXPORT_SYMBOL_GPL(__nft_release_basechain); 6509 6599 6510 - /* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */ 6511 - static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) 6600 + static void __nft_release_tables(struct net *net) 6512 6601 { 6513 6602 struct nft_flowtable *flowtable, *nf; 6514 6603 struct nft_table *table, *nt; ··· 6517 6608 struct nft_set *set, *ns; 6518 6609 struct nft_ctx ctx = { 6519 6610 .net = net, 6520 - .afi = afi, 6521 6611 }; 6522 6612 6523 - list_for_each_entry_safe(table, nt, &afi->tables, list) { 6613 + list_for_each_entry_safe(table, nt, &net->nft.tables, list) { 6614 + ctx.family = table->family; 6615 + 6524 6616 list_for_each_entry(chain, &table->chains, list) 6525 6617 nf_tables_unregister_hook(net, table, chain); 6526 6618 list_for_each_entry(flowtable, &table->flowtables, list) ··· 6562 6652 } 6563 6653 } 6564 6654 6655 + static int __net_init nf_tables_init_net(struct net *net) 6656 + { 6657 + INIT_LIST_HEAD(&net->nft.tables); 6658 + INIT_LIST_HEAD(&net->nft.commit_list); 6659 + net->nft.base_seq = 1; 6660 + return 0; 6661 + } 6662 + 6663 + static void __net_exit nf_tables_exit_net(struct net *net) 6664 + { 6665 + __nft_release_tables(net); 6666 + WARN_ON_ONCE(!list_empty(&net->nft.tables)); 6667 + WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); 6668 + } 6669 + 6565 6670 static struct pernet_operations nf_tables_net_ops = { 6566 6671 .init = nf_tables_init_net, 6567 6672 .exit = nf_tables_exit_net, ··· 6603 6678 6604 6679 register_netdevice_notifier(&nf_tables_flowtable_notifier); 6605 6680 6606 - pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n"); 6607 6681 return register_pernet_subsys(&nf_tables_net_ops); 6608 6682 err3: 6609 6683 nf_tables_core_module_exit();
+2 -47
net/netfilter/nf_tables_inet.c
··· 38 38 return nft_do_chain(&pkt, priv); 39 39 } 40 40 41 - static struct nft_af_info nft_af_inet __read_mostly = { 42 - .family = NFPROTO_INET, 43 - .nhooks = NF_INET_NUMHOOKS, 44 - .owner = THIS_MODULE, 45 - }; 46 - 47 - static int __net_init nf_tables_inet_init_net(struct net *net) 48 - { 49 - net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); 50 - if (net->nft.inet == NULL) 51 - return -ENOMEM; 52 - memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet)); 53 - 54 - if (nft_register_afinfo(net, net->nft.inet) < 0) 55 - goto err; 56 - 57 - return 0; 58 - 59 - err: 60 - kfree(net->nft.inet); 61 - return -ENOMEM; 62 - } 63 - 64 - static void __net_exit nf_tables_inet_exit_net(struct net *net) 65 - { 66 - nft_unregister_afinfo(net, net->nft.inet); 67 - kfree(net->nft.inet); 68 - } 69 - 70 - static struct pernet_operations nf_tables_inet_net_ops = { 71 - .init = nf_tables_inet_init_net, 72 - .exit = nf_tables_inet_exit_net, 73 - }; 74 - 75 41 static const struct nf_chain_type filter_inet = { 76 42 .name = "filter", 77 43 .type = NFT_CHAIN_T_DEFAULT, ··· 59 93 60 94 static int __init nf_tables_inet_init(void) 61 95 { 62 - int ret; 63 - 64 - ret = nft_register_chain_type(&filter_inet); 65 - if (ret < 0) 66 - return ret; 67 - 68 - ret = register_pernet_subsys(&nf_tables_inet_net_ops); 69 - if (ret < 0) 70 - nft_unregister_chain_type(&filter_inet); 71 - 72 - return ret; 96 + return nft_register_chain_type(&filter_inet); 73 97 } 74 98 75 99 static void __exit nf_tables_inet_exit(void) 76 100 { 77 - unregister_pernet_subsys(&nf_tables_inet_net_ops); 78 101 nft_unregister_chain_type(&filter_inet); 79 102 } 80 103 ··· 72 117 73 118 MODULE_LICENSE("GPL"); 74 119 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 75 - MODULE_ALIAS_NFT_FAMILY(1); 120 + MODULE_ALIAS_NFT_CHAIN(1, "filter");
+13 -57
net/netfilter/nf_tables_netdev.c
··· 38 38 return nft_do_chain(&pkt, priv); 39 39 } 40 40 41 - static struct nft_af_info nft_af_netdev __read_mostly = { 42 - .family = NFPROTO_NETDEV, 43 - .nhooks = NF_NETDEV_NUMHOOKS, 44 - .owner = THIS_MODULE, 45 - .flags = NFT_AF_NEEDS_DEV, 46 - }; 47 - 48 - static int nf_tables_netdev_init_net(struct net *net) 49 - { 50 - net->nft.netdev = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); 51 - if (net->nft.netdev == NULL) 52 - return -ENOMEM; 53 - 54 - memcpy(net->nft.netdev, &nft_af_netdev, sizeof(nft_af_netdev)); 55 - 56 - if (nft_register_afinfo(net, net->nft.netdev) < 0) 57 - goto err; 58 - 59 - return 0; 60 - err: 61 - kfree(net->nft.netdev); 62 - return -ENOMEM; 63 - } 64 - 65 - static void nf_tables_netdev_exit_net(struct net *net) 66 - { 67 - nft_unregister_afinfo(net, net->nft.netdev); 68 - kfree(net->nft.netdev); 69 - } 70 - 71 - static struct pernet_operations nf_tables_netdev_net_ops = { 72 - .init = nf_tables_netdev_init_net, 73 - .exit = nf_tables_netdev_exit_net, 74 - }; 75 - 76 41 static const struct nf_chain_type nft_filter_chain_netdev = { 77 42 .name = "filter", 78 43 .type = NFT_CHAIN_T_DEFAULT, ··· 74 109 unsigned long event, void *ptr) 75 110 { 76 111 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 77 - struct nft_af_info *afi; 78 112 struct nft_table *table; 79 113 struct nft_chain *chain, *nr; 80 114 struct nft_ctx ctx = { ··· 85 121 return NOTIFY_DONE; 86 122 87 123 nfnl_lock(NFNL_SUBSYS_NFTABLES); 88 - list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { 89 - ctx.afi = afi; 90 - if (afi->family != NFPROTO_NETDEV) 124 + list_for_each_entry(table, &ctx.net->nft.tables, list) { 125 + if (table->family != NFPROTO_NETDEV) 91 126 continue; 92 127 93 - list_for_each_entry(table, &afi->tables, list) { 94 - ctx.table = table; 95 - list_for_each_entry_safe(chain, nr, &table->chains, list) { 96 - if (!nft_is_base_chain(chain)) 97 - continue; 128 + ctx.family = table->family; 129 + ctx.table = table; 130 + list_for_each_entry_safe(chain, nr, &table->chains, list) { 131 + if (!nft_is_base_chain(chain)) 132 + continue; 98 133 99 - ctx.chain = chain; 100 - nft_netdev_event(event, dev, &ctx); 101 - } 134 + ctx.chain = chain; 135 + nft_netdev_event(event, dev, &ctx); 102 136 } 103 137 } 104 138 nfnl_unlock(NFNL_SUBSYS_NFTABLES); ··· 116 154 if (ret) 117 155 return ret; 118 156 119 - ret = register_pernet_subsys(&nf_tables_netdev_net_ops); 120 - if (ret) 121 - goto err1; 122 - 123 157 ret = register_netdevice_notifier(&nf_tables_netdev_notifier); 124 158 if (ret) 125 - goto err2; 159 + goto err_register_netdevice_notifier; 126 160 127 161 return 0; 128 162 129 - err2: 130 - unregister_pernet_subsys(&nf_tables_netdev_net_ops); 131 - err1: 163 + err_register_netdevice_notifier: 132 164 nft_unregister_chain_type(&nft_filter_chain_netdev); 165 + 133 166 return ret; 134 167 } 135 168 136 169 static void __exit nf_tables_netdev_exit(void) 137 170 { 138 171 unregister_netdevice_notifier(&nf_tables_netdev_notifier); 139 - unregister_pernet_subsys(&nf_tables_netdev_net_ops); 140 172 nft_unregister_chain_type(&nft_filter_chain_netdev); 141 173 } 142 174 ··· 139 183 140 184 MODULE_LICENSE("GPL"); 141 185 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 142 - MODULE_ALIAS_NFT_FAMILY(5); /* NFPROTO_NETDEV */ 186 + MODULE_ALIAS_NFT_CHAIN(5, "filter"); /* NFPROTO_NETDEV */
-4
net/netfilter/nfnetlink.c
··· 37 37 rcu_dereference_protected(table[(id)].subsys, \ 38 38 lockdep_nfnl_is_held((id))) 39 39 40 - static char __initdata nfversion[] = "0.30"; 41 - 42 40 static struct { 43 41 struct mutex mutex; 44 42 const struct nfnetlink_subsystem __rcu *subsys; ··· 578 580 for (i=0; i<NFNL_SUBSYS_COUNT; i++) 579 581 mutex_init(&table[i].mutex); 580 582 581 - pr_info("Netfilter messages via NETLINK v%s.\n", nfversion); 582 583 return register_pernet_subsys(&nfnetlink_net_ops); 583 584 } 584 585 585 586 static void __exit nfnetlink_exit(void) 586 587 { 587 - pr_info("Removing netfilter NETLINK layer.\n"); 588 588 unregister_pernet_subsys(&nfnetlink_net_ops); 589 589 } 590 590 module_init(nfnetlink_init);
+8 -10
net/netfilter/nft_compat.c
··· 144 144 { 145 145 par->net = ctx->net; 146 146 par->table = ctx->table->name; 147 - switch (ctx->afi->family) { 147 + switch (ctx->family) { 148 148 case AF_INET: 149 149 entry->e4.ip.proto = proto; 150 150 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; ··· 175 175 } else { 176 176 par->hook_mask = 0; 177 177 } 178 - par->family = ctx->afi->family; 178 + par->family = ctx->family; 179 179 par->nft_compat = true; 180 180 } 181 181 ··· 267 267 par.net = ctx->net; 268 268 par.target = target; 269 269 par.targinfo = info; 270 - par.family = ctx->afi->family; 270 + par.family = ctx->family; 271 271 if (par.target->destroy != NULL) 272 272 par.target->destroy(&par); 273 273 ··· 358 358 { 359 359 par->net = ctx->net; 360 360 par->table = ctx->table->name; 361 - switch (ctx->afi->family) { 361 + switch (ctx->family) { 362 362 case AF_INET: 363 363 entry->e4.ip.proto = proto; 364 364 entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; ··· 389 389 } else { 390 390 par->hook_mask = 0; 391 391 } 392 - par->family = ctx->afi->family; 392 + par->family = ctx->family; 393 393 par->nft_compat = true; 394 394 } 395 395 ··· 446 446 par.net = ctx->net; 447 447 par.match = match; 448 448 par.matchinfo = info; 449 - par.family = ctx->afi->family; 449 + par.family = ctx->family; 450 450 if (par.match->destroy != NULL) 451 451 par.match->destroy(&par); 452 452 ··· 648 648 649 649 mt_name = nla_data(tb[NFTA_MATCH_NAME]); 650 650 rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV])); 651 - family = ctx->afi->family; 651 + family = ctx->family; 652 652 653 653 /* Re-use the existing match if it's already loaded. */ 654 654 list_for_each_entry(nft_match, &nft_match_list, head) { ··· 733 733 734 734 tg_name = nla_data(tb[NFTA_TARGET_NAME]); 735 735 rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV])); 736 - family = ctx->afi->family; 736 + family = ctx->family; 737 737 738 738 /* Re-use the existing target if it's already loaded. */ 739 739 list_for_each_entry(nft_target, &nft_target_list, head) { ··· 811 811 pr_err("nft_compat: cannot register with nfnetlink.\n"); 812 812 goto err_target; 813 813 } 814 - 815 - pr_info("nf_tables_compat: (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>\n"); 816 814 817 815 return ret; 818 816
+8 -8
net/netfilter/nft_ct.c
··· 405 405 if (tb[NFTA_CT_DIRECTION] == NULL) 406 406 return -EINVAL; 407 407 408 - switch (ctx->afi->family) { 408 + switch (ctx->family) { 409 409 case NFPROTO_IPV4: 410 410 len = FIELD_SIZEOF(struct nf_conntrack_tuple, 411 411 src.u3.ip); ··· 456 456 if (err < 0) 457 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 460 if (err < 0) 461 461 return err; 462 462 ··· 550 550 if (err < 0) 551 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 554 if (err < 0) 555 555 goto err1; 556 556 ··· 564 564 static void nft_ct_get_destroy(const struct nft_ctx *ctx, 565 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 570 570 static void nft_ct_set_destroy(const struct nft_ctx *ctx, ··· 573 573 struct nft_ct *priv = nft_expr_priv(expr); 574 574 575 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 579 579 static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) ··· 734 734 struct nft_ct_helper_obj *priv = nft_obj_data(obj); 735 735 struct nf_conntrack_helper *help4, *help6; 736 736 char name[NF_CT_HELPER_NAME_LEN]; 737 - int family = ctx->afi->family; 737 + int family = ctx->family; 738 738 739 739 if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO]) 740 740 return -EINVAL; ··· 753 753 754 754 switch (family) { 755 755 case NFPROTO_IPV4: 756 - if (ctx->afi->family == NFPROTO_IPV6) 756 + if (ctx->family == NFPROTO_IPV6) 757 757 return -EINVAL; 758 758 759 759 help4 = nf_conntrack_helper_try_module_get(name, family, 760 760 priv->l4proto); 761 761 break; 762 762 case NFPROTO_IPV6: 763 - if (ctx->afi->family == NFPROTO_IPV4) 763 + if (ctx->family == NFPROTO_IPV4) 764 764 return -EINVAL; 765 765 766 766 help6 = nf_conntrack_helper_try_module_get(name, family,
+1 -1
net/netfilter/nft_dynset.c
··· 164 164 } 165 165 166 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 168 if (err < 0) 169 169 return err; 170 170
+2 -2
net/netfilter/nft_flow_offload.c
··· 151 151 priv->flowtable = flowtable; 152 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 157 157 static void nft_flow_offload_destroy(const struct nft_ctx *ctx, ··· 160 160 struct nft_flow_offload *priv = nft_expr_priv(expr); 161 161 162 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 166 166 static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr)
+2 -2
net/netfilter/nft_log.c
··· 112 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 116 if (err < 0) 117 117 goto err1; 118 118 ··· 133 133 if (priv->prefix != nft_log_null_prefix) 134 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 139 139 static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr)
+1 -1
net/netfilter/nft_masq.c
··· 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 } 78 78 EXPORT_SYMBOL_GPL(nft_masq_init); 79 79
+2 -2
net/netfilter/nft_meta.c
··· 339 339 if (priv->key != NFT_META_SECPATH) 340 340 return 0; 341 341 342 - switch (ctx->afi->family) { 342 + switch (ctx->family) { 343 343 case NFPROTO_NETDEV: 344 344 hooks = 1 << NF_NETDEV_INGRESS; 345 345 break; ··· 370 370 if (priv->key != NFT_META_PKTTYPE) 371 371 return 0; 372 372 373 - switch (ctx->afi->family) { 373 + switch (ctx->family) { 374 374 case NFPROTO_BRIDGE: 375 375 hooks = 1 << NF_BR_PRE_ROUTING; 376 376 break;
+1 -1
net/netfilter/nft_nat.c
··· 142 142 return -EINVAL; 143 143 144 144 family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); 145 - if (family != ctx->afi->family) 145 + if (family != ctx->family) 146 146 return -EOPNOTSUPP; 147 147 148 148 switch (family) {
+1 -1
net/netfilter/nft_redir.c
··· 75 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 } 80 80 EXPORT_SYMBOL_GPL(nft_redir_init); 81 81
+2 -5
net/netfilter/x_tables.c
··· 1082 1082 { 1083 1083 struct xt_table *t = xt_find_table_lock(net, af, name); 1084 1084 1085 - #ifdef CONFIG_MODULE 1085 + #ifdef CONFIG_MODULES 1086 1086 if (IS_ERR(t)) { 1087 1087 int err = request_module("%stable_%s", xt_prefix[af], name); 1088 - if (err) 1088 + if (err < 0) 1089 1089 return ERR_PTR(err); 1090 1090 t = xt_find_table_lock(net, af, name); 1091 1091 } ··· 1362 1362 } 1363 1363 1364 1364 static const struct file_operations xt_table_ops = { 1365 - .owner = THIS_MODULE, 1366 1365 .open = xt_table_open, 1367 1366 .read = seq_read, 1368 1367 .llseek = seq_lseek, ··· 1497 1498 } 1498 1499 1499 1500 static const struct file_operations xt_match_ops = { 1500 - .owner = THIS_MODULE, 1501 1501 .open = xt_match_open, 1502 1502 .read = seq_read, 1503 1503 .llseek = seq_lseek, ··· 1549 1551 } 1550 1552 1551 1553 static const struct file_operations xt_target_ops = { 1552 - .owner = THIS_MODULE, 1553 1554 .open = xt_target_open, 1554 1555 .read = seq_read, 1555 1556 .llseek = seq_lseek,
+1 -4
net/netfilter/xt_hashlimit.c
··· 353 353 static bool select_all(const struct xt_hashlimit_htable *ht, 354 354 const struct dsthash_ent *he) 355 355 { 356 - return 1; 356 + return true; 357 357 } 358 358 359 359 static bool select_gc(const struct xt_hashlimit_htable *ht, ··· 1266 1266 } 1267 1267 1268 1268 static const struct file_operations dl_file_ops_v2 = { 1269 - .owner = THIS_MODULE, 1270 1269 .open = dl_proc_open_v2, 1271 1270 .read = seq_read, 1272 1271 .llseek = seq_lseek, ··· 1273 1274 }; 1274 1275 1275 1276 static const struct file_operations dl_file_ops_v1 = { 1276 - .owner = THIS_MODULE, 1277 1277 .open = dl_proc_open_v1, 1278 1278 .read = seq_read, 1279 1279 .llseek = seq_lseek, ··· 1280 1282 }; 1281 1283 1282 1284 static const struct file_operations dl_file_ops = { 1283 - .owner = THIS_MODULE, 1284 1285 .open = dl_proc_open, 1285 1286 .read = seq_read, 1286 1287 .llseek = seq_lseek,
+1 -1
net/netfilter/xt_ipcomp.c
··· 58 58 */ 59 59 pr_debug("Dropping evil IPComp tinygram.\n"); 60 60 par->hotdrop = true; 61 - return 0; 61 + return false; 62 62 } 63 63 64 64 return spi_match(compinfo->spis[0], compinfo->spis[1],