]> git.ipfire.org Git - thirdparty/iw.git/blame - scan.c
update for new scan patch
[thirdparty/iw.git] / scan.c
CommitLineData
3563f4c5
JB
1#include <net/if.h>
2#include <errno.h>
3#include <string.h>
4#include <ctype.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
15static int handle_scan(struct nl_cb *cb,
16 struct nl_msg *msg,
17 int argc, char **argv)
18{
19 struct nl_msg *ssids = NULL;
20 int err = -ENOBUFS;
21
22 ssids = nlmsg_alloc();
23 if (!ssids)
24 return -ENOMEM;
25 NLA_PUT(ssids, 1, 0, "");
26 nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
27
28 err = 0;
29 nla_put_failure:
30 nlmsg_free(ssids);
31 return err;
32}
33COMMAND(scan, trigger, NULL,
34 NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan);
35
36typedef void (*printfn)(unsigned char type, unsigned char len, unsigned char *data);
37
38static void print_ssid(unsigned char type, unsigned char len, unsigned char *data)
39{
40 int i;
41 printf("\tSSID: ");
42 for (i=0; i<len; i++) {
43 if (isprint(data[i]))
44 printf("%c", data[i]);
45 else
46 printf("\\x%.2x", data[i]);
47 }
48 printf("\n");
49}
50
51static void print_supprates(unsigned char type, unsigned char len, unsigned char *data)
52{
53 int i;
54
55 if (type == 1)
56 printf("\tSupported rates: ");
57 else
58 printf("\tExtended supported rates: ");
59
60 for (i=0; i<len; i++) {
61 int r = data[i] & 0x7f;
62 printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":"");
63 }
64 printf("\n");
65}
66
67static void print_ds(unsigned char type, unsigned char len, unsigned char *data)
68{
69 printf("\tDS Parameter set: channel %d\n", data[0]);
70}
71
72static void print_ign(unsigned char type, unsigned char len, unsigned char *data)
73{
74 /* ignore for now, not too useful */
75}
76
77static void print_vendor(unsigned char type, unsigned char len, unsigned char *data)
78{
79 int i;
80
81 printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data: ",
82 data[0], data[1], data[2]);
83 for (i=3; i<len; i++)
84 printf("\\x%.2x", data[i]);
85 printf("\n");
86}
87
88static const printfn ieprinters[] = {
89 [0] = print_ssid,
90 [1] = print_supprates,
91 [3] = print_ds,
92 [5] = print_ign,
93 [50] = print_supprates,
94 [221] = print_vendor,
95};
3563f4c5
JB
96
97static void print_ies(unsigned char *ie, int ielen)
98{
99 while (ielen >= 2 && ielen >= ie[1]) {
97ebbaf5 100 if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]]) {
3563f4c5
JB
101 ieprinters[ie[0]](ie[0], ie[1], ie + 2);
102 } else {
103 int i;
104
105 printf("\tUnknown IE (%d): ", ie[0]);
106 for (i=0; i<ie[1]; i++)
107 printf("\\x%.2x", ie[2+i]);
108 printf("\n");
109 }
110 ielen -= ie[1] + 2;
111 ie += ie[1] + 2;
112 }
113}
114
115static int print_bss_handler(struct nl_msg *msg, void *arg)
116{
117 struct nlattr *tb[NL80211_ATTR_MAX + 1];
118 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
119 struct nlattr *bss[NL80211_BSS_MAX + 1];
120 char mac_addr[20], dev[20];
121 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
122 [NL80211_BSS_TSF] = { .type = NLA_U64 },
123 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
124 [NL80211_BSS_BSSID] = { },
125 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
126 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
127 [NL80211_BSS_INFORMATION_ELEMENTS] = { },
f2e17e1f
JB
128 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
129 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
3563f4c5
JB
130 };
131
132 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
133 genlmsg_attrlen(gnlh, 0), NULL);
134
135 if (!tb[NL80211_ATTR_BSS]) {
136 fprintf(stderr, "bss info missing!");
137 return NL_SKIP;
138 }
139 if (nla_parse_nested(bss, NL80211_BSS_MAX,
140 tb[NL80211_ATTR_BSS],
141 bss_policy)) {
142 fprintf(stderr, "failed to parse nested attributes!");
143 return NL_SKIP;
144 }
145
146 if (!bss[NL80211_BSS_BSSID])
147 return NL_SKIP;
148
149 mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
150 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
151 printf("BSS %s (on %s)\n", mac_addr, dev);
152
153 if (bss[NL80211_BSS_TSF])
154 printf("\tTSF: %llu usec\n",
155 (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]));
156 if (bss[NL80211_BSS_FREQUENCY])
157 printf("\tfreq: %d\n",
158 nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
159 if (bss[NL80211_BSS_BEACON_INTERVAL])
160 printf("\tbeacon interval: %d\n",
161 nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
162 if (bss[NL80211_BSS_CAPABILITY])
163 printf("\tcapability: 0x%.4x\n",
164 nla_get_u16(bss[NL80211_BSS_CAPABILITY]));
f2e17e1f
JB
165 if (bss[NL80211_BSS_SIGNAL_MBM]) {
166 int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
167 printf("\tsignal: %d.%.2d dBm\n", s/100, s%100);
168 }
169 if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
170 unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
171 printf("\tsignal: %d/100\n", s);
172 }
3563f4c5
JB
173 if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
174 print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
175 nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
176
177 return NL_SKIP;
178}
179
180
181
182static int handle_scan_dump(struct nl_cb *cb,
183 struct nl_msg *msg,
184 int argc, char **argv)
185{
186 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler, NULL);
187 return 0;
188}
189COMMAND(scan, dump, NULL,
190 NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump);