diff options
Diffstat (limited to 'net/ipv6/netfilter/nf_conntrack_reasm.c')
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 218 |
1 files changed, 123 insertions, 95 deletions
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index c9c78c2e666..18bd9bbbd1c 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -57,41 +57,27 @@ struct nf_ct_frag6_skb_cb | |||
57 | 57 | ||
58 | #define NFCT_FRAG6_CB(skb) ((struct nf_ct_frag6_skb_cb*)((skb)->cb)) | 58 | #define NFCT_FRAG6_CB(skb) ((struct nf_ct_frag6_skb_cb*)((skb)->cb)) |
59 | 59 | ||
60 | struct nf_ct_frag6_queue | ||
61 | { | ||
62 | struct inet_frag_queue q; | ||
63 | |||
64 | __be32 id; /* fragment id */ | ||
65 | u32 user; | ||
66 | struct in6_addr saddr; | ||
67 | struct in6_addr daddr; | ||
68 | |||
69 | unsigned int csum; | ||
70 | __u16 nhoffset; | ||
71 | }; | ||
72 | |||
73 | static struct inet_frags nf_frags; | 60 | static struct inet_frags nf_frags; |
74 | static struct netns_frags nf_init_frags; | ||
75 | 61 | ||
76 | #ifdef CONFIG_SYSCTL | 62 | #ifdef CONFIG_SYSCTL |
77 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { | 63 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { |
78 | { | 64 | { |
79 | .procname = "nf_conntrack_frag6_timeout", | 65 | .procname = "nf_conntrack_frag6_timeout", |
80 | .data = &nf_init_frags.timeout, | 66 | .data = &init_net.nf_frag.frags.timeout, |
81 | .maxlen = sizeof(unsigned int), | 67 | .maxlen = sizeof(unsigned int), |
82 | .mode = 0644, | 68 | .mode = 0644, |
83 | .proc_handler = proc_dointvec_jiffies, | 69 | .proc_handler = proc_dointvec_jiffies, |
84 | }, | 70 | }, |
85 | { | 71 | { |
86 | .procname = "nf_conntrack_frag6_low_thresh", | 72 | .procname = "nf_conntrack_frag6_low_thresh", |
87 | .data = &nf_init_frags.low_thresh, | 73 | .data = &init_net.nf_frag.frags.low_thresh, |
88 | .maxlen = sizeof(unsigned int), | 74 | .maxlen = sizeof(unsigned int), |
89 | .mode = 0644, | 75 | .mode = 0644, |
90 | .proc_handler = proc_dointvec, | 76 | .proc_handler = proc_dointvec, |
91 | }, | 77 | }, |
92 | { | 78 | { |
93 | .procname = "nf_conntrack_frag6_high_thresh", | 79 | .procname = "nf_conntrack_frag6_high_thresh", |
94 | .data = &nf_init_frags.high_thresh, | 80 | .data = &init_net.nf_frag.frags.high_thresh, |
95 | .maxlen = sizeof(unsigned int), | 81 | .maxlen = sizeof(unsigned int), |
96 | .mode = 0644, | 82 | .mode = 0644, |
97 | .proc_handler = proc_dointvec, | 83 | .proc_handler = proc_dointvec, |
@@ -99,68 +85,86 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = { | |||
99 | { } | 85 | { } |
100 | }; | 86 | }; |
101 | 87 | ||
102 | static struct ctl_table_header *nf_ct_frag6_sysctl_header; | 88 | static int __net_init nf_ct_frag6_sysctl_register(struct net *net) |
103 | #endif | ||
104 | |||
105 | static unsigned int nf_hashfn(struct inet_frag_queue *q) | ||
106 | { | 89 | { |
107 | const struct nf_ct_frag6_queue *nq; | 90 | struct ctl_table *table; |
91 | struct ctl_table_header *hdr; | ||
92 | |||
93 | table = nf_ct_frag6_sysctl_table; | ||
94 | if (!net_eq(net, &init_net)) { | ||
95 | table = kmemdup(table, sizeof(nf_ct_frag6_sysctl_table), | ||
96 | GFP_KERNEL); | ||
97 | if (table == NULL) | ||
98 | goto err_alloc; | ||
99 | |||
100 | table[0].data = &net->ipv6.frags.high_thresh; | ||
101 | table[1].data = &net->ipv6.frags.low_thresh; | ||
102 | table[2].data = &net->ipv6.frags.timeout; | ||
103 | } | ||
108 | 104 | ||
109 | nq = container_of(q, struct nf_ct_frag6_queue, q); | 105 | hdr = register_net_sysctl(net, "net/netfilter", table); |
110 | return inet6_hash_frag(nq->id, &nq->saddr, &nq->daddr, nf_frags.rnd); | 106 | if (hdr == NULL) |
107 | goto err_reg; | ||
108 | |||
109 | net->nf_frag.sysctl.frags_hdr = hdr; | ||
110 | return 0; | ||
111 | |||
112 | err_reg: | ||
113 | if (!net_eq(net, &init_net)) | ||
114 | kfree(table); | ||
115 | err_alloc: | ||
116 | return -ENOMEM; | ||
111 | } | 117 | } |
112 | 118 | ||
113 | static void nf_skb_free(struct sk_buff *skb) | 119 | static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) |
114 | { | 120 | { |
115 | if (NFCT_FRAG6_CB(skb)->orig) | 121 | struct ctl_table *table; |
116 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); | ||
117 | } | ||
118 | 122 | ||
119 | /* Destruction primitives. */ | 123 | table = net->nf_frag.sysctl.frags_hdr->ctl_table_arg; |
124 | unregister_net_sysctl_table(net->nf_frag.sysctl.frags_hdr); | ||
125 | if (!net_eq(net, &init_net)) | ||
126 | kfree(table); | ||
127 | } | ||
120 | 128 | ||
121 | static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) | 129 | #else |
130 | static int __net_init nf_ct_frag6_sysctl_register(struct net *net) | ||
122 | { | 131 | { |
123 | inet_frag_put(&fq->q, &nf_frags); | 132 | return 0; |
124 | } | 133 | } |
134 | static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) | ||
135 | { | ||
136 | } | ||
137 | #endif | ||
125 | 138 | ||
126 | /* Kill fq entry. It is not destroyed immediately, | 139 | static unsigned int nf_hashfn(struct inet_frag_queue *q) |
127 | * because caller (and someone more) holds reference count. | ||
128 | */ | ||
129 | static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) | ||
130 | { | 140 | { |
131 | inet_frag_kill(&fq->q, &nf_frags); | 141 | const struct frag_queue *nq; |
142 | |||
143 | nq = container_of(q, struct frag_queue, q); | ||
144 | return inet6_hash_frag(nq->id, &nq->saddr, &nq->daddr, nf_frags.rnd); | ||
132 | } | 145 | } |
133 | 146 | ||
134 | static void nf_ct_frag6_evictor(void) | 147 | static void nf_skb_free(struct sk_buff *skb) |
135 | { | 148 | { |
136 | local_bh_disable(); | 149 | if (NFCT_FRAG6_CB(skb)->orig) |
137 | inet_frag_evictor(&nf_init_frags, &nf_frags); | 150 | kfree_skb(NFCT_FRAG6_CB(skb)->orig); |
138 | local_bh_enable(); | ||
139 | } | 151 | } |
140 | 152 | ||
141 | static void nf_ct_frag6_expire(unsigned long data) | 153 | static void nf_ct_frag6_expire(unsigned long data) |
142 | { | 154 | { |
143 | struct nf_ct_frag6_queue *fq; | 155 | struct frag_queue *fq; |
144 | 156 | struct net *net; | |
145 | fq = container_of((struct inet_frag_queue *)data, | ||
146 | struct nf_ct_frag6_queue, q); | ||
147 | |||
148 | spin_lock(&fq->q.lock); | ||
149 | 157 | ||
150 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 158 | fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q); |
151 | goto out; | 159 | net = container_of(fq->q.net, struct net, nf_frag.frags); |
152 | 160 | ||
153 | fq_kill(fq); | 161 | ip6_expire_frag_queue(net, fq, &nf_frags); |
154 | |||
155 | out: | ||
156 | spin_unlock(&fq->q.lock); | ||
157 | fq_put(fq); | ||
158 | } | 162 | } |
159 | 163 | ||
160 | /* Creation primitives. */ | 164 | /* Creation primitives. */ |
161 | 165 | static inline struct frag_queue *fq_find(struct net *net, __be32 id, | |
162 | static __inline__ struct nf_ct_frag6_queue * | 166 | u32 user, struct in6_addr *src, |
163 | fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst) | 167 | struct in6_addr *dst) |
164 | { | 168 | { |
165 | struct inet_frag_queue *q; | 169 | struct inet_frag_queue *q; |
166 | struct ip6_create_arg arg; | 170 | struct ip6_create_arg arg; |
@@ -174,22 +178,23 @@ fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst) | |||
174 | read_lock_bh(&nf_frags.lock); | 178 | read_lock_bh(&nf_frags.lock); |
175 | hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); | 179 | hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); |
176 | 180 | ||
177 | q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); | 181 | q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); |
178 | local_bh_enable(); | 182 | local_bh_enable(); |
179 | if (q == NULL) | 183 | if (q == NULL) |
180 | goto oom; | 184 | goto oom; |
181 | 185 | ||
182 | return container_of(q, struct nf_ct_frag6_queue, q); | 186 | return container_of(q, struct frag_queue, q); |
183 | 187 | ||
184 | oom: | 188 | oom: |
185 | return NULL; | 189 | return NULL; |
186 | } | 190 | } |
187 | 191 | ||
188 | 192 | ||
189 | static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | 193 | static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, |
190 | const struct frag_hdr *fhdr, int nhoff) | 194 | const struct frag_hdr *fhdr, int nhoff) |
191 | { | 195 | { |
192 | struct sk_buff *prev, *next; | 196 | struct sk_buff *prev, *next; |
197 | unsigned int payload_len; | ||
193 | int offset, end; | 198 | int offset, end; |
194 | 199 | ||
195 | if (fq->q.last_in & INET_FRAG_COMPLETE) { | 200 | if (fq->q.last_in & INET_FRAG_COMPLETE) { |
@@ -197,8 +202,10 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
197 | goto err; | 202 | goto err; |
198 | } | 203 | } |
199 | 204 | ||
205 | payload_len = ntohs(ipv6_hdr(skb)->payload_len); | ||
206 | |||
200 | offset = ntohs(fhdr->frag_off) & ~0x7; | 207 | offset = ntohs(fhdr->frag_off) & ~0x7; |
201 | end = offset + (ntohs(ipv6_hdr(skb)->payload_len) - | 208 | end = offset + (payload_len - |
202 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); | 209 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); |
203 | 210 | ||
204 | if ((unsigned int)end > IPV6_MAXPLEN) { | 211 | if ((unsigned int)end > IPV6_MAXPLEN) { |
@@ -307,7 +314,9 @@ found: | |||
307 | skb->dev = NULL; | 314 | skb->dev = NULL; |
308 | fq->q.stamp = skb->tstamp; | 315 | fq->q.stamp = skb->tstamp; |
309 | fq->q.meat += skb->len; | 316 | fq->q.meat += skb->len; |
310 | atomic_add(skb->truesize, &nf_init_frags.mem); | 317 | if (payload_len > fq->q.max_size) |
318 | fq->q.max_size = payload_len; | ||
319 | atomic_add(skb->truesize, &fq->q.net->mem); | ||
311 | 320 | ||
312 | /* The first fragment. | 321 | /* The first fragment. |
313 | * nhoffset is obtained from the first fragment, of course. | 322 | * nhoffset is obtained from the first fragment, of course. |
@@ -317,12 +326,12 @@ found: | |||
317 | fq->q.last_in |= INET_FRAG_FIRST_IN; | 326 | fq->q.last_in |= INET_FRAG_FIRST_IN; |
318 | } | 327 | } |
319 | write_lock(&nf_frags.lock); | 328 | write_lock(&nf_frags.lock); |
320 | list_move_tail(&fq->q.lru_list, &nf_init_frags.lru_list); | 329 | list_move_tail(&fq->q.lru_list, &fq->q.net->lru_list); |
321 | write_unlock(&nf_frags.lock); | 330 | write_unlock(&nf_frags.lock); |
322 | return 0; | 331 | return 0; |
323 | 332 | ||
324 | discard_fq: | 333 | discard_fq: |
325 | fq_kill(fq); | 334 | inet_frag_kill(&fq->q, &nf_frags); |
326 | err: | 335 | err: |
327 | return -1; | 336 | return -1; |
328 | } | 337 | } |
@@ -337,12 +346,12 @@ err: | |||
337 | * the last and the first frames arrived and all the bits are here. | 346 | * the last and the first frames arrived and all the bits are here. |
338 | */ | 347 | */ |
339 | static struct sk_buff * | 348 | static struct sk_buff * |
340 | nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | 349 | nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev) |
341 | { | 350 | { |
342 | struct sk_buff *fp, *op, *head = fq->q.fragments; | 351 | struct sk_buff *fp, *op, *head = fq->q.fragments; |
343 | int payload_len; | 352 | int payload_len; |
344 | 353 | ||
345 | fq_kill(fq); | 354 | inet_frag_kill(&fq->q, &nf_frags); |
346 | 355 | ||
347 | WARN_ON(head == NULL); | 356 | WARN_ON(head == NULL); |
348 | WARN_ON(NFCT_FRAG6_CB(head)->offset != 0); | 357 | WARN_ON(NFCT_FRAG6_CB(head)->offset != 0); |
@@ -386,7 +395,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
386 | clone->ip_summed = head->ip_summed; | 395 | clone->ip_summed = head->ip_summed; |
387 | 396 | ||
388 | NFCT_FRAG6_CB(clone)->orig = NULL; | 397 | NFCT_FRAG6_CB(clone)->orig = NULL; |
389 | atomic_add(clone->truesize, &nf_init_frags.mem); | 398 | atomic_add(clone->truesize, &fq->q.net->mem); |
390 | } | 399 | } |
391 | 400 | ||
392 | /* We have to remove fragment header from datagram and to relocate | 401 | /* We have to remove fragment header from datagram and to relocate |
@@ -410,12 +419,14 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
410 | head->csum = csum_add(head->csum, fp->csum); | 419 | head->csum = csum_add(head->csum, fp->csum); |
411 | head->truesize += fp->truesize; | 420 | head->truesize += fp->truesize; |
412 | } | 421 | } |
413 | atomic_sub(head->truesize, &nf_init_frags.mem); | 422 | atomic_sub(head->truesize, &fq->q.net->mem); |
414 | 423 | ||
424 | head->local_df = 1; | ||
415 | head->next = NULL; | 425 | head->next = NULL; |
416 | head->dev = dev; | 426 | head->dev = dev; |
417 | head->tstamp = fq->q.stamp; | 427 | head->tstamp = fq->q.stamp; |
418 | ipv6_hdr(head)->payload_len = htons(payload_len); | 428 | ipv6_hdr(head)->payload_len = htons(payload_len); |
429 | IP6CB(head)->frag_max_size = sizeof(struct ipv6hdr) + fq->q.max_size; | ||
419 | 430 | ||
420 | /* Yes, and fold redundant checksum back. 8) */ | 431 | /* Yes, and fold redundant checksum back. 8) */ |
421 | if (head->ip_summed == CHECKSUM_COMPLETE) | 432 | if (head->ip_summed == CHECKSUM_COMPLETE) |
@@ -520,8 +531,10 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
520 | { | 531 | { |
521 | struct sk_buff *clone; | 532 | struct sk_buff *clone; |
522 | struct net_device *dev = skb->dev; | 533 | struct net_device *dev = skb->dev; |
534 | struct net *net = skb_dst(skb) ? dev_net(skb_dst(skb)->dev) | ||
535 | : dev_net(skb->dev); | ||
523 | struct frag_hdr *fhdr; | 536 | struct frag_hdr *fhdr; |
524 | struct nf_ct_frag6_queue *fq; | 537 | struct frag_queue *fq; |
525 | struct ipv6hdr *hdr; | 538 | struct ipv6hdr *hdr; |
526 | int fhoff, nhoff; | 539 | int fhoff, nhoff; |
527 | u8 prevhdr; | 540 | u8 prevhdr; |
@@ -553,10 +566,11 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
553 | hdr = ipv6_hdr(clone); | 566 | hdr = ipv6_hdr(clone); |
554 | fhdr = (struct frag_hdr *)skb_transport_header(clone); | 567 | fhdr = (struct frag_hdr *)skb_transport_header(clone); |
555 | 568 | ||
556 | if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh) | 569 | local_bh_disable(); |
557 | nf_ct_frag6_evictor(); | 570 | inet_frag_evictor(&net->nf_frag.frags, &nf_frags, false); |
571 | local_bh_enable(); | ||
558 | 572 | ||
559 | fq = fq_find(fhdr->identification, user, &hdr->saddr, &hdr->daddr); | 573 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr); |
560 | if (fq == NULL) { | 574 | if (fq == NULL) { |
561 | pr_debug("Can't find and can't create new queue\n"); | 575 | pr_debug("Can't find and can't create new queue\n"); |
562 | goto ret_orig; | 576 | goto ret_orig; |
@@ -567,7 +581,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
567 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { | 581 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { |
568 | spin_unlock_bh(&fq->q.lock); | 582 | spin_unlock_bh(&fq->q.lock); |
569 | pr_debug("Can't insert skb to queue\n"); | 583 | pr_debug("Can't insert skb to queue\n"); |
570 | fq_put(fq); | 584 | inet_frag_put(&fq->q, &nf_frags); |
571 | goto ret_orig; | 585 | goto ret_orig; |
572 | } | 586 | } |
573 | 587 | ||
@@ -579,7 +593,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
579 | } | 593 | } |
580 | spin_unlock_bh(&fq->q.lock); | 594 | spin_unlock_bh(&fq->q.lock); |
581 | 595 | ||
582 | fq_put(fq); | 596 | inet_frag_put(&fq->q, &nf_frags); |
583 | return ret_skb; | 597 | return ret_skb; |
584 | 598 | ||
585 | ret_orig: | 599 | ret_orig: |
@@ -592,6 +606,7 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | |||
592 | int (*okfn)(struct sk_buff *)) | 606 | int (*okfn)(struct sk_buff *)) |
593 | { | 607 | { |
594 | struct sk_buff *s, *s2; | 608 | struct sk_buff *s, *s2; |
609 | unsigned int ret = 0; | ||
595 | 610 | ||
596 | for (s = NFCT_FRAG6_CB(skb)->orig; s;) { | 611 | for (s = NFCT_FRAG6_CB(skb)->orig; s;) { |
597 | nf_conntrack_put_reasm(s->nfct_reasm); | 612 | nf_conntrack_put_reasm(s->nfct_reasm); |
@@ -601,49 +616,62 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | |||
601 | s2 = s->next; | 616 | s2 = s->next; |
602 | s->next = NULL; | 617 | s->next = NULL; |
603 | 618 | ||
604 | NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, in, out, okfn, | 619 | if (ret != -ECANCELED) |
605 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); | 620 | ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, |
621 | in, out, okfn, | ||
622 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); | ||
623 | else | ||
624 | kfree_skb(s); | ||
625 | |||
606 | s = s2; | 626 | s = s2; |
607 | } | 627 | } |
608 | nf_conntrack_put_reasm(skb); | 628 | nf_conntrack_put_reasm(skb); |
609 | } | 629 | } |
610 | 630 | ||
631 | static int nf_ct_net_init(struct net *net) | ||
632 | { | ||
633 | net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; | ||
634 | net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH; | ||
635 | net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT; | ||
636 | inet_frags_init_net(&net->nf_frag.frags); | ||
637 | |||
638 | return nf_ct_frag6_sysctl_register(net); | ||
639 | } | ||
640 | |||
641 | static void nf_ct_net_exit(struct net *net) | ||
642 | { | ||
643 | nf_ct_frags6_sysctl_unregister(net); | ||
644 | inet_frags_exit_net(&net->nf_frag.frags, &nf_frags); | ||
645 | } | ||
646 | |||
647 | static struct pernet_operations nf_ct_net_ops = { | ||
648 | .init = nf_ct_net_init, | ||
649 | .exit = nf_ct_net_exit, | ||
650 | }; | ||
651 | |||
611 | int nf_ct_frag6_init(void) | 652 | int nf_ct_frag6_init(void) |
612 | { | 653 | { |
654 | int ret = 0; | ||
655 | |||
613 | nf_frags.hashfn = nf_hashfn; | 656 | nf_frags.hashfn = nf_hashfn; |
614 | nf_frags.constructor = ip6_frag_init; | 657 | nf_frags.constructor = ip6_frag_init; |
615 | nf_frags.destructor = NULL; | 658 | nf_frags.destructor = NULL; |
616 | nf_frags.skb_free = nf_skb_free; | 659 | nf_frags.skb_free = nf_skb_free; |
617 | nf_frags.qsize = sizeof(struct nf_ct_frag6_queue); | 660 | nf_frags.qsize = sizeof(struct frag_queue); |
618 | nf_frags.match = ip6_frag_match; | 661 | nf_frags.match = ip6_frag_match; |
619 | nf_frags.frag_expire = nf_ct_frag6_expire; | 662 | nf_frags.frag_expire = nf_ct_frag6_expire; |
620 | nf_frags.secret_interval = 10 * 60 * HZ; | 663 | nf_frags.secret_interval = 10 * 60 * HZ; |
621 | nf_init_frags.timeout = IPV6_FRAG_TIMEOUT; | ||
622 | nf_init_frags.high_thresh = IPV6_FRAG_HIGH_THRESH; | ||
623 | nf_init_frags.low_thresh = IPV6_FRAG_LOW_THRESH; | ||
624 | inet_frags_init_net(&nf_init_frags); | ||
625 | inet_frags_init(&nf_frags); | 664 | inet_frags_init(&nf_frags); |
626 | 665 | ||
627 | #ifdef CONFIG_SYSCTL | 666 | ret = register_pernet_subsys(&nf_ct_net_ops); |
628 | nf_ct_frag6_sysctl_header = register_net_sysctl(&init_net, "net/netfilter", | 667 | if (ret) |
629 | nf_ct_frag6_sysctl_table); | ||
630 | if (!nf_ct_frag6_sysctl_header) { | ||
631 | inet_frags_fini(&nf_frags); | 668 | inet_frags_fini(&nf_frags); |
632 | return -ENOMEM; | ||
633 | } | ||
634 | #endif | ||
635 | 669 | ||
636 | return 0; | 670 | return ret; |
637 | } | 671 | } |
638 | 672 | ||
639 | void nf_ct_frag6_cleanup(void) | 673 | void nf_ct_frag6_cleanup(void) |
640 | { | 674 | { |
641 | #ifdef CONFIG_SYSCTL | 675 | unregister_pernet_subsys(&nf_ct_net_ops); |
642 | unregister_net_sysctl_table(nf_ct_frag6_sysctl_header); | ||
643 | nf_ct_frag6_sysctl_header = NULL; | ||
644 | #endif | ||
645 | inet_frags_fini(&nf_frags); | 676 | inet_frags_fini(&nf_frags); |
646 | |||
647 | nf_init_frags.low_thresh = 0; | ||
648 | nf_ct_frag6_evictor(); | ||
649 | } | 677 | } |