aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/phonet/phonet.h3
-rw-r--r--net/phonet/Makefile1
-rw-r--r--net/phonet/af_phonet.c3
-rw-r--r--net/phonet/socket.c3
-rw-r--r--net/phonet/sysctl.c113
5 files changed, 122 insertions, 1 deletions
diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
index d3957d3be0fd..1c6f7e7d5fea 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -47,6 +47,7 @@ static inline struct pn_sock *pn_sk(struct sock *sk)
47extern const struct proto_ops phonet_dgram_ops; 47extern const struct proto_ops phonet_dgram_ops;
48 48
49struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa); 49struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa);
50void phonet_get_local_port_range(int *min, int *max);
50void pn_sock_hash(struct sock *sk); 51void pn_sock_hash(struct sock *sk);
51void pn_sock_unhash(struct sock *sk); 52void pn_sock_unhash(struct sock *sk);
52int pn_sock_get_port(struct sock *sk, unsigned short sport); 53int pn_sock_get_port(struct sock *sk, unsigned short sport);
@@ -97,6 +98,8 @@ struct phonet_protocol {
97int phonet_proto_register(int protocol, struct phonet_protocol *pp); 98int phonet_proto_register(int protocol, struct phonet_protocol *pp);
98void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); 99void phonet_proto_unregister(int protocol, struct phonet_protocol *pp);
99 100
101int phonet_sysctl_init(void);
102void phonet_sysctl_exit(void);
100void phonet_netlink_register(void); 103void phonet_netlink_register(void);
101int isi_register(void); 104int isi_register(void);
102void isi_unregister(void); 105void isi_unregister(void);
diff --git a/net/phonet/Makefile b/net/phonet/Makefile
index d218abc3f06a..ae9c3ed5be83 100644
--- a/net/phonet/Makefile
+++ b/net/phonet/Makefile
@@ -5,4 +5,5 @@ phonet-objs := \
5 pn_netlink.o \ 5 pn_netlink.o \
6 socket.o \ 6 socket.o \
7 datagram.o \ 7 datagram.o \
8 sysctl.o \
8 af_phonet.o 9 af_phonet.o
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index 51397ff308bd..50dc258d5aa2 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -350,6 +350,7 @@ static int __init phonet_init(void)
350 phonet_device_init(); 350 phonet_device_init();
351 dev_add_pack(&phonet_packet_type); 351 dev_add_pack(&phonet_packet_type);
352 phonet_netlink_register(); 352 phonet_netlink_register();
353 phonet_sysctl_init();
353 354
354 err = isi_register(); 355 err = isi_register();
355 if (err) 356 if (err)
@@ -357,6 +358,7 @@ static int __init phonet_init(void)
357 return 0; 358 return 0;
358 359
359err: 360err:
361 phonet_sysctl_exit();
360 sock_unregister(AF_PHONET); 362 sock_unregister(AF_PHONET);
361 dev_remove_pack(&phonet_packet_type); 363 dev_remove_pack(&phonet_packet_type);
362 phonet_device_exit(); 364 phonet_device_exit();
@@ -366,6 +368,7 @@ err:
366static void __exit phonet_exit(void) 368static void __exit phonet_exit(void)
367{ 369{
368 isi_unregister(); 370 isi_unregister();
371 phonet_sysctl_exit();
369 sock_unregister(AF_PHONET); 372 sock_unregister(AF_PHONET);
370 dev_remove_pack(&phonet_packet_type); 373 dev_remove_pack(&phonet_packet_type);
371 phonet_device_exit(); 374 phonet_device_exit();
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 99a4945d565d..dfd4061646db 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -273,8 +273,9 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
273 273
274 if (!sport) { 274 if (!sport) {
275 /* search free port */ 275 /* search free port */
276 int port, pmin = 0x40, pmax = 0x7f; 276 int port, pmin, pmax;
277 277
278 phonet_get_local_port_range(&pmin, &pmax);
278 for (port = pmin; port <= pmax; port++) { 279 for (port = pmin; port <= pmax; port++) {
279 port_cur++; 280 port_cur++;
280 if (port_cur < pmin || port_cur > pmax) 281 if (port_cur < pmin || port_cur > pmax)
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
33static DEFINE_SEQLOCK(local_port_range_lock);
34static int local_port_range_min[2] = {0, 0};
35static int local_port_range_max[2] = {1023, 1023};
36static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX};
37static struct ctl_table_header *phonet_table_hrd;
38
39static 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
47void 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
59static 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
85static 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
98struct ctl_path phonet_ctl_path[] = {
99 { .procname = "net", .ctl_name = CTL_NET, },
100 { .procname = "phonet", .ctl_name = CTL_UNNUMBERED, },
101 { },
102};
103
104int __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
110void phonet_sysctl_exit(void)
111{
112 unregister_sysctl_table(phonet_table_hrd);
113}