aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-02-04 21:44:51 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2012-03-07 11:40:46 -0500
commit544d5c7d9f4d1ec4f170bc5bcc522012cb7704bc (patch)
treed7e4eff56efb23801a5ad0e4720efe13c68672ca
parent076a0ca02644657b13e4af363f487ced2942e9cb (diff)
netfilter: ctnetlink: allow to set expectfn for expectations
This patch allows you to set expectfn which is specifically used by the NAT side of most of the existing conntrack helpers. I have added a symbol map that uses a string as key to look up for the function that is attached to the expectation object. This is the best solution I came out with to solve this issue. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h1
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h13
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c14
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c7
-rw-r--r--net/netfilter/nf_conntrack_helper.c54
-rw-r--r--net/netfilter/nf_conntrack_netlink.c19
7 files changed, 115 insertions, 1 deletions
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index a2f1f483ecc9..e58e4b93c108 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -175,6 +175,7 @@ enum ctattr_expect {
175 CTA_EXPECT_FLAGS, 175 CTA_EXPECT_FLAGS,
176 CTA_EXPECT_CLASS, 176 CTA_EXPECT_CLASS,
177 CTA_EXPECT_NAT, 177 CTA_EXPECT_NAT,
178 CTA_EXPECT_FN,
178 __CTA_EXPECT_MAX 179 __CTA_EXPECT_MAX
179}; 180};
180#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) 181#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index f1c1311adc2c..5767dc242dee 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -69,4 +69,17 @@ extern int nf_conntrack_broadcast_help(struct sk_buff *skb,
69 enum ip_conntrack_info ctinfo, 69 enum ip_conntrack_info ctinfo,
70 unsigned int timeout); 70 unsigned int timeout);
71 71
72struct nf_ct_helper_expectfn {
73 struct list_head head;
74 const char *name;
75 void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
76};
77
78void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
79void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
80struct nf_ct_helper_expectfn *
81nf_ct_helper_expectfn_find_by_name(const char *name);
82struct nf_ct_helper_expectfn *
83nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
84
72#endif /*_NF_CONNTRACK_HELPER_H*/ 85#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index a708933dc230..abb52adf5acd 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -686,6 +686,11 @@ static struct pernet_operations nf_nat_net_ops = {
686 .exit = nf_nat_net_exit, 686 .exit = nf_nat_net_exit,
687}; 687};
688 688
689static struct nf_ct_helper_expectfn follow_master_nat = {
690 .name = "nat-follow-master",
691 .expectfn = nf_nat_follow_master,
692};
693
689static int __init nf_nat_init(void) 694static int __init nf_nat_init(void)
690{ 695{
691 size_t i; 696 size_t i;
@@ -717,6 +722,8 @@ static int __init nf_nat_init(void)
717 722
718 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); 723 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
719 724
725 nf_ct_helper_expectfn_register(&follow_master_nat);
726
720 BUG_ON(nf_nat_seq_adjust_hook != NULL); 727 BUG_ON(nf_nat_seq_adjust_hook != NULL);
721 RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); 728 RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
722 BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); 729 BUG_ON(nfnetlink_parse_nat_setup_hook != NULL);
@@ -736,6 +743,7 @@ static void __exit nf_nat_cleanup(void)
736 unregister_pernet_subsys(&nf_nat_net_ops); 743 unregister_pernet_subsys(&nf_nat_net_ops);
737 nf_ct_l3proto_put(l3proto); 744 nf_ct_l3proto_put(l3proto);
738 nf_ct_extend_unregister(&nat_extend); 745 nf_ct_extend_unregister(&nat_extend);
746 nf_ct_helper_expectfn_unregister(&follow_master_nat);
739 RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL); 747 RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL);
740 RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); 748 RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL);
741 RCU_INIT_POINTER(nf_ct_nat_offset, NULL); 749 RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index dc1dd912baf4..82536701e3a3 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -568,6 +568,16 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
568 return 0; 568 return 0;
569} 569}
570 570
571static struct nf_ct_helper_expectfn q931_nat = {
572 .name = "Q.931",
573 .expectfn = ip_nat_q931_expect,
574};
575
576static struct nf_ct_helper_expectfn callforwarding_nat = {
577 .name = "callforwarding",
578 .expectfn = ip_nat_callforwarding_expect,
579};
580
571/****************************************************************************/ 581/****************************************************************************/
572static int __init init(void) 582static int __init init(void)
573{ 583{
@@ -590,6 +600,8 @@ static int __init init(void)
590 RCU_INIT_POINTER(nat_h245_hook, nat_h245); 600 RCU_INIT_POINTER(nat_h245_hook, nat_h245);
591 RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding); 601 RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
592 RCU_INIT_POINTER(nat_q931_hook, nat_q931); 602 RCU_INIT_POINTER(nat_q931_hook, nat_q931);
603 nf_ct_helper_expectfn_register(&q931_nat);
604 nf_ct_helper_expectfn_register(&callforwarding_nat);
593 return 0; 605 return 0;
594} 606}
595 607
@@ -605,6 +617,8 @@ static void __exit fini(void)
605 RCU_INIT_POINTER(nat_h245_hook, NULL); 617 RCU_INIT_POINTER(nat_h245_hook, NULL);
606 RCU_INIT_POINTER(nat_callforwarding_hook, NULL); 618 RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
607 RCU_INIT_POINTER(nat_q931_hook, NULL); 619 RCU_INIT_POINTER(nat_q931_hook, NULL);
620 nf_ct_helper_expectfn_unregister(&q931_nat);
621 nf_ct_helper_expectfn_unregister(&callforwarding_nat);
608 synchronize_rcu(); 622 synchronize_rcu();
609} 623}
610 624
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index d0319f96269f..57932c43960e 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -526,6 +526,11 @@ err1:
526 return NF_DROP; 526 return NF_DROP;
527} 527}
528 528
529static struct nf_ct_helper_expectfn sip_nat = {
530 .name = "sip",
531 .expectfn = ip_nat_sip_expected,
532};
533
529static void __exit nf_nat_sip_fini(void) 534static void __exit nf_nat_sip_fini(void)
530{ 535{
531 RCU_INIT_POINTER(nf_nat_sip_hook, NULL); 536 RCU_INIT_POINTER(nf_nat_sip_hook, NULL);
@@ -535,6 +540,7 @@ static void __exit nf_nat_sip_fini(void)
535 RCU_INIT_POINTER(nf_nat_sdp_port_hook, NULL); 540 RCU_INIT_POINTER(nf_nat_sdp_port_hook, NULL);
536 RCU_INIT_POINTER(nf_nat_sdp_session_hook, NULL); 541 RCU_INIT_POINTER(nf_nat_sdp_session_hook, NULL);
537 RCU_INIT_POINTER(nf_nat_sdp_media_hook, NULL); 542 RCU_INIT_POINTER(nf_nat_sdp_media_hook, NULL);
543 nf_ct_helper_expectfn_unregister(&sip_nat);
538 synchronize_rcu(); 544 synchronize_rcu();
539} 545}
540 546
@@ -554,6 +560,7 @@ static int __init nf_nat_sip_init(void)
554 RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port); 560 RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port);
555 RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session); 561 RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session);
556 RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media); 562 RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media);
563 nf_ct_helper_expectfn_register(&sip_nat);
557 return 0; 564 return 0;
558} 565}
559 566
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index bbe23baa19b6..436b7cb79ba4 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -181,6 +181,60 @@ void nf_ct_helper_destroy(struct nf_conn *ct)
181 } 181 }
182} 182}
183 183
184static LIST_HEAD(nf_ct_helper_expectfn_list);
185
186void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n)
187{
188 spin_lock_bh(&nf_conntrack_lock);
189 list_add_rcu(&n->head, &nf_ct_helper_expectfn_list);
190 spin_unlock_bh(&nf_conntrack_lock);
191}
192EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register);
193
194void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n)
195{
196 spin_lock_bh(&nf_conntrack_lock);
197 list_del_rcu(&n->head);
198 spin_unlock_bh(&nf_conntrack_lock);
199}
200EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister);
201
202struct nf_ct_helper_expectfn *
203nf_ct_helper_expectfn_find_by_name(const char *name)
204{
205 struct nf_ct_helper_expectfn *cur;
206 bool found = false;
207
208 rcu_read_lock();
209 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) {
210 if (!strcmp(cur->name, name)) {
211 found = true;
212 break;
213 }
214 }
215 rcu_read_unlock();
216 return found ? cur : NULL;
217}
218EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name);
219
220struct nf_ct_helper_expectfn *
221nf_ct_helper_expectfn_find_by_symbol(const void *symbol)
222{
223 struct nf_ct_helper_expectfn *cur;
224 bool found = false;
225
226 rcu_read_lock();
227 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) {
228 if (cur->expectfn == symbol) {
229 found = true;
230 break;
231 }
232 }
233 rcu_read_unlock();
234 return found ? cur : NULL;
235}
236EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol);
237
184int nf_conntrack_helper_register(struct nf_conntrack_helper *me) 238int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
185{ 239{
186 unsigned int h = helper_hash(&me->tuple); 240 unsigned int h = helper_hash(&me->tuple);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 845c8ca28563..b8827e8a11fe 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1679,6 +1679,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
1679 struct nlattr *nest_parms; 1679 struct nlattr *nest_parms;
1680 struct nf_conntrack_tuple nat_tuple = {}; 1680 struct nf_conntrack_tuple nat_tuple = {};
1681#endif 1681#endif
1682 struct nf_ct_helper_expectfn *expfn;
1683
1682 if (timeout < 0) 1684 if (timeout < 0)
1683 timeout = 0; 1685 timeout = 0;
1684 1686
@@ -1722,6 +1724,9 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
1722 if (helper) 1724 if (helper)
1723 NLA_PUT_STRING(skb, CTA_EXPECT_HELP_NAME, helper->name); 1725 NLA_PUT_STRING(skb, CTA_EXPECT_HELP_NAME, helper->name);
1724 } 1726 }
1727 expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn);
1728 if (expfn != NULL)
1729 NLA_PUT_STRING(skb, CTA_EXPECT_FN, expfn->name);
1725 1730
1726 return 0; 1731 return 0;
1727 1732
@@ -1881,6 +1886,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
1881 [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, 1886 [CTA_EXPECT_FLAGS] = { .type = NLA_U32 },
1882 [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, 1887 [CTA_EXPECT_CLASS] = { .type = NLA_U32 },
1883 [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, 1888 [CTA_EXPECT_NAT] = { .type = NLA_NESTED },
1889 [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING },
1884}; 1890};
1885 1891
1886static int 1892static int
@@ -2182,9 +2188,20 @@ ctnetlink_create_expect(struct net *net, u16 zone,
2182 } else 2188 } else
2183 exp->flags = 0; 2189 exp->flags = 0;
2184 } 2190 }
2191 if (cda[CTA_EXPECT_FN]) {
2192 const char *name = nla_data(cda[CTA_EXPECT_FN]);
2193 struct nf_ct_helper_expectfn *expfn;
2194
2195 expfn = nf_ct_helper_expectfn_find_by_name(name);
2196 if (expfn == NULL) {
2197 err = -EINVAL;
2198 goto err_out;
2199 }
2200 exp->expectfn = expfn->expectfn;
2201 } else
2202 exp->expectfn = NULL;
2185 2203
2186 exp->class = class; 2204 exp->class = class;
2187 exp->expectfn = NULL;
2188 exp->master = ct; 2205 exp->master = ct;
2189 exp->helper = helper; 2206 exp->helper = helper;
2190 memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple)); 2207 memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));