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 },
[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] &&
+ 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("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];
+
+ 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_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)
{
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]));
}
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);
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])
(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;
default:
printf("unknown event %d\n", gnlh->cmd);
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;