File Index
Files and directories
Sign in
FILE

nf_conntrack_standalone.c

File preview with syntax highlighting.

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