7 #include <netlink/genl/genl.h>
8 #include <netlink/genl/family.h>
9 #include <netlink/genl/ctrl.h>
10 #include <netlink/msg.h>
11 #include <netlink/attr.h>
20 static int handle_scan(struct nl80211_state
*state
,
23 int argc
, char **argv
)
25 struct nl_msg
*ssids
= NULL
;
28 ssids
= nlmsg_alloc();
31 NLA_PUT(ssids
, 1, 0, "");
32 nla_put_nested(msg
, NL80211_ATTR_SCAN_SSIDS
, ssids
);
39 COMMAND(scan
, trigger
, NULL
,
40 NL80211_CMD_TRIGGER_SCAN
, 0, CIB_NETDEV
, handle_scan
);
42 typedef void (*printfn
)(unsigned char type
, unsigned char len
, unsigned char *data
);
44 static void print_ssid(unsigned char type
, unsigned char len
, unsigned char *data
)
48 for (i
=0; i
<len
; i
++) {
50 printf("%c", data
[i
]);
52 printf("\\x%.2x", data
[i
]);
57 static void print_supprates(unsigned char type
, unsigned char len
, unsigned char *data
)
62 printf("\tSupported rates: ");
64 printf("\tExtended supported rates: ");
66 for (i
=0; i
<len
; i
++) {
67 int r
= data
[i
] & 0x7f;
68 printf("%d.%d%s ", r
/2, 5*(r
&1), data
[i
] & 0x80 ? "*":"");
73 static void print_ds(unsigned char type
, unsigned char len
, unsigned char *data
)
75 printf("\tDS Parameter set: channel %d\n", data
[0]);
78 static void print_ign(unsigned char type
, unsigned char len
, unsigned char *data
)
80 /* ignore for now, not too useful */
83 static const printfn ieprinters
[] = {
85 [1] = print_supprates
,
88 [50] = print_supprates
,
91 static void print_vendor(unsigned char len
, unsigned char *data
,
92 struct scan_params
*params
)
96 /* currently _all_ vendor IEs are unknown (not parsed) */
100 printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data: ",
101 data
[0], data
[1], data
[2]);
102 for (i
=3; i
<len
; i
++)
103 printf("\\x%.2x", data
[i
]);
107 static void print_ies(unsigned char *ie
, int ielen
, struct scan_params
*params
)
109 while (ielen
>= 2 && ielen
>= ie
[1]) {
110 if (ie
[0] < ARRAY_SIZE(ieprinters
) && ieprinters
[ie
[0]]) {
111 ieprinters
[ie
[0]](ie
[0], ie
[1], ie
+ 2);
112 } else if (ie
[0] == 221 /* vendor */) {
113 print_vendor(ie
[1], ie
+ 2, params
);
114 } else if (params
->unknown
) {
117 printf("\tUnknown IE (%d): ", ie
[0]);
118 for (i
=0; i
<ie
[1]; i
++)
119 printf("\\x%.2x", ie
[2+i
]);
127 static int print_bss_handler(struct nl_msg
*msg
, void *arg
)
129 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
130 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
131 struct nlattr
*bss
[NL80211_BSS_MAX
+ 1];
132 char mac_addr
[20], dev
[20];
133 static struct nla_policy bss_policy
[NL80211_BSS_MAX
+ 1] = {
134 [NL80211_BSS_TSF
] = { .type
= NLA_U64
},
135 [NL80211_BSS_FREQUENCY
] = { .type
= NLA_U32
},
136 [NL80211_BSS_BSSID
] = { },
137 [NL80211_BSS_BEACON_INTERVAL
] = { .type
= NLA_U16
},
138 [NL80211_BSS_CAPABILITY
] = { .type
= NLA_U16
},
139 [NL80211_BSS_INFORMATION_ELEMENTS
] = { },
140 [NL80211_BSS_SIGNAL_MBM
] = { .type
= NLA_U32
},
141 [NL80211_BSS_SIGNAL_UNSPEC
] = { .type
= NLA_U8
},
144 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
145 genlmsg_attrlen(gnlh
, 0), NULL
);
147 if (!tb
[NL80211_ATTR_BSS
]) {
148 fprintf(stderr
, "bss info missing!");
151 if (nla_parse_nested(bss
, NL80211_BSS_MAX
,
152 tb
[NL80211_ATTR_BSS
],
154 fprintf(stderr
, "failed to parse nested attributes!");
158 if (!bss
[NL80211_BSS_BSSID
])
161 mac_addr_n2a(mac_addr
, nla_data(bss
[NL80211_BSS_BSSID
]));
162 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), dev
);
163 printf("BSS %s (on %s)\n", mac_addr
, dev
);
165 if (bss
[NL80211_BSS_TSF
]) {
166 unsigned long long tsf
;
167 tsf
= (unsigned long long)nla_get_u64(bss
[NL80211_BSS_TSF
]);
168 printf("\tTSF: %llu usec (%llud, %.2lld:%.2llu:%.2llu)\n",
169 tsf
, tsf
/1000/1000/60/60/24, (tsf
/1000/1000/60/60) % 24,
170 (tsf
/1000/1000/60) % 60, (tsf
/1000/1000) % 60);
172 if (bss
[NL80211_BSS_FREQUENCY
])
173 printf("\tfreq: %d\n",
174 nla_get_u32(bss
[NL80211_BSS_FREQUENCY
]));
175 if (bss
[NL80211_BSS_BEACON_INTERVAL
])
176 printf("\tbeacon interval: %d\n",
177 nla_get_u16(bss
[NL80211_BSS_BEACON_INTERVAL
]));
178 if (bss
[NL80211_BSS_CAPABILITY
])
179 printf("\tcapability: 0x%.4x\n",
180 nla_get_u16(bss
[NL80211_BSS_CAPABILITY
]));
181 if (bss
[NL80211_BSS_SIGNAL_MBM
]) {
182 int s
= nla_get_u32(bss
[NL80211_BSS_SIGNAL_MBM
]);
183 printf("\tsignal: %d.%.2d dBm\n", s
/100, s
%100);
185 if (bss
[NL80211_BSS_SIGNAL_UNSPEC
]) {
186 unsigned char s
= nla_get_u8(bss
[NL80211_BSS_SIGNAL_UNSPEC
]);
187 printf("\tsignal: %d/100\n", s
);
189 if (bss
[NL80211_BSS_INFORMATION_ELEMENTS
])
190 print_ies(nla_data(bss
[NL80211_BSS_INFORMATION_ELEMENTS
]),
191 nla_len(bss
[NL80211_BSS_INFORMATION_ELEMENTS
]),
197 static struct scan_params scan_params
;
199 static int handle_scan_dump(struct nl80211_state
*state
,
202 int argc
, char **argv
)
207 scan_params
.unknown
= false;
208 if (argc
== 1 && !strcmp(argv
[0], "-u"))
209 scan_params
.unknown
= true;
211 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_bss_handler
,
215 COMMAND(scan
, dump
, "[-u]",
216 NL80211_CMD_GET_SCAN
, NLM_F_DUMP
, CIB_NETDEV
, handle_scan_dump
);
218 static int handle_scan_combined(struct nl80211_state
*state
,
221 int argc
, char **argv
)
223 static char *trig_argv
[] = {
228 static char *dump_argv
[] = {
233 static const __u32 cmds
[] = {
234 NL80211_CMD_NEW_SCAN_RESULTS
,
235 NL80211_CMD_SCAN_ABORTED
,
239 trig_argv
[0] = argv
[0];
240 err
= handle_cmd(state
, II_NETDEV
, ARRAY_SIZE(trig_argv
), trig_argv
);
244 if (listen_events(state
, ARRAY_SIZE(cmds
), cmds
) ==
245 NL80211_CMD_SCAN_ABORTED
) {
246 printf("scan aborted!\n");
250 dump_argv
[0] = argv
[0];
251 return handle_cmd(state
, II_NETDEV
, ARRAY_SIZE(dump_argv
), dump_argv
);
253 TOPLEVEL(scan
, NULL
, 0, 0, CIB_NETDEV
, handle_scan_combined
);