diff options
author | Remi Denis-Courmont <remi.denis-courmont@nokia.com> | 2008-09-22 23:08:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-22 23:08:39 -0400 |
commit | 87ab4e20b445c6d2d2727ab4f96fa17f7259511e (patch) | |
tree | 42ee249e27e293b94f9f0c5a72dc6ef58fee5d38 /net/phonet/sysctl.c | |
parent | 5f77076d75d35c9f5619e1f9d7e7428a627f65e6 (diff) |
Phonet: proc interface for port range
Phonet endpoints are bound to individual ports.
This provides a /proc/sys/net/phonet (or sysctl) interface for
selecting the range of automatically allocated ports (much like the
ip_local_port_range with IPv4).
Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/phonet/sysctl.c')
-rw-r--r-- | net/phonet/sysctl.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c new file mode 100644 index 000000000000..600a4309b8c8 --- /dev/null +++ b/net/phonet/sysctl.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * File: sysctl.c | ||
3 | * | ||
4 | * Phonet /proc/sys/net/phonet interface implementation | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/seqlock.h> | ||
26 | #include <linux/sysctl.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/init.h> | ||
29 | |||
30 | #define DYNAMIC_PORT_MIN 0x40 | ||
31 | #define DYNAMIC_PORT_MAX 0x7f | ||
32 | |||
33 | static DEFINE_SEQLOCK(local_port_range_lock); | ||
34 | static int local_port_range_min[2] = {0, 0}; | ||
35 | static int local_port_range_max[2] = {1023, 1023}; | ||
36 | static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX}; | ||
37 | static struct ctl_table_header *phonet_table_hrd; | ||
38 | |||
39 | static void set_local_port_range(int range[2]) | ||
40 | { | ||
41 | write_seqlock(&local_port_range_lock); | ||
42 | local_port_range[0] = range[0]; | ||
43 | local_port_range[1] = range[1]; | ||
44 | write_sequnlock(&local_port_range_lock); | ||
45 | } | ||
46 | |||
47 | void phonet_get_local_port_range(int *min, int *max) | ||
48 | { | ||
49 | unsigned seq; | ||
50 | do { | ||
51 | seq = read_seqbegin(&local_port_range_lock); | ||
52 | if (min) | ||
53 | *min = local_port_range[0]; | ||
54 | if (max) | ||
55 | *max = local_port_range[1]; | ||
56 | } while (read_seqretry(&local_port_range_lock, seq)); | ||
57 | } | ||
58 | |||
59 | static int proc_local_port_range(ctl_table *table, int write, struct file *filp, | ||
60 | void __user *buffer, | ||
61 | size_t *lenp, loff_t *ppos) | ||
62 | { | ||
63 | int ret; | ||
64 | int range[2] = {local_port_range[0], local_port_range[1]}; | ||
65 | ctl_table tmp = { | ||
66 | .data = &range, | ||
67 | .maxlen = sizeof(range), | ||
68 | .mode = table->mode, | ||
69 | .extra1 = &local_port_range_min, | ||
70 | .extra2 = &local_port_range_max, | ||
71 | }; | ||
72 | |||
73 | ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); | ||
74 | |||
75 | if (write && ret == 0) { | ||
76 | if (range[1] < range[0]) | ||
77 | ret = -EINVAL; | ||
78 | else | ||
79 | set_local_port_range(range); | ||
80 | } | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static struct ctl_table phonet_table[] = { | ||
86 | { | ||
87 | .ctl_name = CTL_UNNUMBERED, | ||
88 | .procname = "local_port_range", | ||
89 | .data = &local_port_range, | ||
90 | .maxlen = sizeof(local_port_range), | ||
91 | .mode = 0644, | ||
92 | .proc_handler = &proc_local_port_range, | ||
93 | .strategy = NULL, | ||
94 | }, | ||
95 | { .ctl_name = 0 } | ||
96 | }; | ||
97 | |||
98 | struct ctl_path phonet_ctl_path[] = { | ||
99 | { .procname = "net", .ctl_name = CTL_NET, }, | ||
100 | { .procname = "phonet", .ctl_name = CTL_UNNUMBERED, }, | ||
101 | { }, | ||
102 | }; | ||
103 | |||
104 | int __init phonet_sysctl_init(void) | ||
105 | { | ||
106 | phonet_table_hrd = register_sysctl_paths(phonet_ctl_path, phonet_table); | ||
107 | return phonet_table_hrd == NULL ? -ENOMEM : 0; | ||
108 | } | ||
109 | |||
110 | void phonet_sysctl_exit(void) | ||
111 | { | ||
112 | unregister_sysctl_table(phonet_table_hrd); | ||
113 | } | ||