#include <stdbool.h>
#include <net/if.h>
#include <errno.h>
+#include <inttypes.h>
#include "iw.h"
static int no_seq_check(struct nl_msg *msg, void *arg)
{
uint8_t *frame;
size_t len;
- int i;
+ unsigned int i;
char macbuf[6*3];
uint16_t tmp;
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);
+ nla_parse_nested(tb_match, NL80211_ATTR_MAX, match,
+ NULL);
printf("\t\tSSID: \"");
print_ssid_escaped(nla_len(tb_match[NL80211_ATTR_SSID]),
nla_data(tb_match[NL80211_ATTR_SSID]));
printf("\t* TCP connection ran out of tokens\n");
}
+static void parse_nan_term(struct nlattr **attrs)
+{
+ struct nlattr *func[NL80211_NAN_FUNC_ATTR_MAX + 1];
+
+ static struct nla_policy
+ nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
+ [NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_SERVICE_ID] = { },
+ [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { },
+ [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
+ [NL80211_NAN_FUNC_SERVICE_INFO] = { },
+ [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8},
+ };
+
+ if (!attrs[NL80211_ATTR_COOKIE]) {
+ printf("Bad NAN func termination format - cookie is missing\n");
+ return;
+ }
+
+ if (nla_parse_nested(func, NL80211_NAN_FUNC_ATTR_MAX,
+ attrs[NL80211_ATTR_NAN_FUNC],
+ nan_func_policy)) {
+ printf("NAN: failed to parse nan func\n");
+ return;
+ }
+
+ if (!func[NL80211_NAN_FUNC_INSTANCE_ID]) {
+ printf("Bad NAN func termination format-instance id missing\n");
+ return;
+ }
+
+ if (!func[NL80211_NAN_FUNC_TERM_REASON]) {
+ printf("Bad NAN func termination format - reason is missing\n");
+ return;
+ }
+ printf("NAN(cookie=0x%llx): Termination event: id = %d, reason = ",
+ (long long int)nla_get_u64(attrs[NL80211_ATTR_COOKIE]),
+ nla_get_u8(func[NL80211_NAN_FUNC_INSTANCE_ID]));
+ switch (nla_get_u8(func[NL80211_NAN_FUNC_TERM_REASON])) {
+ case NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST:
+ printf("user request\n");
+ break;
+ case NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED:
+ printf("expired\n");
+ break;
+ case NL80211_NAN_FUNC_TERM_REASON_ERROR:
+ printf("error\n");
+ break;
+ default:
+ printf("unknown\n");
+ }
+}
+
+static void parse_nan_match(struct nlattr **attrs)
+{
+ char macbuf[6*3];
+ __u64 cookie;
+ struct nlattr *match[NL80211_NAN_MATCH_ATTR_MAX + 1];
+ struct nlattr *local_func[NL80211_NAN_FUNC_ATTR_MAX + 1];
+ struct nlattr *peer_func[NL80211_NAN_FUNC_ATTR_MAX + 1];
+
+ static struct nla_policy
+ nan_match_policy[NL80211_NAN_MATCH_ATTR_MAX + 1] = {
+ [NL80211_NAN_MATCH_FUNC_LOCAL] = { .type = NLA_NESTED },
+ [NL80211_NAN_MATCH_FUNC_PEER] = { .type = NLA_NESTED },
+ };
+
+ static struct nla_policy
+ nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
+ [NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_SERVICE_ID] = { },
+ [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { },
+ [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
+ [NL80211_NAN_FUNC_SERVICE_INFO] = { },
+ [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8},
+ };
+
+ cookie = nla_get_u64(attrs[NL80211_ATTR_COOKIE]);
+ mac_addr_n2a(macbuf, nla_data(attrs[NL80211_ATTR_MAC]));
+
+ if (nla_parse_nested(match, NL80211_NAN_MATCH_ATTR_MAX,
+ attrs[NL80211_ATTR_NAN_MATCH],
+ nan_match_policy)) {
+ printf("NAN: failed to parse nan match event\n");
+ return;
+ }
+
+ if (nla_parse_nested(local_func, NL80211_NAN_FUNC_ATTR_MAX,
+ match[NL80211_NAN_MATCH_FUNC_LOCAL],
+ nan_func_policy)) {
+ printf("NAN: failed to parse nan local func\n");
+ return;
+ }
+
+ if (nla_parse_nested(peer_func, NL80211_NAN_FUNC_ATTR_MAX,
+ match[NL80211_NAN_MATCH_FUNC_PEER],
+ nan_func_policy)) {
+ printf("NAN: failed to parse nan local func\n");
+ return;
+ }
+
+ if (nla_get_u8(peer_func[NL80211_NAN_FUNC_TYPE]) ==
+ NL80211_NAN_FUNC_PUBLISH) {
+ printf(
+ "NAN(cookie=0x%llx): DiscoveryResult, peer_id=%d, local_id=%d, peer_mac=%s, ",
+ cookie,
+ nla_get_u8(peer_func[NL80211_NAN_FUNC_INSTANCE_ID]),
+ nla_get_u8(local_func[NL80211_NAN_FUNC_INSTANCE_ID]),
+ macbuf);
+ if (peer_func[NL80211_NAN_FUNC_SERVICE_INFO])
+ printf("info=%.*s",
+ nla_len(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]),
+ (char *)nla_data(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]));
+ } else if (nla_get_u8(peer_func[NL80211_NAN_FUNC_TYPE]) ==
+ NL80211_NAN_FUNC_SUBSCRIBE) {
+ printf(
+ "NAN(cookie=0x%llx): Replied, peer_id=%d, local_id=%d, peer_mac=%s\n",
+ cookie,
+ nla_get_u8(peer_func[NL80211_NAN_FUNC_INSTANCE_ID]),
+ nla_get_u8(local_func[NL80211_NAN_FUNC_INSTANCE_ID]),
+ macbuf);
+ } else if (nla_get_u8(peer_func[NL80211_NAN_FUNC_TYPE]) ==
+ NL80211_NAN_FUNC_FOLLOW_UP) {
+ printf(
+ "NAN(cookie=0x%llx): FollowUpReceive, peer_id=%d, local_id=%d, peer_mac=%s, ",
+ cookie,
+ nla_get_u8(peer_func[NL80211_NAN_FUNC_INSTANCE_ID]),
+ nla_get_u8(local_func[NL80211_NAN_FUNC_INSTANCE_ID]),
+ macbuf);
+ if (peer_func[NL80211_NAN_FUNC_SERVICE_INFO])
+ printf("info=%.*s",
+ nla_len(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]),
+ (char *)nla_data(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]));
+ } else {
+ printf("NaN: Malformed event\n");
+ }
+}
+
static int print_event(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
break;
case NL80211_CMD_NEW_SCAN_RESULTS:
printf("scan finished:");
+ /* fall through */
case NL80211_CMD_SCAN_ABORTED:
if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED)
printf("scan aborted:");
break;
case NL80211_CMD_CONNECT:
status = 0;
- if (!tb[NL80211_ATTR_STATUS_CODE])
+ if (tb[NL80211_ATTR_TIMED_OUT])
+ printf("timed out");
+ else if (!tb[NL80211_ATTR_STATUS_CODE])
printf("unknown connect status");
else if (nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]) == 0)
printf("connected");
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)");
+ case NL80211_CMD_RADAR_DETECT: {
+ enum nl80211_radar_event event_type;
+ uint32_t freq;
+
+ if (!tb[NL80211_ATTR_RADAR_EVENT] ||
+ !tb[NL80211_ATTR_WIPHY_FREQ]) {
+ printf("BAD radar event\n");
+ break;
+ }
+
+ freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
+ event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
+
+ switch (event_type) {
+ case NL80211_RADAR_DETECTED:
+ printf("%d MHz: radar detected\n", freq);
+ break;
+ case NL80211_RADAR_CAC_FINISHED:
+ printf("%d MHz: CAC finished\n", freq);
+ break;
+ case NL80211_RADAR_CAC_ABORTED:
+ printf("%d MHz: CAC was aborted\n", freq);
+ break;
+ case NL80211_RADAR_NOP_FINISHED:
+ printf("%d MHz: NOP finished\n", freq);
+ break;
+ default:
+ printf("%d MHz: unknown radar event\n", freq);
+ }
}
- printf("\n");
break;
case NL80211_CMD_DEL_WIPHY:
printf("delete wiphy\n");
break;
+ case NL80211_CMD_DEL_NAN_FUNCTION:
+ parse_nan_term(tb);
+ break;
+ case NL80211_CMD_NAN_MATCH: {
+ parse_nan_match(tb);
+ break;
+ }
default:
printf("unknown event %d (%s)\n",
gnlh->cmd, command_name(gnlh->cmd));
return ret;
}
+ mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "nan");
+ if (mcid >= 0) {
+ ret = nl_socket_add_membership(state->nl_sock, mcid);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
return __do_listen_events(state, 0, NULL, &args);
}
-TOPLEVEL(event, "[-t] [-r] [-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"