X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=event.c;h=896f03ab7636a49b3e477581fa3744175437e27c;hb=96fa73c7564fa7eba89cd78a24f20acd68d2f55f;hp=ac2dabc51c2359873e3a2166a843086b8c3d3051;hpb=ce3b2ed9e98699a3f406f8cece78e54351028f0e;p=thirdparty%2Fiw.git diff --git a/event.c b/event.c index ac2dabc..896f03a 100644 --- a/event.c +++ b/event.c @@ -11,7 +11,7 @@ static int no_seq_check(struct nl_msg *msg, void *arg) struct ieee80211_beacon_channel { __u16 center_freq; - bool passive_scan; + bool no_ir; bool no_ibss; }; @@ -21,8 +21,8 @@ static int parse_beacon_hint_chan(struct nlattr *tb, struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; static struct nla_policy beacon_freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, - [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, + [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG }, + [__NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, }; if (nla_parse_nested(tb_freq, @@ -33,9 +33,9 @@ static int parse_beacon_hint_chan(struct nlattr *tb, chan->center_freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); - if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) - chan->passive_scan = true; - if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS]) + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR]) + chan->no_ir = true; + if (tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]) chan->no_ibss = true; return 0; @@ -45,12 +45,14 @@ static void print_frame(struct print_event_args *args, struct nlattr *attr) { uint8_t *frame; size_t len; - int i; + unsigned int i; char macbuf[6*3]; uint16_t tmp; - if (!attr) + if (!attr) { printf(" [no frame]"); + return; + } frame = nla_data(attr); len = nla_len(attr); @@ -80,7 +82,6 @@ static void print_frame(struct print_event_args *args, struct nlattr *attr) tmp = (frame[29] << 8) + frame[28]; printf(" status: %d: %s", tmp, get_status_str(tmp)); break; - break; case 0xa0: /* disassoc */ case 0xc0: /* deauth */ /* reason */ @@ -100,7 +101,7 @@ static void print_frame(struct print_event_args *args, struct nlattr *attr) printf("]"); } -static void parse_cqm_event(struct nlattr *tb) +static void parse_cqm_event(struct nlattr **attrs) { static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, @@ -108,25 +109,189 @@ static void parse_cqm_event(struct nlattr *tb) [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, }; struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; + struct nlattr *cqm_attr = attrs[NL80211_ATTR_CQM]; - printf("connection quality monitor event: "); + printf("CQM event: "); - if (!tb || nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb, cqm_policy)) { + if (!cqm_attr || + nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, cqm_attr, cqm_policy)) { printf("missing data!\n"); return; } if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]) { enum nl80211_cqm_rssi_threshold_event rssi_event; + bool found_one = false; + rssi_event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]); - if (rssi_event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) - printf("RSSI went above threshold"); - else - printf("RSSI went below threshold"); + + switch (rssi_event) { + case NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: + printf("RSSI went above threshold\n"); + found_one = true; + break; + case NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: + printf("RSSI went below threshold\n"); + found_one = true; + break; + case NL80211_CQM_RSSI_BEACON_LOSS_EVENT: + printf("Beacon loss detected\n"); + found_one = true; + break; + } + + if (!found_one) + printf("Unknown event type: %i\n", rssi_event); + } else if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) { + if (attrs[NL80211_ATTR_MAC]) { + uint32_t frames; + char buf[3*6]; + + frames = nla_get_u32(cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]); + mac_addr_n2a(buf, nla_data(attrs[NL80211_ATTR_MAC])); + printf("peer %s didn't ACK %d packets\n", buf, frames); + } else { + printf("PKT-LOSS-EVENT did not have MAC attribute!\n"); + } + } else if (cqm[NL80211_ATTR_CQM_BEACON_LOSS_EVENT]) { + printf("beacon loss\n"); + } else { + printf("unknown event\n"); + } +} + +static const char * key_type_str(enum nl80211_key_type key_type) +{ + static char buf[30]; + switch (key_type) { + case NL80211_KEYTYPE_GROUP: + return "Group"; + case NL80211_KEYTYPE_PAIRWISE: + return "Pairwise"; + case NL80211_KEYTYPE_PEERKEY: + return "PeerKey"; + default: + snprintf(buf, sizeof(buf), "unknown(%d)", key_type); + return buf; } +} + +static void parse_mic_failure(struct nlattr **attrs) +{ + printf("Michael MIC failure event:"); + + if (attrs[NL80211_ATTR_MAC]) { + char addr[3 * ETH_ALEN]; + mac_addr_n2a(addr, nla_data(attrs[NL80211_ATTR_MAC])); + printf(" source MAC address %s", addr); + } + + if (attrs[NL80211_ATTR_KEY_SEQ] && + nla_len(attrs[NL80211_ATTR_KEY_SEQ]) == 6) { + unsigned char *seq = nla_data(attrs[NL80211_ATTR_KEY_SEQ]); + printf(" seq=%02x%02x%02x%02x%02x%02x", + seq[0], seq[1], seq[2], seq[3], seq[4], seq[5]); + } + if (attrs[NL80211_ATTR_KEY_TYPE]) { + enum nl80211_key_type key_type = + nla_get_u32(attrs[NL80211_ATTR_KEY_TYPE]); + printf(" Key Type %s", key_type_str(key_type)); + } + + if (attrs[NL80211_ATTR_KEY_IDX]) { + __u8 key_id = nla_get_u8(attrs[NL80211_ATTR_KEY_IDX]); + printf(" Key Id %d", key_id); + } + printf("\n"); } +static void parse_wowlan_wake_event(struct nlattr **attrs) +{ + struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG], + *tb_match[NUM_NL80211_ATTR]; + + printf("WoWLAN wakeup\n"); + if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { + printf("\twakeup not due to WoWLAN\n"); + return; + } + + nla_parse(tb, MAX_NL80211_WOWLAN_TRIG, + nla_data(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), + nla_len(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), NULL); + + if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) + printf("\t* was disconnected\n"); + if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) + printf("\t* magic packet received\n"); + if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) + printf("\t* pattern index: %u\n", + nla_get_u32(tb[NL80211_WOWLAN_TRIG_PKT_PATTERN])); + if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE]) + printf("\t* GTK rekey failure\n"); + if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) + printf("\t* EAP identity request\n"); + if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) + printf("\t* 4-way handshake\n"); + if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) + printf("\t* RF-kill released\n"); + if (tb[NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS]) { + struct nlattr *match, *freq; + int rem_nst, rem_nst2; + + printf("\t* network detected\n"); + nla_for_each_nested(match, + tb[NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS], + rem_nst) { + nla_parse(tb_match, NUM_NL80211_ATTR, nla_data(match), + nla_len(match), + NULL); + printf("\t\tSSID: \""); + print_ssid_escaped(nla_len(tb_match[NL80211_ATTR_SSID]), + nla_data(tb_match[NL80211_ATTR_SSID])); + printf("\""); + if (tb_match[NL80211_ATTR_SCAN_FREQUENCIES]) { + printf(" freq(s):"); + nla_for_each_nested(freq, + tb_match[NL80211_ATTR_SCAN_FREQUENCIES], + rem_nst2) + printf(" %d", nla_get_u32(freq)); + } + printf("\n"); + } + } + if (tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]) { + uint8_t *d = nla_data(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]); + int l = nla_len(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]); + int i; + printf("\t* packet (might be truncated): "); + for (i = 0; i < l; i++) { + if (i > 0) + printf(":"); + printf("%.2x", d[i]); + } + printf("\n"); + } + if (tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]) { + uint8_t *d = nla_data(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]); + int l = nla_len(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]); + int i; + printf("\t* packet (might be truncated): "); + for (i = 0; i < l; i++) { + if (i > 0) + printf(":"); + printf("%.2x", d[i]); + } + printf("\n"); + } + if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH]) + printf("\t* TCP connection wakeup received\n"); + if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST]) + printf("\t* TCP connection lost\n"); + if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS]) + printf("\t* TCP connection ran out of tokens\n"); +} static int print_event(struct nl_msg *msg, void *arg) { @@ -141,10 +306,20 @@ static int print_event(struct nl_msg *msg, void *arg) int rem_nst; __u16 status; - if (args->time) { - struct timeval tv; - gettimeofday(&tv, NULL); - printf("%ld.%06u: ", (long) tv.tv_sec, (unsigned int) tv.tv_usec); + if (args->time || args->reltime) { + unsigned long long usecs, previous; + + previous = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec; + gettimeofday(&args->ts, NULL); + usecs = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec; + if (args->reltime) { + if (!args->have_ts) { + usecs = 0; + args->have_ts = true; + } else + usecs -= previous; + } + printf("%llu.%06llu: ", usecs/1000000, usecs % 1000000); } nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), @@ -153,9 +328,15 @@ static int print_event(struct nl_msg *msg, void *arg) if (tb[NL80211_ATTR_IFINDEX] && tb[NL80211_ATTR_WIPHY]) { if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname); printf("%s (phy #%d): ", ifname, nla_get_u32(tb[NL80211_ATTR_WIPHY])); + } else if (tb[NL80211_ATTR_WDEV] && tb[NL80211_ATTR_WIPHY]) { + printf("wdev 0x%llx (phy #%d): ", + (unsigned long long)nla_get_u64(tb[NL80211_ATTR_WDEV]), + nla_get_u32(tb[NL80211_ATTR_WIPHY])); } else if (tb[NL80211_ATTR_IFINDEX]) { if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname); printf("%s: ", ifname); + } else if (tb[NL80211_ATTR_WDEV]) { + printf("wdev 0x%llx: ", (unsigned long long)nla_get_u64(tb[NL80211_ATTR_WDEV])); } else if (tb[NL80211_ATTR_WIPHY]) { printf("phy #%d: ", nla_get_u32(tb[NL80211_ATTR_WIPHY])); } @@ -186,6 +367,15 @@ static int print_event(struct nl_msg *msg, void *arg) } printf("\n"); break; + case NL80211_CMD_START_SCHED_SCAN: + printf("scheduled scan started\n"); + break; + case NL80211_CMD_SCHED_SCAN_STOPPED: + printf("sched scan stopped\n"); + break; + case NL80211_CMD_SCHED_SCAN_RESULTS: + printf("got scheduled scan results\n"); + break; case NL80211_CMD_REG_CHANGE: printf("regulatory domain change: "); @@ -246,16 +436,24 @@ static int print_event(struct nl_msg *msg, void *arg) chan_before_beacon.center_freq, ieee80211_frequency_to_channel(chan_before_beacon.center_freq)); - if (chan_before_beacon.passive_scan && !chan_after_beacon.passive_scan) - printf("\to active scanning enabled\n"); - if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss) - printf("\to beaconing enabled\n"); + if (chan_before_beacon.no_ir && !chan_after_beacon.no_ir) { + if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss) + printf("\to Initiating radiation enabled\n"); + else + printf("\to active scan enabled\n"); + } else if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss) { + printf("\to ibss enabled\n"); + } break; case NL80211_CMD_NEW_STATION: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); printf("new station %s\n", macbuf); break; + case NL80211_CMD_DEL_STATION: + mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); + printf("del station %s\n", macbuf); + break; case NL80211_CMD_JOIN_IBSS: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); printf("IBSS %s joined\n", macbuf); @@ -290,6 +488,16 @@ static int print_event(struct nl_msg *msg, void *arg) print_frame(args, tb[NL80211_ATTR_FRAME]); printf("\n"); break; + case NL80211_CMD_UNPROT_DEAUTHENTICATE: + printf("unprotected deauth"); + print_frame(args, tb[NL80211_ATTR_FRAME]); + printf("\n"); + break; + case NL80211_CMD_UNPROT_DISASSOCIATE: + printf("unprotected disassoc"); + print_frame(args, tb[NL80211_ATTR_FRAME]); + printf("\n"); + break; case NL80211_CMD_CONNECT: status = 0; if (!tb[NL80211_ATTR_STATUS_CODE]) @@ -339,10 +547,72 @@ static int print_event(struct nl_msg *msg, void *arg) (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE])); break; case NL80211_CMD_NOTIFY_CQM: - parse_cqm_event(tb[NL80211_ATTR_CQM]); + parse_cqm_event(tb); + break; + case NL80211_CMD_MICHAEL_MIC_FAILURE: + parse_mic_failure(tb); + break; + case NL80211_CMD_FRAME_TX_STATUS: + printf("mgmt TX status (cookie %llx): %s\n", + (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]), + tb[NL80211_ATTR_ACK] ? "acked" : "no ack"); + break; + case NL80211_CMD_PMKSA_CANDIDATE: + printf("PMKSA candidate found\n"); + break; + case NL80211_CMD_SET_WOWLAN: + parse_wowlan_wake_event(tb); + break; + case NL80211_CMD_PROBE_CLIENT: + if (tb[NL80211_ATTR_MAC]) + mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); + else + strcpy(macbuf, "??"); + printf("probe client %s (cookie %llx): %s\n", + macbuf, + (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]), + tb[NL80211_ATTR_ACK] ? "acked" : "no ack"); + break; + case NL80211_CMD_VENDOR: + printf("vendor event %.6x:%d\n", + nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]), + nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD])); + if (args->frame && tb[NL80211_ATTR_VENDOR_DATA]) + iw_hexdump("vendor event", + nla_data(tb[NL80211_ATTR_VENDOR_DATA]), + nla_len(tb[NL80211_ATTR_VENDOR_DATA])); + break; + case NL80211_CMD_RADAR_DETECT: + printf("radar event "); + if (tb[NL80211_ATTR_RADAR_EVENT]) { + switch (nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT])) { + case NL80211_RADAR_DETECTED: + printf("(radar detected)"); + break; + case NL80211_RADAR_CAC_FINISHED: + printf("(cac finished)"); + break; + case NL80211_RADAR_CAC_ABORTED: + printf("(cac aborted)"); + break; + case NL80211_RADAR_NOP_FINISHED: + printf("(nop finished)"); + break; + default: + printf("(unknown)"); + break; + }; + } else { + printf("(unknown)"); + } + printf("\n"); + break; + case NL80211_CMD_DEL_WIPHY: + printf("delete wiphy\n"); break; default: - printf("unknown event %d\n", gnlh->cmd); + printf("unknown event %d (%s)\n", + gnlh->cmd, command_name(gnlh->cmd)); break; } @@ -411,6 +681,13 @@ int __prepare_listen_events(struct nl80211_state *state) return ret; } + mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "vendor"); + if (mcid >= 0) { + ret = nl_socket_add_membership(state->nl_sock, mcid); + if (ret) + return ret; + } + return 0; } @@ -428,14 +705,15 @@ __u32 __do_listen_events(struct nl80211_state *state, /* no sequence checking for multicast messages */ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, NULL); if (n_waits && waits) { wait_ev.cmds = waits; wait_ev.n_cmds = n_waits; wait_ev.pargs = args; - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, wait_event, &wait_ev); + register_handler(wait_event, &wait_ev); } else - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_event, args); + register_handler(print_event, args); wait_ev.cmd = 0; @@ -460,9 +738,9 @@ __u32 listen_events(struct nl80211_state *state, } static int print_events(struct nl80211_state *state, - struct nl_cb *cb, struct nl_msg *msg, - int argc, char **argv) + int argc, char **argv, + enum id_input id) { struct print_event_args args; int ret; @@ -477,12 +755,17 @@ static int print_events(struct nl80211_state *state, args.frame = true; else if (strcmp(argv[0], "-t") == 0) args.time = true; + else if (strcmp(argv[0], "-r") == 0) + args.reltime = true; else return 1; argc--; argv++; } + if (args.time && args.reltime) + return 1; + if (argc) return 1; @@ -492,7 +775,8 @@ static int print_events(struct nl80211_state *state, return __do_listen_events(state, 0, NULL, &args); } -TOPLEVEL(event, "[-t] [-f]", 0, 0, CIB_NONE, print_events, +TOPLEVEL(event, "[-t|-r] [-f]", 0, 0, CIB_NONE, print_events, "Monitor events from the kernel.\n" "-t - print timestamp\n" + "-r - print relative timstamp\n" "-f - print full frame for auth/assoc etc.");