diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-02-28 12:23:31 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-03-07 11:41:19 -0500 |
commit | 2c8503f55fbdfbeff4164f133df804cf4d316290 (patch) | |
tree | fe491bc79fd59aa4b8b99ea63d13e62b6a2ef1cb /net | |
parent | b888341c7f33035694f70428d7001d73f0b2a3b1 (diff) |
netfilter: nf_conntrack: pass timeout array to l4->new and l4->packet
This patch defines a new interface for l4 protocol trackers:
unsigned int *(*get_timeouts)(struct net *net);
that is used to return the array of unsigned int that contains
the timeouts that will be applied for this flow. This is passed
to the l4proto->new(...) and l4proto->packet(...) functions to
specify the timeout policy.
This interface allows per-net global timeout configuration
(although only DCCP supports this by now) and it will allow
custom custom timeout configuration by means of follow-up
patches.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 13 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 13 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 18 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_dccp.c | 16 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_generic.c | 29 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_gre.c | 15 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_sctp.c | 14 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 22 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_udp.c | 16 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_udplite.c | 16 |
10 files changed, 122 insertions, 50 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index ab5b27a2916f..6b801124b31f 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -75,25 +75,31 @@ static int icmp_print_tuple(struct seq_file *s, | |||
75 | ntohs(tuple->src.u.icmp.id)); | 75 | ntohs(tuple->src.u.icmp.id)); |
76 | } | 76 | } |
77 | 77 | ||
78 | static unsigned int *icmp_get_timeouts(struct net *net) | ||
79 | { | ||
80 | return &nf_ct_icmp_timeout; | ||
81 | } | ||
82 | |||
78 | /* Returns verdict for packet, or -1 for invalid. */ | 83 | /* Returns verdict for packet, or -1 for invalid. */ |
79 | static int icmp_packet(struct nf_conn *ct, | 84 | static int icmp_packet(struct nf_conn *ct, |
80 | const struct sk_buff *skb, | 85 | const struct sk_buff *skb, |
81 | unsigned int dataoff, | 86 | unsigned int dataoff, |
82 | enum ip_conntrack_info ctinfo, | 87 | enum ip_conntrack_info ctinfo, |
83 | u_int8_t pf, | 88 | u_int8_t pf, |
84 | unsigned int hooknum) | 89 | unsigned int hooknum, |
90 | unsigned int *timeout) | ||
85 | { | 91 | { |
86 | /* Do not immediately delete the connection after the first | 92 | /* Do not immediately delete the connection after the first |
87 | successful reply to avoid excessive conntrackd traffic | 93 | successful reply to avoid excessive conntrackd traffic |
88 | and also to handle correctly ICMP echo reply duplicates. */ | 94 | and also to handle correctly ICMP echo reply duplicates. */ |
89 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); | 95 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); |
90 | 96 | ||
91 | return NF_ACCEPT; | 97 | return NF_ACCEPT; |
92 | } | 98 | } |
93 | 99 | ||
94 | /* Called when a new connection for this protocol found. */ | 100 | /* Called when a new connection for this protocol found. */ |
95 | static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, | 101 | static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, |
96 | unsigned int dataoff) | 102 | unsigned int dataoff, unsigned int *timeouts) |
97 | { | 103 | { |
98 | static const u_int8_t valid_new[] = { | 104 | static const u_int8_t valid_new[] = { |
99 | [ICMP_ECHO] = 1, | 105 | [ICMP_ECHO] = 1, |
@@ -298,6 +304,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = | |||
298 | .invert_tuple = icmp_invert_tuple, | 304 | .invert_tuple = icmp_invert_tuple, |
299 | .print_tuple = icmp_print_tuple, | 305 | .print_tuple = icmp_print_tuple, |
300 | .packet = icmp_packet, | 306 | .packet = icmp_packet, |
307 | .get_timeouts = icmp_get_timeouts, | ||
301 | .new = icmp_new, | 308 | .new = icmp_new, |
302 | .error = icmp_error, | 309 | .error = icmp_error, |
303 | .destroy = NULL, | 310 | .destroy = NULL, |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 7c05e7eacbc6..2eb9751eb7a8 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -88,25 +88,31 @@ static int icmpv6_print_tuple(struct seq_file *s, | |||
88 | ntohs(tuple->src.u.icmp.id)); | 88 | ntohs(tuple->src.u.icmp.id)); |
89 | } | 89 | } |
90 | 90 | ||
91 | static unsigned int *icmpv6_get_timeouts(struct net *net) | ||
92 | { | ||
93 | return &nf_ct_icmpv6_timeout; | ||
94 | } | ||
95 | |||
91 | /* Returns verdict for packet, or -1 for invalid. */ | 96 | /* Returns verdict for packet, or -1 for invalid. */ |
92 | static int icmpv6_packet(struct nf_conn *ct, | 97 | static int icmpv6_packet(struct nf_conn *ct, |
93 | const struct sk_buff *skb, | 98 | const struct sk_buff *skb, |
94 | unsigned int dataoff, | 99 | unsigned int dataoff, |
95 | enum ip_conntrack_info ctinfo, | 100 | enum ip_conntrack_info ctinfo, |
96 | u_int8_t pf, | 101 | u_int8_t pf, |
97 | unsigned int hooknum) | 102 | unsigned int hooknum, |
103 | unsigned int *timeout) | ||
98 | { | 104 | { |
99 | /* Do not immediately delete the connection after the first | 105 | /* Do not immediately delete the connection after the first |
100 | successful reply to avoid excessive conntrackd traffic | 106 | successful reply to avoid excessive conntrackd traffic |
101 | and also to handle correctly ICMP echo reply duplicates. */ | 107 | and also to handle correctly ICMP echo reply duplicates. */ |
102 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); | 108 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); |
103 | 109 | ||
104 | return NF_ACCEPT; | 110 | return NF_ACCEPT; |
105 | } | 111 | } |
106 | 112 | ||
107 | /* Called when a new connection for this protocol found. */ | 113 | /* Called when a new connection for this protocol found. */ |
108 | static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, | 114 | static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, |
109 | unsigned int dataoff) | 115 | unsigned int dataoff, unsigned int *timeouts) |
110 | { | 116 | { |
111 | static const u_int8_t valid_new[] = { | 117 | static const u_int8_t valid_new[] = { |
112 | [ICMPV6_ECHO_REQUEST - 128] = 1, | 118 | [ICMPV6_ECHO_REQUEST - 128] = 1, |
@@ -293,6 +299,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = | |||
293 | .invert_tuple = icmpv6_invert_tuple, | 299 | .invert_tuple = icmpv6_invert_tuple, |
294 | .print_tuple = icmpv6_print_tuple, | 300 | .print_tuple = icmpv6_print_tuple, |
295 | .packet = icmpv6_packet, | 301 | .packet = icmpv6_packet, |
302 | .get_timeouts = icmpv6_get_timeouts, | ||
296 | .new = icmpv6_new, | 303 | .new = icmpv6_new, |
297 | .error = icmpv6_error, | 304 | .error = icmpv6_error, |
298 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 305 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ed86a3be678e..d18995eea1c6 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -763,7 +763,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
763 | struct nf_conntrack_l3proto *l3proto, | 763 | struct nf_conntrack_l3proto *l3proto, |
764 | struct nf_conntrack_l4proto *l4proto, | 764 | struct nf_conntrack_l4proto *l4proto, |
765 | struct sk_buff *skb, | 765 | struct sk_buff *skb, |
766 | unsigned int dataoff, u32 hash) | 766 | unsigned int dataoff, u32 hash, |
767 | unsigned int *timeouts) | ||
767 | { | 768 | { |
768 | struct nf_conn *ct; | 769 | struct nf_conn *ct; |
769 | struct nf_conn_help *help; | 770 | struct nf_conn_help *help; |
@@ -782,7 +783,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
782 | if (IS_ERR(ct)) | 783 | if (IS_ERR(ct)) |
783 | return (struct nf_conntrack_tuple_hash *)ct; | 784 | return (struct nf_conntrack_tuple_hash *)ct; |
784 | 785 | ||
785 | if (!l4proto->new(ct, skb, dataoff)) { | 786 | if (!l4proto->new(ct, skb, dataoff, timeouts)) { |
786 | nf_conntrack_free(ct); | 787 | nf_conntrack_free(ct); |
787 | pr_debug("init conntrack: can't track with proto module\n"); | 788 | pr_debug("init conntrack: can't track with proto module\n"); |
788 | return NULL; | 789 | return NULL; |
@@ -848,7 +849,8 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
848 | struct nf_conntrack_l3proto *l3proto, | 849 | struct nf_conntrack_l3proto *l3proto, |
849 | struct nf_conntrack_l4proto *l4proto, | 850 | struct nf_conntrack_l4proto *l4proto, |
850 | int *set_reply, | 851 | int *set_reply, |
851 | enum ip_conntrack_info *ctinfo) | 852 | enum ip_conntrack_info *ctinfo, |
853 | unsigned int *timeouts) | ||
852 | { | 854 | { |
853 | struct nf_conntrack_tuple tuple; | 855 | struct nf_conntrack_tuple tuple; |
854 | struct nf_conntrack_tuple_hash *h; | 856 | struct nf_conntrack_tuple_hash *h; |
@@ -868,7 +870,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
868 | h = __nf_conntrack_find_get(net, zone, &tuple, hash); | 870 | h = __nf_conntrack_find_get(net, zone, &tuple, hash); |
869 | if (!h) { | 871 | if (!h) { |
870 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, | 872 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, |
871 | skb, dataoff, hash); | 873 | skb, dataoff, hash, timeouts); |
872 | if (!h) | 874 | if (!h) |
873 | return NULL; | 875 | return NULL; |
874 | if (IS_ERR(h)) | 876 | if (IS_ERR(h)) |
@@ -909,6 +911,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
909 | enum ip_conntrack_info ctinfo; | 911 | enum ip_conntrack_info ctinfo; |
910 | struct nf_conntrack_l3proto *l3proto; | 912 | struct nf_conntrack_l3proto *l3proto; |
911 | struct nf_conntrack_l4proto *l4proto; | 913 | struct nf_conntrack_l4proto *l4proto; |
914 | unsigned int *timeouts; | ||
912 | unsigned int dataoff; | 915 | unsigned int dataoff; |
913 | u_int8_t protonum; | 916 | u_int8_t protonum; |
914 | int set_reply = 0; | 917 | int set_reply = 0; |
@@ -955,8 +958,11 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
955 | goto out; | 958 | goto out; |
956 | } | 959 | } |
957 | 960 | ||
961 | timeouts = l4proto->get_timeouts(net); | ||
962 | |||
958 | ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, | 963 | ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, |
959 | l3proto, l4proto, &set_reply, &ctinfo); | 964 | l3proto, l4proto, &set_reply, &ctinfo, |
965 | timeouts); | ||
960 | if (!ct) { | 966 | if (!ct) { |
961 | /* Not valid part of a connection */ | 967 | /* Not valid part of a connection */ |
962 | NF_CT_STAT_INC_ATOMIC(net, invalid); | 968 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
@@ -973,7 +979,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
973 | 979 | ||
974 | NF_CT_ASSERT(skb->nfct); | 980 | NF_CT_ASSERT(skb->nfct); |
975 | 981 | ||
976 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum); | 982 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts); |
977 | if (ret <= 0) { | 983 | if (ret <= 0) { |
978 | /* Invalid: inverse of the return code tells | 984 | /* Invalid: inverse of the return code tells |
979 | * the netfilter core what to do */ | 985 | * the netfilter core what to do */ |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index d6dde6dc09e6..8ea33598a0a7 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -423,7 +423,7 @@ static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv, | |||
423 | } | 423 | } |
424 | 424 | ||
425 | static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, | 425 | static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, |
426 | unsigned int dataoff) | 426 | unsigned int dataoff, unsigned int *timeouts) |
427 | { | 427 | { |
428 | struct net *net = nf_ct_net(ct); | 428 | struct net *net = nf_ct_net(ct); |
429 | struct dccp_net *dn; | 429 | struct dccp_net *dn; |
@@ -472,12 +472,17 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh) | |||
472 | ntohl(dhack->dccph_ack_nr_low); | 472 | ntohl(dhack->dccph_ack_nr_low); |
473 | } | 473 | } |
474 | 474 | ||
475 | static unsigned int *dccp_get_timeouts(struct net *net) | ||
476 | { | ||
477 | return dccp_pernet(net)->dccp_timeout; | ||
478 | } | ||
479 | |||
475 | static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, | 480 | static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, |
476 | unsigned int dataoff, enum ip_conntrack_info ctinfo, | 481 | unsigned int dataoff, enum ip_conntrack_info ctinfo, |
477 | u_int8_t pf, unsigned int hooknum) | 482 | u_int8_t pf, unsigned int hooknum, |
483 | unsigned int *timeouts) | ||
478 | { | 484 | { |
479 | struct net *net = nf_ct_net(ct); | 485 | struct net *net = nf_ct_net(ct); |
480 | struct dccp_net *dn; | ||
481 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 486 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
482 | struct dccp_hdr _dh, *dh; | 487 | struct dccp_hdr _dh, *dh; |
483 | u_int8_t type, old_state, new_state; | 488 | u_int8_t type, old_state, new_state; |
@@ -559,8 +564,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, | |||
559 | if (new_state != old_state) | 564 | if (new_state != old_state) |
560 | nf_conntrack_event_cache(IPCT_PROTOINFO, ct); | 565 | nf_conntrack_event_cache(IPCT_PROTOINFO, ct); |
561 | 566 | ||
562 | dn = dccp_pernet(net); | 567 | nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); |
563 | nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]); | ||
564 | 568 | ||
565 | return NF_ACCEPT; | 569 | return NF_ACCEPT; |
566 | } | 570 | } |
@@ -767,6 +771,7 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { | |||
767 | .invert_tuple = dccp_invert_tuple, | 771 | .invert_tuple = dccp_invert_tuple, |
768 | .new = dccp_new, | 772 | .new = dccp_new, |
769 | .packet = dccp_packet, | 773 | .packet = dccp_packet, |
774 | .get_timeouts = dccp_get_timeouts, | ||
770 | .error = dccp_error, | 775 | .error = dccp_error, |
771 | .print_tuple = dccp_print_tuple, | 776 | .print_tuple = dccp_print_tuple, |
772 | .print_conntrack = dccp_print_conntrack, | 777 | .print_conntrack = dccp_print_conntrack, |
@@ -789,6 +794,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { | |||
789 | .invert_tuple = dccp_invert_tuple, | 794 | .invert_tuple = dccp_invert_tuple, |
790 | .new = dccp_new, | 795 | .new = dccp_new, |
791 | .packet = dccp_packet, | 796 | .packet = dccp_packet, |
797 | .get_timeouts = dccp_get_timeouts, | ||
792 | .error = dccp_error, | 798 | .error = dccp_error, |
793 | .print_tuple = dccp_print_tuple, | 799 | .print_tuple = dccp_print_tuple, |
794 | .print_conntrack = dccp_print_conntrack, | 800 | .print_conntrack = dccp_print_conntrack, |
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index e2091d0c7a2f..0e6c5451db80 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c | |||
@@ -40,21 +40,27 @@ static int generic_print_tuple(struct seq_file *s, | |||
40 | return 0; | 40 | return 0; |
41 | } | 41 | } |
42 | 42 | ||
43 | static unsigned int *generic_get_timeouts(struct net *net) | ||
44 | { | ||
45 | return &nf_ct_generic_timeout; | ||
46 | } | ||
47 | |||
43 | /* Returns verdict for packet, or -1 for invalid. */ | 48 | /* Returns verdict for packet, or -1 for invalid. */ |
44 | static int packet(struct nf_conn *ct, | 49 | static int generic_packet(struct nf_conn *ct, |
45 | const struct sk_buff *skb, | 50 | const struct sk_buff *skb, |
46 | unsigned int dataoff, | 51 | unsigned int dataoff, |
47 | enum ip_conntrack_info ctinfo, | 52 | enum ip_conntrack_info ctinfo, |
48 | u_int8_t pf, | 53 | u_int8_t pf, |
49 | unsigned int hooknum) | 54 | unsigned int hooknum, |
55 | unsigned int *timeout) | ||
50 | { | 56 | { |
51 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_generic_timeout); | 57 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); |
52 | return NF_ACCEPT; | 58 | return NF_ACCEPT; |
53 | } | 59 | } |
54 | 60 | ||
55 | /* Called when a new connection for this protocol found. */ | 61 | /* Called when a new connection for this protocol found. */ |
56 | static bool new(struct nf_conn *ct, const struct sk_buff *skb, | 62 | static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, |
57 | unsigned int dataoff) | 63 | unsigned int dataoff, unsigned int *timeouts) |
58 | { | 64 | { |
59 | return true; | 65 | return true; |
60 | } | 66 | } |
@@ -93,8 +99,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = | |||
93 | .pkt_to_tuple = generic_pkt_to_tuple, | 99 | .pkt_to_tuple = generic_pkt_to_tuple, |
94 | .invert_tuple = generic_invert_tuple, | 100 | .invert_tuple = generic_invert_tuple, |
95 | .print_tuple = generic_print_tuple, | 101 | .print_tuple = generic_print_tuple, |
96 | .packet = packet, | 102 | .packet = generic_packet, |
97 | .new = new, | 103 | .get_timeouts = generic_get_timeouts, |
104 | .new = generic_new, | ||
98 | #ifdef CONFIG_SYSCTL | 105 | #ifdef CONFIG_SYSCTL |
99 | .ctl_table_header = &generic_sysctl_header, | 106 | .ctl_table_header = &generic_sysctl_header, |
100 | .ctl_table = generic_sysctl_table, | 107 | .ctl_table = generic_sysctl_table, |
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 8144f22d159a..1bf01c95658b 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
@@ -235,13 +235,19 @@ static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct) | |||
235 | (ct->proto.gre.stream_timeout / HZ)); | 235 | (ct->proto.gre.stream_timeout / HZ)); |
236 | } | 236 | } |
237 | 237 | ||
238 | static unsigned int *gre_get_timeouts(struct net *net) | ||
239 | { | ||
240 | return gre_timeouts; | ||
241 | } | ||
242 | |||
238 | /* Returns verdict for packet, and may modify conntrack */ | 243 | /* Returns verdict for packet, and may modify conntrack */ |
239 | static int gre_packet(struct nf_conn *ct, | 244 | static int gre_packet(struct nf_conn *ct, |
240 | const struct sk_buff *skb, | 245 | const struct sk_buff *skb, |
241 | unsigned int dataoff, | 246 | unsigned int dataoff, |
242 | enum ip_conntrack_info ctinfo, | 247 | enum ip_conntrack_info ctinfo, |
243 | u_int8_t pf, | 248 | u_int8_t pf, |
244 | unsigned int hooknum) | 249 | unsigned int hooknum, |
250 | unsigned int *timeouts) | ||
245 | { | 251 | { |
246 | /* If we've seen traffic both ways, this is a GRE connection. | 252 | /* If we've seen traffic both ways, this is a GRE connection. |
247 | * Extend timeout. */ | 253 | * Extend timeout. */ |
@@ -260,15 +266,15 @@ static int gre_packet(struct nf_conn *ct, | |||
260 | 266 | ||
261 | /* Called when a new connection for this protocol found. */ | 267 | /* Called when a new connection for this protocol found. */ |
262 | static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb, | 268 | static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb, |
263 | unsigned int dataoff) | 269 | unsigned int dataoff, unsigned int *timeouts) |
264 | { | 270 | { |
265 | pr_debug(": "); | 271 | pr_debug(": "); |
266 | nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 272 | nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
267 | 273 | ||
268 | /* initialize to sane value. Ideally a conntrack helper | 274 | /* initialize to sane value. Ideally a conntrack helper |
269 | * (e.g. in case of pptp) is increasing them */ | 275 | * (e.g. in case of pptp) is increasing them */ |
270 | ct->proto.gre.stream_timeout = gre_timeouts[GRE_CT_REPLIED]; | 276 | ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED]; |
271 | ct->proto.gre.timeout = gre_timeouts[GRE_CT_UNREPLIED]; | 277 | ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED]; |
272 | 278 | ||
273 | return true; | 279 | return true; |
274 | } | 280 | } |
@@ -295,6 +301,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { | |||
295 | .invert_tuple = gre_invert_tuple, | 301 | .invert_tuple = gre_invert_tuple, |
296 | .print_tuple = gre_print_tuple, | 302 | .print_tuple = gre_print_tuple, |
297 | .print_conntrack = gre_print_conntrack, | 303 | .print_conntrack = gre_print_conntrack, |
304 | .get_timeouts = gre_get_timeouts, | ||
298 | .packet = gre_packet, | 305 | .packet = gre_packet, |
299 | .new = gre_new, | 306 | .new = gre_new, |
300 | .destroy = gre_destroy, | 307 | .destroy = gre_destroy, |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index afa69136061a..2a0703371e24 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -279,13 +279,19 @@ static int sctp_new_state(enum ip_conntrack_dir dir, | |||
279 | return sctp_conntracks[dir][i][cur_state]; | 279 | return sctp_conntracks[dir][i][cur_state]; |
280 | } | 280 | } |
281 | 281 | ||
282 | static unsigned int *sctp_get_timeouts(struct net *net) | ||
283 | { | ||
284 | return sctp_timeouts; | ||
285 | } | ||
286 | |||
282 | /* Returns verdict for packet, or -NF_ACCEPT for invalid. */ | 287 | /* Returns verdict for packet, or -NF_ACCEPT for invalid. */ |
283 | static int sctp_packet(struct nf_conn *ct, | 288 | static int sctp_packet(struct nf_conn *ct, |
284 | const struct sk_buff *skb, | 289 | const struct sk_buff *skb, |
285 | unsigned int dataoff, | 290 | unsigned int dataoff, |
286 | enum ip_conntrack_info ctinfo, | 291 | enum ip_conntrack_info ctinfo, |
287 | u_int8_t pf, | 292 | u_int8_t pf, |
288 | unsigned int hooknum) | 293 | unsigned int hooknum, |
294 | unsigned int *timeouts) | ||
289 | { | 295 | { |
290 | enum sctp_conntrack new_state, old_state; | 296 | enum sctp_conntrack new_state, old_state; |
291 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 297 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
@@ -370,7 +376,7 @@ static int sctp_packet(struct nf_conn *ct, | |||
370 | } | 376 | } |
371 | spin_unlock_bh(&ct->lock); | 377 | spin_unlock_bh(&ct->lock); |
372 | 378 | ||
373 | nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]); | 379 | nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); |
374 | 380 | ||
375 | if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && | 381 | if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && |
376 | dir == IP_CT_DIR_REPLY && | 382 | dir == IP_CT_DIR_REPLY && |
@@ -390,7 +396,7 @@ out: | |||
390 | 396 | ||
391 | /* Called when a new connection for this protocol found. */ | 397 | /* Called when a new connection for this protocol found. */ |
392 | static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb, | 398 | static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb, |
393 | unsigned int dataoff) | 399 | unsigned int dataoff, unsigned int *timeouts) |
394 | { | 400 | { |
395 | enum sctp_conntrack new_state; | 401 | enum sctp_conntrack new_state; |
396 | const struct sctphdr *sh; | 402 | const struct sctphdr *sh; |
@@ -664,6 +670,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { | |||
664 | .print_tuple = sctp_print_tuple, | 670 | .print_tuple = sctp_print_tuple, |
665 | .print_conntrack = sctp_print_conntrack, | 671 | .print_conntrack = sctp_print_conntrack, |
666 | .packet = sctp_packet, | 672 | .packet = sctp_packet, |
673 | .get_timeouts = sctp_get_timeouts, | ||
667 | .new = sctp_new, | 674 | .new = sctp_new, |
668 | .me = THIS_MODULE, | 675 | .me = THIS_MODULE, |
669 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 676 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
@@ -694,6 +701,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { | |||
694 | .print_tuple = sctp_print_tuple, | 701 | .print_tuple = sctp_print_tuple, |
695 | .print_conntrack = sctp_print_conntrack, | 702 | .print_conntrack = sctp_print_conntrack, |
696 | .packet = sctp_packet, | 703 | .packet = sctp_packet, |
704 | .get_timeouts = sctp_get_timeouts, | ||
697 | .new = sctp_new, | 705 | .new = sctp_new, |
698 | .me = THIS_MODULE, | 706 | .me = THIS_MODULE, |
699 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 707 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 57c778546094..8372bb43feb0 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -813,13 +813,19 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, | |||
813 | return NF_ACCEPT; | 813 | return NF_ACCEPT; |
814 | } | 814 | } |
815 | 815 | ||
816 | static unsigned int *tcp_get_timeouts(struct net *net) | ||
817 | { | ||
818 | return tcp_timeouts; | ||
819 | } | ||
820 | |||
816 | /* Returns verdict for packet, or -1 for invalid. */ | 821 | /* Returns verdict for packet, or -1 for invalid. */ |
817 | static int tcp_packet(struct nf_conn *ct, | 822 | static int tcp_packet(struct nf_conn *ct, |
818 | const struct sk_buff *skb, | 823 | const struct sk_buff *skb, |
819 | unsigned int dataoff, | 824 | unsigned int dataoff, |
820 | enum ip_conntrack_info ctinfo, | 825 | enum ip_conntrack_info ctinfo, |
821 | u_int8_t pf, | 826 | u_int8_t pf, |
822 | unsigned int hooknum) | 827 | unsigned int hooknum, |
828 | unsigned int *timeouts) | ||
823 | { | 829 | { |
824 | struct net *net = nf_ct_net(ct); | 830 | struct net *net = nf_ct_net(ct); |
825 | struct nf_conntrack_tuple *tuple; | 831 | struct nf_conntrack_tuple *tuple; |
@@ -1014,14 +1020,14 @@ static int tcp_packet(struct nf_conn *ct, | |||
1014 | ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; | 1020 | ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; |
1015 | 1021 | ||
1016 | if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans && | 1022 | if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans && |
1017 | tcp_timeouts[new_state] > tcp_timeouts[TCP_CONNTRACK_RETRANS]) | 1023 | timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS]) |
1018 | timeout = tcp_timeouts[TCP_CONNTRACK_RETRANS]; | 1024 | timeout = timeouts[TCP_CONNTRACK_RETRANS]; |
1019 | else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) & | 1025 | else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) & |
1020 | IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && | 1026 | IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && |
1021 | tcp_timeouts[new_state] > tcp_timeouts[TCP_CONNTRACK_UNACK]) | 1027 | timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]) |
1022 | timeout = tcp_timeouts[TCP_CONNTRACK_UNACK]; | 1028 | timeout = timeouts[TCP_CONNTRACK_UNACK]; |
1023 | else | 1029 | else |
1024 | timeout = tcp_timeouts[new_state]; | 1030 | timeout = timeouts[new_state]; |
1025 | spin_unlock_bh(&ct->lock); | 1031 | spin_unlock_bh(&ct->lock); |
1026 | 1032 | ||
1027 | if (new_state != old_state) | 1033 | if (new_state != old_state) |
@@ -1053,7 +1059,7 @@ static int tcp_packet(struct nf_conn *ct, | |||
1053 | 1059 | ||
1054 | /* Called when a new connection for this protocol found. */ | 1060 | /* Called when a new connection for this protocol found. */ |
1055 | static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, | 1061 | static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, |
1056 | unsigned int dataoff) | 1062 | unsigned int dataoff, unsigned int *timeouts) |
1057 | { | 1063 | { |
1058 | enum tcp_conntrack new_state; | 1064 | enum tcp_conntrack new_state; |
1059 | const struct tcphdr *th; | 1065 | const struct tcphdr *th; |
@@ -1444,6 +1450,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = | |||
1444 | .print_tuple = tcp_print_tuple, | 1450 | .print_tuple = tcp_print_tuple, |
1445 | .print_conntrack = tcp_print_conntrack, | 1451 | .print_conntrack = tcp_print_conntrack, |
1446 | .packet = tcp_packet, | 1452 | .packet = tcp_packet, |
1453 | .get_timeouts = tcp_get_timeouts, | ||
1447 | .new = tcp_new, | 1454 | .new = tcp_new, |
1448 | .error = tcp_error, | 1455 | .error = tcp_error, |
1449 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 1456 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
@@ -1476,6 +1483,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = | |||
1476 | .print_tuple = tcp_print_tuple, | 1483 | .print_tuple = tcp_print_tuple, |
1477 | .print_conntrack = tcp_print_conntrack, | 1484 | .print_conntrack = tcp_print_conntrack, |
1478 | .packet = tcp_packet, | 1485 | .packet = tcp_packet, |
1486 | .get_timeouts = tcp_get_timeouts, | ||
1479 | .new = tcp_new, | 1487 | .new = tcp_new, |
1480 | .error = tcp_error, | 1488 | .error = tcp_error, |
1481 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 1489 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 5b24ff882f95..70e005992d5b 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c | |||
@@ -71,32 +71,38 @@ static int udp_print_tuple(struct seq_file *s, | |||
71 | ntohs(tuple->dst.u.udp.port)); | 71 | ntohs(tuple->dst.u.udp.port)); |
72 | } | 72 | } |
73 | 73 | ||
74 | static unsigned int *udp_get_timeouts(struct net *net) | ||
75 | { | ||
76 | return udp_timeouts; | ||
77 | } | ||
78 | |||
74 | /* Returns verdict for packet, and may modify conntracktype */ | 79 | /* Returns verdict for packet, and may modify conntracktype */ |
75 | static int udp_packet(struct nf_conn *ct, | 80 | static int udp_packet(struct nf_conn *ct, |
76 | const struct sk_buff *skb, | 81 | const struct sk_buff *skb, |
77 | unsigned int dataoff, | 82 | unsigned int dataoff, |
78 | enum ip_conntrack_info ctinfo, | 83 | enum ip_conntrack_info ctinfo, |
79 | u_int8_t pf, | 84 | u_int8_t pf, |
80 | unsigned int hooknum) | 85 | unsigned int hooknum, |
86 | unsigned int *timeouts) | ||
81 | { | 87 | { |
82 | /* If we've seen traffic both ways, this is some kind of UDP | 88 | /* If we've seen traffic both ways, this is some kind of UDP |
83 | stream. Extend timeout. */ | 89 | stream. Extend timeout. */ |
84 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { | 90 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
85 | nf_ct_refresh_acct(ct, ctinfo, skb, | 91 | nf_ct_refresh_acct(ct, ctinfo, skb, |
86 | udp_timeouts[UDP_CT_REPLIED]); | 92 | timeouts[UDP_CT_REPLIED]); |
87 | /* Also, more likely to be important, and not a probe */ | 93 | /* Also, more likely to be important, and not a probe */ |
88 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) | 94 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) |
89 | nf_conntrack_event_cache(IPCT_ASSURED, ct); | 95 | nf_conntrack_event_cache(IPCT_ASSURED, ct); |
90 | } else { | 96 | } else { |
91 | nf_ct_refresh_acct(ct, ctinfo, skb, | 97 | nf_ct_refresh_acct(ct, ctinfo, skb, |
92 | udp_timeouts[UDP_CT_UNREPLIED]); | 98 | timeouts[UDP_CT_UNREPLIED]); |
93 | } | 99 | } |
94 | return NF_ACCEPT; | 100 | return NF_ACCEPT; |
95 | } | 101 | } |
96 | 102 | ||
97 | /* Called when a new connection for this protocol found. */ | 103 | /* Called when a new connection for this protocol found. */ |
98 | static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb, | 104 | static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb, |
99 | unsigned int dataoff) | 105 | unsigned int dataoff, unsigned int *timeouts) |
100 | { | 106 | { |
101 | return true; | 107 | return true; |
102 | } | 108 | } |
@@ -196,6 +202,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = | |||
196 | .invert_tuple = udp_invert_tuple, | 202 | .invert_tuple = udp_invert_tuple, |
197 | .print_tuple = udp_print_tuple, | 203 | .print_tuple = udp_print_tuple, |
198 | .packet = udp_packet, | 204 | .packet = udp_packet, |
205 | .get_timeouts = udp_get_timeouts, | ||
199 | .new = udp_new, | 206 | .new = udp_new, |
200 | .error = udp_error, | 207 | .error = udp_error, |
201 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 208 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
@@ -224,6 +231,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = | |||
224 | .invert_tuple = udp_invert_tuple, | 231 | .invert_tuple = udp_invert_tuple, |
225 | .print_tuple = udp_print_tuple, | 232 | .print_tuple = udp_print_tuple, |
226 | .packet = udp_packet, | 233 | .packet = udp_packet, |
234 | .get_timeouts = udp_get_timeouts, | ||
227 | .new = udp_new, | 235 | .new = udp_new, |
228 | .error = udp_error, | 236 | .error = udp_error, |
229 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 237 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index e73071743e01..0b32ccb1d515 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c | |||
@@ -68,32 +68,38 @@ static int udplite_print_tuple(struct seq_file *s, | |||
68 | ntohs(tuple->dst.u.udp.port)); | 68 | ntohs(tuple->dst.u.udp.port)); |
69 | } | 69 | } |
70 | 70 | ||
71 | static unsigned int *udplite_get_timeouts(struct net *net) | ||
72 | { | ||
73 | return udplite_timeouts; | ||
74 | } | ||
75 | |||
71 | /* Returns verdict for packet, and may modify conntracktype */ | 76 | /* Returns verdict for packet, and may modify conntracktype */ |
72 | static int udplite_packet(struct nf_conn *ct, | 77 | static int udplite_packet(struct nf_conn *ct, |
73 | const struct sk_buff *skb, | 78 | const struct sk_buff *skb, |
74 | unsigned int dataoff, | 79 | unsigned int dataoff, |
75 | enum ip_conntrack_info ctinfo, | 80 | enum ip_conntrack_info ctinfo, |
76 | u_int8_t pf, | 81 | u_int8_t pf, |
77 | unsigned int hooknum) | 82 | unsigned int hooknum, |
83 | unsigned int *timeouts) | ||
78 | { | 84 | { |
79 | /* If we've seen traffic both ways, this is some kind of UDP | 85 | /* If we've seen traffic both ways, this is some kind of UDP |
80 | stream. Extend timeout. */ | 86 | stream. Extend timeout. */ |
81 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { | 87 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
82 | nf_ct_refresh_acct(ct, ctinfo, skb, | 88 | nf_ct_refresh_acct(ct, ctinfo, skb, |
83 | udplite_timeouts[UDPLITE_CT_REPLIED]); | 89 | timeouts[UDPLITE_CT_REPLIED]); |
84 | /* Also, more likely to be important, and not a probe */ | 90 | /* Also, more likely to be important, and not a probe */ |
85 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) | 91 | if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) |
86 | nf_conntrack_event_cache(IPCT_ASSURED, ct); | 92 | nf_conntrack_event_cache(IPCT_ASSURED, ct); |
87 | } else { | 93 | } else { |
88 | nf_ct_refresh_acct(ct, ctinfo, skb, | 94 | nf_ct_refresh_acct(ct, ctinfo, skb, |
89 | udplite_timeouts[UDPLITE_CT_UNREPLIED]); | 95 | timeouts[UDPLITE_CT_UNREPLIED]); |
90 | } | 96 | } |
91 | return NF_ACCEPT; | 97 | return NF_ACCEPT; |
92 | } | 98 | } |
93 | 99 | ||
94 | /* Called when a new connection for this protocol found. */ | 100 | /* Called when a new connection for this protocol found. */ |
95 | static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb, | 101 | static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb, |
96 | unsigned int dataoff) | 102 | unsigned int dataoff, unsigned int *timeouts) |
97 | { | 103 | { |
98 | return true; | 104 | return true; |
99 | } | 105 | } |
@@ -181,6 +187,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = | |||
181 | .invert_tuple = udplite_invert_tuple, | 187 | .invert_tuple = udplite_invert_tuple, |
182 | .print_tuple = udplite_print_tuple, | 188 | .print_tuple = udplite_print_tuple, |
183 | .packet = udplite_packet, | 189 | .packet = udplite_packet, |
190 | .get_timeouts = udplite_get_timeouts, | ||
184 | .new = udplite_new, | 191 | .new = udplite_new, |
185 | .error = udplite_error, | 192 | .error = udplite_error, |
186 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 193 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
@@ -205,6 +212,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = | |||
205 | .invert_tuple = udplite_invert_tuple, | 212 | .invert_tuple = udplite_invert_tuple, |
206 | .print_tuple = udplite_print_tuple, | 213 | .print_tuple = udplite_print_tuple, |
207 | .packet = udplite_packet, | 214 | .packet = udplite_packet, |
215 | .get_timeouts = udplite_get_timeouts, | ||
208 | .new = udplite_new, | 216 | .new = udplite_new, |
209 | .error = udplite_error, | 217 | .error = udplite_error, |
210 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 218 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |