blob: 7c6c7c8146db73640b4869d0161bdc3755e5ac49 [file] [log] [blame]
Johannes Berg379f8392008-12-08 12:53:58 +01001#include <stdbool.h>
Johannes Berg0f55e0b2008-09-16 17:40:48 +02002#include <errno.h>
Johannes Berg0f55e0b2008-09-16 17:40:48 +02003#include <net/if.h>
Johannes Bergd0260392010-09-22 11:33:28 +02004#include <strings.h>
Johannes Berg0f55e0b2008-09-16 17:40:48 +02005
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
Johannes Bergf408e012008-09-18 19:32:11 +020012#include "nl80211.h"
Johannes Berg0f55e0b2008-09-16 17:40:48 +020013#include "iw.h"
14
Johannes Berg7c37a242009-04-08 13:13:28 +020015static int handle_name(struct nl80211_state *state,
16 struct nl_cb *cb,
Johannes Berg0f55e0b2008-09-16 17:40:48 +020017 struct nl_msg *msg,
18 int argc, char **argv)
19{
Johannes Berg0f55e0b2008-09-16 17:40:48 +020020 if (argc != 1)
Johannes Berg5e75fd02008-09-16 18:13:12 +020021 return 1;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020022
23 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, *argv);
24
Johannes Berg70391cc2008-09-16 18:35:06 +020025 return 0;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020026 nla_put_failure:
Johannes Berg70391cc2008-09-16 18:35:06 +020027 return -ENOBUFS;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020028}
Johannes Bergcea8fa12009-05-05 15:05:10 +020029COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
30 "Rename this wireless device.");
Johannes Bergb822cda2008-12-08 12:43:42 +010031
Johannes Berg379f8392008-12-08 12:53:58 +010032static int handle_freqchan(struct nl_msg *msg, bool chan,
33 int argc, char **argv)
Johannes Bergb822cda2008-12-08 12:43:42 +010034{
Johannes Berge86b7e02010-04-01 18:49:21 +020035 char *end;
Johannes Bergb822cda2008-12-08 12:43:42 +010036 static const struct {
37 const char *name;
38 unsigned int val;
39 } htmap[] = {
Johannes Berg68632dc2008-12-12 22:40:45 +010040 { .name = "HT20", .val = NL80211_CHAN_HT20, },
41 { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
42 { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
Johannes Bergb822cda2008-12-08 12:43:42 +010043 };
Johannes Berg68632dc2008-12-12 22:40:45 +010044 unsigned int htval = NL80211_CHAN_NO_HT;
Johannes Bergb822cda2008-12-08 12:43:42 +010045 unsigned int freq;
46 int i;
47
48 if (!argc || argc > 2)
49 return 1;
50
51 if (argc == 2) {
Johannes Berg7d736012008-12-08 12:59:16 +010052 for (i = 0; i < ARRAY_SIZE(htmap); i++) {
Johannes Bergb822cda2008-12-08 12:43:42 +010053 if (strcasecmp(htmap[i].name, argv[1]) == 0) {
54 htval = htmap[i].val;
55 break;
56 }
57 }
Johannes Berg68632dc2008-12-12 22:40:45 +010058 if (htval == NL80211_CHAN_NO_HT)
Johannes Bergb822cda2008-12-08 12:43:42 +010059 return 1;
60 }
61
Johannes Berge86b7e02010-04-01 18:49:21 +020062 if (!*argv[0])
63 return 1;
64 freq = strtoul(argv[0], &end, 10);
65 if (*end)
66 return 1;
67
Johannes Berg379f8392008-12-08 12:53:58 +010068 if (chan)
69 freq = ieee80211_channel_to_frequency(freq);
Johannes Bergb822cda2008-12-08 12:43:42 +010070
71 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
Johannes Berg68632dc2008-12-12 22:40:45 +010072 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
Johannes Bergb822cda2008-12-08 12:43:42 +010073
74 return 0;
75 nla_put_failure:
76 return -ENOBUFS;
77}
Johannes Berg379f8392008-12-08 12:53:58 +010078
Johannes Berg7c37a242009-04-08 13:13:28 +020079static int handle_freq(struct nl80211_state *state,
80 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg379f8392008-12-08 12:53:58 +010081 int argc, char **argv)
82{
83 return handle_freqchan(msg, false, argc, argv);
84}
Johannes Bergb822cda2008-12-08 12:43:42 +010085COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
Johannes Berg00c448b2009-05-05 15:04:19 +020086 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
87 "Set frequency/channel the hardware is using, including HT\n"
88 "configuration.");
Johannes Bergb822cda2008-12-08 12:43:42 +010089COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +020090 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
Johannes Berg379f8392008-12-08 12:53:58 +010091
Johannes Berg7c37a242009-04-08 13:13:28 +020092static int handle_chan(struct nl80211_state *state,
93 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg379f8392008-12-08 12:53:58 +010094 int argc, char **argv)
95{
96 return handle_freqchan(msg, true, argc, argv);
97}
98COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +020099 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
Johannes Berg379f8392008-12-08 12:53:58 +0100100COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +0200101 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
Johannes Berg625aa4a2009-08-11 11:26:42 +0200102
103static int handle_fragmentation(struct nl80211_state *state,
104 struct nl_cb *cb, struct nl_msg *msg,
105 int argc, char **argv)
106{
107 unsigned int frag;
108
109 if (argc != 1)
110 return 1;
111
112 if (strcmp("off", argv[0]) == 0)
113 frag = -1;
Johannes Berge86b7e02010-04-01 18:49:21 +0200114 else {
115 char *end;
116
117 if (!*argv[0])
118 return 1;
119 frag = strtoul(argv[0], &end, 10);
120 if (*end != '\0')
121 return 1;
122 }
Johannes Berg625aa4a2009-08-11 11:26:42 +0200123
124 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
125
126 return 0;
127 nla_put_failure:
128 return -ENOBUFS;
129}
130COMMAND(set, frag, "<fragmentation threshold|off>",
131 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
132 "Set fragmentation threshold.");
133
134static int handle_rts(struct nl80211_state *state,
135 struct nl_cb *cb, struct nl_msg *msg,
136 int argc, char **argv)
137{
138 unsigned int rts;
139
140 if (argc != 1)
141 return 1;
142
143 if (strcmp("off", argv[0]) == 0)
144 rts = -1;
Johannes Berge86b7e02010-04-01 18:49:21 +0200145 else {
146 char *end;
147
148 if (!*argv[0])
149 return 1;
150 rts = strtoul(argv[0], &end, 10);
151 if (*end != '\0')
152 return 1;
153 }
Johannes Berg625aa4a2009-08-11 11:26:42 +0200154
155 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
156
157 return 0;
158 nla_put_failure:
159 return -ENOBUFS;
160}
161COMMAND(set, rts, "<rts threshold|off>",
162 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
163 "Set rts threshold.");
Johannes Berge960e062009-09-24 20:18:47 +0200164
165static int handle_netns(struct nl80211_state *state,
166 struct nl_cb *cb,
167 struct nl_msg *msg,
168 int argc, char **argv)
169{
170 char *end;
171
172 if (argc != 1)
173 return 1;
174
Johannes Berge86b7e02010-04-01 18:49:21 +0200175 if (!*argv[0])
176 return 1;
177
Johannes Berge960e062009-09-24 20:18:47 +0200178 NLA_PUT_U32(msg, NL80211_ATTR_PID,
179 strtoul(argv[0], &end, 10));
180
181 if (*end != '\0')
182 return 1;
183
184 return 0;
185 nla_put_failure:
186 return -ENOBUFS;
187}
188COMMAND(set, netns, "<pid>",
189 NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
190 "Put this wireless device into a different network namespace");
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500191
192static int handle_coverage(struct nl80211_state *state,
193 struct nl_cb *cb,
194 struct nl_msg *msg,
195 int argc, char **argv)
196{
Johannes Berge86b7e02010-04-01 18:49:21 +0200197 char *end;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500198 unsigned int coverage;
199
200 if (argc != 1)
201 return 1;
202
Johannes Berge86b7e02010-04-01 18:49:21 +0200203 if (!*argv[0])
204 return 1;
205 coverage = strtoul(argv[0], &end, 10);
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500206 if (coverage > 255)
207 return 1;
208
Johannes Berge86b7e02010-04-01 18:49:21 +0200209 if (*end)
210 return 1;
211
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500212 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
213
214 return 0;
215 nla_put_failure:
216 return -ENOBUFS;
217}
218COMMAND(set, coverage, "<coverage class>",
219 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_coverage,
220 "Set coverage class (1 for every 3 usec of air propagation time).\n"
221 "Valid values: 0 - 255.");
222
223static int handle_distance(struct nl80211_state *state,
224 struct nl_cb *cb,
225 struct nl_msg *msg,
226 int argc, char **argv)
227{
Johannes Berge86b7e02010-04-01 18:49:21 +0200228 char *end;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500229 unsigned int distance, coverage;
230
231 if (argc != 1)
232 return 1;
233
Johannes Berge86b7e02010-04-01 18:49:21 +0200234 if (!*argv[0])
235 return 1;
236
237 distance = strtoul(argv[0], &end, 10);
238
239 if (*end)
240 return 1;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500241
242 /*
243 * Divide double the distance by the speed of light in m/usec (300) to
244 * get round-trip time in microseconds and then divide the result by
245 * three to get coverage class as specified in IEEE 802.11-2007 table
246 * 7-27. Values are rounded upwards.
247 */
248 coverage = (distance + 449) / 450;
249 if (coverage > 255)
250 return 1;
251
252 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
253
254 return 0;
255 nla_put_failure:
256 return -ENOBUFS;
257}
258COMMAND(set, distance, "<distance>",
259 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
260 "Set appropriate coverage class for given link distance in meters.\n"
261 "Valid values: 0 - 114750");
Juuso Oikarinena0b1f572010-06-23 12:12:57 +0300262
263static int handle_txpower(struct nl80211_state *state,
264 struct nl_cb *cb,
265 struct nl_msg *msg,
266 int argc, char **argv)
267{
268 enum nl80211_tx_power_setting type;
269 int mbm;
270
271 /* get the required args */
272 if (argc != 1 && argc != 2)
273 return 1;
274
275 if (!strcmp(argv[0], "auto"))
276 type = NL80211_TX_POWER_AUTOMATIC;
277 else if (!strcmp(argv[0], "fixed"))
278 type = NL80211_TX_POWER_FIXED;
279 else if (!strcmp(argv[0], "limit"))
280 type = NL80211_TX_POWER_LIMITED;
281 else {
282 printf("Invalid parameter: %s\n", argv[0]);
283 return 2;
284 }
285
286 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, type);
287
288 if (type != NL80211_TX_POWER_AUTOMATIC) {
289 if (argc != 2) {
290 printf("Missing TX power level argument.\n");
291 return 2;
292 }
293
294 mbm = atoi(argv[1]);
295 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
296 } else if (argc != 1)
297 return 1;
298
299 return 0;
300
301 nla_put_failure:
302 return -ENOBUFS;
303}
304COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
305 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txpower,
306 "Specify transmit power level and setting type.");
307COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
308 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txpower,
309 "Specify transmit power level and setting type.");