Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 1 | #include <stdint.h> |
| 2 | #include <stdbool.h> |
| 3 | #include <net/if.h> |
| 4 | #include <errno.h> |
| 5 | #include "iw.h" |
| 6 | |
| 7 | static int no_seq_check(struct nl_msg *msg, void *arg) |
| 8 | { |
| 9 | return NL_OK; |
| 10 | } |
| 11 | |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 12 | struct ieee80211_beacon_channel { |
| 13 | __u16 center_freq; |
Ilan Peer | f0c48e7 | 2013-11-14 09:15:34 +0200 | [diff] [blame] | 14 | bool no_ir; |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 15 | bool no_ibss; |
| 16 | }; |
| 17 | |
| 18 | static int parse_beacon_hint_chan(struct nlattr *tb, |
| 19 | struct ieee80211_beacon_channel *chan) |
| 20 | { |
| 21 | struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; |
| 22 | static struct nla_policy beacon_freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { |
| 23 | [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, |
Ilan Peer | f0c48e7 | 2013-11-14 09:15:34 +0200 | [diff] [blame] | 24 | [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG }, |
| 25 | [__NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 26 | }; |
| 27 | |
| 28 | if (nla_parse_nested(tb_freq, |
| 29 | NL80211_FREQUENCY_ATTR_MAX, |
| 30 | tb, |
| 31 | beacon_freq_policy)) |
| 32 | return -EINVAL; |
| 33 | |
| 34 | chan->center_freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); |
| 35 | |
Ilan Peer | f0c48e7 | 2013-11-14 09:15:34 +0200 | [diff] [blame] | 36 | if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR]) |
| 37 | chan->no_ir = true; |
| 38 | if (tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]) |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 39 | chan->no_ibss = true; |
| 40 | |
| 41 | return 0; |
| 42 | } |
| 43 | |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 44 | static void print_frame(struct print_event_args *args, struct nlattr *attr) |
| 45 | { |
| 46 | uint8_t *frame; |
| 47 | size_t len; |
| 48 | int i; |
| 49 | char macbuf[6*3]; |
| 50 | uint16_t tmp; |
| 51 | |
| 52 | if (!attr) |
| 53 | printf(" [no frame]"); |
| 54 | |
| 55 | frame = nla_data(attr); |
| 56 | len = nla_len(attr); |
| 57 | |
| 58 | if (len < 26) { |
| 59 | printf(" [invalid frame: "); |
| 60 | goto print_frame; |
| 61 | } |
| 62 | |
| 63 | mac_addr_n2a(macbuf, frame + 10); |
| 64 | printf(" %s -> ", macbuf); |
| 65 | mac_addr_n2a(macbuf, frame + 4); |
| 66 | printf("%s", macbuf); |
| 67 | |
| 68 | switch (frame[0] & 0xfc) { |
| 69 | case 0x10: /* assoc resp */ |
| 70 | case 0x30: /* reassoc resp */ |
| 71 | /* status */ |
| 72 | tmp = (frame[27] << 8) + frame[26]; |
| 73 | printf(" status: %d: %s", tmp, get_status_str(tmp)); |
| 74 | break; |
| 75 | case 0x00: /* assoc req */ |
| 76 | case 0x20: /* reassoc req */ |
| 77 | break; |
| 78 | case 0xb0: /* auth */ |
| 79 | /* status */ |
| 80 | tmp = (frame[29] << 8) + frame[28]; |
| 81 | printf(" status: %d: %s", tmp, get_status_str(tmp)); |
| 82 | break; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 83 | case 0xa0: /* disassoc */ |
| 84 | case 0xc0: /* deauth */ |
| 85 | /* reason */ |
| 86 | tmp = (frame[25] << 8) + frame[24]; |
| 87 | printf(" reason %d: %s", tmp, get_reason_str(tmp)); |
| 88 | break; |
| 89 | } |
| 90 | |
| 91 | if (!args->frame) |
| 92 | return; |
| 93 | |
| 94 | printf(" [frame:"); |
| 95 | |
| 96 | print_frame: |
| 97 | for (i = 0; i < len; i++) |
| 98 | printf(" %.02x", frame[i]); |
| 99 | printf("]"); |
| 100 | } |
| 101 | |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 102 | static void parse_cqm_event(struct nlattr **attrs) |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 103 | { |
| 104 | static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { |
| 105 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, |
| 106 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, |
| 107 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, |
| 108 | }; |
| 109 | struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 110 | struct nlattr *cqm_attr = attrs[NL80211_ATTR_CQM]; |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 111 | |
Ben Greear | e5497f1 | 2013-01-30 21:31:29 -0800 | [diff] [blame] | 112 | printf("CQM event: "); |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 113 | |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 114 | if (!cqm_attr || |
| 115 | nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, cqm_attr, cqm_policy)) { |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 116 | printf("missing data!\n"); |
| 117 | return; |
| 118 | } |
| 119 | |
| 120 | if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]) { |
| 121 | enum nl80211_cqm_rssi_threshold_event rssi_event; |
Ben Greear | e5497f1 | 2013-01-30 21:31:29 -0800 | [diff] [blame] | 122 | bool found_one = false; |
| 123 | |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 124 | rssi_event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]); |
Ben Greear | e5497f1 | 2013-01-30 21:31:29 -0800 | [diff] [blame] | 125 | |
| 126 | switch (rssi_event) { |
| 127 | case NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 128 | printf("RSSI went above threshold\n"); |
Ben Greear | e5497f1 | 2013-01-30 21:31:29 -0800 | [diff] [blame] | 129 | found_one = true; |
| 130 | break; |
| 131 | case NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 132 | printf("RSSI went below threshold\n"); |
Ben Greear | e5497f1 | 2013-01-30 21:31:29 -0800 | [diff] [blame] | 133 | found_one = true; |
| 134 | break; |
| 135 | case NL80211_CQM_RSSI_BEACON_LOSS_EVENT: |
| 136 | printf("Beacon loss detected\n"); |
| 137 | found_one = true; |
| 138 | break; |
| 139 | } |
| 140 | |
| 141 | if (!found_one) |
| 142 | printf("Unknown event type: %i\n", rssi_event); |
Ben Greear | a3ca7c6 | 2015-06-11 15:54:11 -0400 | [diff] [blame] | 143 | } else if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) { |
| 144 | if (attrs[NL80211_ATTR_MAC]) { |
| 145 | uint32_t frames; |
| 146 | char buf[3*6]; |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 147 | |
Ben Greear | a3ca7c6 | 2015-06-11 15:54:11 -0400 | [diff] [blame] | 148 | frames = nla_get_u32(cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]); |
| 149 | mac_addr_n2a(buf, nla_data(attrs[NL80211_ATTR_MAC])); |
| 150 | printf("peer %s didn't ACK %d packets\n", buf, frames); |
| 151 | } else { |
| 152 | printf("PKT-LOSS-EVENT did not have MAC attribute!\n"); |
| 153 | } |
| 154 | } else if (cqm[NL80211_ATTR_CQM_BEACON_LOSS_EVENT]) { |
| 155 | printf("beacon loss\n"); |
| 156 | } else { |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 157 | printf("unknown event\n"); |
Ben Greear | a3ca7c6 | 2015-06-11 15:54:11 -0400 | [diff] [blame] | 158 | } |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 159 | } |
| 160 | |
Jouni Malinen | 8612433 | 2011-02-04 13:28:23 +0100 | [diff] [blame] | 161 | static const char * key_type_str(enum nl80211_key_type key_type) |
| 162 | { |
| 163 | static char buf[30]; |
| 164 | switch (key_type) { |
| 165 | case NL80211_KEYTYPE_GROUP: |
| 166 | return "Group"; |
| 167 | case NL80211_KEYTYPE_PAIRWISE: |
| 168 | return "Pairwise"; |
| 169 | case NL80211_KEYTYPE_PEERKEY: |
| 170 | return "PeerKey"; |
| 171 | default: |
| 172 | snprintf(buf, sizeof(buf), "unknown(%d)", key_type); |
| 173 | return buf; |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | static void parse_mic_failure(struct nlattr **attrs) |
| 178 | { |
| 179 | printf("Michael MIC failure event:"); |
| 180 | |
| 181 | if (attrs[NL80211_ATTR_MAC]) { |
| 182 | char addr[3 * ETH_ALEN]; |
| 183 | mac_addr_n2a(addr, nla_data(attrs[NL80211_ATTR_MAC])); |
| 184 | printf(" source MAC address %s", addr); |
| 185 | } |
| 186 | |
| 187 | if (attrs[NL80211_ATTR_KEY_SEQ] && |
| 188 | nla_len(attrs[NL80211_ATTR_KEY_SEQ]) == 6) { |
| 189 | unsigned char *seq = nla_data(attrs[NL80211_ATTR_KEY_SEQ]); |
| 190 | printf(" seq=%02x%02x%02x%02x%02x%02x", |
| 191 | seq[0], seq[1], seq[2], seq[3], seq[4], seq[5]); |
| 192 | } |
| 193 | if (attrs[NL80211_ATTR_KEY_TYPE]) { |
| 194 | enum nl80211_key_type key_type = |
| 195 | nla_get_u32(attrs[NL80211_ATTR_KEY_TYPE]); |
| 196 | printf(" Key Type %s", key_type_str(key_type)); |
| 197 | } |
| 198 | |
| 199 | if (attrs[NL80211_ATTR_KEY_IDX]) { |
| 200 | __u8 key_id = nla_get_u8(attrs[NL80211_ATTR_KEY_IDX]); |
| 201 | printf(" Key Id %d", key_id); |
| 202 | } |
| 203 | |
| 204 | printf("\n"); |
| 205 | } |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 206 | |
Johannes Berg | 819b78c | 2013-02-19 23:31:27 +0100 | [diff] [blame] | 207 | static void parse_wowlan_wake_event(struct nlattr **attrs) |
| 208 | { |
Luciano Coelho | d516c5b | 2014-11-28 23:05:55 +0200 | [diff] [blame] | 209 | struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG], |
| 210 | *tb_match[NUM_NL80211_ATTR]; |
Johannes Berg | 819b78c | 2013-02-19 23:31:27 +0100 | [diff] [blame] | 211 | |
| 212 | printf("WoWLAN wakeup\n"); |
| 213 | if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { |
| 214 | printf("\twakeup not due to WoWLAN\n"); |
| 215 | return; |
| 216 | } |
| 217 | |
| 218 | nla_parse(tb, MAX_NL80211_WOWLAN_TRIG, |
| 219 | nla_data(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), |
| 220 | nla_len(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), NULL); |
| 221 | |
| 222 | if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) |
| 223 | printf("\t* was disconnected\n"); |
| 224 | if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) |
| 225 | printf("\t* magic packet received\n"); |
| 226 | if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) |
| 227 | printf("\t* pattern index: %u\n", |
| 228 | nla_get_u32(tb[NL80211_WOWLAN_TRIG_PKT_PATTERN])); |
| 229 | if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) |
| 230 | printf("\t* GTK rekey failure\n"); |
| 231 | if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) |
| 232 | printf("\t* EAP identity request\n"); |
| 233 | if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) |
| 234 | printf("\t* 4-way handshake\n"); |
| 235 | if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) |
| 236 | printf("\t* RF-kill released\n"); |
Luciano Coelho | d516c5b | 2014-11-28 23:05:55 +0200 | [diff] [blame] | 237 | if (tb[NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS]) { |
| 238 | struct nlattr *match, *freq; |
| 239 | int rem_nst, rem_nst2; |
| 240 | |
| 241 | printf("\t* network detected\n"); |
| 242 | nla_for_each_nested(match, |
| 243 | tb[NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS], |
| 244 | rem_nst) { |
| 245 | nla_parse(tb_match, NUM_NL80211_ATTR, nla_data(match), |
| 246 | nla_len(match), |
| 247 | NULL); |
| 248 | printf("\t\tSSID: \""); |
| 249 | print_ssid_escaped(nla_len(tb_match[NL80211_ATTR_SSID]), |
| 250 | nla_data(tb_match[NL80211_ATTR_SSID])); |
| 251 | printf("\""); |
| 252 | if (tb_match[NL80211_ATTR_SCAN_FREQUENCIES]) { |
| 253 | printf(" freq(s):"); |
| 254 | nla_for_each_nested(freq, |
| 255 | tb_match[NL80211_ATTR_SCAN_FREQUENCIES], |
| 256 | rem_nst2) |
| 257 | printf(" %d", nla_get_u32(freq)); |
| 258 | } |
| 259 | printf("\n"); |
| 260 | } |
| 261 | } |
Johannes Berg | 819b78c | 2013-02-19 23:31:27 +0100 | [diff] [blame] | 262 | if (tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]) { |
| 263 | uint8_t *d = nla_data(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]); |
| 264 | int l = nla_len(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]); |
| 265 | int i; |
| 266 | printf("\t* packet (might be truncated): "); |
| 267 | for (i = 0; i < l; i++) { |
| 268 | if (i > 0) |
| 269 | printf(":"); |
| 270 | printf("%.2x", d[i]); |
| 271 | } |
| 272 | printf("\n"); |
| 273 | } |
| 274 | if (tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]) { |
| 275 | uint8_t *d = nla_data(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]); |
| 276 | int l = nla_len(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]); |
| 277 | int i; |
| 278 | printf("\t* packet (might be truncated): "); |
| 279 | for (i = 0; i < l; i++) { |
| 280 | if (i > 0) |
| 281 | printf(":"); |
| 282 | printf("%.2x", d[i]); |
| 283 | } |
| 284 | printf("\n"); |
| 285 | } |
| 286 | if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH]) |
| 287 | printf("\t* TCP connection wakeup received\n"); |
| 288 | if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST]) |
| 289 | printf("\t* TCP connection lost\n"); |
| 290 | if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS]) |
| 291 | printf("\t* TCP connection ran out of tokens\n"); |
| 292 | } |
| 293 | |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 294 | static int print_event(struct nl_msg *msg, void *arg) |
| 295 | { |
| 296 | struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); |
Johannes Berg | 748f848 | 2009-05-24 16:48:17 +0200 | [diff] [blame] | 297 | struct nlattr *tb[NL80211_ATTR_MAX + 1], *nst; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 298 | struct print_event_args *args = arg; |
| 299 | char ifname[100]; |
| 300 | char macbuf[6*3]; |
| 301 | __u8 reg_type; |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 302 | struct ieee80211_beacon_channel chan_before_beacon, chan_after_beacon; |
| 303 | __u32 wiphy_idx = 0; |
Johannes Berg | 748f848 | 2009-05-24 16:48:17 +0200 | [diff] [blame] | 304 | int rem_nst; |
Johannes Berg | f1a666a | 2009-07-02 09:54:02 +0200 | [diff] [blame] | 305 | __u16 status; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 306 | |
Johannes Berg | 981b21a | 2010-10-13 17:52:15 +0200 | [diff] [blame] | 307 | if (args->time || args->reltime) { |
| 308 | unsigned long long usecs, previous; |
| 309 | |
| 310 | previous = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec; |
| 311 | gettimeofday(&args->ts, NULL); |
| 312 | usecs = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec; |
| 313 | if (args->reltime) { |
| 314 | if (!args->have_ts) { |
| 315 | usecs = 0; |
| 316 | args->have_ts = true; |
| 317 | } else |
| 318 | usecs -= previous; |
| 319 | } |
| 320 | printf("%llu.%06llu: ", usecs/1000000, usecs % 1000000); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 321 | } |
| 322 | |
| 323 | nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), |
| 324 | genlmsg_attrlen(gnlh, 0), NULL); |
| 325 | |
| 326 | if (tb[NL80211_ATTR_IFINDEX] && tb[NL80211_ATTR_WIPHY]) { |
| 327 | if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname); |
| 328 | printf("%s (phy #%d): ", ifname, nla_get_u32(tb[NL80211_ATTR_WIPHY])); |
Johannes Berg | d888017 | 2012-07-25 16:24:07 +0200 | [diff] [blame] | 329 | } else if (tb[NL80211_ATTR_WDEV] && tb[NL80211_ATTR_WIPHY]) { |
| 330 | printf("wdev 0x%llx (phy #%d): ", |
| 331 | (unsigned long long)nla_get_u64(tb[NL80211_ATTR_WDEV]), |
| 332 | nla_get_u32(tb[NL80211_ATTR_WIPHY])); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 333 | } else if (tb[NL80211_ATTR_IFINDEX]) { |
| 334 | if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname); |
| 335 | printf("%s: ", ifname); |
Johannes Berg | d888017 | 2012-07-25 16:24:07 +0200 | [diff] [blame] | 336 | } else if (tb[NL80211_ATTR_WDEV]) { |
| 337 | printf("wdev 0x%llx: ", (unsigned long long)nla_get_u64(tb[NL80211_ATTR_WDEV])); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 338 | } else if (tb[NL80211_ATTR_WIPHY]) { |
| 339 | printf("phy #%d: ", nla_get_u32(tb[NL80211_ATTR_WIPHY])); |
| 340 | } |
| 341 | |
| 342 | switch (gnlh->cmd) { |
| 343 | case NL80211_CMD_NEW_WIPHY: |
| 344 | printf("renamed to %s\n", nla_get_string(tb[NL80211_ATTR_WIPHY_NAME])); |
| 345 | break; |
Johannes Berg | e67be81 | 2009-06-16 18:53:21 +0200 | [diff] [blame] | 346 | case NL80211_CMD_TRIGGER_SCAN: |
| 347 | printf("scan started\n"); |
| 348 | break; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 349 | case NL80211_CMD_NEW_SCAN_RESULTS: |
Johannes Berg | 748f848 | 2009-05-24 16:48:17 +0200 | [diff] [blame] | 350 | printf("scan finished:"); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 351 | case NL80211_CMD_SCAN_ABORTED: |
Johannes Berg | 748f848 | 2009-05-24 16:48:17 +0200 | [diff] [blame] | 352 | if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) |
| 353 | printf("scan aborted:"); |
| 354 | if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) { |
| 355 | nla_for_each_nested(nst, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem_nst) |
| 356 | printf(" %d", nla_get_u32(nst)); |
| 357 | printf(","); |
| 358 | } |
| 359 | if (tb[NL80211_ATTR_SCAN_SSIDS]) { |
| 360 | nla_for_each_nested(nst, tb[NL80211_ATTR_SCAN_SSIDS], rem_nst) { |
| 361 | printf(" \""); |
| 362 | print_ssid_escaped(nla_len(nst), nla_data(nst)); |
| 363 | printf("\""); |
| 364 | } |
| 365 | } |
| 366 | printf("\n"); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 367 | break; |
Luciano Coelho | 3fce58a | 2015-03-17 16:11:48 +0200 | [diff] [blame] | 368 | case NL80211_CMD_START_SCHED_SCAN: |
| 369 | printf("scheduled scan started\n"); |
| 370 | break; |
| 371 | case NL80211_CMD_SCHED_SCAN_STOPPED: |
| 372 | printf("sched scan stopped\n"); |
| 373 | break; |
| 374 | case NL80211_CMD_SCHED_SCAN_RESULTS: |
| 375 | printf("got scheduled scan results\n"); |
| 376 | break; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 377 | case NL80211_CMD_REG_CHANGE: |
| 378 | printf("regulatory domain change: "); |
| 379 | |
| 380 | reg_type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]); |
| 381 | |
| 382 | switch (reg_type) { |
| 383 | case NL80211_REGDOM_TYPE_COUNTRY: |
| 384 | printf("set to %s by %s request", |
| 385 | nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]), |
| 386 | reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]))); |
| 387 | if (tb[NL80211_ATTR_WIPHY]) |
| 388 | printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY])); |
| 389 | break; |
| 390 | case NL80211_REGDOM_TYPE_WORLD: |
| 391 | printf("set to world roaming by %s request", |
| 392 | reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]))); |
| 393 | break; |
| 394 | case NL80211_REGDOM_TYPE_CUSTOM_WORLD: |
| 395 | printf("custom world roaming rules in place on phy%d by %s request", |
| 396 | nla_get_u32(tb[NL80211_ATTR_WIPHY]), |
| 397 | reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR]))); |
| 398 | break; |
| 399 | case NL80211_REGDOM_TYPE_INTERSECTION: |
| 400 | printf("intersection used due to a request made by %s", |
| 401 | reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR]))); |
| 402 | if (tb[NL80211_ATTR_WIPHY]) |
| 403 | printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY])); |
| 404 | break; |
| 405 | default: |
| 406 | printf("unknown source (upgrade this utility)"); |
| 407 | break; |
| 408 | } |
| 409 | |
| 410 | printf("\n"); |
| 411 | break; |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 412 | case NL80211_CMD_REG_BEACON_HINT: |
| 413 | |
| 414 | wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]); |
| 415 | |
| 416 | memset(&chan_before_beacon, 0, sizeof(chan_before_beacon)); |
| 417 | memset(&chan_after_beacon, 0, sizeof(chan_after_beacon)); |
| 418 | |
Johannes Berg | ce3b2ed | 2010-09-29 22:32:17 +0200 | [diff] [blame] | 419 | if (parse_beacon_hint_chan(tb[NL80211_ATTR_FREQ_BEFORE], |
| 420 | &chan_before_beacon)) |
| 421 | break; |
| 422 | if (parse_beacon_hint_chan(tb[NL80211_ATTR_FREQ_AFTER], |
| 423 | &chan_after_beacon)) |
| 424 | break; |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 425 | |
| 426 | if (chan_before_beacon.center_freq != chan_after_beacon.center_freq) |
| 427 | break; |
| 428 | |
| 429 | /* A beacon hint is sent _only_ if something _did_ change */ |
| 430 | printf("beacon hint:\n"); |
| 431 | |
| 432 | printf("phy%d %d MHz [%d]:\n", |
| 433 | wiphy_idx, |
| 434 | chan_before_beacon.center_freq, |
| 435 | ieee80211_frequency_to_channel(chan_before_beacon.center_freq)); |
| 436 | |
Ilan Peer | f0c48e7 | 2013-11-14 09:15:34 +0200 | [diff] [blame] | 437 | if (chan_before_beacon.no_ir && !chan_after_beacon.no_ir) { |
| 438 | if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss) |
| 439 | printf("\to Initiating radiation enabled\n"); |
| 440 | else |
| 441 | printf("\to active scan enabled\n"); |
| 442 | } else if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss) { |
| 443 | printf("\to ibss enabled\n"); |
| 444 | } |
Luis R. Rodriguez | 0168589 | 2009-07-30 17:05:50 -0700 | [diff] [blame] | 445 | |
| 446 | break; |
Johannes Berg | cec6d6a | 2009-12-06 18:58:00 +0100 | [diff] [blame] | 447 | case NL80211_CMD_NEW_STATION: |
| 448 | mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); |
| 449 | printf("new station %s\n", macbuf); |
| 450 | break; |
Antonio Quartulli | 27bf109 | 2012-01-08 12:39:26 +0100 | [diff] [blame] | 451 | case NL80211_CMD_DEL_STATION: |
| 452 | mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); |
| 453 | printf("del station %s\n", macbuf); |
| 454 | break; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 455 | case NL80211_CMD_JOIN_IBSS: |
| 456 | mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); |
| 457 | printf("IBSS %s joined\n", macbuf); |
| 458 | break; |
| 459 | case NL80211_CMD_AUTHENTICATE: |
| 460 | printf("auth"); |
Johannes Berg | aea5dbd | 2009-06-10 13:55:31 +0200 | [diff] [blame] | 461 | if (tb[NL80211_ATTR_FRAME]) |
| 462 | print_frame(args, tb[NL80211_ATTR_FRAME]); |
| 463 | else if (tb[NL80211_ATTR_TIMED_OUT]) |
| 464 | printf(": timed out"); |
| 465 | else |
| 466 | printf(": unknown event"); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 467 | printf("\n"); |
| 468 | break; |
| 469 | case NL80211_CMD_ASSOCIATE: |
| 470 | printf("assoc"); |
Johannes Berg | aea5dbd | 2009-06-10 13:55:31 +0200 | [diff] [blame] | 471 | if (tb[NL80211_ATTR_FRAME]) |
| 472 | print_frame(args, tb[NL80211_ATTR_FRAME]); |
| 473 | else if (tb[NL80211_ATTR_TIMED_OUT]) |
| 474 | printf(": timed out"); |
| 475 | else |
| 476 | printf(": unknown event"); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 477 | printf("\n"); |
| 478 | break; |
| 479 | case NL80211_CMD_DEAUTHENTICATE: |
| 480 | printf("deauth"); |
| 481 | print_frame(args, tb[NL80211_ATTR_FRAME]); |
| 482 | printf("\n"); |
| 483 | break; |
| 484 | case NL80211_CMD_DISASSOCIATE: |
| 485 | printf("disassoc"); |
| 486 | print_frame(args, tb[NL80211_ATTR_FRAME]); |
| 487 | printf("\n"); |
| 488 | break; |
Johannes Berg | 99802e5 | 2011-01-06 16:00:49 +0100 | [diff] [blame] | 489 | case NL80211_CMD_UNPROT_DEAUTHENTICATE: |
| 490 | printf("unprotected deauth"); |
| 491 | print_frame(args, tb[NL80211_ATTR_FRAME]); |
| 492 | printf("\n"); |
| 493 | break; |
| 494 | case NL80211_CMD_UNPROT_DISASSOCIATE: |
| 495 | printf("unprotected disassoc"); |
| 496 | print_frame(args, tb[NL80211_ATTR_FRAME]); |
| 497 | printf("\n"); |
| 498 | break; |
Johannes Berg | f1a666a | 2009-07-02 09:54:02 +0200 | [diff] [blame] | 499 | case NL80211_CMD_CONNECT: |
| 500 | status = 0; |
| 501 | if (!tb[NL80211_ATTR_STATUS_CODE]) |
| 502 | printf("unknown connect status"); |
| 503 | else if (nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]) == 0) |
| 504 | printf("connected"); |
| 505 | else { |
| 506 | status = nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]); |
| 507 | printf("failed to connect"); |
| 508 | } |
| 509 | if (tb[NL80211_ATTR_MAC]) { |
| 510 | mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); |
| 511 | printf(" to %s", macbuf); |
| 512 | } |
| 513 | if (status) |
| 514 | printf(", status: %d: %s", status, get_status_str(status)); |
| 515 | printf("\n"); |
| 516 | break; |
| 517 | case NL80211_CMD_ROAM: |
| 518 | printf("roamed"); |
| 519 | if (tb[NL80211_ATTR_MAC]) { |
| 520 | mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); |
| 521 | printf(" to %s", macbuf); |
| 522 | } |
| 523 | printf("\n"); |
| 524 | break; |
| 525 | case NL80211_CMD_DISCONNECT: |
| 526 | printf("disconnected"); |
| 527 | if (tb[NL80211_ATTR_DISCONNECTED_BY_AP]) |
| 528 | printf(" (by AP)"); |
| 529 | else |
| 530 | printf(" (local request)"); |
| 531 | if (tb[NL80211_ATTR_REASON_CODE]) |
| 532 | printf(" reason: %d: %s", nla_get_u16(tb[NL80211_ATTR_REASON_CODE]), |
| 533 | get_reason_str(nla_get_u16(tb[NL80211_ATTR_REASON_CODE]))); |
| 534 | printf("\n"); |
| 535 | break; |
Johannes Berg | 6829308 | 2010-02-02 20:51:42 +0100 | [diff] [blame] | 536 | case NL80211_CMD_REMAIN_ON_CHANNEL: |
| 537 | printf("remain on freq %d (%dms, cookie %llx)\n", |
| 538 | nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]), |
| 539 | nla_get_u32(tb[NL80211_ATTR_DURATION]), |
| 540 | (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE])); |
| 541 | break; |
| 542 | case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: |
| 543 | printf("done with remain on freq %d (cookie %llx)\n", |
| 544 | nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]), |
| 545 | (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE])); |
| 546 | break; |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 547 | case NL80211_CMD_NOTIFY_CQM: |
Johannes Berg | f19444f | 2011-01-06 15:58:58 +0100 | [diff] [blame] | 548 | parse_cqm_event(tb); |
Juuso Oikarinen | 7988b22 | 2010-03-26 07:46:19 +0200 | [diff] [blame] | 549 | break; |
Jouni Malinen | 8612433 | 2011-02-04 13:28:23 +0100 | [diff] [blame] | 550 | case NL80211_CMD_MICHAEL_MIC_FAILURE: |
| 551 | parse_mic_failure(tb); |
| 552 | break; |
Johannes Berg | cbff708 | 2011-04-20 15:41:54 +0200 | [diff] [blame] | 553 | case NL80211_CMD_FRAME_TX_STATUS: |
| 554 | printf("mgmt TX status (cookie %llx): %s\n", |
| 555 | (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]), |
| 556 | tb[NL80211_ATTR_ACK] ? "acked" : "no ack"); |
| 557 | break; |
Johannes Berg | 0bf2c6a | 2013-01-22 13:06:18 +0100 | [diff] [blame] | 558 | case NL80211_CMD_PMKSA_CANDIDATE: |
Johannes Berg | b6688cb | 2011-11-04 11:51:05 +0100 | [diff] [blame] | 559 | printf("PMKSA candidate found\n"); |
| 560 | break; |
Johannes Berg | 819b78c | 2013-02-19 23:31:27 +0100 | [diff] [blame] | 561 | case NL80211_CMD_SET_WOWLAN: |
| 562 | parse_wowlan_wake_event(tb); |
| 563 | break; |
Ben Greear | 4310994 | 2013-04-24 12:25:52 -0700 | [diff] [blame] | 564 | case NL80211_CMD_PROBE_CLIENT: |
| 565 | if (tb[NL80211_ATTR_MAC]) |
| 566 | mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); |
| 567 | else |
| 568 | strcpy(macbuf, "??"); |
| 569 | printf("probe client %s (cookie %llx): %s\n", |
| 570 | macbuf, |
| 571 | (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]), |
| 572 | tb[NL80211_ATTR_ACK] ? "acked" : "no ack"); |
| 573 | break; |
Johannes Berg | e8b3b31 | 2014-01-24 15:56:02 +0100 | [diff] [blame] | 574 | case NL80211_CMD_VENDOR: |
| 575 | printf("vendor event %.6x:%d\n", |
| 576 | nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]), |
| 577 | nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD])); |
Janusz Dziedzic | 492354d | 2014-08-27 09:58:28 +0200 | [diff] [blame] | 578 | if (args->frame && tb[NL80211_ATTR_VENDOR_DATA]) |
| 579 | iw_hexdump("vendor event", |
| 580 | nla_data(tb[NL80211_ATTR_VENDOR_DATA]), |
| 581 | nla_len(tb[NL80211_ATTR_VENDOR_DATA])); |
Johannes Berg | e8b3b31 | 2014-01-24 15:56:02 +0100 | [diff] [blame] | 582 | break; |
Helmut Schaa | 085f4f0 | 2015-01-30 10:42:44 +0100 | [diff] [blame] | 583 | case NL80211_CMD_RADAR_DETECT: |
| 584 | printf("radar event "); |
| 585 | if (tb[NL80211_ATTR_RADAR_EVENT]) { |
| 586 | switch (nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT])) { |
| 587 | case NL80211_RADAR_DETECTED: |
| 588 | printf("(radar detected)"); |
| 589 | break; |
| 590 | case NL80211_RADAR_CAC_FINISHED: |
| 591 | printf("(cac finished)"); |
| 592 | break; |
| 593 | case NL80211_RADAR_CAC_ABORTED: |
| 594 | printf("(cac aborted)"); |
| 595 | break; |
| 596 | case NL80211_RADAR_NOP_FINISHED: |
| 597 | printf("(nop finished)"); |
| 598 | break; |
| 599 | default: |
| 600 | printf("(unknown)"); |
| 601 | break; |
| 602 | }; |
| 603 | } else { |
| 604 | printf("(unknown)"); |
| 605 | } |
| 606 | printf("\n"); |
| 607 | break; |
Ben Greear | a3ca7c6 | 2015-06-11 15:54:11 -0400 | [diff] [blame] | 608 | case NL80211_CMD_DEL_WIPHY: |
| 609 | printf("delete wiphy\n"); |
| 610 | break; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 611 | default: |
Johannes Berg | 7c712c8 | 2014-01-28 12:16:16 +0100 | [diff] [blame] | 612 | printf("unknown event %d (%s)\n", |
| 613 | gnlh->cmd, command_name(gnlh->cmd)); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 614 | break; |
| 615 | } |
| 616 | |
Johannes Berg | 374e8a2 | 2010-09-29 09:00:14 +0200 | [diff] [blame] | 617 | fflush(stdout); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 618 | return NL_SKIP; |
| 619 | } |
| 620 | |
| 621 | struct wait_event { |
| 622 | int n_cmds; |
| 623 | const __u32 *cmds; |
| 624 | __u32 cmd; |
Johannes Berg | 7fabd34 | 2009-07-08 18:53:06 +0200 | [diff] [blame] | 625 | struct print_event_args *pargs; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 626 | }; |
| 627 | |
| 628 | static int wait_event(struct nl_msg *msg, void *arg) |
| 629 | { |
| 630 | struct wait_event *wait = arg; |
| 631 | struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); |
| 632 | int i; |
| 633 | |
| 634 | for (i = 0; i < wait->n_cmds; i++) { |
| 635 | if (gnlh->cmd == wait->cmds[i]) { |
| 636 | wait->cmd = gnlh->cmd; |
Johannes Berg | 7e7c544 | 2010-09-29 14:48:26 +0200 | [diff] [blame] | 637 | if (wait->pargs) |
| 638 | print_event(msg, wait->pargs); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 639 | } |
| 640 | } |
| 641 | |
| 642 | return NL_SKIP; |
| 643 | } |
| 644 | |
Johannes Berg | ee374e4 | 2010-06-09 11:59:56 +0200 | [diff] [blame] | 645 | int __prepare_listen_events(struct nl80211_state *state) |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 646 | { |
| 647 | int mcid, ret; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 648 | |
| 649 | /* Configuration multicast group */ |
| 650 | mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "config"); |
| 651 | if (mcid < 0) |
| 652 | return mcid; |
| 653 | |
| 654 | ret = nl_socket_add_membership(state->nl_sock, mcid); |
| 655 | if (ret) |
| 656 | return ret; |
| 657 | |
| 658 | /* Scan multicast group */ |
| 659 | mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan"); |
| 660 | if (mcid >= 0) { |
| 661 | ret = nl_socket_add_membership(state->nl_sock, mcid); |
| 662 | if (ret) |
| 663 | return ret; |
| 664 | } |
| 665 | |
| 666 | /* Regulatory multicast group */ |
| 667 | mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "regulatory"); |
| 668 | if (mcid >= 0) { |
| 669 | ret = nl_socket_add_membership(state->nl_sock, mcid); |
| 670 | if (ret) |
| 671 | return ret; |
| 672 | } |
| 673 | |
| 674 | /* MLME multicast group */ |
| 675 | mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "mlme"); |
| 676 | if (mcid >= 0) { |
| 677 | ret = nl_socket_add_membership(state->nl_sock, mcid); |
| 678 | if (ret) |
| 679 | return ret; |
| 680 | } |
| 681 | |
Johannes Berg | e8b3b31 | 2014-01-24 15:56:02 +0100 | [diff] [blame] | 682 | mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "vendor"); |
| 683 | if (mcid >= 0) { |
| 684 | ret = nl_socket_add_membership(state->nl_sock, mcid); |
| 685 | if (ret) |
| 686 | return ret; |
| 687 | } |
| 688 | |
Johannes Berg | 105aed5 | 2010-06-09 11:50:07 +0200 | [diff] [blame] | 689 | return 0; |
| 690 | } |
| 691 | |
Johannes Berg | ee374e4 | 2010-06-09 11:59:56 +0200 | [diff] [blame] | 692 | __u32 __do_listen_events(struct nl80211_state *state, |
| 693 | const int n_waits, const __u32 *waits, |
| 694 | struct print_event_args *args) |
Johannes Berg | 105aed5 | 2010-06-09 11:50:07 +0200 | [diff] [blame] | 695 | { |
| 696 | struct nl_cb *cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); |
| 697 | struct wait_event wait_ev; |
Johannes Berg | 105aed5 | 2010-06-09 11:50:07 +0200 | [diff] [blame] | 698 | |
| 699 | if (!cb) { |
| 700 | fprintf(stderr, "failed to allocate netlink callbacks\n"); |
| 701 | return -ENOMEM; |
| 702 | } |
| 703 | |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 704 | /* no sequence checking for multicast messages */ |
| 705 | nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); |
| 706 | |
| 707 | if (n_waits && waits) { |
| 708 | wait_ev.cmds = waits; |
| 709 | wait_ev.n_cmds = n_waits; |
Johannes Berg | 7fabd34 | 2009-07-08 18:53:06 +0200 | [diff] [blame] | 710 | wait_ev.pargs = args; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 711 | nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, wait_event, &wait_ev); |
Johannes Berg | 7fabd34 | 2009-07-08 18:53:06 +0200 | [diff] [blame] | 712 | } else |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 713 | nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_event, args); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 714 | |
| 715 | wait_ev.cmd = 0; |
| 716 | |
| 717 | while (!wait_ev.cmd) |
| 718 | nl_recvmsgs(state->nl_sock, cb); |
| 719 | |
| 720 | nl_cb_put(cb); |
| 721 | |
| 722 | return wait_ev.cmd; |
| 723 | } |
| 724 | |
| 725 | __u32 listen_events(struct nl80211_state *state, |
| 726 | const int n_waits, const __u32 *waits) |
| 727 | { |
Johannes Berg | ee374e4 | 2010-06-09 11:59:56 +0200 | [diff] [blame] | 728 | int ret; |
| 729 | |
| 730 | ret = __prepare_listen_events(state); |
| 731 | if (ret) |
| 732 | return ret; |
| 733 | |
| 734 | return __do_listen_events(state, n_waits, waits, NULL); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 735 | } |
| 736 | |
| 737 | static int print_events(struct nl80211_state *state, |
| 738 | struct nl_cb *cb, |
| 739 | struct nl_msg *msg, |
Johannes Berg | 05514f9 | 2012-07-19 11:50:50 +0200 | [diff] [blame] | 740 | int argc, char **argv, |
| 741 | enum id_input id) |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 742 | { |
| 743 | struct print_event_args args; |
Johannes Berg | ee374e4 | 2010-06-09 11:59:56 +0200 | [diff] [blame] | 744 | int ret; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 745 | |
| 746 | memset(&args, 0, sizeof(args)); |
| 747 | |
| 748 | argc--; |
| 749 | argv++; |
| 750 | |
| 751 | while (argc > 0) { |
| 752 | if (strcmp(argv[0], "-f") == 0) |
| 753 | args.frame = true; |
| 754 | else if (strcmp(argv[0], "-t") == 0) |
| 755 | args.time = true; |
Johannes Berg | 981b21a | 2010-10-13 17:52:15 +0200 | [diff] [blame] | 756 | else if (strcmp(argv[0], "-r") == 0) |
| 757 | args.reltime = true; |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 758 | else |
| 759 | return 1; |
| 760 | argc--; |
| 761 | argv++; |
| 762 | } |
| 763 | |
Johannes Berg | 981b21a | 2010-10-13 17:52:15 +0200 | [diff] [blame] | 764 | if (args.time && args.reltime) |
| 765 | return 1; |
| 766 | |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 767 | if (argc) |
| 768 | return 1; |
| 769 | |
Johannes Berg | ee374e4 | 2010-06-09 11:59:56 +0200 | [diff] [blame] | 770 | ret = __prepare_listen_events(state); |
| 771 | if (ret) |
| 772 | return ret; |
| 773 | |
| 774 | return __do_listen_events(state, 0, NULL, &args); |
Johannes Berg | 957a0f0 | 2009-05-05 14:10:09 +0200 | [diff] [blame] | 775 | } |
Johannes Berg | 981b21a | 2010-10-13 17:52:15 +0200 | [diff] [blame] | 776 | TOPLEVEL(event, "[-t] [-r] [-f]", 0, 0, CIB_NONE, print_events, |
Johannes Berg | 01ae06f | 2009-05-05 14:48:16 +0200 | [diff] [blame] | 777 | "Monitor events from the kernel.\n" |
| 778 | "-t - print timestamp\n" |
Johannes Berg | 981b21a | 2010-10-13 17:52:15 +0200 | [diff] [blame] | 779 | "-r - print relative timstamp\n" |
Johannes Berg | 01ae06f | 2009-05-05 14:48:16 +0200 | [diff] [blame] | 780 | "-f - print full frame for auth/assoc etc."); |