Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Multipath TCP
  3 *
  4 * Copyright (c) 2019, Tessares SA.
  5 */
  6
  7#include <linux/sysctl.h>
  8
  9#include <net/net_namespace.h>
 10#include <net/netns/generic.h>
 11
 12#include "protocol.h"
 13
 14#define MPTCP_SYSCTL_PATH "net/mptcp"
 15
 16static int mptcp_pernet_id;
 17struct mptcp_pernet {
 18	struct ctl_table_header *ctl_table_hdr;
 19
 20	int mptcp_enabled;
 21};
 22
 23static struct mptcp_pernet *mptcp_get_pernet(struct net *net)
 24{
 25	return net_generic(net, mptcp_pernet_id);
 26}
 27
 28int mptcp_is_enabled(struct net *net)
 29{
 30	return mptcp_get_pernet(net)->mptcp_enabled;
 31}
 32
 33static struct ctl_table mptcp_sysctl_table[] = {
 34	{
 35		.procname = "enabled",
 36		.maxlen = sizeof(int),
 37		.mode = 0644,
 38		/* users with CAP_NET_ADMIN or root (not and) can change this
 39		 * value, same as other sysctl or the 'net' tree.
 40		 */
 41		.proc_handler = proc_dointvec,
 42	},
 43	{}
 44};
 45
 46static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
 47{
 48	pernet->mptcp_enabled = 1;
 49}
 50
 51static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
 52{
 53	struct ctl_table_header *hdr;
 54	struct ctl_table *table;
 55
 56	table = mptcp_sysctl_table;
 57	if (!net_eq(net, &init_net)) {
 58		table = kmemdup(table, sizeof(mptcp_sysctl_table), GFP_KERNEL);
 59		if (!table)
 60			goto err_alloc;
 61	}
 62
 63	table[0].data = &pernet->mptcp_enabled;
 64
 65	hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
 66	if (!hdr)
 67		goto err_reg;
 68
 69	pernet->ctl_table_hdr = hdr;
 70
 71	return 0;
 72
 73err_reg:
 74	if (!net_eq(net, &init_net))
 75		kfree(table);
 76err_alloc:
 77	return -ENOMEM;
 78}
 79
 80static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
 81{
 82	struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
 83
 84	unregister_net_sysctl_table(pernet->ctl_table_hdr);
 85
 86	kfree(table);
 87}
 88
 89static int __net_init mptcp_net_init(struct net *net)
 90{
 91	struct mptcp_pernet *pernet = mptcp_get_pernet(net);
 92
 93	mptcp_pernet_set_defaults(pernet);
 94
 95	return mptcp_pernet_new_table(net, pernet);
 96}
 97
 98/* Note: the callback will only be called per extra netns */
 99static void __net_exit mptcp_net_exit(struct net *net)
100{
101	struct mptcp_pernet *pernet = mptcp_get_pernet(net);
102
103	mptcp_pernet_del_table(pernet);
104}
105
106static struct pernet_operations mptcp_pernet_ops = {
107	.init = mptcp_net_init,
108	.exit = mptcp_net_exit,
109	.id = &mptcp_pernet_id,
110	.size = sizeof(struct mptcp_pernet),
111};
112
113void __init mptcp_init(void)
114{
115	mptcp_join_cookie_init();
116	mptcp_proto_init();
117
118	if (register_pernet_subsys(&mptcp_pernet_ops) < 0)
119		panic("Failed to register MPTCP pernet subsystem.\n");
120}
121
122#if IS_ENABLED(CONFIG_MPTCP_IPV6)
123int __init mptcpv6_init(void)
124{
125	int err;
126
127	err = mptcp_proto_v6_init();
128
129	return err;
130}
131#endif