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

[NETFILTER]: nf_conntrack: split out helper handling

This patch splits out handling of helpers into its own file
nf_conntrack_helper.c

Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by

Martin Josefsson and committed by
David S. Miller
7e5d03bb 77ab9cff

+165 -120
+2
include/net/netfilter/nf_conntrack_core.h
··· 80 80 extern struct list_head *nf_conntrack_hash; 81 81 extern struct list_head nf_conntrack_expect_list; 82 82 extern rwlock_t nf_conntrack_lock ; 83 + extern struct list_head unconfirmed; 84 + 83 85 #endif /* _NF_CONNTRACK_CORE_H */
+10
include/net/netfilter/nf_conntrack_helper.h
··· 37 37 int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct); 38 38 }; 39 39 40 + extern struct nf_conntrack_helper * 41 + __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple); 42 + 43 + extern struct nf_conntrack_helper * 44 + nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple); 45 + 46 + extern struct nf_conntrack_helper * 47 + __nf_conntrack_helper_find_byname(const char *name); 48 + 49 + extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); 40 50 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); 41 51 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); 42 52
+1 -1
net/netfilter/Makefile
··· 1 1 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 2 - nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o 2 + nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o 3 3 4 4 obj-$(CONFIG_NETFILTER) = netfilter.o 5 5
+1 -119
net/netfilter/nf_conntrack_core.c
··· 75 75 void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; 76 76 struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; 77 77 struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; 78 - static LIST_HEAD(helpers); 79 78 unsigned int nf_conntrack_htable_size __read_mostly = 0; 80 79 int nf_conntrack_max __read_mostly; 81 80 struct list_head *nf_conntrack_hash __read_mostly; 82 81 struct nf_conn nf_conntrack_untracked; 83 82 unsigned int nf_ct_log_invalid __read_mostly; 84 - static LIST_HEAD(unconfirmed); 83 + LIST_HEAD(unconfirmed); 85 84 static int nf_conntrack_vmalloc __read_mostly; 86 85 87 86 static unsigned int nf_conntrack_next_id; ··· 695 696 return dropped; 696 697 } 697 698 698 - static struct nf_conntrack_helper * 699 - __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) 700 - { 701 - struct nf_conntrack_helper *h; 702 - 703 - list_for_each_entry(h, &helpers, list) { 704 - if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) 705 - return h; 706 - } 707 - return NULL; 708 - } 709 - 710 - struct nf_conntrack_helper * 711 - nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) 712 - { 713 - struct nf_conntrack_helper *helper; 714 - 715 - /* need nf_conntrack_lock to assure that helper exists until 716 - * try_module_get() is called */ 717 - read_lock_bh(&nf_conntrack_lock); 718 - 719 - helper = __nf_ct_helper_find(tuple); 720 - if (helper) { 721 - /* need to increase module usage count to assure helper will 722 - * not go away while the caller is e.g. busy putting a 723 - * conntrack in the hash that uses the helper */ 724 - if (!try_module_get(helper->me)) 725 - helper = NULL; 726 - } 727 - 728 - read_unlock_bh(&nf_conntrack_lock); 729 - 730 - return helper; 731 - } 732 - 733 - void nf_ct_helper_put(struct nf_conntrack_helper *helper) 734 - { 735 - module_put(helper->me); 736 - } 737 - 738 699 static struct nf_conn * 739 700 __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, 740 701 const struct nf_conntrack_tuple *repl, ··· 992 1033 __nf_ct_l3proto_find(orig->src.l3num), 993 1034 __nf_ct_proto_find(orig->src.l3num, 994 1035 orig->dst.protonum)); 995 - } 996 - 997 - int nf_conntrack_helper_register(struct nf_conntrack_helper *me) 998 - { 999 - int ret; 1000 - BUG_ON(me->timeout == 0); 1001 - 1002 - ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", 1003 - sizeof(struct nf_conn) 1004 - + sizeof(struct nf_conn_help) 1005 - + __alignof__(struct nf_conn_help)); 1006 - if (ret < 0) { 1007 - printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n"); 1008 - return ret; 1009 - } 1010 - write_lock_bh(&nf_conntrack_lock); 1011 - list_add(&me->list, &helpers); 1012 - write_unlock_bh(&nf_conntrack_lock); 1013 - 1014 - return 0; 1015 - } 1016 - 1017 - struct nf_conntrack_helper * 1018 - __nf_conntrack_helper_find_byname(const char *name) 1019 - { 1020 - struct nf_conntrack_helper *h; 1021 - 1022 - list_for_each_entry(h, &helpers, list) { 1023 - if (!strcmp(h->name, name)) 1024 - return h; 1025 - } 1026 - 1027 - return NULL; 1028 - } 1029 - 1030 - static inline void unhelp(struct nf_conntrack_tuple_hash *i, 1031 - const struct nf_conntrack_helper *me) 1032 - { 1033 - struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); 1034 - struct nf_conn_help *help = nfct_help(ct); 1035 - 1036 - if (help && help->helper == me) { 1037 - nf_conntrack_event(IPCT_HELPER, ct); 1038 - help->helper = NULL; 1039 - } 1040 - } 1041 - 1042 - void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) 1043 - { 1044 - unsigned int i; 1045 - struct nf_conntrack_tuple_hash *h; 1046 - struct nf_conntrack_expect *exp, *tmp; 1047 - 1048 - /* Need write lock here, to delete helper. */ 1049 - write_lock_bh(&nf_conntrack_lock); 1050 - list_del(&me->list); 1051 - 1052 - /* Get rid of expectations */ 1053 - list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { 1054 - struct nf_conn_help *help = nfct_help(exp->master); 1055 - if (help->helper == me && del_timer(&exp->timeout)) { 1056 - nf_ct_unlink_expect(exp); 1057 - nf_conntrack_expect_put(exp); 1058 - } 1059 - } 1060 - 1061 - /* Get rid of expecteds, set helpers to NULL. */ 1062 - list_for_each_entry(h, &unconfirmed, list) 1063 - unhelp(h, me); 1064 - for (i = 0; i < nf_conntrack_htable_size; i++) { 1065 - list_for_each_entry(h, &nf_conntrack_hash[i], list) 1066 - unhelp(h, me); 1067 - } 1068 - write_unlock_bh(&nf_conntrack_lock); 1069 - 1070 - /* Someone could be still looking at the helper in a bh. */ 1071 - synchronize_net(); 1072 1036 } 1073 1037 1074 1038 /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
+151
net/netfilter/nf_conntrack_helper.c
··· 1 + /* Helper handling for netfilter. */ 2 + 3 + /* (C) 1999-2001 Paul `Rusty' Russell 4 + * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> 5 + * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/types.h> 13 + #include <linux/netfilter.h> 14 + #include <linux/module.h> 15 + #include <linux/skbuff.h> 16 + #include <linux/vmalloc.h> 17 + #include <linux/stddef.h> 18 + #include <linux/slab.h> 19 + #include <linux/random.h> 20 + #include <linux/err.h> 21 + #include <linux/kernel.h> 22 + #include <linux/netdevice.h> 23 + 24 + #define ASSERT_READ_LOCK(x) 25 + #define ASSERT_WRITE_LOCK(x) 26 + 27 + #include <net/netfilter/nf_conntrack.h> 28 + #include <net/netfilter/nf_conntrack_l3proto.h> 29 + #include <net/netfilter/nf_conntrack_protocol.h> 30 + #include <net/netfilter/nf_conntrack_helper.h> 31 + #include <net/netfilter/nf_conntrack_core.h> 32 + 33 + static LIST_HEAD(helpers); 34 + 35 + struct nf_conntrack_helper * 36 + __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) 37 + { 38 + struct nf_conntrack_helper *h; 39 + 40 + list_for_each_entry(h, &helpers, list) { 41 + if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) 42 + return h; 43 + } 44 + return NULL; 45 + } 46 + 47 + struct nf_conntrack_helper * 48 + nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) 49 + { 50 + struct nf_conntrack_helper *helper; 51 + 52 + /* need nf_conntrack_lock to assure that helper exists until 53 + * try_module_get() is called */ 54 + read_lock_bh(&nf_conntrack_lock); 55 + 56 + helper = __nf_ct_helper_find(tuple); 57 + if (helper) { 58 + /* need to increase module usage count to assure helper will 59 + * not go away while the caller is e.g. busy putting a 60 + * conntrack in the hash that uses the helper */ 61 + if (!try_module_get(helper->me)) 62 + helper = NULL; 63 + } 64 + 65 + read_unlock_bh(&nf_conntrack_lock); 66 + 67 + return helper; 68 + } 69 + 70 + void nf_ct_helper_put(struct nf_conntrack_helper *helper) 71 + { 72 + module_put(helper->me); 73 + } 74 + 75 + struct nf_conntrack_helper * 76 + __nf_conntrack_helper_find_byname(const char *name) 77 + { 78 + struct nf_conntrack_helper *h; 79 + 80 + list_for_each_entry(h, &helpers, list) { 81 + if (!strcmp(h->name, name)) 82 + return h; 83 + } 84 + 85 + return NULL; 86 + } 87 + 88 + static inline int unhelp(struct nf_conntrack_tuple_hash *i, 89 + const struct nf_conntrack_helper *me) 90 + { 91 + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); 92 + struct nf_conn_help *help = nfct_help(ct); 93 + 94 + if (help && help->helper == me) { 95 + nf_conntrack_event(IPCT_HELPER, ct); 96 + help->helper = NULL; 97 + } 98 + return 0; 99 + } 100 + 101 + int nf_conntrack_helper_register(struct nf_conntrack_helper *me) 102 + { 103 + int ret; 104 + BUG_ON(me->timeout == 0); 105 + 106 + ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", 107 + sizeof(struct nf_conn) 108 + + sizeof(struct nf_conn_help) 109 + + __alignof__(struct nf_conn_help)); 110 + if (ret < 0) { 111 + printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n"); 112 + return ret; 113 + } 114 + write_lock_bh(&nf_conntrack_lock); 115 + list_add(&me->list, &helpers); 116 + write_unlock_bh(&nf_conntrack_lock); 117 + 118 + return 0; 119 + } 120 + 121 + void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) 122 + { 123 + unsigned int i; 124 + struct nf_conntrack_tuple_hash *h; 125 + struct nf_conntrack_expect *exp, *tmp; 126 + 127 + /* Need write lock here, to delete helper. */ 128 + write_lock_bh(&nf_conntrack_lock); 129 + list_del(&me->list); 130 + 131 + /* Get rid of expectations */ 132 + list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { 133 + struct nf_conn_help *help = nfct_help(exp->master); 134 + if (help->helper == me && del_timer(&exp->timeout)) { 135 + nf_ct_unlink_expect(exp); 136 + nf_conntrack_expect_put(exp); 137 + } 138 + } 139 + 140 + /* Get rid of expecteds, set helpers to NULL. */ 141 + list_for_each_entry(h, &unconfirmed, list) 142 + unhelp(h, me); 143 + for (i = 0; i < nf_conntrack_htable_size; i++) { 144 + list_for_each_entry(h, &nf_conntrack_hash[i], list) 145 + unhelp(h, me); 146 + } 147 + write_unlock_bh(&nf_conntrack_lock); 148 + 149 + /* Someone could be still looking at the helper in a bh. */ 150 + synchronize_net(); 151 + }