]> git.ipfire.org Git - thirdparty/iw.git/blame - phy.c
add P2P Device handling primitives
[thirdparty/iw.git] / phy.c
CommitLineData
379f8397 1#include <stdbool.h>
0f55e0b8 2#include <errno.h>
0f55e0b8 3#include <net/if.h>
d0260390 4#include <strings.h>
0f55e0b8
JB
5
6#include <netlink/genl/genl.h>
7#include <netlink/genl/family.h>
8#include <netlink/genl/ctrl.h>
9#include <netlink/msg.h>
10#include <netlink/attr.h>
11
f408e01b 12#include "nl80211.h"
0f55e0b8
JB
13#include "iw.h"
14
7c37a24d
JB
15static int handle_name(struct nl80211_state *state,
16 struct nl_cb *cb,
0f55e0b8 17 struct nl_msg *msg,
05514f95
JB
18 int argc, char **argv,
19 enum id_input id)
0f55e0b8 20{
0f55e0b8 21 if (argc != 1)
5e75fd04 22 return 1;
0f55e0b8
JB
23
24 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, *argv);
25
70391ccf 26 return 0;
0f55e0b8 27 nla_put_failure:
70391ccf 28 return -ENOBUFS;
0f55e0b8 29}
cea8fa1c
JB
30COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
31 "Rename this wireless device.");
b822cda9 32
379f8397
JB
33static int handle_freqchan(struct nl_msg *msg, bool chan,
34 int argc, char **argv)
b822cda9 35{
e86b7e02 36 char *end;
b822cda9
JB
37 static const struct {
38 const char *name;
39 unsigned int val;
40 } htmap[] = {
68632dc7
JB
41 { .name = "HT20", .val = NL80211_CHAN_HT20, },
42 { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
43 { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
b822cda9 44 };
68632dc7 45 unsigned int htval = NL80211_CHAN_NO_HT;
b822cda9
JB
46 unsigned int freq;
47 int i;
48
49 if (!argc || argc > 2)
50 return 1;
51
52 if (argc == 2) {
7d736016 53 for (i = 0; i < ARRAY_SIZE(htmap); i++) {
b822cda9
JB
54 if (strcasecmp(htmap[i].name, argv[1]) == 0) {
55 htval = htmap[i].val;
56 break;
57 }
58 }
68632dc7 59 if (htval == NL80211_CHAN_NO_HT)
b822cda9
JB
60 return 1;
61 }
62
e86b7e02
JB
63 if (!*argv[0])
64 return 1;
65 freq = strtoul(argv[0], &end, 10);
66 if (*end)
67 return 1;
68
379f8397
JB
69 if (chan)
70 freq = ieee80211_channel_to_frequency(freq);
b822cda9
JB
71
72 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
68632dc7 73 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
b822cda9
JB
74
75 return 0;
76 nla_put_failure:
77 return -ENOBUFS;
78}
379f8397 79
7c37a24d
JB
80static int handle_freq(struct nl80211_state *state,
81 struct nl_cb *cb, struct nl_msg *msg,
05514f95
JB
82 int argc, char **argv,
83 enum id_input id)
379f8397
JB
84{
85 return handle_freqchan(msg, false, argc, argv);
86}
b822cda9 87COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
00c448b2
JB
88 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
89 "Set frequency/channel the hardware is using, including HT\n"
90 "configuration.");
b822cda9 91COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
01ae06f9 92 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
379f8397 93
7c37a24d
JB
94static int handle_chan(struct nl80211_state *state,
95 struct nl_cb *cb, struct nl_msg *msg,
05514f95
JB
96 int argc, char **argv,
97 enum id_input id)
379f8397
JB
98{
99 return handle_freqchan(msg, true, argc, argv);
100}
101COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
01ae06f9 102 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
379f8397 103COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
01ae06f9 104 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
625aa4ae
JB
105
106static int handle_fragmentation(struct nl80211_state *state,
107 struct nl_cb *cb, struct nl_msg *msg,
05514f95
JB
108 int argc, char **argv,
109 enum id_input id)
625aa4ae
JB
110{
111 unsigned int frag;
112
113 if (argc != 1)
114 return 1;
115
116 if (strcmp("off", argv[0]) == 0)
117 frag = -1;
e86b7e02
JB
118 else {
119 char *end;
120
121 if (!*argv[0])
122 return 1;
123 frag = strtoul(argv[0], &end, 10);
124 if (*end != '\0')
125 return 1;
126 }
625aa4ae
JB
127
128 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
129
130 return 0;
131 nla_put_failure:
132 return -ENOBUFS;
133}
134COMMAND(set, frag, "<fragmentation threshold|off>",
135 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
136 "Set fragmentation threshold.");
137
138static int handle_rts(struct nl80211_state *state,
139 struct nl_cb *cb, struct nl_msg *msg,
05514f95
JB
140 int argc, char **argv,
141 enum id_input id)
625aa4ae
JB
142{
143 unsigned int rts;
144
145 if (argc != 1)
146 return 1;
147
148 if (strcmp("off", argv[0]) == 0)
149 rts = -1;
e86b7e02
JB
150 else {
151 char *end;
152
153 if (!*argv[0])
154 return 1;
155 rts = strtoul(argv[0], &end, 10);
156 if (*end != '\0')
157 return 1;
158 }
625aa4ae
JB
159
160 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
161
162 return 0;
163 nla_put_failure:
164 return -ENOBUFS;
165}
166COMMAND(set, rts, "<rts threshold|off>",
167 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
168 "Set rts threshold.");
e960e066
JB
169
170static int handle_netns(struct nl80211_state *state,
171 struct nl_cb *cb,
172 struct nl_msg *msg,
05514f95
JB
173 int argc, char **argv,
174 enum id_input id)
e960e066
JB
175{
176 char *end;
177
178 if (argc != 1)
179 return 1;
180
e86b7e02
JB
181 if (!*argv[0])
182 return 1;
183
e960e066 184 NLA_PUT_U32(msg, NL80211_ATTR_PID,
c551449a 185 strtoul(argv[0], &end, 10));
e960e066
JB
186
187 if (*end != '\0')
188 return 1;
189
190 return 0;
191 nla_put_failure:
192 return -ENOBUFS;
193}
194COMMAND(set, netns, "<pid>",
195 NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
196 "Put this wireless device into a different network namespace");
b2f92dd0
LT
197
198static int handle_coverage(struct nl80211_state *state,
199 struct nl_cb *cb,
200 struct nl_msg *msg,
05514f95
JB
201 int argc, char **argv,
202 enum id_input id)
b2f92dd0 203{
e86b7e02 204 char *end;
b2f92dd0
LT
205 unsigned int coverage;
206
207 if (argc != 1)
208 return 1;
209
e86b7e02
JB
210 if (!*argv[0])
211 return 1;
212 coverage = strtoul(argv[0], &end, 10);
b2f92dd0
LT
213 if (coverage > 255)
214 return 1;
215
e86b7e02
JB
216 if (*end)
217 return 1;
218
b2f92dd0
LT
219 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
220
221 return 0;
222 nla_put_failure:
223 return -ENOBUFS;
224}
225COMMAND(set, coverage, "<coverage class>",
226 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_coverage,
227 "Set coverage class (1 for every 3 usec of air propagation time).\n"
228 "Valid values: 0 - 255.");
229
230static int handle_distance(struct nl80211_state *state,
231 struct nl_cb *cb,
232 struct nl_msg *msg,
05514f95
JB
233 int argc, char **argv,
234 enum id_input id)
b2f92dd0 235{
e86b7e02 236 char *end;
b2f92dd0
LT
237 unsigned int distance, coverage;
238
239 if (argc != 1)
240 return 1;
241
e86b7e02
JB
242 if (!*argv[0])
243 return 1;
244
245 distance = strtoul(argv[0], &end, 10);
246
247 if (*end)
248 return 1;
b2f92dd0
LT
249
250 /*
251 * Divide double the distance by the speed of light in m/usec (300) to
252 * get round-trip time in microseconds and then divide the result by
253 * three to get coverage class as specified in IEEE 802.11-2007 table
254 * 7-27. Values are rounded upwards.
255 */
256 coverage = (distance + 449) / 450;
257 if (coverage > 255)
258 return 1;
259
260 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
261
262 return 0;
263 nla_put_failure:
264 return -ENOBUFS;
265}
266COMMAND(set, distance, "<distance>",
267 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
268 "Set appropriate coverage class for given link distance in meters.\n"
269 "Valid values: 0 - 114750");
a0b1f574
JO
270
271static int handle_txpower(struct nl80211_state *state,
272 struct nl_cb *cb,
273 struct nl_msg *msg,
05514f95
JB
274 int argc, char **argv,
275 enum id_input id)
a0b1f574
JO
276{
277 enum nl80211_tx_power_setting type;
278 int mbm;
279
280 /* get the required args */
281 if (argc != 1 && argc != 2)
282 return 1;
283
284 if (!strcmp(argv[0], "auto"))
285 type = NL80211_TX_POWER_AUTOMATIC;
286 else if (!strcmp(argv[0], "fixed"))
287 type = NL80211_TX_POWER_FIXED;
288 else if (!strcmp(argv[0], "limit"))
289 type = NL80211_TX_POWER_LIMITED;
290 else {
291 printf("Invalid parameter: %s\n", argv[0]);
292 return 2;
293 }
294
295 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, type);
296
297 if (type != NL80211_TX_POWER_AUTOMATIC) {
18e05613 298 char *endptr;
a0b1f574
JO
299 if (argc != 2) {
300 printf("Missing TX power level argument.\n");
301 return 2;
302 }
303
18e05613 304 mbm = strtol(argv[1], &endptr, 10);
08ec4c6b 305 if (*endptr)
18e05613 306 return 2;
a0b1f574
JO
307 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
308 } else if (argc != 1)
309 return 1;
310
311 return 0;
312
313 nla_put_failure:
314 return -ENOBUFS;
315}
316COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
317 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txpower,
318 "Specify transmit power level and setting type.");
319COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
320 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txpower,
321 "Specify transmit power level and setting type.");
afce7986
BR
322
323static int handle_antenna(struct nl80211_state *state,
324 struct nl_cb *cb,
325 struct nl_msg *msg,
05514f95
JB
326 int argc, char **argv,
327 enum id_input id)
afce7986
BR
328{
329 char *end;
330 uint32_t tx_ant = 0, rx_ant = 0;
331
332 if (argc == 1 && strcmp(argv[0], "all") == 0) {
333 tx_ant = 0xffffffff;
334 rx_ant = 0xffffffff;
335 } else if (argc == 1) {
336 tx_ant = rx_ant = strtoul(argv[0], &end, 0);
337 if (*end)
338 return 1;
339 }
340 else if (argc == 2) {
341 tx_ant = strtoul(argv[0], &end, 0);
342 if (*end)
343 return 1;
344 rx_ant = strtoul(argv[1], &end, 0);
345 if (*end)
346 return 1;
347 } else
348 return 1;
349
350 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant);
351 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant);
352
353 return 0;
354
355 nla_put_failure:
356 return -ENOBUFS;
357}
358COMMAND(set, antenna, "<bitmap> | all | <tx bitmap> <rx bitmap>",
359 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna,
360 "Set a bitmap of allowed antennas to use for TX and RX.\n"
361 "The driver may reject antenna configurations it cannot support.");