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 | |
| 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>
| -rw-r--r-- | include/net/phonet/phonet.h | 3 | ||||
| -rw-r--r-- | net/phonet/Makefile | 1 | ||||
| -rw-r--r-- | net/phonet/af_phonet.c | 3 | ||||
| -rw-r--r-- | net/phonet/socket.c | 3 | ||||
| -rw-r--r-- | net/phonet/sysctl.c | 113 |
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) | |||
| 47 | extern const struct proto_ops phonet_dgram_ops; | 47 | extern const struct proto_ops phonet_dgram_ops; |
| 48 | 48 | ||
| 49 | struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa); | 49 | struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa); |
| 50 | void phonet_get_local_port_range(int *min, int *max); | ||
| 50 | void pn_sock_hash(struct sock *sk); | 51 | void pn_sock_hash(struct sock *sk); |
| 51 | void pn_sock_unhash(struct sock *sk); | 52 | void pn_sock_unhash(struct sock *sk); |
| 52 | int pn_sock_get_port(struct sock *sk, unsigned short sport); | 53 | int pn_sock_get_port(struct sock *sk, unsigned short sport); |
| @@ -97,6 +98,8 @@ struct phonet_protocol { | |||
| 97 | int phonet_proto_register(int protocol, struct phonet_protocol *pp); | 98 | int phonet_proto_register(int protocol, struct phonet_protocol *pp); |
| 98 | void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); | 99 | void phonet_proto_unregister(int protocol, struct phonet_protocol *pp); |
| 99 | 100 | ||
| 101 | int phonet_sysctl_init(void); | ||
| 102 | void phonet_sysctl_exit(void); | ||
| 100 | void phonet_netlink_register(void); | 103 | void phonet_netlink_register(void); |
| 101 | int isi_register(void); | 104 | int isi_register(void); |
| 102 | void isi_unregister(void); | 105 | void 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 | ||
| 359 | err: | 360 | err: |
| 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: | |||
| 366 | static void __exit phonet_exit(void) | 368 | static 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 | |||
| 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 | } | ||
