diff options
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 10 | ||||
-rw-r--r-- | include/net/inet_frag.h | 4 | ||||
-rw-r--r-- | net/ieee802154/reassembly.c | 5 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 43 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 1 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 5 |
7 files changed, 40 insertions, 33 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 625c8dda4be7..e8c304e37831 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -111,11 +111,6 @@ ipfrag_low_thresh - INTEGER | |||
111 | ipfrag_time - INTEGER | 111 | ipfrag_time - INTEGER |
112 | Time in seconds to keep an IP fragment in memory. | 112 | Time in seconds to keep an IP fragment in memory. |
113 | 113 | ||
114 | ipfrag_secret_interval - INTEGER | ||
115 | Regeneration interval (in seconds) of the hash secret (or lifetime | ||
116 | for the hash secret) for IP fragments. | ||
117 | Default: 600 | ||
118 | |||
119 | ipfrag_max_dist - INTEGER | 114 | ipfrag_max_dist - INTEGER |
120 | ipfrag_max_dist is a non-negative integer value which defines the | 115 | ipfrag_max_dist is a non-negative integer value which defines the |
121 | maximum "disorder" which is allowed among fragments which share a | 116 | maximum "disorder" which is allowed among fragments which share a |
@@ -1164,11 +1159,6 @@ ip6frag_low_thresh - INTEGER | |||
1164 | ip6frag_time - INTEGER | 1159 | ip6frag_time - INTEGER |
1165 | Time in seconds to keep an IPv6 fragment in memory. | 1160 | Time in seconds to keep an IPv6 fragment in memory. |
1166 | 1161 | ||
1167 | ip6frag_secret_interval - INTEGER | ||
1168 | Regeneration interval (in seconds) of the hash secret (or lifetime | ||
1169 | for the hash secret) for IPv6 fragments. | ||
1170 | Default: 600 | ||
1171 | |||
1172 | conf/default/*: | 1162 | conf/default/*: |
1173 | Change the interface-specific default settings. | 1163 | Change the interface-specific default settings. |
1174 | 1164 | ||
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index 90d21ea62c59..d9cc5bb64854 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h | |||
@@ -58,11 +58,11 @@ struct inet_frags { | |||
58 | * Its primarily a rebuild protection rwlock. | 58 | * Its primarily a rebuild protection rwlock. |
59 | */ | 59 | */ |
60 | rwlock_t lock ____cacheline_aligned_in_smp; | 60 | rwlock_t lock ____cacheline_aligned_in_smp; |
61 | int secret_interval; | ||
62 | struct timer_list secret_timer; | ||
63 | 61 | ||
64 | struct work_struct frags_work; | 62 | struct work_struct frags_work; |
65 | unsigned int next_bucket; | 63 | unsigned int next_bucket; |
64 | unsigned long last_rebuild_jiffies; | ||
65 | bool rebuild; | ||
66 | 66 | ||
67 | /* The first call to hashfn is responsible to initialize | 67 | /* The first call to hashfn is responsible to initialize |
68 | * rnd. This is best done with net_get_random_once. | 68 | * rnd. This is best done with net_get_random_once. |
diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c index b4bc7a50eccf..20d219682d84 100644 --- a/net/ieee802154/reassembly.c +++ b/net/ieee802154/reassembly.c | |||
@@ -419,10 +419,12 @@ static struct ctl_table lowpan_frags_ns_ctl_table[] = { | |||
419 | { } | 419 | { } |
420 | }; | 420 | }; |
421 | 421 | ||
422 | /* secret interval has been deprecated */ | ||
423 | static int lowpan_frags_secret_interval_unused; | ||
422 | static struct ctl_table lowpan_frags_ctl_table[] = { | 424 | static struct ctl_table lowpan_frags_ctl_table[] = { |
423 | { | 425 | { |
424 | .procname = "6lowpanfrag_secret_interval", | 426 | .procname = "6lowpanfrag_secret_interval", |
425 | .data = &lowpan_frags.secret_interval, | 427 | .data = &lowpan_frags_secret_interval_unused, |
426 | .maxlen = sizeof(int), | 428 | .maxlen = sizeof(int), |
427 | .mode = 0644, | 429 | .mode = 0644, |
428 | .proc_handler = proc_dointvec_jiffies, | 430 | .proc_handler = proc_dointvec_jiffies, |
@@ -562,7 +564,6 @@ int __init lowpan_net_frag_init(void) | |||
562 | lowpan_frags.qsize = sizeof(struct frag_queue); | 564 | lowpan_frags.qsize = sizeof(struct frag_queue); |
563 | lowpan_frags.match = lowpan_frag_match; | 565 | lowpan_frags.match = lowpan_frag_match; |
564 | lowpan_frags.frag_expire = lowpan_frag_expire; | 566 | lowpan_frags.frag_expire = lowpan_frag_expire; |
565 | lowpan_frags.secret_interval = 10 * 60 * HZ; | ||
566 | inet_frags_init(&lowpan_frags); | 567 | inet_frags_init(&lowpan_frags); |
567 | 568 | ||
568 | return ret; | 569 | return ret; |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 198a5ed7a815..58d4c38534f6 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #define INETFRAGS_EVICT_BUCKETS 128 | 28 | #define INETFRAGS_EVICT_BUCKETS 128 |
29 | #define INETFRAGS_EVICT_MAX 512 | 29 | #define INETFRAGS_EVICT_MAX 512 |
30 | 30 | ||
31 | /* don't rebuild inetfrag table with new secret more often than this */ | ||
32 | #define INETFRAGS_MIN_REBUILD_INTERVAL (5 * HZ) | ||
33 | |||
31 | /* Given the OR values of all fragments, apply RFC 3168 5.3 requirements | 34 | /* Given the OR values of all fragments, apply RFC 3168 5.3 requirements |
32 | * Value : 0xff if frame should be dropped. | 35 | * Value : 0xff if frame should be dropped. |
33 | * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field | 36 | * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field |
@@ -55,16 +58,24 @@ inet_frag_hashfn(const struct inet_frags *f, const struct inet_frag_queue *q) | |||
55 | return f->hashfn(q) & (INETFRAGS_HASHSZ - 1); | 58 | return f->hashfn(q) & (INETFRAGS_HASHSZ - 1); |
56 | } | 59 | } |
57 | 60 | ||
58 | static void inet_frag_secret_rebuild(unsigned long dummy) | 61 | static bool inet_frag_may_rebuild(struct inet_frags *f) |
62 | { | ||
63 | return time_after(jiffies, | ||
64 | f->last_rebuild_jiffies + INETFRAGS_MIN_REBUILD_INTERVAL); | ||
65 | } | ||
66 | |||
67 | static void inet_frag_secret_rebuild(struct inet_frags *f) | ||
59 | { | 68 | { |
60 | struct inet_frags *f = (struct inet_frags *)dummy; | ||
61 | unsigned long now = jiffies; | ||
62 | int i; | 69 | int i; |
63 | 70 | ||
64 | /* Per bucket lock NOT needed here, due to write lock protection */ | 71 | /* Per bucket lock NOT needed here, due to write lock protection */ |
65 | write_lock(&f->lock); | 72 | write_lock_bh(&f->lock); |
73 | |||
74 | if (!inet_frag_may_rebuild(f)) | ||
75 | goto out; | ||
66 | 76 | ||
67 | get_random_bytes(&f->rnd, sizeof(u32)); | 77 | get_random_bytes(&f->rnd, sizeof(u32)); |
78 | |||
68 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { | 79 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { |
69 | struct inet_frag_bucket *hb; | 80 | struct inet_frag_bucket *hb; |
70 | struct inet_frag_queue *q; | 81 | struct inet_frag_queue *q; |
@@ -85,9 +96,11 @@ static void inet_frag_secret_rebuild(unsigned long dummy) | |||
85 | } | 96 | } |
86 | } | 97 | } |
87 | } | 98 | } |
88 | write_unlock(&f->lock); | ||
89 | 99 | ||
90 | mod_timer(&f->secret_timer, now + f->secret_interval); | 100 | f->rebuild = false; |
101 | f->last_rebuild_jiffies = jiffies; | ||
102 | out: | ||
103 | write_unlock_bh(&f->lock); | ||
91 | } | 104 | } |
92 | 105 | ||
93 | static bool inet_fragq_should_evict(const struct inet_frag_queue *q) | 106 | static bool inet_fragq_should_evict(const struct inet_frag_queue *q) |
@@ -162,6 +175,8 @@ static void inet_frag_worker(struct work_struct *work) | |||
162 | f->next_bucket = i; | 175 | f->next_bucket = i; |
163 | 176 | ||
164 | read_unlock_bh(&f->lock); | 177 | read_unlock_bh(&f->lock); |
178 | if (f->rebuild && inet_frag_may_rebuild(f)) | ||
179 | inet_frag_secret_rebuild(f); | ||
165 | } | 180 | } |
166 | 181 | ||
167 | static void inet_frag_schedule_worker(struct inet_frags *f) | 182 | static void inet_frag_schedule_worker(struct inet_frags *f) |
@@ -183,11 +198,7 @@ void inet_frags_init(struct inet_frags *f) | |||
183 | INIT_HLIST_HEAD(&hb->chain); | 198 | INIT_HLIST_HEAD(&hb->chain); |
184 | } | 199 | } |
185 | rwlock_init(&f->lock); | 200 | rwlock_init(&f->lock); |
186 | 201 | f->last_rebuild_jiffies = 0; | |
187 | setup_timer(&f->secret_timer, inet_frag_secret_rebuild, | ||
188 | (unsigned long)f); | ||
189 | f->secret_timer.expires = jiffies + f->secret_interval; | ||
190 | add_timer(&f->secret_timer); | ||
191 | } | 202 | } |
192 | EXPORT_SYMBOL(inet_frags_init); | 203 | EXPORT_SYMBOL(inet_frags_init); |
193 | 204 | ||
@@ -199,7 +210,6 @@ EXPORT_SYMBOL(inet_frags_init_net); | |||
199 | 210 | ||
200 | void inet_frags_fini(struct inet_frags *f) | 211 | void inet_frags_fini(struct inet_frags *f) |
201 | { | 212 | { |
202 | del_timer(&f->secret_timer); | ||
203 | cancel_work_sync(&f->frags_work); | 213 | cancel_work_sync(&f->frags_work); |
204 | } | 214 | } |
205 | EXPORT_SYMBOL(inet_frags_fini); | 215 | EXPORT_SYMBOL(inet_frags_fini); |
@@ -399,8 +409,13 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, | |||
399 | 409 | ||
400 | if (depth <= INETFRAGS_MAXDEPTH) | 410 | if (depth <= INETFRAGS_MAXDEPTH) |
401 | return inet_frag_create(nf, f, key); | 411 | return inet_frag_create(nf, f, key); |
402 | else | 412 | |
403 | return ERR_PTR(-ENOBUFS); | 413 | if (inet_frag_may_rebuild(f)) { |
414 | f->rebuild = true; | ||
415 | inet_frag_schedule_worker(f); | ||
416 | } | ||
417 | |||
418 | return ERR_PTR(-ENOBUFS); | ||
404 | } | 419 | } |
405 | EXPORT_SYMBOL(inet_frag_find); | 420 | EXPORT_SYMBOL(inet_frag_find); |
406 | 421 | ||
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 8fbeee495037..44e591a7e03f 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -720,10 +720,12 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = { | |||
720 | { } | 720 | { } |
721 | }; | 721 | }; |
722 | 722 | ||
723 | /* secret interval has been deprecated */ | ||
724 | static int ip4_frags_secret_interval_unused; | ||
723 | static struct ctl_table ip4_frags_ctl_table[] = { | 725 | static struct ctl_table ip4_frags_ctl_table[] = { |
724 | { | 726 | { |
725 | .procname = "ipfrag_secret_interval", | 727 | .procname = "ipfrag_secret_interval", |
726 | .data = &ip4_frags.secret_interval, | 728 | .data = &ip4_frags_secret_interval_unused, |
727 | .maxlen = sizeof(int), | 729 | .maxlen = sizeof(int), |
728 | .mode = 0644, | 730 | .mode = 0644, |
729 | .proc_handler = proc_dointvec_jiffies, | 731 | .proc_handler = proc_dointvec_jiffies, |
@@ -853,6 +855,5 @@ void __init ipfrag_init(void) | |||
853 | ip4_frags.qsize = sizeof(struct ipq); | 855 | ip4_frags.qsize = sizeof(struct ipq); |
854 | ip4_frags.match = ip4_frag_match; | 856 | ip4_frags.match = ip4_frag_match; |
855 | ip4_frags.frag_expire = ip_expire; | 857 | ip4_frags.frag_expire = ip_expire; |
856 | ip4_frags.secret_interval = 10 * 60 * HZ; | ||
857 | inet_frags_init(&ip4_frags); | 858 | inet_frags_init(&ip4_frags); |
858 | } | 859 | } |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index fb0f72a0ff31..3b3ef9774cc2 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -669,7 +669,6 @@ int nf_ct_frag6_init(void) | |||
669 | nf_frags.qsize = sizeof(struct frag_queue); | 669 | nf_frags.qsize = sizeof(struct frag_queue); |
670 | nf_frags.match = ip6_frag_match; | 670 | nf_frags.match = ip6_frag_match; |
671 | nf_frags.frag_expire = nf_ct_frag6_expire; | 671 | nf_frags.frag_expire = nf_ct_frag6_expire; |
672 | nf_frags.secret_interval = 10 * 60 * HZ; | ||
673 | inet_frags_init(&nf_frags); | 672 | inet_frags_init(&nf_frags); |
674 | 673 | ||
675 | ret = register_pernet_subsys(&nf_ct_net_ops); | 674 | ret = register_pernet_subsys(&nf_ct_net_ops); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index af85551682c2..987fea46b915 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -604,10 +604,12 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = { | |||
604 | { } | 604 | { } |
605 | }; | 605 | }; |
606 | 606 | ||
607 | /* secret interval has been deprecated */ | ||
608 | static int ip6_frags_secret_interval_unused; | ||
607 | static struct ctl_table ip6_frags_ctl_table[] = { | 609 | static struct ctl_table ip6_frags_ctl_table[] = { |
608 | { | 610 | { |
609 | .procname = "ip6frag_secret_interval", | 611 | .procname = "ip6frag_secret_interval", |
610 | .data = &ip6_frags.secret_interval, | 612 | .data = &ip6_frags_secret_interval_unused, |
611 | .maxlen = sizeof(int), | 613 | .maxlen = sizeof(int), |
612 | .mode = 0644, | 614 | .mode = 0644, |
613 | .proc_handler = proc_dointvec_jiffies, | 615 | .proc_handler = proc_dointvec_jiffies, |
@@ -737,7 +739,6 @@ int __init ipv6_frag_init(void) | |||
737 | ip6_frags.qsize = sizeof(struct frag_queue); | 739 | ip6_frags.qsize = sizeof(struct frag_queue); |
738 | ip6_frags.match = ip6_frag_match; | 740 | ip6_frags.match = ip6_frag_match; |
739 | ip6_frags.frag_expire = ip6_frag_expire; | 741 | ip6_frags.frag_expire = ip6_frag_expire; |
740 | ip6_frags.secret_interval = 10 * 60 * HZ; | ||
741 | inet_frags_init(&ip6_frags); | 742 | inet_frags_init(&ip6_frags); |
742 | out: | 743 | out: |
743 | return ret; | 744 | return ret; |