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.
Unified · Split
| @@ -175,6 +175,7 @@ enum ctattr_expect { · 174 unmodified lines | ||
| 175 | 175 | CTA_EXPECT_FLAGS, |
| 176 | 176 | CTA_EXPECT_CLASS, |
| 177 | 177 | CTA_EXPECT_NAT, |
| 178 | + CTA_EXPECT_FN, | |
| 178 | 179 | __CTA_EXPECT_MAX |
| 179 | 180 | }; |
| 180 | 181 | #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) |
| @@ -69,4 +69,17 @@ extern int nf_conntrack_broadcast_help(struct sk_buff *skb, · 68 unmodified lines | ||
| 69 | 69 | enum ip_conntrack_info ctinfo, |
| 70 | 70 | unsigned int timeout); |
| 71 | 71 | |
| 72 | +struct 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 | + | |
| 78 | +void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n); | |
| 79 | +void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n); | |
| 80 | +struct nf_ct_helper_expectfn * | |
| 81 | +nf_ct_helper_expectfn_find_by_name(const char *name); | |
| 82 | +struct nf_ct_helper_expectfn * | |
| 83 | +nf_ct_helper_expectfn_find_by_symbol(const void *symbol); | |
| 84 | + | |
| 72 | 85 | #endif /*_NF_CONNTRACK_HELPER_H*/ |
| @@ -686,6 +686,11 @@ static struct pernet_operations nf_nat_net_ops = { · 685 unmodified lines | ||
| 686 | 686 | .exit = nf_nat_net_exit, |
| 687 | 687 | }; |
| 688 | 688 | |
| 689 | +static struct nf_ct_helper_expectfn follow_master_nat = { | |
| 690 | + .name = "nat-follow-master", | |
| 691 | + .expectfn = nf_nat_follow_master, | |
| 692 | +}; | |
| 693 | + | |
| 689 | 694 | static int __init nf_nat_init(void) |
| 690 | 695 | { |
| 691 | 696 | size_t i; |
| @@ -717,6 +722,8 @@ static int __init nf_nat_init(void) · 25 unmodified lines | ||
| 717 | 722 | |
| 718 | 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 | 727 | BUG_ON(nf_nat_seq_adjust_hook != NULL); |
| 721 | 728 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); |
| 722 | 729 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); |
| @@ -736,6 +743,7 @@ static void __exit nf_nat_cleanup(void) · 13 unmodified lines | ||
| 736 | 743 | unregister_pernet_subsys(&nf_nat_net_ops); |
| 737 | 744 | nf_ct_l3proto_put(l3proto); |
| 738 | 745 | nf_ct_extend_unregister(&nat_extend); |
| 746 | + nf_ct_helper_expectfn_unregister(&follow_master_nat); | |
| 739 | 747 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL); |
| 740 | 748 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); |
| 741 | 749 | RCU_INIT_POINTER(nf_ct_nat_offset, NULL); |
| @@ -568,6 +568,16 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, · 567 unmodified lines | ||
| 568 | 568 | return 0; |
| 569 | 569 | } |
| 570 | 570 | |
| 571 | +static struct nf_ct_helper_expectfn q931_nat = { | |
| 572 | + .name = "Q.931", | |
| 573 | + .expectfn = ip_nat_q931_expect, | |
| 574 | +}; | |
| 575 | + | |
| 576 | +static struct nf_ct_helper_expectfn callforwarding_nat = { | |
| 577 | + .name = "callforwarding", | |
| 578 | + .expectfn = ip_nat_callforwarding_expect, | |
| 579 | +}; | |
| 580 | + | |
| 571 | 581 | /****************************************************************************/ |
| 572 | 582 | static int __init init(void) |
| 573 | 583 | { |
| @@ -590,6 +600,8 @@ static int __init init(void) · 16 unmodified lines | ||
| 590 | 600 | RCU_INIT_POINTER(nat_h245_hook, nat_h245); |
| 591 | 601 | RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding); |
| 592 | 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 | 605 | return 0; |
| 594 | 606 | } |
| 595 | 607 | |
| @@ -605,6 +617,8 @@ static void __exit fini(void) · 9 unmodified lines | ||
| 605 | 617 | RCU_INIT_POINTER(nat_h245_hook, NULL); |
| 606 | 618 | RCU_INIT_POINTER(nat_callforwarding_hook, NULL); |
| 607 | 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 | 622 | synchronize_rcu(); |
| 609 | 623 | } |
| 610 | 624 | |
| @@ -526,6 +526,11 @@ err1: · 525 unmodified lines | ||
| 526 | 526 | return NF_DROP; |
| 527 | 527 | } |
| 528 | 528 | |
| 529 | +static struct nf_ct_helper_expectfn sip_nat = { | |
| 530 | + .name = "sip", | |
| 531 | + .expectfn = ip_nat_sip_expected, | |
| 532 | +}; | |
| 533 | + | |
| 529 | 534 | static void __exit nf_nat_sip_fini(void) |
| 530 | 535 | { |
| 531 | 536 | RCU_INIT_POINTER(nf_nat_sip_hook, NULL); |
| @@ -535,6 +540,7 @@ static void __exit nf_nat_sip_fini(void) · 3 unmodified lines | ||
| 535 | 540 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, NULL); |
| 536 | 541 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, NULL); |
| 537 | 542 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, NULL); |
| 543 | + nf_ct_helper_expectfn_unregister(&sip_nat); | |
| 538 | 544 | synchronize_rcu(); |
| 539 | 545 | } |
| 540 | 546 | |
| @@ -554,6 +560,7 @@ static int __init nf_nat_sip_init(void) · 13 unmodified lines | ||
| 554 | 560 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port); |
| 555 | 561 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session); |
| 556 | 562 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media); |
| 563 | + nf_ct_helper_expectfn_register(&sip_nat); | |
| 557 | 564 | return 0; |
| 558 | 565 | } |
| 559 | 566 | |
| @@ -181,6 +181,60 @@ void nf_ct_helper_destroy(struct nf_conn *ct) · 180 unmodified lines | ||
| 181 | 181 | } |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | +static LIST_HEAD(nf_ct_helper_expectfn_list); | |
| 185 | + | |
| 186 | +void 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 | +} | |
| 192 | +EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register); | |
| 193 | + | |
| 194 | +void 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 | +} | |
| 200 | +EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister); | |
| 201 | + | |
| 202 | +struct nf_ct_helper_expectfn * | |
| 203 | +nf_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 | +} | |
| 218 | +EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name); | |
| 219 | + | |
| 220 | +struct nf_ct_helper_expectfn * | |
| 221 | +nf_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 | +} | |
| 236 | +EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); | |
| 237 | + | |
| 184 | 238 | int nf_conntrack_helper_register(struct nf_conntrack_helper *me) |
| 185 | 239 | { |
| 186 | 240 | unsigned int h = helper_hash(&me->tuple); |
| @@ -1679,6 +1679,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, · 1678 unmodified lines | ||
| 1679 | 1679 | struct nlattr *nest_parms; |
| 1680 | 1680 | struct nf_conntrack_tuple nat_tuple = {}; |
| 1681 | 1681 | #endif |
| 1682 | + struct nf_ct_helper_expectfn *expfn; | |
| 1683 | + | |
| 1682 | 1684 | if (timeout < 0) |
| 1683 | 1685 | timeout = 0; |
| 1684 | 1686 | |
| @@ -1722,6 +1724,9 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, · 37 unmodified lines | ||
| 1722 | 1724 | if (helper) |
| 1723 | 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 | 1731 | return 0; |
| 1727 | 1732 | |
| @@ -1881,6 +1886,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { · 153 unmodified lines | ||
| 1881 | 1886 | [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, |
| 1882 | 1887 | [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, |
| 1883 | 1888 | [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, |
| 1889 | + [CTA_EXPECT_FN] = { .type = NLA_NUL_STRING }, | |
| 1884 | 1890 | }; |
| 1885 | 1891 | |
| 1886 | 1892 | static int |
| @@ -2182,9 +2188,20 @@ ctnetlink_create_expect(struct net *net, u16 zone, · 295 unmodified lines | ||
| 2182 | 2188 | } else |
| 2183 | 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 | 2204 | exp->class = class; |
| 2187 | − exp->expectfn = NULL; | |
| 2188 | 2205 | exp->master = ct; |
| 2189 | 2206 | exp->helper = helper; |
| 2190 | 2207 | memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple)); |