]> git.ipfire.org Git - thirdparty/iw.git/blob - phy.c
iw: Add support for NL80211_ATTR_WIPHY_COVERAGE_CLASS
[thirdparty/iw.git] / phy.c
1 #include <stdbool.h>
2 #include <errno.h>
3 #include <net/if.h>
4
5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <netlink/msg.h>
9 #include <netlink/attr.h>
10
11 #include "nl80211.h"
12 #include "iw.h"
13
14 static int handle_name(struct nl80211_state *state,
15 struct nl_cb *cb,
16 struct nl_msg *msg,
17 int argc, char **argv)
18 {
19 if (argc != 1)
20 return 1;
21
22 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, *argv);
23
24 return 0;
25 nla_put_failure:
26 return -ENOBUFS;
27 }
28 COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
29 "Rename this wireless device.");
30
31 static int handle_freqchan(struct nl_msg *msg, bool chan,
32 int argc, char **argv)
33 {
34 static const struct {
35 const char *name;
36 unsigned int val;
37 } htmap[] = {
38 { .name = "HT20", .val = NL80211_CHAN_HT20, },
39 { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
40 { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
41 };
42 unsigned int htval = NL80211_CHAN_NO_HT;
43 unsigned int freq;
44 int i;
45
46 if (!argc || argc > 2)
47 return 1;
48
49 if (argc == 2) {
50 for (i = 0; i < ARRAY_SIZE(htmap); i++) {
51 if (strcasecmp(htmap[i].name, argv[1]) == 0) {
52 htval = htmap[i].val;
53 break;
54 }
55 }
56 if (htval == NL80211_CHAN_NO_HT)
57 return 1;
58 }
59
60 freq = strtoul(argv[0], NULL, 10);
61 if (chan)
62 freq = ieee80211_channel_to_frequency(freq);
63
64 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
65 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
66
67 return 0;
68 nla_put_failure:
69 return -ENOBUFS;
70 }
71
72 static int handle_freq(struct nl80211_state *state,
73 struct nl_cb *cb, struct nl_msg *msg,
74 int argc, char **argv)
75 {
76 return handle_freqchan(msg, false, argc, argv);
77 }
78 COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
79 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
80 "Set frequency/channel the hardware is using, including HT\n"
81 "configuration.");
82 COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
83 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
84
85 static int handle_chan(struct nl80211_state *state,
86 struct nl_cb *cb, struct nl_msg *msg,
87 int argc, char **argv)
88 {
89 return handle_freqchan(msg, true, argc, argv);
90 }
91 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
92 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
93 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
94 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
95
96 static int handle_fragmentation(struct nl80211_state *state,
97 struct nl_cb *cb, struct nl_msg *msg,
98 int argc, char **argv)
99 {
100 unsigned int frag;
101
102 if (argc != 1)
103 return 1;
104
105 if (strcmp("off", argv[0]) == 0)
106 frag = -1;
107 else
108 frag = strtoul(argv[0], NULL, 10);
109
110 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
111
112 return 0;
113 nla_put_failure:
114 return -ENOBUFS;
115 }
116 COMMAND(set, frag, "<fragmentation threshold|off>",
117 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
118 "Set fragmentation threshold.");
119
120 static int handle_rts(struct nl80211_state *state,
121 struct nl_cb *cb, struct nl_msg *msg,
122 int argc, char **argv)
123 {
124 unsigned int rts;
125
126 if (argc != 1)
127 return 1;
128
129 if (strcmp("off", argv[0]) == 0)
130 rts = -1;
131 else
132 rts = strtoul(argv[0], NULL, 10);
133
134 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
135
136 return 0;
137 nla_put_failure:
138 return -ENOBUFS;
139 }
140 COMMAND(set, rts, "<rts threshold|off>",
141 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
142 "Set rts threshold.");
143
144 static int handle_netns(struct nl80211_state *state,
145 struct nl_cb *cb,
146 struct nl_msg *msg,
147 int argc, char **argv)
148 {
149 char *end;
150
151 if (argc != 1)
152 return 1;
153
154 NLA_PUT_U32(msg, NL80211_ATTR_PID,
155 strtoul(argv[0], &end, 10));
156
157 if (*end != '\0')
158 return 1;
159
160 return 0;
161 nla_put_failure:
162 return -ENOBUFS;
163 }
164 COMMAND(set, netns, "<pid>",
165 NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
166 "Put this wireless device into a different network namespace");
167
168 static int handle_coverage(struct nl80211_state *state,
169 struct nl_cb *cb,
170 struct nl_msg *msg,
171 int argc, char **argv)
172 {
173 unsigned int coverage;
174
175 if (argc != 1)
176 return 1;
177
178 coverage = strtoul(argv[0], NULL, 10);
179 if (coverage > 255)
180 return 1;
181
182 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
183
184 return 0;
185 nla_put_failure:
186 return -ENOBUFS;
187 }
188 COMMAND(set, coverage, "<coverage class>",
189 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_coverage,
190 "Set coverage class (1 for every 3 usec of air propagation time).\n"
191 "Valid values: 0 - 255.");
192
193 static int handle_distance(struct nl80211_state *state,
194 struct nl_cb *cb,
195 struct nl_msg *msg,
196 int argc, char **argv)
197 {
198 unsigned int distance, coverage;
199
200 if (argc != 1)
201 return 1;
202
203 distance = strtoul(argv[0], NULL, 10);
204
205 /*
206 * Divide double the distance by the speed of light in m/usec (300) to
207 * get round-trip time in microseconds and then divide the result by
208 * three to get coverage class as specified in IEEE 802.11-2007 table
209 * 7-27. Values are rounded upwards.
210 */
211 coverage = (distance + 449) / 450;
212 if (coverage > 255)
213 return 1;
214
215 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
216
217 return 0;
218 nla_put_failure:
219 return -ENOBUFS;
220 }
221 COMMAND(set, distance, "<distance>",
222 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
223 "Set appropriate coverage class for given link distance in meters.\n"
224 "Valid values: 0 - 114750");