blob: 1f54ba3aec2545de14c7d3fdd1cb4b1070445525 [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>
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
Johannes Bergf408e012008-09-18 19:32:11 +020011#include "nl80211.h"
Johannes Berg0f55e0b2008-09-16 17:40:48 +020012#include "iw.h"
13
Johannes Berg7c37a242009-04-08 13:13:28 +020014static int handle_name(struct nl80211_state *state,
15 struct nl_cb *cb,
Johannes Berg0f55e0b2008-09-16 17:40:48 +020016 struct nl_msg *msg,
17 int argc, char **argv)
18{
Johannes Berg0f55e0b2008-09-16 17:40:48 +020019 if (argc != 1)
Johannes Berg5e75fd02008-09-16 18:13:12 +020020 return 1;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020021
22 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, *argv);
23
Johannes Berg70391cc2008-09-16 18:35:06 +020024 return 0;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020025 nla_put_failure:
Johannes Berg70391cc2008-09-16 18:35:06 +020026 return -ENOBUFS;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020027}
Johannes Bergcea8fa12009-05-05 15:05:10 +020028COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
29 "Rename this wireless device.");
Johannes Bergb822cda2008-12-08 12:43:42 +010030
Johannes Berg379f8392008-12-08 12:53:58 +010031static int handle_freqchan(struct nl_msg *msg, bool chan,
32 int argc, char **argv)
Johannes Bergb822cda2008-12-08 12:43:42 +010033{
Johannes Berge86b7e02010-04-01 18:49:21 +020034 char *end;
Johannes Bergb822cda2008-12-08 12:43:42 +010035 static const struct {
36 const char *name;
37 unsigned int val;
38 } htmap[] = {
Johannes Berg68632dc2008-12-12 22:40:45 +010039 { .name = "HT20", .val = NL80211_CHAN_HT20, },
40 { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
41 { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
Johannes Bergb822cda2008-12-08 12:43:42 +010042 };
Johannes Berg68632dc2008-12-12 22:40:45 +010043 unsigned int htval = NL80211_CHAN_NO_HT;
Johannes Bergb822cda2008-12-08 12:43:42 +010044 unsigned int freq;
45 int i;
46
47 if (!argc || argc > 2)
48 return 1;
49
50 if (argc == 2) {
Johannes Berg7d736012008-12-08 12:59:16 +010051 for (i = 0; i < ARRAY_SIZE(htmap); i++) {
Johannes Bergb822cda2008-12-08 12:43:42 +010052 if (strcasecmp(htmap[i].name, argv[1]) == 0) {
53 htval = htmap[i].val;
54 break;
55 }
56 }
Johannes Berg68632dc2008-12-12 22:40:45 +010057 if (htval == NL80211_CHAN_NO_HT)
Johannes Bergb822cda2008-12-08 12:43:42 +010058 return 1;
59 }
60
Johannes Berge86b7e02010-04-01 18:49:21 +020061 if (!*argv[0])
62 return 1;
63 freq = strtoul(argv[0], &end, 10);
64 if (*end)
65 return 1;
66
Johannes Berg379f8392008-12-08 12:53:58 +010067 if (chan)
68 freq = ieee80211_channel_to_frequency(freq);
Johannes Bergb822cda2008-12-08 12:43:42 +010069
70 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
Johannes Berg68632dc2008-12-12 22:40:45 +010071 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
Johannes Bergb822cda2008-12-08 12:43:42 +010072
73 return 0;
74 nla_put_failure:
75 return -ENOBUFS;
76}
Johannes Berg379f8392008-12-08 12:53:58 +010077
Johannes Berg7c37a242009-04-08 13:13:28 +020078static int handle_freq(struct nl80211_state *state,
79 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg379f8392008-12-08 12:53:58 +010080 int argc, char **argv)
81{
82 return handle_freqchan(msg, false, argc, argv);
83}
Johannes Bergb822cda2008-12-08 12:43:42 +010084COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
Johannes Berg00c448b2009-05-05 15:04:19 +020085 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
86 "Set frequency/channel the hardware is using, including HT\n"
87 "configuration.");
Johannes Bergb822cda2008-12-08 12:43:42 +010088COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +020089 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
Johannes Berg379f8392008-12-08 12:53:58 +010090
Johannes Berg7c37a242009-04-08 13:13:28 +020091static int handle_chan(struct nl80211_state *state,
92 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg379f8392008-12-08 12:53:58 +010093 int argc, char **argv)
94{
95 return handle_freqchan(msg, true, argc, argv);
96}
97COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +020098 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
Johannes Berg379f8392008-12-08 12:53:58 +010099COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +0200100 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
Johannes Berg625aa4a2009-08-11 11:26:42 +0200101
102static int handle_fragmentation(struct nl80211_state *state,
103 struct nl_cb *cb, struct nl_msg *msg,
104 int argc, char **argv)
105{
106 unsigned int frag;
107
108 if (argc != 1)
109 return 1;
110
111 if (strcmp("off", argv[0]) == 0)
112 frag = -1;
Johannes Berge86b7e02010-04-01 18:49:21 +0200113 else {
114 char *end;
115
116 if (!*argv[0])
117 return 1;
118 frag = strtoul(argv[0], &end, 10);
119 if (*end != '\0')
120 return 1;
121 }
Johannes Berg625aa4a2009-08-11 11:26:42 +0200122
123 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
124
125 return 0;
126 nla_put_failure:
127 return -ENOBUFS;
128}
129COMMAND(set, frag, "<fragmentation threshold|off>",
130 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
131 "Set fragmentation threshold.");
132
133static int handle_rts(struct nl80211_state *state,
134 struct nl_cb *cb, struct nl_msg *msg,
135 int argc, char **argv)
136{
137 unsigned int rts;
138
139 if (argc != 1)
140 return 1;
141
142 if (strcmp("off", argv[0]) == 0)
143 rts = -1;
Johannes Berge86b7e02010-04-01 18:49:21 +0200144 else {
145 char *end;
146
147 if (!*argv[0])
148 return 1;
149 rts = strtoul(argv[0], &end, 10);
150 if (*end != '\0')
151 return 1;
152 }
Johannes Berg625aa4a2009-08-11 11:26:42 +0200153
154 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
155
156 return 0;
157 nla_put_failure:
158 return -ENOBUFS;
159}
160COMMAND(set, rts, "<rts threshold|off>",
161 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
162 "Set rts threshold.");
Johannes Berge960e062009-09-24 20:18:47 +0200163
164static int handle_netns(struct nl80211_state *state,
165 struct nl_cb *cb,
166 struct nl_msg *msg,
167 int argc, char **argv)
168{
169 char *end;
170
171 if (argc != 1)
172 return 1;
173
Johannes Berge86b7e02010-04-01 18:49:21 +0200174 if (!*argv[0])
175 return 1;
176
Johannes Berge960e062009-09-24 20:18:47 +0200177 NLA_PUT_U32(msg, NL80211_ATTR_PID,
178 strtoul(argv[0], &end, 10));
179
180 if (*end != '\0')
181 return 1;
182
183 return 0;
184 nla_put_failure:
185 return -ENOBUFS;
186}
187COMMAND(set, netns, "<pid>",
188 NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
189 "Put this wireless device into a different network namespace");
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500190
191static int handle_coverage(struct nl80211_state *state,
192 struct nl_cb *cb,
193 struct nl_msg *msg,
194 int argc, char **argv)
195{
Johannes Berge86b7e02010-04-01 18:49:21 +0200196 char *end;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500197 unsigned int coverage;
198
199 if (argc != 1)
200 return 1;
201
Johannes Berge86b7e02010-04-01 18:49:21 +0200202 if (!*argv[0])
203 return 1;
204 coverage = strtoul(argv[0], &end, 10);
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500205 if (coverage > 255)
206 return 1;
207
Johannes Berge86b7e02010-04-01 18:49:21 +0200208 if (*end)
209 return 1;
210
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500211 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
212
213 return 0;
214 nla_put_failure:
215 return -ENOBUFS;
216}
217COMMAND(set, coverage, "<coverage class>",
218 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_coverage,
219 "Set coverage class (1 for every 3 usec of air propagation time).\n"
220 "Valid values: 0 - 255.");
221
222static int handle_distance(struct nl80211_state *state,
223 struct nl_cb *cb,
224 struct nl_msg *msg,
225 int argc, char **argv)
226{
Johannes Berge86b7e02010-04-01 18:49:21 +0200227 char *end;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500228 unsigned int distance, coverage;
229
230 if (argc != 1)
231 return 1;
232
Johannes Berge86b7e02010-04-01 18:49:21 +0200233 if (!*argv[0])
234 return 1;
235
236 distance = strtoul(argv[0], &end, 10);
237
238 if (*end)
239 return 1;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500240
241 /*
242 * Divide double the distance by the speed of light in m/usec (300) to
243 * get round-trip time in microseconds and then divide the result by
244 * three to get coverage class as specified in IEEE 802.11-2007 table
245 * 7-27. Values are rounded upwards.
246 */
247 coverage = (distance + 449) / 450;
248 if (coverage > 255)
249 return 1;
250
251 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
252
253 return 0;
254 nla_put_failure:
255 return -ENOBUFS;
256}
257COMMAND(set, distance, "<distance>",
258 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
259 "Set appropriate coverage class for given link distance in meters.\n"
260 "Valid values: 0 - 114750");
Juuso Oikarinena0b1f572010-06-23 12:12:57 +0300261
262static int handle_txpower(struct nl80211_state *state,
263 struct nl_cb *cb,
264 struct nl_msg *msg,
265 int argc, char **argv)
266{
267 enum nl80211_tx_power_setting type;
268 int mbm;
269
270 /* get the required args */
271 if (argc != 1 && argc != 2)
272 return 1;
273
274 if (!strcmp(argv[0], "auto"))
275 type = NL80211_TX_POWER_AUTOMATIC;
276 else if (!strcmp(argv[0], "fixed"))
277 type = NL80211_TX_POWER_FIXED;
278 else if (!strcmp(argv[0], "limit"))
279 type = NL80211_TX_POWER_LIMITED;
280 else {
281 printf("Invalid parameter: %s\n", argv[0]);
282 return 2;
283 }
284
285 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, type);
286
287 if (type != NL80211_TX_POWER_AUTOMATIC) {
288 if (argc != 2) {
289 printf("Missing TX power level argument.\n");
290 return 2;
291 }
292
293 mbm = atoi(argv[1]);
294 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
295 } else if (argc != 1)
296 return 1;
297
298 return 0;
299
300 nla_put_failure:
301 return -ENOBUFS;
302}
303COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
304 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txpower,
305 "Specify transmit power level and setting type.");
306COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
307 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txpower,
308 "Specify transmit power level and setting type.");