]> git.ipfire.org Git - thirdparty/iw.git/blob - phy.c
add P2P Device handling primitives
[thirdparty/iw.git] / phy.c
1 #include <stdbool.h>
2 #include <errno.h>
3 #include <net/if.h>
4 #include <strings.h>
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
12 #include "nl80211.h"
13 #include "iw.h"
14
15 static int handle_name(struct nl80211_state *state,
16 struct nl_cb *cb,
17 struct nl_msg *msg,
18 int argc, char **argv,
19 enum id_input id)
20 {
21 if (argc != 1)
22 return 1;
23
24 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, *argv);
25
26 return 0;
27 nla_put_failure:
28 return -ENOBUFS;
29 }
30 COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
31 "Rename this wireless device.");
32
33 static int handle_freqchan(struct nl_msg *msg, bool chan,
34 int argc, char **argv)
35 {
36 char *end;
37 static const struct {
38 const char *name;
39 unsigned int val;
40 } htmap[] = {
41 { .name = "HT20", .val = NL80211_CHAN_HT20, },
42 { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
43 { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
44 };
45 unsigned int htval = NL80211_CHAN_NO_HT;
46 unsigned int freq;
47 int i;
48
49 if (!argc || argc > 2)
50 return 1;
51
52 if (argc == 2) {
53 for (i = 0; i < ARRAY_SIZE(htmap); i++) {
54 if (strcasecmp(htmap[i].name, argv[1]) == 0) {
55 htval = htmap[i].val;
56 break;
57 }
58 }
59 if (htval == NL80211_CHAN_NO_HT)
60 return 1;
61 }
62
63 if (!*argv[0])
64 return 1;
65 freq = strtoul(argv[0], &end, 10);
66 if (*end)
67 return 1;
68
69 if (chan)
70 freq = ieee80211_channel_to_frequency(freq);
71
72 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
73 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
74
75 return 0;
76 nla_put_failure:
77 return -ENOBUFS;
78 }
79
80 static int handle_freq(struct nl80211_state *state,
81 struct nl_cb *cb, struct nl_msg *msg,
82 int argc, char **argv,
83 enum id_input id)
84 {
85 return handle_freqchan(msg, false, argc, argv);
86 }
87 COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
88 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
89 "Set frequency/channel the hardware is using, including HT\n"
90 "configuration.");
91 COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
92 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
93
94 static int handle_chan(struct nl80211_state *state,
95 struct nl_cb *cb, struct nl_msg *msg,
96 int argc, char **argv,
97 enum id_input id)
98 {
99 return handle_freqchan(msg, true, argc, argv);
100 }
101 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
102 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
103 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
104 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
105
106 static int handle_fragmentation(struct nl80211_state *state,
107 struct nl_cb *cb, struct nl_msg *msg,
108 int argc, char **argv,
109 enum id_input id)
110 {
111 unsigned int frag;
112
113 if (argc != 1)
114 return 1;
115
116 if (strcmp("off", argv[0]) == 0)
117 frag = -1;
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 }
127
128 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
129
130 return 0;
131 nla_put_failure:
132 return -ENOBUFS;
133 }
134 COMMAND(set, frag, "<fragmentation threshold|off>",
135 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
136 "Set fragmentation threshold.");
137
138 static int handle_rts(struct nl80211_state *state,
139 struct nl_cb *cb, struct nl_msg *msg,
140 int argc, char **argv,
141 enum id_input id)
142 {
143 unsigned int rts;
144
145 if (argc != 1)
146 return 1;
147
148 if (strcmp("off", argv[0]) == 0)
149 rts = -1;
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 }
159
160 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
161
162 return 0;
163 nla_put_failure:
164 return -ENOBUFS;
165 }
166 COMMAND(set, rts, "<rts threshold|off>",
167 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
168 "Set rts threshold.");
169
170 static int handle_netns(struct nl80211_state *state,
171 struct nl_cb *cb,
172 struct nl_msg *msg,
173 int argc, char **argv,
174 enum id_input id)
175 {
176 char *end;
177
178 if (argc != 1)
179 return 1;
180
181 if (!*argv[0])
182 return 1;
183
184 NLA_PUT_U32(msg, NL80211_ATTR_PID,
185 strtoul(argv[0], &end, 10));
186
187 if (*end != '\0')
188 return 1;
189
190 return 0;
191 nla_put_failure:
192 return -ENOBUFS;
193 }
194 COMMAND(set, netns, "<pid>",
195 NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
196 "Put this wireless device into a different network namespace");
197
198 static int handle_coverage(struct nl80211_state *state,
199 struct nl_cb *cb,
200 struct nl_msg *msg,
201 int argc, char **argv,
202 enum id_input id)
203 {
204 char *end;
205 unsigned int coverage;
206
207 if (argc != 1)
208 return 1;
209
210 if (!*argv[0])
211 return 1;
212 coverage = strtoul(argv[0], &end, 10);
213 if (coverage > 255)
214 return 1;
215
216 if (*end)
217 return 1;
218
219 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
220
221 return 0;
222 nla_put_failure:
223 return -ENOBUFS;
224 }
225 COMMAND(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
230 static int handle_distance(struct nl80211_state *state,
231 struct nl_cb *cb,
232 struct nl_msg *msg,
233 int argc, char **argv,
234 enum id_input id)
235 {
236 char *end;
237 unsigned int distance, coverage;
238
239 if (argc != 1)
240 return 1;
241
242 if (!*argv[0])
243 return 1;
244
245 distance = strtoul(argv[0], &end, 10);
246
247 if (*end)
248 return 1;
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 }
266 COMMAND(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");
270
271 static int handle_txpower(struct nl80211_state *state,
272 struct nl_cb *cb,
273 struct nl_msg *msg,
274 int argc, char **argv,
275 enum id_input id)
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) {
298 char *endptr;
299 if (argc != 2) {
300 printf("Missing TX power level argument.\n");
301 return 2;
302 }
303
304 mbm = strtol(argv[1], &endptr, 10);
305 if (*endptr)
306 return 2;
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 }
316 COMMAND(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.");
319 COMMAND(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.");
322
323 static int handle_antenna(struct nl80211_state *state,
324 struct nl_cb *cb,
325 struct nl_msg *msg,
326 int argc, char **argv,
327 enum id_input id)
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 }
358 COMMAND(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.");