]>
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, |
32927393 | 52 | void *buffer, size_t *lenp, loff_t *ppos) |
87ab4e20 RDC |
53 | { |
54 | int ret; | |
55 | int range[2] = {local_port_range[0], local_port_range[1]}; | |
fe2c6338 | 56 | struct ctl_table tmp = { |
87ab4e20 RDC |
57 | .data = &range, |
58 | .maxlen = sizeof(range), | |
59 | .mode = table->mode, | |
60 | .extra1 = &local_port_range_min, | |
61 | .extra2 = &local_port_range_max, | |
62 | }; | |
63 | ||
8d65af78 | 64 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); |
87ab4e20 RDC |
65 | |
66 | if (write && ret == 0) { | |
67 | if (range[1] < range[0]) | |
68 | ret = -EINVAL; | |
69 | else | |
70 | set_local_port_range(range); | |
71 | } | |
72 | ||
73 | return ret; | |
74 | } | |
75 | ||
76 | static struct ctl_table phonet_table[] = { | |
77 | { | |
87ab4e20 RDC |
78 | .procname = "local_port_range", |
79 | .data = &local_port_range, | |
80 | .maxlen = sizeof(local_port_range), | |
81 | .mode = 0644, | |
6d9f239a | 82 | .proc_handler = proc_local_port_range, |
87ab4e20 | 83 | }, |
f8572d8f | 84 | { } |
87ab4e20 RDC |
85 | }; |
86 | ||
87ab4e20 RDC |
87 | int __init phonet_sysctl_init(void) |
88 | { | |
ec8f23ce | 89 | phonet_table_hrd = register_net_sysctl(&init_net, "net/phonet", phonet_table); |
87ab4e20 RDC |
90 | return phonet_table_hrd == NULL ? -ENOMEM : 0; |
91 | } | |
92 | ||
93 | void phonet_sysctl_exit(void) | |
94 | { | |
5dd3df10 | 95 | unregister_net_sysctl_table(phonet_table_hrd); |
87ab4e20 | 96 | } |