]> git.ipfire.org Git - thirdparty/iw.git/blame - scan.c
scan code
[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};
96#define NUMPRINTERS (sizeof(ieprinters)/sizeof(ieprinters[0]))
97
98static void print_ies(unsigned char *ie, int ielen)
99{
100 while (ielen >= 2 && ielen >= ie[1]) {
101 if (ie[0] < NUMPRINTERS && ieprinters[ie[0]]) {
102 ieprinters[ie[0]](ie[0], ie[1], ie + 2);
103 } else {
104 int i;
105
106 printf("\tUnknown IE (%d): ", ie[0]);
107 for (i=0; i<ie[1]; i++)
108 printf("\\x%.2x", ie[2+i]);
109 printf("\n");
110 }
111 ielen -= ie[1] + 2;
112 ie += ie[1] + 2;
113 }
114}
115
116static int print_bss_handler(struct nl_msg *msg, void *arg)
117{
118 struct nlattr *tb[NL80211_ATTR_MAX + 1];
119 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
120 struct nlattr *bss[NL80211_BSS_MAX + 1];
121 char mac_addr[20], dev[20];
122 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
123 [NL80211_BSS_TSF] = { .type = NLA_U64 },
124 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
125 [NL80211_BSS_BSSID] = { },
126 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
127 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
128 [NL80211_BSS_INFORMATION_ELEMENTS] = { },
129 };
130
131 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
132 genlmsg_attrlen(gnlh, 0), NULL);
133
134 if (!tb[NL80211_ATTR_BSS]) {
135 fprintf(stderr, "bss info missing!");
136 return NL_SKIP;
137 }
138 if (nla_parse_nested(bss, NL80211_BSS_MAX,
139 tb[NL80211_ATTR_BSS],
140 bss_policy)) {
141 fprintf(stderr, "failed to parse nested attributes!");
142 return NL_SKIP;
143 }
144
145 if (!bss[NL80211_BSS_BSSID])
146 return NL_SKIP;
147
148 mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
149 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
150 printf("BSS %s (on %s)\n", mac_addr, dev);
151
152 if (bss[NL80211_BSS_TSF])
153 printf("\tTSF: %llu usec\n",
154 (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]));
155 if (bss[NL80211_BSS_FREQUENCY])
156 printf("\tfreq: %d\n",
157 nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
158 if (bss[NL80211_BSS_BEACON_INTERVAL])
159 printf("\tbeacon interval: %d\n",
160 nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
161 if (bss[NL80211_BSS_CAPABILITY])
162 printf("\tcapability: 0x%.4x\n",
163 nla_get_u16(bss[NL80211_BSS_CAPABILITY]));
164 if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
165 print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
166 nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
167
168 return NL_SKIP;
169}
170
171
172
173static int handle_scan_dump(struct nl_cb *cb,
174 struct nl_msg *msg,
175 int argc, char **argv)
176{
177 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler, NULL);
178 return 0;
179}
180COMMAND(scan, dump, NULL,
181 NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump);