xref: /openbmc/linux/net/phonet/sysctl.c (revision 32927393)
12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
287ab4e20SRemi Denis-Courmont /*
387ab4e20SRemi Denis-Courmont  * File: sysctl.c
487ab4e20SRemi Denis-Courmont  *
587ab4e20SRemi Denis-Courmont  * Phonet /proc/sys/net/phonet interface implementation
687ab4e20SRemi Denis-Courmont  *
787ab4e20SRemi Denis-Courmont  * Copyright (C) 2008 Nokia Corporation.
887ab4e20SRemi Denis-Courmont  *
931fdc555SRémi Denis-Courmont  * Author: Rémi Denis-Courmont
1087ab4e20SRemi Denis-Courmont  */
1187ab4e20SRemi Denis-Courmont 
1287ab4e20SRemi Denis-Courmont #include <linux/seqlock.h>
1387ab4e20SRemi Denis-Courmont #include <linux/sysctl.h>
1487ab4e20SRemi Denis-Courmont #include <linux/errno.h>
1587ab4e20SRemi Denis-Courmont #include <linux/init.h>
1687ab4e20SRemi Denis-Courmont 
178e052e52SRémi Denis-Courmont #include <net/sock.h>
188e052e52SRémi Denis-Courmont #include <linux/phonet.h>
198e052e52SRémi Denis-Courmont #include <net/phonet/phonet.h>
208e052e52SRémi Denis-Courmont 
2187ab4e20SRemi Denis-Courmont #define DYNAMIC_PORT_MIN	0x40
2287ab4e20SRemi Denis-Courmont #define DYNAMIC_PORT_MAX	0x7f
2387ab4e20SRemi Denis-Courmont 
2487ab4e20SRemi Denis-Courmont static DEFINE_SEQLOCK(local_port_range_lock);
2587ab4e20SRemi Denis-Courmont static int local_port_range_min[2] = {0, 0};
2687ab4e20SRemi Denis-Courmont static int local_port_range_max[2] = {1023, 1023};
2787ab4e20SRemi Denis-Courmont static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX};
2887ab4e20SRemi Denis-Courmont static struct ctl_table_header *phonet_table_hrd;
2987ab4e20SRemi Denis-Courmont 
set_local_port_range(int range[2])3087ab4e20SRemi Denis-Courmont static void set_local_port_range(int range[2])
3187ab4e20SRemi Denis-Courmont {
3287ab4e20SRemi Denis-Courmont 	write_seqlock(&local_port_range_lock);
3387ab4e20SRemi Denis-Courmont 	local_port_range[0] = range[0];
3487ab4e20SRemi Denis-Courmont 	local_port_range[1] = range[1];
3587ab4e20SRemi Denis-Courmont 	write_sequnlock(&local_port_range_lock);
3687ab4e20SRemi Denis-Courmont }
3787ab4e20SRemi Denis-Courmont 
phonet_get_local_port_range(int * min,int * max)3887ab4e20SRemi Denis-Courmont void phonet_get_local_port_range(int *min, int *max)
3987ab4e20SRemi Denis-Courmont {
4095c96174SEric Dumazet 	unsigned int seq;
4195c96174SEric Dumazet 
4287ab4e20SRemi Denis-Courmont 	do {
4387ab4e20SRemi Denis-Courmont 		seq = read_seqbegin(&local_port_range_lock);
4487ab4e20SRemi Denis-Courmont 		if (min)
4587ab4e20SRemi Denis-Courmont 			*min = local_port_range[0];
4687ab4e20SRemi Denis-Courmont 		if (max)
4787ab4e20SRemi Denis-Courmont 			*max = local_port_range[1];
4887ab4e20SRemi Denis-Courmont 	} while (read_seqretry(&local_port_range_lock, seq));
4987ab4e20SRemi Denis-Courmont }
5087ab4e20SRemi Denis-Courmont 
proc_local_port_range(struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)51fe2c6338SJoe Perches static int proc_local_port_range(struct ctl_table *table, int write,
5232927393SChristoph Hellwig 				 void *buffer, size_t *lenp, loff_t *ppos)
5387ab4e20SRemi Denis-Courmont {
5487ab4e20SRemi Denis-Courmont 	int ret;
5587ab4e20SRemi Denis-Courmont 	int range[2] = {local_port_range[0], local_port_range[1]};
56fe2c6338SJoe Perches 	struct ctl_table tmp = {
5787ab4e20SRemi Denis-Courmont 		.data = &range,
5887ab4e20SRemi Denis-Courmont 		.maxlen = sizeof(range),
5987ab4e20SRemi Denis-Courmont 		.mode = table->mode,
6087ab4e20SRemi Denis-Courmont 		.extra1 = &local_port_range_min,
6187ab4e20SRemi Denis-Courmont 		.extra2 = &local_port_range_max,
6287ab4e20SRemi Denis-Courmont 	};
6387ab4e20SRemi Denis-Courmont 
648d65af78SAlexey Dobriyan 	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
6587ab4e20SRemi Denis-Courmont 
6687ab4e20SRemi Denis-Courmont 	if (write && ret == 0) {
6787ab4e20SRemi Denis-Courmont 		if (range[1] < range[0])
6887ab4e20SRemi Denis-Courmont 			ret = -EINVAL;
6987ab4e20SRemi Denis-Courmont 		else
7087ab4e20SRemi Denis-Courmont 			set_local_port_range(range);
7187ab4e20SRemi Denis-Courmont 	}
7287ab4e20SRemi Denis-Courmont 
7387ab4e20SRemi Denis-Courmont 	return ret;
7487ab4e20SRemi Denis-Courmont }
7587ab4e20SRemi Denis-Courmont 
7687ab4e20SRemi Denis-Courmont static struct ctl_table phonet_table[] = {
7787ab4e20SRemi Denis-Courmont 	{
7887ab4e20SRemi Denis-Courmont 		.procname	= "local_port_range",
7987ab4e20SRemi Denis-Courmont 		.data		= &local_port_range,
8087ab4e20SRemi Denis-Courmont 		.maxlen		= sizeof(local_port_range),
8187ab4e20SRemi Denis-Courmont 		.mode		= 0644,
826d9f239aSAlexey Dobriyan 		.proc_handler	= proc_local_port_range,
8387ab4e20SRemi Denis-Courmont 	},
84f8572d8fSEric W. Biederman 	{ }
8587ab4e20SRemi Denis-Courmont };
8687ab4e20SRemi Denis-Courmont 
phonet_sysctl_init(void)8787ab4e20SRemi Denis-Courmont int __init phonet_sysctl_init(void)
8887ab4e20SRemi Denis-Courmont {
89ec8f23ceSEric W. Biederman 	phonet_table_hrd = register_net_sysctl(&init_net, "net/phonet", phonet_table);
9087ab4e20SRemi Denis-Courmont 	return phonet_table_hrd == NULL ? -ENOMEM : 0;
9187ab4e20SRemi Denis-Courmont }
9287ab4e20SRemi Denis-Courmont 
phonet_sysctl_exit(void)9387ab4e20SRemi Denis-Courmont void phonet_sysctl_exit(void)
9487ab4e20SRemi Denis-Courmont {
955dd3df10SEric W. Biederman 	unregister_net_sysctl_table(phonet_table_hrd);
9687ab4e20SRemi Denis-Courmont }
97