123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- /*
- * File: sysctl.c
- *
- * Phonet /proc/sys/net/phonet interface implementation
- *
- * Copyright (C) 2008 Nokia Corporation.
- *
- * Author: Rémi Denis-Courmont
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
- #include <linux/seqlock.h>
- #include <linux/sysctl.h>
- #include <linux/errno.h>
- #include <linux/init.h>
- #include <net/sock.h>
- #include <linux/phonet.h>
- #include <net/phonet/phonet.h>
- #define DYNAMIC_PORT_MIN 0x40
- #define DYNAMIC_PORT_MAX 0x7f
- static DEFINE_SEQLOCK(local_port_range_lock);
- static int local_port_range_min[2] = {0, 0};
- static int local_port_range_max[2] = {1023, 1023};
- static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX};
- static struct ctl_table_header *phonet_table_hrd;
- static void set_local_port_range(int range[2])
- {
- write_seqlock(&local_port_range_lock);
- local_port_range[0] = range[0];
- local_port_range[1] = range[1];
- write_sequnlock(&local_port_range_lock);
- }
- void phonet_get_local_port_range(int *min, int *max)
- {
- unsigned int seq;
- do {
- seq = read_seqbegin(&local_port_range_lock);
- if (min)
- *min = local_port_range[0];
- if (max)
- *max = local_port_range[1];
- } while (read_seqretry(&local_port_range_lock, seq));
- }
- static int proc_local_port_range(struct ctl_table *table, int write,
- void __user *buffer,
- size_t *lenp, loff_t *ppos)
- {
- int ret;
- int range[2] = {local_port_range[0], local_port_range[1]};
- struct ctl_table tmp = {
- .data = &range,
- .maxlen = sizeof(range),
- .mode = table->mode,
- .extra1 = &local_port_range_min,
- .extra2 = &local_port_range_max,
- };
- ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
- if (write && ret == 0) {
- if (range[1] < range[0])
- ret = -EINVAL;
- else
- set_local_port_range(range);
- }
- return ret;
- }
- static struct ctl_table phonet_table[] = {
- {
- .procname = "local_port_range",
- .data = &local_port_range,
- .maxlen = sizeof(local_port_range),
- .mode = 0644,
- .proc_handler = proc_local_port_range,
- },
- { }
- };
- int __init phonet_sysctl_init(void)
- {
- phonet_table_hrd = register_net_sysctl(&init_net, "net/phonet", phonet_table);
- return phonet_table_hrd == NULL ? -ENOMEM : 0;
- }
- void phonet_sysctl_exit(void)
- {
- unregister_net_sysctl_table(phonet_table_hrd);
- }
|