]> git.ipfire.org Git - thirdparty/iw.git/blame - scan.c
Merge branch 'master' into scan-test
[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] = { },
128 };
129
130 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
131 genlmsg_attrlen(gnlh, 0), NULL);
132
133 if (!tb[NL80211_ATTR_BSS]) {
134 fprintf(stderr, "bss info missing!");
135 return NL_SKIP;
136 }
137 if (nla_parse_nested(bss, NL80211_BSS_MAX,
138 tb[NL80211_ATTR_BSS],
139 bss_policy)) {
140 fprintf(stderr, "failed to parse nested attributes!");
141 return NL_SKIP;
142 }
143
144 if (!bss[NL80211_BSS_BSSID])
145 return NL_SKIP;
146
147 mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
148 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
149 printf("BSS %s (on %s)\n", mac_addr, dev);
150
151 if (bss[NL80211_BSS_TSF])
152 printf("\tTSF: %llu usec\n",
153 (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]));
154 if (bss[NL80211_BSS_FREQUENCY])
155 printf("\tfreq: %d\n",
156 nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
157 if (bss[NL80211_BSS_BEACON_INTERVAL])
158 printf("\tbeacon interval: %d\n",
159 nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
160 if (bss[NL80211_BSS_CAPABILITY])
161 printf("\tcapability: 0x%.4x\n",
162 nla_get_u16(bss[NL80211_BSS_CAPABILITY]));
163 if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
164 print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
165 nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
166
167 return NL_SKIP;
168}
169
170
171
172static int handle_scan_dump(struct nl_cb *cb,
173 struct nl_msg *msg,
174 int argc, char **argv)
175{
176 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler, NULL);
177 return 0;
178}
179COMMAND(scan, dump, NULL,
180 NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump);