]>
Commit | Line | Data |
---|---|---|
1 | // SPDX-License-Identifier: GPL-2.0 | |
2 | #include <linux/types.h> | |
3 | #include <linux/netfilter.h> | |
4 | #include <linux/slab.h> | |
5 | #include <linux/module.h> | |
6 | #include <linux/skbuff.h> | |
7 | #include <linux/proc_fs.h> | |
8 | #include <linux/seq_file.h> | |
9 | #include <linux/percpu.h> | |
10 | #include <linux/netdevice.h> | |
11 | #include <linux/security.h> | |
12 | #include <net/net_namespace.h> | |
13 | #ifdef CONFIG_SYSCTL | |
14 | #include <linux/sysctl.h> | |
15 | #endif | |
16 | ||
17 | #include <net/netfilter/nf_conntrack.h> | |
18 | #include <net/netfilter/nf_conntrack_core.h> | |
19 | #include <net/netfilter/nf_conntrack_l4proto.h> | |
20 | #include <net/netfilter/nf_conntrack_expect.h> | |
21 | #include <net/netfilter/nf_conntrack_helper.h> | |
22 | #include <net/netfilter/nf_conntrack_acct.h> | |
23 | #include <net/netfilter/nf_conntrack_zones.h> | |
24 | #include <net/netfilter/nf_conntrack_timestamp.h> | |
25 | #ifdef CONFIG_LWTUNNEL | |
26 | #include <net/netfilter/nf_hooks_lwtunnel.h> | |
27 | #endif | |
28 | #include <linux/rculist_nulls.h> | |
29 | ||
30 | static bool enable_hooks __read_mostly; | |
31 | MODULE_PARM_DESC(enable_hooks, "Always enable conntrack hooks"); | |
32 | module_param(enable_hooks, bool, 0000); | |
33 | ||
34 | unsigned int nf_conntrack_net_id __read_mostly; | |
35 | ||
36 | #ifdef CONFIG_NF_CONNTRACK_PROCFS | |
37 | void | |
38 | print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, | |
39 | const struct nf_conntrack_l4proto *l4proto) | |
40 | { | |
41 | switch (tuple->src.l3num) { | |
42 | case NFPROTO_IPV4: | |
43 | seq_printf(s, "src=%pI4 dst=%pI4 ", | |
44 | &tuple->src.u3.ip, &tuple->dst.u3.ip); | |
45 | break; | |
46 | case NFPROTO_IPV6: | |
47 | seq_printf(s, "src=%pI6 dst=%pI6 ", | |
48 | tuple->src.u3.ip6, tuple->dst.u3.ip6); | |
49 | break; | |
50 | default: | |
51 | break; | |
52 | } | |
53 | ||
54 | switch (l4proto->l4proto) { | |
55 | case IPPROTO_ICMP: | |
56 | seq_printf(s, "type=%u code=%u id=%u ", | |
57 | tuple->dst.u.icmp.type, | |
58 | tuple->dst.u.icmp.code, | |
59 | ntohs(tuple->src.u.icmp.id)); | |
60 | break; | |
61 | case IPPROTO_TCP: | |
62 | seq_printf(s, "sport=%hu dport=%hu ", | |
63 | ntohs(tuple->src.u.tcp.port), | |
64 | ntohs(tuple->dst.u.tcp.port)); | |
65 | break; | |
66 | case IPPROTO_UDPLITE: | |
67 | case IPPROTO_UDP: | |
68 | seq_printf(s, "sport=%hu dport=%hu ", | |
69 | ntohs(tuple->src.u.udp.port), | |
70 | ntohs(tuple->dst.u.udp.port)); | |
71 | ||
72 | break; | |
73 | case IPPROTO_DCCP: | |
74 | seq_printf(s, "sport=%hu dport=%hu ", | |
75 | ntohs(tuple->src.u.dccp.port), | |
76 | ntohs(tuple->dst.u.dccp.port)); | |
77 | break; | |
78 | case IPPROTO_SCTP: | |
79 | seq_printf(s, "sport=%hu dport=%hu ", | |
80 | ntohs(tuple->src.u.sctp.port), | |
81 | ntohs(tuple->dst.u.sctp.port)); | |
82 | break; | |
83 | case IPPROTO_ICMPV6: | |
84 | seq_printf(s, "type=%u code=%u id=%u ", | |
85 | tuple->dst.u.icmp.type, | |
86 | tuple->dst.u.icmp.code, | |
87 | ntohs(tuple->src.u.icmp.id)); | |
88 | break; | |
89 | case IPPROTO_GRE: | |
90 | seq_printf(s, "srckey=0x%x dstkey=0x%x ", | |
91 | ntohs(tuple->src.u.gre.key), | |
92 | ntohs(tuple->dst.u.gre.key)); | |
93 | break; | |
94 | default: | |
95 | break; | |
96 | } | |
97 | } | |
98 | EXPORT_SYMBOL_GPL(print_tuple); | |
99 | ||
100 | struct ct_iter_state { | |
101 | struct seq_net_private p; | |
102 | struct hlist_nulls_head *hash; | |
103 | unsigned int htable_size; | |
104 | unsigned int bucket; | |
105 | u_int64_t time_now; | |
106 | }; | |
107 | ||
108 | static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) | |
109 | { | |
110 | struct ct_iter_state *st = seq->private; | |
111 | struct hlist_nulls_node *n; | |
112 | ||
113 | for (st->bucket = 0; | |
114 | st->bucket < st->htable_size; | |
115 | st->bucket++) { | |
116 | n = rcu_dereference( | |
117 | hlist_nulls_first_rcu(&st->hash[st->bucket])); | |
118 | if (!is_a_nulls(n)) | |
119 | return n; | |
120 | } | |
121 | return NULL; | |
122 | } | |
123 | ||
124 | static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, | |
125 | struct hlist_nulls_node *head) | |
126 | { | |
127 | struct ct_iter_state *st = seq->private; | |
128 | ||
129 | head = rcu_dereference(hlist_nulls_next_rcu(head)); | |
130 | while (is_a_nulls(head)) { | |
131 | if (likely(get_nulls_value(head) == st->bucket)) { | |
132 | if (++st->bucket >= st->htable_size) | |
133 | return NULL; | |
134 | } | |
135 | head = rcu_dereference( | |
136 | hlist_nulls_first_rcu(&st->hash[st->bucket])); | |
137 | } | |
138 | return head; | |
139 | } | |
140 | ||
141 | static struct hlist_nulls_node *ct_get_idx(struct seq_file *seq, loff_t pos) | |
142 | { | |
143 | struct hlist_nulls_node *head = ct_get_first(seq); | |
144 | ||
145 | if (head) | |
146 | while (pos && (head = ct_get_next(seq, head))) | |
147 | pos--; | |
148 | return pos ? NULL : head; | |
149 | } | |
150 | ||
151 | static void *ct_seq_start(struct seq_file *seq, loff_t *pos) | |
152 | __acquires(RCU) | |
153 | { | |
154 | struct ct_iter_state *st = seq->private; | |
155 | ||
156 | st->time_now = ktime_get_real_ns(); | |
157 | rcu_read_lock(); | |
158 | ||
159 | nf_conntrack_get_ht(&st->hash, &st->htable_size); | |
160 | return ct_get_idx(seq, *pos); | |
161 | } | |
162 | ||
163 | static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) | |
164 | { | |
165 | (*pos)++; | |
166 | return ct_get_next(s, v); | |
167 | } | |
168 | ||
169 | static void ct_seq_stop(struct seq_file *s, void *v) | |
170 | __releases(RCU) | |
171 | { | |
172 | rcu_read_unlock(); | |
173 | } | |
174 | ||
175 | #ifdef CONFIG_NF_CONNTRACK_SECMARK | |
176 | static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct) | |
177 | { | |
178 | int ret; | |
179 | struct lsmblob blob; | |
180 | struct lsmcontext context; | |
181 | ||
182 | lsmblob_init(&blob, ct->secmark); | |
183 | ret = security_secid_to_secctx(&blob, &context, LSMBLOB_DISPLAY); | |
184 | if (ret) | |
185 | return; | |
186 | ||
187 | seq_printf(s, "secctx=%s ", context.context); | |
188 | ||
189 | security_release_secctx(&context); | |
190 | } | |
191 | #else | |
192 | static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct) | |
193 | { | |
194 | } | |
195 | #endif | |
196 | ||
197 | #ifdef CONFIG_NF_CONNTRACK_ZONES | |
198 | static void ct_show_zone(struct seq_file *s, const struct nf_conn *ct, | |
199 | int dir) | |
200 | { | |
201 | const struct nf_conntrack_zone *zone = nf_ct_zone(ct); | |
202 | ||
203 | if (zone->dir != dir) | |
204 | return; | |
205 | switch (zone->dir) { | |
206 | case NF_CT_DEFAULT_ZONE_DIR: | |
207 | seq_printf(s, "zone=%u ", zone->id); | |
208 | break; | |
209 | case NF_CT_ZONE_DIR_ORIG: | |
210 | seq_printf(s, "zone-orig=%u ", zone->id); | |
211 | break; | |
212 | case NF_CT_ZONE_DIR_REPL: | |
213 | seq_printf(s, "zone-reply=%u ", zone->id); | |
214 | break; | |
215 | default: | |
216 | break; | |
217 | } | |
218 | } | |
219 | #else | |
220 | static inline void ct_show_zone(struct seq_file *s, const struct nf_conn *ct, | |
221 | int dir) | |
222 | { | |
223 | } | |
224 | #endif | |
225 | ||
226 | #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP | |
227 | static void ct_show_delta_time(struct seq_file *s, const struct nf_conn *ct) | |
228 | { | |
229 | struct ct_iter_state *st = s->private; | |
230 | struct nf_conn_tstamp *tstamp; | |
231 | s64 delta_time; | |
232 | ||
233 | tstamp = nf_conn_tstamp_find(ct); | |
234 | if (tstamp) { | |
235 | delta_time = st->time_now - tstamp->start; | |
236 | if (delta_time > 0) | |
237 | delta_time = div_s64(delta_time, NSEC_PER_SEC); | |
238 | else | |
239 | delta_time = 0; | |
240 | ||
241 | seq_printf(s, "delta-time=%llu ", | |
242 | (unsigned long long)delta_time); | |
243 | } | |
244 | return; | |
245 | } | |
246 | #else | |
247 | static inline void | |
248 | ct_show_delta_time(struct seq_file *s, const struct nf_conn *ct) | |
249 | { | |
250 | } | |
251 | #endif | |
252 | ||
253 | static const char* l3proto_name(u16 proto) | |
254 | { | |
255 | switch (proto) { | |
256 | case AF_INET: return "ipv4"; | |
257 | case AF_INET6: return "ipv6"; | |
258 | } | |
259 | ||
260 | return "unknown"; | |
261 | } | |
262 | ||
263 | static const char* l4proto_name(u16 proto) | |
264 | { | |
265 | switch (proto) { | |
266 | case IPPROTO_ICMP: return "icmp"; | |
267 | case IPPROTO_TCP: return "tcp"; | |
268 | case IPPROTO_UDP: return "udp"; | |
269 | case IPPROTO_DCCP: return "dccp"; | |
270 | case IPPROTO_GRE: return "gre"; | |
271 | case IPPROTO_SCTP: return "sctp"; | |
272 | case IPPROTO_UDPLITE: return "udplite"; | |
273 | case IPPROTO_ICMPV6: return "icmpv6"; | |
274 | } | |
275 | ||
276 | return "unknown"; | |
277 | } | |
278 | ||
279 | static unsigned int | |
280 | seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir) | |
281 | { | |
282 | struct nf_conn_acct *acct; | |
283 | struct nf_conn_counter *counter; | |
284 | ||
285 | acct = nf_conn_acct_find(ct); | |
286 | if (!acct) | |
287 | return 0; | |
288 | ||
289 | counter = acct->counter; | |
290 | seq_printf(s, "packets=%llu bytes=%llu ", | |
291 | (unsigned long long)atomic64_read(&counter[dir].packets), | |
292 | (unsigned long long)atomic64_read(&counter[dir].bytes)); | |
293 | ||
294 | return 0; | |
295 | } | |
296 | ||
297 | /* return 0 on success, 1 in case of error */ | |
298 | static int ct_seq_show(struct seq_file *s, void *v) | |
299 | { | |
300 | struct nf_conntrack_tuple_hash *hash = v; | |
301 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); | |
302 | const struct nf_conntrack_l4proto *l4proto; | |
303 | struct net *net = seq_file_net(s); | |
304 | int ret = 0; | |
305 | ||
306 | WARN_ON(!ct); | |
307 | if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) | |
308 | return 0; | |
309 | ||
310 | if (nf_ct_should_gc(ct)) { | |
311 | nf_ct_kill(ct); | |
312 | goto release; | |
313 | } | |
314 | ||
315 | /* we only want to print DIR_ORIGINAL */ | |
316 | if (NF_CT_DIRECTION(hash)) | |
317 | goto release; | |
318 | ||
319 | if (!net_eq(nf_ct_net(ct), net)) | |
320 | goto release; | |
321 | ||
322 | l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct)); | |
323 | ||
324 | ret = -ENOSPC; | |
325 | seq_printf(s, "%-8s %u %-8s %u ", | |
326 | l3proto_name(nf_ct_l3num(ct)), nf_ct_l3num(ct), | |
327 | l4proto_name(l4proto->l4proto), nf_ct_protonum(ct)); | |
328 | ||
329 | if (!test_bit(IPS_OFFLOAD_BIT, &ct->status)) | |
330 | seq_printf(s, "%ld ", nf_ct_expires(ct) / HZ); | |
331 | ||
332 | if (l4proto->print_conntrack) | |
333 | l4proto->print_conntrack(s, ct); | |
334 | ||
335 | print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | |
336 | l4proto); | |
337 | ||
338 | ct_show_zone(s, ct, NF_CT_ZONE_DIR_ORIG); | |
339 | ||
340 | if (seq_has_overflowed(s)) | |
341 | goto release; | |
342 | ||
343 | if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL)) | |
344 | goto release; | |
345 | ||
346 | if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) | |
347 | seq_puts(s, "[UNREPLIED] "); | |
348 | ||
349 | print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, l4proto); | |
350 | ||
351 | ct_show_zone(s, ct, NF_CT_ZONE_DIR_REPL); | |
352 | ||
353 | if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) | |
354 | goto release; | |
355 | ||
356 | if (test_bit(IPS_HW_OFFLOAD_BIT, &ct->status)) | |
357 | seq_puts(s, "[HW_OFFLOAD] "); | |
358 | else if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) | |
359 | seq_puts(s, "[OFFLOAD] "); | |
360 | else if (test_bit(IPS_ASSURED_BIT, &ct->status)) | |
361 | seq_puts(s, "[ASSURED] "); | |
362 | ||
363 | if (seq_has_overflowed(s)) | |
364 | goto release; | |
365 | ||
366 | #if defined(CONFIG_NF_CONNTRACK_MARK) | |
367 | seq_printf(s, "mark=%u ", ct->mark); | |
368 | #endif | |
369 | ||
370 | ct_show_secctx(s, ct); | |
371 | ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR); | |
372 | ct_show_delta_time(s, ct); | |
373 | ||
374 | seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)); | |
375 | ||
376 | if (seq_has_overflowed(s)) | |
377 | goto release; | |
378 | ||
379 | ret = 0; | |
380 | release: | |
381 | nf_ct_put(ct); | |
382 | return ret; | |
383 | } | |
384 | ||
385 | static const struct seq_operations ct_seq_ops = { | |
386 | .start = ct_seq_start, | |
387 | .next = ct_seq_next, | |
388 | .stop = ct_seq_stop, | |
389 | .show = ct_seq_show | |
390 | }; | |
391 | ||
392 | static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) | |
393 | { | |
394 | struct net *net = seq_file_net(seq); | |
395 | int cpu; | |
396 | ||
397 | if (*pos == 0) | |
398 | return SEQ_START_TOKEN; | |
399 | ||
400 | for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) { | |
401 | if (!cpu_possible(cpu)) | |
402 | continue; | |
403 | *pos = cpu + 1; | |
404 | return per_cpu_ptr(net->ct.stat, cpu); | |
405 | } | |
406 | ||
407 | return NULL; | |
408 | } | |
409 | ||
410 | static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |
411 | { | |
412 | struct net *net = seq_file_net(seq); | |
413 | int cpu; | |
414 | ||
415 | for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { | |
416 | if (!cpu_possible(cpu)) | |
417 | continue; | |
418 | *pos = cpu + 1; | |
419 | return per_cpu_ptr(net->ct.stat, cpu); | |
420 | } | |
421 | (*pos)++; | |
422 | return NULL; | |
423 | } | |
424 | ||
425 | static void ct_cpu_seq_stop(struct seq_file *seq, void *v) | |
426 | { | |
427 | } | |
428 | ||
429 | static int ct_cpu_seq_show(struct seq_file *seq, void *v) | |
430 | { | |
431 | struct net *net = seq_file_net(seq); | |
432 | const struct ip_conntrack_stat *st = v; | |
433 | unsigned int nr_conntracks; | |
434 | ||
435 | if (v == SEQ_START_TOKEN) { | |
436 | seq_puts(seq, "entries clashres found new invalid ignore delete chainlength insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart\n"); | |
437 | return 0; | |
438 | } | |
439 | ||
440 | nr_conntracks = nf_conntrack_count(net); | |
441 | ||
442 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x " | |
443 | "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n", | |
444 | nr_conntracks, | |
445 | st->clash_resolve, | |
446 | st->found, | |
447 | 0, | |
448 | st->invalid, | |
449 | 0, | |
450 | 0, | |
451 | st->chaintoolong, | |
452 | st->insert, | |
453 | st->insert_failed, | |
454 | st->drop, | |
455 | st->early_drop, | |
456 | st->error, | |
457 | ||
458 | st->expect_new, | |
459 | st->expect_create, | |
460 | st->expect_delete, | |
461 | st->search_restart | |
462 | ); | |
463 | return 0; | |
464 | } | |
465 | ||
466 | static const struct seq_operations ct_cpu_seq_ops = { | |
467 | .start = ct_cpu_seq_start, | |
468 | .next = ct_cpu_seq_next, | |
469 | .stop = ct_cpu_seq_stop, | |
470 | .show = ct_cpu_seq_show, | |
471 | }; | |
472 | ||
473 | static int nf_conntrack_standalone_init_proc(struct net *net) | |
474 | { | |
475 | struct proc_dir_entry *pde; | |
476 | kuid_t root_uid; | |
477 | kgid_t root_gid; | |
478 | ||
479 | pde = proc_create_net("nf_conntrack", 0440, net->proc_net, &ct_seq_ops, | |
480 | sizeof(struct ct_iter_state)); | |
481 | if (!pde) | |
482 | goto out_nf_conntrack; | |
483 | ||
484 | root_uid = make_kuid(net->user_ns, 0); | |
485 | root_gid = make_kgid(net->user_ns, 0); | |
486 | if (uid_valid(root_uid) && gid_valid(root_gid)) | |
487 | proc_set_user(pde, root_uid, root_gid); | |
488 | ||
489 | pde = proc_create_net("nf_conntrack", 0444, net->proc_net_stat, | |
490 | &ct_cpu_seq_ops, sizeof(struct seq_net_private)); | |
491 | if (!pde) | |
492 | goto out_stat_nf_conntrack; | |
493 | return 0; | |
494 | ||
495 | out_stat_nf_conntrack: | |
496 | remove_proc_entry("nf_conntrack", net->proc_net); | |
497 | out_nf_conntrack: | |
498 | return -ENOMEM; | |
499 | } | |
500 | ||
501 | static void nf_conntrack_standalone_fini_proc(struct net *net) | |
502 | { | |
503 | remove_proc_entry("nf_conntrack", net->proc_net_stat); | |
504 | remove_proc_entry("nf_conntrack", net->proc_net); | |
505 | } | |
506 | #else | |
507 | static int nf_conntrack_standalone_init_proc(struct net *net) | |
508 | { | |
509 | return 0; | |
510 | } | |
511 | ||
512 | static void nf_conntrack_standalone_fini_proc(struct net *net) | |
513 | { | |
514 | } | |
515 | #endif /* CONFIG_NF_CONNTRACK_PROCFS */ | |
516 | ||
517 | u32 nf_conntrack_count(const struct net *net) | |
518 | { | |
519 | const struct nf_conntrack_net *cnet = nf_ct_pernet(net); | |
520 | ||
521 | return atomic_read(&cnet->count); | |
522 | } | |
523 | EXPORT_SYMBOL_GPL(nf_conntrack_count); | |
524 | ||
525 | /* Sysctl support */ | |
526 | ||
527 | #ifdef CONFIG_SYSCTL | |
528 | /* size the user *wants to set */ | |
529 | static unsigned int nf_conntrack_htable_size_user __read_mostly; | |
530 | ||
531 | static int | |
532 | nf_conntrack_hash_sysctl(struct ctl_table *table, int write, | |
533 | void *buffer, size_t *lenp, loff_t *ppos) | |
534 | { | |
535 | int ret; | |
536 | ||
537 | /* module_param hashsize could have changed value */ | |
538 | nf_conntrack_htable_size_user = nf_conntrack_htable_size; | |
539 | ||
540 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | |
541 | if (ret < 0 || !write) | |
542 | return ret; | |
543 | ||
544 | /* update ret, we might not be able to satisfy request */ | |
545 | ret = nf_conntrack_hash_resize(nf_conntrack_htable_size_user); | |
546 | ||
547 | /* update it to the actual value used by conntrack */ | |
548 | nf_conntrack_htable_size_user = nf_conntrack_htable_size; | |
549 | return ret; | |
550 | } | |
551 | ||
552 | static struct ctl_table_header *nf_ct_netfilter_header; | |
553 | ||
554 | enum nf_ct_sysctl_index { | |
555 | NF_SYSCTL_CT_MAX, | |
556 | NF_SYSCTL_CT_COUNT, | |
557 | NF_SYSCTL_CT_BUCKETS, | |
558 | NF_SYSCTL_CT_CHECKSUM, | |
559 | NF_SYSCTL_CT_LOG_INVALID, | |
560 | NF_SYSCTL_CT_EXPECT_MAX, | |
561 | NF_SYSCTL_CT_ACCT, | |
562 | NF_SYSCTL_CT_HELPER, | |
563 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | |
564 | NF_SYSCTL_CT_EVENTS, | |
565 | #endif | |
566 | #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP | |
567 | NF_SYSCTL_CT_TIMESTAMP, | |
568 | #endif | |
569 | NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC, | |
570 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_SYN_SENT, | |
571 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_SYN_RECV, | |
572 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_ESTABLISHED, | |
573 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_FIN_WAIT, | |
574 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_CLOSE_WAIT, | |
575 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_LAST_ACK, | |
576 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_TIME_WAIT, | |
577 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_CLOSE, | |
578 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_RETRANS, | |
579 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_UNACK, | |
580 | #if IS_ENABLED(CONFIG_NF_FLOW_TABLE) | |
581 | NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD, | |
582 | #endif | |
583 | NF_SYSCTL_CT_PROTO_TCP_LOOSE, | |
584 | NF_SYSCTL_CT_PROTO_TCP_LIBERAL, | |
585 | NF_SYSCTL_CT_PROTO_TCP_IGNORE_INVALID_RST, | |
586 | NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS, | |
587 | NF_SYSCTL_CT_PROTO_TIMEOUT_UDP, | |
588 | NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM, | |
589 | #if IS_ENABLED(CONFIG_NF_FLOW_TABLE) | |
590 | NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD, | |
591 | #endif | |
592 | NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP, | |
593 | NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6, | |
594 | #ifdef CONFIG_NF_CT_PROTO_SCTP | |
595 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_CLOSED, | |
596 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_COOKIE_WAIT, | |
597 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_COOKIE_ECHOED, | |
598 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_ESTABLISHED, | |
599 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_SENT, | |
600 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_RECD, | |
601 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT, | |
602 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_SENT, | |
603 | NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_ACKED, | |
604 | #endif | |
605 | #ifdef CONFIG_NF_CT_PROTO_DCCP | |
606 | NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST, | |
607 | NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_RESPOND, | |
608 | NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_PARTOPEN, | |
609 | NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_OPEN, | |
610 | NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_CLOSEREQ, | |
611 | NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_CLOSING, | |
612 | NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_TIMEWAIT, | |
613 | NF_SYSCTL_CT_PROTO_DCCP_LOOSE, | |
614 | #endif | |
615 | #ifdef CONFIG_NF_CT_PROTO_GRE | |
616 | NF_SYSCTL_CT_PROTO_TIMEOUT_GRE, | |
617 | NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM, | |
618 | #endif | |
619 | #ifdef CONFIG_LWTUNNEL | |
620 | NF_SYSCTL_CT_LWTUNNEL, | |
621 | #endif | |
622 | ||
623 | __NF_SYSCTL_CT_LAST_SYSCTL, | |
624 | }; | |
625 | ||
626 | #define NF_SYSCTL_CT_LAST_SYSCTL (__NF_SYSCTL_CT_LAST_SYSCTL + 1) | |
627 | ||
628 | static struct ctl_table nf_ct_sysctl_table[] = { | |
629 | [NF_SYSCTL_CT_MAX] = { | |
630 | .procname = "nf_conntrack_max", | |
631 | .data = &nf_conntrack_max, | |
632 | .maxlen = sizeof(int), | |
633 | .mode = 0644, | |
634 | .proc_handler = proc_dointvec, | |
635 | }, | |
636 | [NF_SYSCTL_CT_COUNT] = { | |
637 | .procname = "nf_conntrack_count", | |
638 | .maxlen = sizeof(int), | |
639 | .mode = 0444, | |
640 | .proc_handler = proc_dointvec, | |
641 | }, | |
642 | [NF_SYSCTL_CT_BUCKETS] = { | |
643 | .procname = "nf_conntrack_buckets", | |
644 | .data = &nf_conntrack_htable_size_user, | |
645 | .maxlen = sizeof(unsigned int), | |
646 | .mode = 0644, | |
647 | .proc_handler = nf_conntrack_hash_sysctl, | |
648 | }, | |
649 | [NF_SYSCTL_CT_CHECKSUM] = { | |
650 | .procname = "nf_conntrack_checksum", | |
651 | .data = &init_net.ct.sysctl_checksum, | |
652 | .maxlen = sizeof(u8), | |
653 | .mode = 0644, | |
654 | .proc_handler = proc_dou8vec_minmax, | |
655 | .extra1 = SYSCTL_ZERO, | |
656 | .extra2 = SYSCTL_ONE, | |
657 | }, | |
658 | [NF_SYSCTL_CT_LOG_INVALID] = { | |
659 | .procname = "nf_conntrack_log_invalid", | |
660 | .data = &init_net.ct.sysctl_log_invalid, | |
661 | .maxlen = sizeof(u8), | |
662 | .mode = 0644, | |
663 | .proc_handler = proc_dou8vec_minmax, | |
664 | }, | |
665 | [NF_SYSCTL_CT_EXPECT_MAX] = { | |
666 | .procname = "nf_conntrack_expect_max", | |
667 | .data = &nf_ct_expect_max, | |
668 | .maxlen = sizeof(int), | |
669 | .mode = 0644, | |
670 | .proc_handler = proc_dointvec, | |
671 | }, | |
672 | [NF_SYSCTL_CT_ACCT] = { | |
673 | .procname = "nf_conntrack_acct", | |
674 | .data = &init_net.ct.sysctl_acct, | |
675 | .maxlen = sizeof(u8), | |
676 | .mode = 0644, | |
677 | .proc_handler = proc_dou8vec_minmax, | |
678 | .extra1 = SYSCTL_ZERO, | |
679 | .extra2 = SYSCTL_ONE, | |
680 | }, | |
681 | [NF_SYSCTL_CT_HELPER] = { | |
682 | .procname = "nf_conntrack_helper", | |
683 | .maxlen = sizeof(u8), | |
684 | .mode = 0644, | |
685 | .proc_handler = proc_dou8vec_minmax, | |
686 | .extra1 = SYSCTL_ZERO, | |
687 | .extra2 = SYSCTL_ONE, | |
688 | }, | |
689 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | |
690 | [NF_SYSCTL_CT_EVENTS] = { | |
691 | .procname = "nf_conntrack_events", | |
692 | .data = &init_net.ct.sysctl_events, | |
693 | .maxlen = sizeof(u8), | |
694 | .mode = 0644, | |
695 | .proc_handler = proc_dou8vec_minmax, | |
696 | .extra1 = SYSCTL_ZERO, | |
697 | .extra2 = SYSCTL_ONE, | |
698 | }, | |
699 | #endif | |
700 | #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP | |
701 | [NF_SYSCTL_CT_TIMESTAMP] = { | |
702 | .procname = "nf_conntrack_timestamp", | |
703 | .data = &init_net.ct.sysctl_tstamp, | |
704 | .maxlen = sizeof(u8), | |
705 | .mode = 0644, | |
706 | .proc_handler = proc_dou8vec_minmax, | |
707 | .extra1 = SYSCTL_ZERO, | |
708 | .extra2 = SYSCTL_ONE, | |
709 | }, | |
710 | #endif | |
711 | [NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC] = { | |
712 | .procname = "nf_conntrack_generic_timeout", | |
713 | .maxlen = sizeof(unsigned int), | |
714 | .mode = 0644, | |
715 | .proc_handler = proc_dointvec_jiffies, | |
716 | }, | |
717 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_SYN_SENT] = { | |
718 | .procname = "nf_conntrack_tcp_timeout_syn_sent", | |
719 | .maxlen = sizeof(unsigned int), | |
720 | .mode = 0644, | |
721 | .proc_handler = proc_dointvec_jiffies, | |
722 | }, | |
723 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_SYN_RECV] = { | |
724 | .procname = "nf_conntrack_tcp_timeout_syn_recv", | |
725 | .maxlen = sizeof(unsigned int), | |
726 | .mode = 0644, | |
727 | .proc_handler = proc_dointvec_jiffies, | |
728 | }, | |
729 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_ESTABLISHED] = { | |
730 | .procname = "nf_conntrack_tcp_timeout_established", | |
731 | .maxlen = sizeof(unsigned int), | |
732 | .mode = 0644, | |
733 | .proc_handler = proc_dointvec_jiffies, | |
734 | }, | |
735 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_FIN_WAIT] = { | |
736 | .procname = "nf_conntrack_tcp_timeout_fin_wait", | |
737 | .maxlen = sizeof(unsigned int), | |
738 | .mode = 0644, | |
739 | .proc_handler = proc_dointvec_jiffies, | |
740 | }, | |
741 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_CLOSE_WAIT] = { | |
742 | .procname = "nf_conntrack_tcp_timeout_close_wait", | |
743 | .maxlen = sizeof(unsigned int), | |
744 | .mode = 0644, | |
745 | .proc_handler = proc_dointvec_jiffies, | |
746 | }, | |
747 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_LAST_ACK] = { | |
748 | .procname = "nf_conntrack_tcp_timeout_last_ack", | |
749 | .maxlen = sizeof(unsigned int), | |
750 | .mode = 0644, | |
751 | .proc_handler = proc_dointvec_jiffies, | |
752 | }, | |
753 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_TIME_WAIT] = { | |
754 | .procname = "nf_conntrack_tcp_timeout_time_wait", | |
755 | .maxlen = sizeof(unsigned int), | |
756 | .mode = 0644, | |
757 | .proc_handler = proc_dointvec_jiffies, | |
758 | }, | |
759 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_CLOSE] = { | |
760 | .procname = "nf_conntrack_tcp_timeout_close", | |
761 | .maxlen = sizeof(unsigned int), | |
762 | .mode = 0644, | |
763 | .proc_handler = proc_dointvec_jiffies, | |
764 | }, | |
765 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_RETRANS] = { | |
766 | .procname = "nf_conntrack_tcp_timeout_max_retrans", | |
767 | .maxlen = sizeof(unsigned int), | |
768 | .mode = 0644, | |
769 | .proc_handler = proc_dointvec_jiffies, | |
770 | }, | |
771 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_UNACK] = { | |
772 | .procname = "nf_conntrack_tcp_timeout_unacknowledged", | |
773 | .maxlen = sizeof(unsigned int), | |
774 | .mode = 0644, | |
775 | .proc_handler = proc_dointvec_jiffies, | |
776 | }, | |
777 | #if IS_ENABLED(CONFIG_NF_FLOW_TABLE) | |
778 | [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD] = { | |
779 | .procname = "nf_flowtable_tcp_timeout", | |
780 | .maxlen = sizeof(unsigned int), | |
781 | .mode = 0644, | |
782 | .proc_handler = proc_dointvec_jiffies, | |
783 | }, | |
784 | #endif | |
785 | [NF_SYSCTL_CT_PROTO_TCP_LOOSE] = { | |
786 | .procname = "nf_conntrack_tcp_loose", | |
787 | .maxlen = sizeof(u8), | |
788 | .mode = 0644, | |
789 | .proc_handler = proc_dou8vec_minmax, | |
790 | .extra1 = SYSCTL_ZERO, | |
791 | .extra2 = SYSCTL_ONE, | |
792 | }, | |
793 | [NF_SYSCTL_CT_PROTO_TCP_LIBERAL] = { | |
794 | .procname = "nf_conntrack_tcp_be_liberal", | |
795 | .maxlen = sizeof(u8), | |
796 | .mode = 0644, | |
797 | .proc_handler = proc_dou8vec_minmax, | |
798 | .extra1 = SYSCTL_ZERO, | |
799 | .extra2 = SYSCTL_ONE, | |
800 | }, | |
801 | [NF_SYSCTL_CT_PROTO_TCP_IGNORE_INVALID_RST] = { | |
802 | .procname = "nf_conntrack_tcp_ignore_invalid_rst", | |
803 | .maxlen = sizeof(u8), | |
804 | .mode = 0644, | |
805 | .proc_handler = proc_dou8vec_minmax, | |
806 | .extra1 = SYSCTL_ZERO, | |
807 | .extra2 = SYSCTL_ONE, | |
808 | }, | |
809 | [NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS] = { | |
810 | .procname = "nf_conntrack_tcp_max_retrans", | |
811 | .maxlen = sizeof(u8), | |
812 | .mode = 0644, | |
813 | .proc_handler = proc_dou8vec_minmax, | |
814 | }, | |
815 | [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP] = { | |
816 | .procname = "nf_conntrack_udp_timeout", | |
817 | .maxlen = sizeof(unsigned int), | |
818 | .mode = 0644, | |
819 | .proc_handler = proc_dointvec_jiffies, | |
820 | }, | |
821 | [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM] = { | |
822 | .procname = "nf_conntrack_udp_timeout_stream", | |
823 | .maxlen = sizeof(unsigned int), | |
824 | .mode = 0644, | |
825 | .proc_handler = proc_dointvec_jiffies, | |
826 | }, | |
827 | #if IS_ENABLED(CONFIG_NFT_FLOW_OFFLOAD) | |
828 | [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD] = { | |
829 | .procname = "nf_flowtable_udp_timeout", | |
830 | .maxlen = sizeof(unsigned int), | |
831 | .mode = 0644, | |
832 | .proc_handler = proc_dointvec_jiffies, | |
833 | }, | |
834 | #endif | |
835 | [NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP] = { | |
836 | .procname = "nf_conntrack_icmp_timeout", | |
837 | .maxlen = sizeof(unsigned int), | |
838 | .mode = 0644, | |
839 | .proc_handler = proc_dointvec_jiffies, | |
840 | }, | |
841 | [NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6] = { | |
842 | .procname = "nf_conntrack_icmpv6_timeout", | |
843 | .maxlen = sizeof(unsigned int), | |
844 | .mode = 0644, | |
845 | .proc_handler = proc_dointvec_jiffies, | |
846 | }, | |
847 | #ifdef CONFIG_NF_CT_PROTO_SCTP | |
848 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_CLOSED] = { | |
849 | .procname = "nf_conntrack_sctp_timeout_closed", | |
850 | .maxlen = sizeof(unsigned int), | |
851 | .mode = 0644, | |
852 | .proc_handler = proc_dointvec_jiffies, | |
853 | }, | |
854 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_COOKIE_WAIT] = { | |
855 | .procname = "nf_conntrack_sctp_timeout_cookie_wait", | |
856 | .maxlen = sizeof(unsigned int), | |
857 | .mode = 0644, | |
858 | .proc_handler = proc_dointvec_jiffies, | |
859 | }, | |
860 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_COOKIE_ECHOED] = { | |
861 | .procname = "nf_conntrack_sctp_timeout_cookie_echoed", | |
862 | .maxlen = sizeof(unsigned int), | |
863 | .mode = 0644, | |
864 | .proc_handler = proc_dointvec_jiffies, | |
865 | }, | |
866 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_ESTABLISHED] = { | |
867 | .procname = "nf_conntrack_sctp_timeout_established", | |
868 | .maxlen = sizeof(unsigned int), | |
869 | .mode = 0644, | |
870 | .proc_handler = proc_dointvec_jiffies, | |
871 | }, | |
872 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_SENT] = { | |
873 | .procname = "nf_conntrack_sctp_timeout_shutdown_sent", | |
874 | .maxlen = sizeof(unsigned int), | |
875 | .mode = 0644, | |
876 | .proc_handler = proc_dointvec_jiffies, | |
877 | }, | |
878 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_RECD] = { | |
879 | .procname = "nf_conntrack_sctp_timeout_shutdown_recd", | |
880 | .maxlen = sizeof(unsigned int), | |
881 | .mode = 0644, | |
882 | .proc_handler = proc_dointvec_jiffies, | |
883 | }, | |
884 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT] = { | |
885 | .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent", | |
886 | .maxlen = sizeof(unsigned int), | |
887 | .mode = 0644, | |
888 | .proc_handler = proc_dointvec_jiffies, | |
889 | }, | |
890 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_SENT] = { | |
891 | .procname = "nf_conntrack_sctp_timeout_heartbeat_sent", | |
892 | .maxlen = sizeof(unsigned int), | |
893 | .mode = 0644, | |
894 | .proc_handler = proc_dointvec_jiffies, | |
895 | }, | |
896 | [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_ACKED] = { | |
897 | .procname = "nf_conntrack_sctp_timeout_heartbeat_acked", | |
898 | .maxlen = sizeof(unsigned int), | |
899 | .mode = 0644, | |
900 | .proc_handler = proc_dointvec_jiffies, | |
901 | }, | |
902 | #endif | |
903 | #ifdef CONFIG_NF_CT_PROTO_DCCP | |
904 | [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST] = { | |
905 | .procname = "nf_conntrack_dccp_timeout_request", | |
906 | .maxlen = sizeof(unsigned int), | |
907 | .mode = 0644, | |
908 | .proc_handler = proc_dointvec_jiffies, | |
909 | }, | |
910 | [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_RESPOND] = { | |
911 | .procname = "nf_conntrack_dccp_timeout_respond", | |
912 | .maxlen = sizeof(unsigned int), | |
913 | .mode = 0644, | |
914 | .proc_handler = proc_dointvec_jiffies, | |
915 | }, | |
916 | [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_PARTOPEN] = { | |
917 | .procname = "nf_conntrack_dccp_timeout_partopen", | |
918 | .maxlen = sizeof(unsigned int), | |
919 | .mode = 0644, | |
920 | .proc_handler = proc_dointvec_jiffies, | |
921 | }, | |
922 | [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_OPEN] = { | |
923 | .procname = "nf_conntrack_dccp_timeout_open", | |
924 | .maxlen = sizeof(unsigned int), | |
925 | .mode = 0644, | |
926 | .proc_handler = proc_dointvec_jiffies, | |
927 | }, | |
928 | [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_CLOSEREQ] = { | |
929 | .procname = "nf_conntrack_dccp_timeout_closereq", | |
930 | .maxlen = sizeof(unsigned int), | |
931 | .mode = 0644, | |
932 | .proc_handler = proc_dointvec_jiffies, | |
933 | }, | |
934 | [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_CLOSING] = { | |
935 | .procname = "nf_conntrack_dccp_timeout_closing", | |
936 | .maxlen = sizeof(unsigned int), | |
937 | .mode = 0644, | |
938 | .proc_handler = proc_dointvec_jiffies, | |
939 | }, | |
940 | [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_TIMEWAIT] = { | |
941 | .procname = "nf_conntrack_dccp_timeout_timewait", | |
942 | .maxlen = sizeof(unsigned int), | |
943 | .mode = 0644, | |
944 | .proc_handler = proc_dointvec_jiffies, | |
945 | }, | |
946 | [NF_SYSCTL_CT_PROTO_DCCP_LOOSE] = { | |
947 | .procname = "nf_conntrack_dccp_loose", | |
948 | .maxlen = sizeof(u8), | |
949 | .mode = 0644, | |
950 | .proc_handler = proc_dou8vec_minmax, | |
951 | .extra1 = SYSCTL_ZERO, | |
952 | .extra2 = SYSCTL_ONE, | |
953 | }, | |
954 | #endif | |
955 | #ifdef CONFIG_NF_CT_PROTO_GRE | |
956 | [NF_SYSCTL_CT_PROTO_TIMEOUT_GRE] = { | |
957 | .procname = "nf_conntrack_gre_timeout", | |
958 | .maxlen = sizeof(unsigned int), | |
959 | .mode = 0644, | |
960 | .proc_handler = proc_dointvec_jiffies, | |
961 | }, | |
962 | [NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM] = { | |
963 | .procname = "nf_conntrack_gre_timeout_stream", | |
964 | .maxlen = sizeof(unsigned int), | |
965 | .mode = 0644, | |
966 | .proc_handler = proc_dointvec_jiffies, | |
967 | }, | |
968 | #endif | |
969 | #ifdef CONFIG_LWTUNNEL | |
970 | [NF_SYSCTL_CT_LWTUNNEL] = { | |
971 | .procname = "nf_hooks_lwtunnel", | |
972 | .data = NULL, | |
973 | .maxlen = sizeof(int), | |
974 | .mode = 0644, | |
975 | .proc_handler = nf_hooks_lwtunnel_sysctl_handler, | |
976 | }, | |
977 | #endif | |
978 | {} | |
979 | }; | |
980 | ||
981 | static struct ctl_table nf_ct_netfilter_table[] = { | |
982 | { | |
983 | .procname = "nf_conntrack_max", | |
984 | .data = &nf_conntrack_max, | |
985 | .maxlen = sizeof(int), | |
986 | .mode = 0644, | |
987 | .proc_handler = proc_dointvec, | |
988 | }, | |
989 | { } | |
990 | }; | |
991 | ||
992 | static void nf_conntrack_standalone_init_tcp_sysctl(struct net *net, | |
993 | struct ctl_table *table) | |
994 | { | |
995 | struct nf_tcp_net *tn = nf_tcp_pernet(net); | |
996 | ||
997 | #define XASSIGN(XNAME, tn) \ | |
998 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_ ## XNAME].data = \ | |
999 | &(tn)->timeouts[TCP_CONNTRACK_ ## XNAME] | |
1000 | ||
1001 | XASSIGN(SYN_SENT, tn); | |
1002 | XASSIGN(SYN_RECV, tn); | |
1003 | XASSIGN(ESTABLISHED, tn); | |
1004 | XASSIGN(FIN_WAIT, tn); | |
1005 | XASSIGN(CLOSE_WAIT, tn); | |
1006 | XASSIGN(LAST_ACK, tn); | |
1007 | XASSIGN(TIME_WAIT, tn); | |
1008 | XASSIGN(CLOSE, tn); | |
1009 | XASSIGN(RETRANS, tn); | |
1010 | XASSIGN(UNACK, tn); | |
1011 | #undef XASSIGN | |
1012 | #define XASSIGN(XNAME, rval) \ | |
1013 | table[NF_SYSCTL_CT_PROTO_TCP_ ## XNAME].data = (rval) | |
1014 | ||
1015 | XASSIGN(LOOSE, &tn->tcp_loose); | |
1016 | XASSIGN(LIBERAL, &tn->tcp_be_liberal); | |
1017 | XASSIGN(MAX_RETRANS, &tn->tcp_max_retrans); | |
1018 | XASSIGN(IGNORE_INVALID_RST, &tn->tcp_ignore_invalid_rst); | |
1019 | #undef XASSIGN | |
1020 | ||
1021 | #if IS_ENABLED(CONFIG_NF_FLOW_TABLE) | |
1022 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD].data = &tn->offload_timeout; | |
1023 | #endif | |
1024 | ||
1025 | } | |
1026 | ||
1027 | static void nf_conntrack_standalone_init_sctp_sysctl(struct net *net, | |
1028 | struct ctl_table *table) | |
1029 | { | |
1030 | #ifdef CONFIG_NF_CT_PROTO_SCTP | |
1031 | struct nf_sctp_net *sn = nf_sctp_pernet(net); | |
1032 | ||
1033 | #define XASSIGN(XNAME, sn) \ | |
1034 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_ ## XNAME].data = \ | |
1035 | &(sn)->timeouts[SCTP_CONNTRACK_ ## XNAME] | |
1036 | ||
1037 | XASSIGN(CLOSED, sn); | |
1038 | XASSIGN(COOKIE_WAIT, sn); | |
1039 | XASSIGN(COOKIE_ECHOED, sn); | |
1040 | XASSIGN(ESTABLISHED, sn); | |
1041 | XASSIGN(SHUTDOWN_SENT, sn); | |
1042 | XASSIGN(SHUTDOWN_RECD, sn); | |
1043 | XASSIGN(SHUTDOWN_ACK_SENT, sn); | |
1044 | XASSIGN(HEARTBEAT_SENT, sn); | |
1045 | XASSIGN(HEARTBEAT_ACKED, sn); | |
1046 | #undef XASSIGN | |
1047 | #endif | |
1048 | } | |
1049 | ||
1050 | static void nf_conntrack_standalone_init_dccp_sysctl(struct net *net, | |
1051 | struct ctl_table *table) | |
1052 | { | |
1053 | #ifdef CONFIG_NF_CT_PROTO_DCCP | |
1054 | struct nf_dccp_net *dn = nf_dccp_pernet(net); | |
1055 | ||
1056 | #define XASSIGN(XNAME, dn) \ | |
1057 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_ ## XNAME].data = \ | |
1058 | &(dn)->dccp_timeout[CT_DCCP_ ## XNAME] | |
1059 | ||
1060 | XASSIGN(REQUEST, dn); | |
1061 | XASSIGN(RESPOND, dn); | |
1062 | XASSIGN(PARTOPEN, dn); | |
1063 | XASSIGN(OPEN, dn); | |
1064 | XASSIGN(CLOSEREQ, dn); | |
1065 | XASSIGN(CLOSING, dn); | |
1066 | XASSIGN(TIMEWAIT, dn); | |
1067 | #undef XASSIGN | |
1068 | ||
1069 | table[NF_SYSCTL_CT_PROTO_DCCP_LOOSE].data = &dn->dccp_loose; | |
1070 | #endif | |
1071 | } | |
1072 | ||
1073 | static void nf_conntrack_standalone_init_gre_sysctl(struct net *net, | |
1074 | struct ctl_table *table) | |
1075 | { | |
1076 | #ifdef CONFIG_NF_CT_PROTO_GRE | |
1077 | struct nf_gre_net *gn = nf_gre_pernet(net); | |
1078 | ||
1079 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_GRE].data = &gn->timeouts[GRE_CT_UNREPLIED]; | |
1080 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_GRE_STREAM].data = &gn->timeouts[GRE_CT_REPLIED]; | |
1081 | #endif | |
1082 | } | |
1083 | ||
1084 | static int nf_conntrack_standalone_init_sysctl(struct net *net) | |
1085 | { | |
1086 | struct nf_conntrack_net *cnet = nf_ct_pernet(net); | |
1087 | struct nf_udp_net *un = nf_udp_pernet(net); | |
1088 | struct ctl_table *table; | |
1089 | ||
1090 | BUILD_BUG_ON(ARRAY_SIZE(nf_ct_sysctl_table) != NF_SYSCTL_CT_LAST_SYSCTL); | |
1091 | ||
1092 | table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table), | |
1093 | GFP_KERNEL); | |
1094 | if (!table) | |
1095 | return -ENOMEM; | |
1096 | ||
1097 | table[NF_SYSCTL_CT_COUNT].data = &cnet->count; | |
1098 | table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum; | |
1099 | table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid; | |
1100 | table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct; | |
1101 | table[NF_SYSCTL_CT_HELPER].data = &cnet->sysctl_auto_assign_helper; | |
1102 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | |
1103 | table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events; | |
1104 | #endif | |
1105 | #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP | |
1106 | table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp; | |
1107 | #endif | |
1108 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout; | |
1109 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout; | |
1110 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout; | |
1111 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP].data = &un->timeouts[UDP_CT_UNREPLIED]; | |
1112 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM].data = &un->timeouts[UDP_CT_REPLIED]; | |
1113 | #if IS_ENABLED(CONFIG_NF_FLOW_TABLE) | |
1114 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD].data = &un->offload_timeout; | |
1115 | #endif | |
1116 | ||
1117 | nf_conntrack_standalone_init_tcp_sysctl(net, table); | |
1118 | nf_conntrack_standalone_init_sctp_sysctl(net, table); | |
1119 | nf_conntrack_standalone_init_dccp_sysctl(net, table); | |
1120 | nf_conntrack_standalone_init_gre_sysctl(net, table); | |
1121 | ||
1122 | /* Don't allow non-init_net ns to alter global sysctls */ | |
1123 | if (!net_eq(&init_net, net)) { | |
1124 | table[NF_SYSCTL_CT_MAX].mode = 0444; | |
1125 | table[NF_SYSCTL_CT_EXPECT_MAX].mode = 0444; | |
1126 | table[NF_SYSCTL_CT_BUCKETS].mode = 0444; | |
1127 | } | |
1128 | ||
1129 | cnet->sysctl_header = register_net_sysctl(net, "net/netfilter", table); | |
1130 | if (!cnet->sysctl_header) | |
1131 | goto out_unregister_netfilter; | |
1132 | ||
1133 | return 0; | |
1134 | ||
1135 | out_unregister_netfilter: | |
1136 | kfree(table); | |
1137 | return -ENOMEM; | |
1138 | } | |
1139 | ||
1140 | static void nf_conntrack_standalone_fini_sysctl(struct net *net) | |
1141 | { | |
1142 | struct nf_conntrack_net *cnet = nf_ct_pernet(net); | |
1143 | struct ctl_table *table; | |
1144 | ||
1145 | table = cnet->sysctl_header->ctl_table_arg; | |
1146 | unregister_net_sysctl_table(cnet->sysctl_header); | |
1147 | kfree(table); | |
1148 | } | |
1149 | #else | |
1150 | static int nf_conntrack_standalone_init_sysctl(struct net *net) | |
1151 | { | |
1152 | return 0; | |
1153 | } | |
1154 | ||
1155 | static void nf_conntrack_standalone_fini_sysctl(struct net *net) | |
1156 | { | |
1157 | } | |
1158 | #endif /* CONFIG_SYSCTL */ | |
1159 | ||
1160 | static void nf_conntrack_fini_net(struct net *net) | |
1161 | { | |
1162 | if (enable_hooks) | |
1163 | nf_ct_netns_put(net, NFPROTO_INET); | |
1164 | ||
1165 | nf_conntrack_standalone_fini_proc(net); | |
1166 | nf_conntrack_standalone_fini_sysctl(net); | |
1167 | } | |
1168 | ||
1169 | static int nf_conntrack_pernet_init(struct net *net) | |
1170 | { | |
1171 | int ret; | |
1172 | ||
1173 | net->ct.sysctl_checksum = 1; | |
1174 | ||
1175 | ret = nf_conntrack_standalone_init_sysctl(net); | |
1176 | if (ret < 0) | |
1177 | return ret; | |
1178 | ||
1179 | ret = nf_conntrack_standalone_init_proc(net); | |
1180 | if (ret < 0) | |
1181 | goto out_proc; | |
1182 | ||
1183 | ret = nf_conntrack_init_net(net); | |
1184 | if (ret < 0) | |
1185 | goto out_init_net; | |
1186 | ||
1187 | if (enable_hooks) { | |
1188 | ret = nf_ct_netns_get(net, NFPROTO_INET); | |
1189 | if (ret < 0) | |
1190 | goto out_hooks; | |
1191 | } | |
1192 | ||
1193 | return 0; | |
1194 | ||
1195 | out_hooks: | |
1196 | nf_conntrack_cleanup_net(net); | |
1197 | out_init_net: | |
1198 | nf_conntrack_standalone_fini_proc(net); | |
1199 | out_proc: | |
1200 | nf_conntrack_standalone_fini_sysctl(net); | |
1201 | return ret; | |
1202 | } | |
1203 | ||
1204 | static void nf_conntrack_pernet_exit(struct list_head *net_exit_list) | |
1205 | { | |
1206 | struct net *net; | |
1207 | ||
1208 | list_for_each_entry(net, net_exit_list, exit_list) | |
1209 | nf_conntrack_fini_net(net); | |
1210 | ||
1211 | nf_conntrack_cleanup_net_list(net_exit_list); | |
1212 | } | |
1213 | ||
1214 | static struct pernet_operations nf_conntrack_net_ops = { | |
1215 | .init = nf_conntrack_pernet_init, | |
1216 | .exit_batch = nf_conntrack_pernet_exit, | |
1217 | .id = &nf_conntrack_net_id, | |
1218 | .size = sizeof(struct nf_conntrack_net), | |
1219 | }; | |
1220 | ||
1221 | static int __init nf_conntrack_standalone_init(void) | |
1222 | { | |
1223 | int ret = nf_conntrack_init_start(); | |
1224 | if (ret < 0) | |
1225 | goto out_start; | |
1226 | ||
1227 | BUILD_BUG_ON(NFCT_INFOMASK <= IP_CT_NUMBER); | |
1228 | ||
1229 | #ifdef CONFIG_SYSCTL | |
1230 | nf_ct_netfilter_header = | |
1231 | register_net_sysctl(&init_net, "net", nf_ct_netfilter_table); | |
1232 | if (!nf_ct_netfilter_header) { | |
1233 | pr_err("nf_conntrack: can't register to sysctl.\n"); | |
1234 | ret = -ENOMEM; | |
1235 | goto out_sysctl; | |
1236 | } | |
1237 | ||
1238 | nf_conntrack_htable_size_user = nf_conntrack_htable_size; | |
1239 | #endif | |
1240 | ||
1241 | ret = register_pernet_subsys(&nf_conntrack_net_ops); | |
1242 | if (ret < 0) | |
1243 | goto out_pernet; | |
1244 | ||
1245 | nf_conntrack_init_end(); | |
1246 | return 0; | |
1247 | ||
1248 | out_pernet: | |
1249 | #ifdef CONFIG_SYSCTL | |
1250 | unregister_net_sysctl_table(nf_ct_netfilter_header); | |
1251 | out_sysctl: | |
1252 | #endif | |
1253 | nf_conntrack_cleanup_end(); | |
1254 | out_start: | |
1255 | return ret; | |
1256 | } | |
1257 | ||
1258 | static void __exit nf_conntrack_standalone_fini(void) | |
1259 | { | |
1260 | nf_conntrack_cleanup_start(); | |
1261 | unregister_pernet_subsys(&nf_conntrack_net_ops); | |
1262 | #ifdef CONFIG_SYSCTL | |
1263 | unregister_net_sysctl_table(nf_ct_netfilter_header); | |
1264 | #endif | |
1265 | nf_conntrack_cleanup_end(); | |
1266 | } | |
1267 | ||
1268 | module_init(nf_conntrack_standalone_init); | |
1269 | module_exit(nf_conntrack_standalone_fini); |