]>
Commit | Line | Data |
---|---|---|
2b27bdcc | 1 | // SPDX-License-Identifier: GPL-2.0-only |
87ab4e20 RDC |
2 | /* |
3 | * File: sysctl.c | |
4 | * | |
5 | * Phonet /proc/sys/net/phonet interface implementation | |
6 | * | |
7 | * Copyright (C) 2008 Nokia Corporation. | |
8 | * | |
31fdc555 | 9 | * Author: Rémi Denis-Courmont |
87ab4e20 RDC |
10 | */ |
11 | ||
12 | #include <linux/seqlock.h> | |
13 | #include <linux/sysctl.h> | |
14 | #include <linux/errno.h> | |
15 | #include <linux/init.h> | |
16 | ||
8e052e52 RDC |
17 | #include <net/sock.h> |
18 | #include <linux/phonet.h> | |
19 | #include <net/phonet/phonet.h> | |
20 | ||
87ab4e20 RDC |
21 | #define DYNAMIC_PORT_MIN 0x40 |
22 | #define DYNAMIC_PORT_MAX 0x7f | |
23 | ||
24 | static DEFINE_SEQLOCK(local_port_range_lock); | |
25 | static int local_port_range_min[2] = {0, 0}; | |
26 | static int local_port_range_max[2] = {1023, 1023}; | |
27 | static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX}; | |
28 | static struct ctl_table_header *phonet_table_hrd; | |
29 | ||
30 | static void set_local_port_range(int range[2]) | |
31 | { | |
32 | write_seqlock(&local_port_range_lock); | |
33 | local_port_range[0] = range[0]; | |
34 | local_port_range[1] = range[1]; | |
35 | write_sequnlock(&local_port_range_lock); | |
36 | } | |
37 | ||
38 | void phonet_get_local_port_range(int *min, int *max) | |
39 | { | |
95c96174 ED |
40 | unsigned int seq; |
41 | ||
87ab4e20 RDC |
42 | do { |
43 | seq = read_seqbegin(&local_port_range_lock); | |
44 | if (min) | |
45 | *min = local_port_range[0]; | |
46 | if (max) | |
47 | *max = local_port_range[1]; | |
48 | } while (read_seqretry(&local_port_range_lock, seq)); | |
49 | } | |
50 | ||
fe2c6338 | 51 | static int proc_local_port_range(struct ctl_table *table, int write, |
87ab4e20 RDC |
52 | void __user *buffer, |
53 | size_t *lenp, loff_t *ppos) | |
54 | { | |
55 | int ret; | |
56 | int range[2] = {local_port_range[0], local_port_range[1]}; | |
fe2c6338 | 57 | struct ctl_table tmp = { |
87ab4e20 RDC |
58 | .data = &range, |
59 | .maxlen = sizeof(range), | |
60 | .mode = table->mode, | |
61 | .extra1 = &local_port_range_min, | |
62 | .extra2 = &local_port_range_max, | |
63 | }; | |
64 | ||
8d65af78 | 65 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); |
87ab4e20 RDC |
66 | |
67 | if (write && ret == 0) { | |
68 | if (range[1] < range[0]) | |
69 | ret = -EINVAL; | |
70 | else | |
71 | set_local_port_range(range); | |
72 | } | |
73 | ||
74 | return ret; | |
75 | } | |
76 | ||
77 | static struct ctl_table phonet_table[] = { | |
78 | { | |
87ab4e20 RDC |
79 | .procname = "local_port_range", |
80 | .data = &local_port_range, | |
81 | .maxlen = sizeof(local_port_range), | |
82 | .mode = 0644, | |
6d9f239a | 83 | .proc_handler = proc_local_port_range, |
87ab4e20 | 84 | }, |
f8572d8f | 85 | { } |
87ab4e20 RDC |
86 | }; |
87 | ||
87ab4e20 RDC |
88 | int __init phonet_sysctl_init(void) |
89 | { | |
ec8f23ce | 90 | phonet_table_hrd = register_net_sysctl(&init_net, "net/phonet", phonet_table); |
87ab4e20 RDC |
91 | return phonet_table_hrd == NULL ? -ENOMEM : 0; |
92 | } | |
93 | ||
94 | void phonet_sysctl_exit(void) | |
95 | { | |
5dd3df10 | 96 | unregister_net_sysctl_table(phonet_table_hrd); |
87ab4e20 | 97 | } |