]> git.ipfire.org Git - thirdparty/iw.git/blame - ibss.c
iw: support multiple regdom print
[thirdparty/iw.git] / ibss.c
CommitLineData
b893686f
JB
1#ifndef _POSIX_SOURCE
2#define _POSIX_SOURCE
3#endif
edea4d14 4#include <errno.h>
b893686f 5#include <string.h>
135cb523 6#include <strings.h>
edea4d14
JB
7
8#include <netlink/genl/genl.h>
9#include <netlink/genl/family.h>
10#include <netlink/genl/ctrl.h>
11#include <netlink/msg.h>
12#include <netlink/attr.h>
13
14#include "nl80211.h"
15#include "iw.h"
16
4698bfc2
JB
17SECTION(ibss);
18
edea4d14
JB
19static int join_ibss(struct nl80211_state *state,
20 struct nl_cb *cb,
21 struct nl_msg *msg,
05514f95
JB
22 int argc, char **argv,
23 enum id_input id)
edea4d14 24{
95940df3 25 char *end;
edea4d14 26 unsigned char abssid[6];
6a24bb22
TP
27 unsigned char rates[NL80211_MAX_SUPP_RATES];
28 int n_rates = 0;
29 char *value = NULL, *sptr = NULL;
30 float rate;
ec46ba52 31 int bintval;
135cb523 32 int i;
85da7703 33 unsigned long freq;
135cb523
SW
34 static const struct {
35 const char *name;
85da7703
SW
36 unsigned int width;
37 int freq1_diff;
38 int chantype; /* for older kernel */
39 } *chanmode_selected = NULL, chanmode[] = {
40 { .name = "HT20",
41 .width = NL80211_CHAN_WIDTH_20,
42 .freq1_diff = 0,
43 .chantype = NL80211_CHAN_HT20 },
44 { .name = "HT40+",
45 .width = NL80211_CHAN_WIDTH_40,
46 .freq1_diff = 10,
47 .chantype = NL80211_CHAN_HT40PLUS },
48 { .name = "HT40-",
49 .width = NL80211_CHAN_WIDTH_40,
50 .freq1_diff = -10,
51 .chantype = NL80211_CHAN_HT40MINUS },
52 { .name = "NOHT",
53 .width = NL80211_CHAN_WIDTH_20_NOHT,
54 .freq1_diff = 0,
55 .chantype = NL80211_CHAN_NO_HT },
56 { .name = "5MHZ",
57 .width = NL80211_CHAN_WIDTH_5,
58 .freq1_diff = 0,
59 .chantype = -1 },
60 { .name = "10MHZ",
61 .width = NL80211_CHAN_WIDTH_10,
62 .freq1_diff = 0,
63 .chantype = -1 },
135cb523 64 };
edea4d14 65
95940df3
JB
66 if (argc < 2)
67 return 1;
edea4d14 68
95940df3
JB
69 /* SSID */
70 NLA_PUT(msg, NL80211_ATTR_SSID, strlen(argv[0]), argv[0]);
edea4d14
JB
71 argv++;
72 argc--;
73
95940df3 74 /* freq */
85da7703 75 freq = strtoul(argv[0], &end, 10);
95940df3
JB
76 if (*end != '\0')
77 return 1;
85da7703
SW
78
79 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
95940df3
JB
80 argv++;
81 argc--;
edea4d14 82
135cb523 83 if (argc) {
85da7703
SW
84 for (i = 0; i < ARRAY_SIZE(chanmode); i++) {
85 if (strcasecmp(chanmode[i].name, argv[0]) == 0) {
86 chanmode_selected = &chanmode[i];
135cb523
SW
87 break;
88 }
89 }
85da7703
SW
90 if (chanmode_selected) {
91 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
92 chanmode_selected->width);
93 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1,
94 freq + chanmode_selected->freq1_diff);
95 if (chanmode_selected->chantype != -1)
96 NLA_PUT_U32(msg,
97 NL80211_ATTR_WIPHY_CHANNEL_TYPE,
98 chanmode_selected->chantype);
99
135cb523
SW
100 argv++;
101 argc--;
102 }
103
104 }
105
95940df3
JB
106 if (argc && strcmp(argv[0], "fixed-freq") == 0) {
107 NLA_PUT_FLAG(msg, NL80211_ATTR_FREQ_FIXED);
108 argv++;
109 argc--;
edea4d14
JB
110 }
111
95940df3 112 if (argc) {
51e9bd80
JB
113 if (mac_addr_a2n(abssid, argv[0]) == 0) {
114 NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
115 argv++;
116 argc--;
117 }
edea4d14
JB
118 }
119
ec46ba52
BR
120 if (argc > 1 && strcmp(argv[0], "beacon-interval") == 0) {
121 argv++;
122 argc--;
123 bintval = strtoul(argv[0], &end, 10);
124 if (*end != '\0')
125 return 1;
126 NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, bintval);
127 argv++;
128 argc--;
129 }
130
6a24bb22
TP
131 /* basic rates */
132 if (argc > 1 && strcmp(argv[0], "basic-rates") == 0) {
133 argv++;
134 argc--;
135
136 value = strtok_r(argv[0], ",", &sptr);
137
138 while (value && n_rates < NL80211_MAX_SUPP_RATES) {
139 rate = strtod(value, &end);
140 rates[n_rates] = rate * 2;
141
142 /* filter out suspicious values */
143 if (*end != '\0' || !rates[n_rates] ||
144 rate*2 != rates[n_rates])
145 return 1;
146
147 n_rates++;
148 value = strtok_r(NULL, ",", &sptr);
149 }
150
151 NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, n_rates, rates);
152
153 argv++;
154 argc--;
155 }
156
506b442b
FF
157 /* multicast rate */
158 if (argc > 1 && strcmp(argv[0], "mcast-rate") == 0) {
159 argv++;
160 argc--;
161
162 rate = strtod(argv[0], &end);
163 if (*end != '\0')
164 return 1;
165
e399be8c 166 NLA_PUT_U32(msg, NL80211_ATTR_MCAST_RATE, (int)(rate * 10));
506b442b
FF
167 argv++;
168 argc--;
169 }
170
1e03690e
JB
171 if (!argc)
172 return 0;
edea4d14 173
1e03690e
JB
174 if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0)
175 return 1;
ded1f078 176
1e03690e
JB
177 argv++;
178 argc--;
51e9bd80 179
1e03690e 180 return parse_keys(msg, argv, argc);
edea4d14
JB
181 nla_put_failure:
182 return -ENOSPC;
183}
184
185static int leave_ibss(struct nl80211_state *state,
186 struct nl_cb *cb,
187 struct nl_msg *msg,
05514f95
JB
188 int argc, char **argv,
189 enum id_input id)
edea4d14
JB
190{
191 return 0;
192}
193COMMAND(ibss, leave, NULL,
806bad30
JB
194 NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss,
195 "Leave the current IBSS cell.");
6a24bb22 196COMMAND(ibss, join,
85da7703 197 "<SSID> <freq in MHz> [HT20|HT40+|HT40-|NOHT|5MHZ|10MHZ] [fixed-freq] [<fixed bssid>] [beacon-interval <TU>]"
506b442b
FF
198 " [basic-rates <rate in Mbps,rate2,...>] [mcast-rate <rate in Mbps>] "
199 "[key d:0:abcde]",
806bad30
JB
200 NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
201 "Join the IBSS cell with the given SSID, if it doesn't exist create\n"
202 "it on the given frequency. When fixed frequency is requested, don't\n"
203 "join/create a cell on a different frequency. When a fixed BSSID is\n"
204 "requested use that BSSID and do not adopt another cell's BSSID even\n"
ec46ba52 205 "if it has higher TSF and the same SSID. If an IBSS is created, create\n"
506b442b 206 "it with the specified basic-rates, multicast-rate and beacon-interval.");