7 static int no_seq_check(struct nl_msg
*msg
, void *arg
)
12 struct print_event_args
{
16 static void print_frame(struct print_event_args
*args
, struct nlattr
*attr
)
25 printf(" [no frame]");
27 frame
= nla_data(attr
);
31 printf(" [invalid frame: ");
35 mac_addr_n2a(macbuf
, frame
+ 10);
36 printf(" %s -> ", macbuf
);
37 mac_addr_n2a(macbuf
, frame
+ 4);
40 switch (frame
[0] & 0xfc) {
41 case 0x10: /* assoc resp */
42 case 0x30: /* reassoc resp */
44 tmp
= (frame
[27] << 8) + frame
[26];
45 printf(" status: %d: %s", tmp
, get_status_str(tmp
));
47 case 0x00: /* assoc req */
48 case 0x20: /* reassoc req */
52 tmp
= (frame
[29] << 8) + frame
[28];
53 printf(" status: %d: %s", tmp
, get_status_str(tmp
));
56 case 0xa0: /* disassoc */
57 case 0xc0: /* deauth */
59 tmp
= (frame
[25] << 8) + frame
[24];
60 printf(" reason %d: %s", tmp
, get_reason_str(tmp
));
70 for (i
= 0; i
< len
; i
++)
71 printf(" %.02x", frame
[i
]);
75 static int print_event(struct nl_msg
*msg
, void *arg
)
77 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
78 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1], *nst
;
79 struct print_event_args
*args
= arg
;
87 gettimeofday(&tv
, NULL
);
88 printf("%ld.%06u: ", (long) tv
.tv_sec
, (unsigned int) tv
.tv_usec
);
91 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
92 genlmsg_attrlen(gnlh
, 0), NULL
);
94 if (tb
[NL80211_ATTR_IFINDEX
] && tb
[NL80211_ATTR_WIPHY
]) {
95 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
96 printf("%s (phy #%d): ", ifname
, nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
97 } else if (tb
[NL80211_ATTR_IFINDEX
]) {
98 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
99 printf("%s: ", ifname
);
100 } else if (tb
[NL80211_ATTR_WIPHY
]) {
101 printf("phy #%d: ", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
105 case NL80211_CMD_NEW_WIPHY
:
106 printf("renamed to %s\n", nla_get_string(tb
[NL80211_ATTR_WIPHY_NAME
]));
108 case NL80211_CMD_TRIGGER_SCAN
:
109 printf("scan started\n");
111 case NL80211_CMD_NEW_SCAN_RESULTS
:
112 printf("scan finished:");
113 case NL80211_CMD_SCAN_ABORTED
:
114 if (gnlh
->cmd
== NL80211_CMD_SCAN_ABORTED
)
115 printf("scan aborted:");
116 if (tb
[NL80211_ATTR_SCAN_FREQUENCIES
]) {
117 nla_for_each_nested(nst
, tb
[NL80211_ATTR_SCAN_FREQUENCIES
], rem_nst
)
118 printf(" %d", nla_get_u32(nst
));
121 if (tb
[NL80211_ATTR_SCAN_SSIDS
]) {
122 nla_for_each_nested(nst
, tb
[NL80211_ATTR_SCAN_SSIDS
], rem_nst
) {
124 print_ssid_escaped(nla_len(nst
), nla_data(nst
));
130 case NL80211_CMD_REG_CHANGE
:
131 printf("regulatory domain change: ");
133 reg_type
= nla_get_u8(tb
[NL80211_ATTR_REG_TYPE
]);
136 case NL80211_REGDOM_TYPE_COUNTRY
:
137 printf("set to %s by %s request",
138 nla_get_string(tb
[NL80211_ATTR_REG_ALPHA2
]),
139 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
140 if (tb
[NL80211_ATTR_WIPHY
])
141 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
143 case NL80211_REGDOM_TYPE_WORLD
:
144 printf("set to world roaming by %s request",
145 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
147 case NL80211_REGDOM_TYPE_CUSTOM_WORLD
:
148 printf("custom world roaming rules in place on phy%d by %s request",
149 nla_get_u32(tb
[NL80211_ATTR_WIPHY
]),
150 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
152 case NL80211_REGDOM_TYPE_INTERSECTION
:
153 printf("intersection used due to a request made by %s",
154 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
155 if (tb
[NL80211_ATTR_WIPHY
])
156 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
159 printf("unknown source (upgrade this utility)");
165 case NL80211_CMD_JOIN_IBSS
:
166 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
167 printf("IBSS %s joined\n", macbuf
);
169 case NL80211_CMD_AUTHENTICATE
:
171 if (tb
[NL80211_ATTR_FRAME
])
172 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
173 else if (tb
[NL80211_ATTR_TIMED_OUT
])
174 printf(": timed out");
176 printf(": unknown event");
179 case NL80211_CMD_ASSOCIATE
:
181 if (tb
[NL80211_ATTR_FRAME
])
182 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
183 else if (tb
[NL80211_ATTR_TIMED_OUT
])
184 printf(": timed out");
186 printf(": unknown event");
189 case NL80211_CMD_DEAUTHENTICATE
:
191 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
194 case NL80211_CMD_DISASSOCIATE
:
196 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
200 printf("unknown event %d\n", gnlh
->cmd
);
213 static int wait_event(struct nl_msg
*msg
, void *arg
)
215 struct wait_event
*wait
= arg
;
216 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
219 for (i
= 0; i
< wait
->n_cmds
; i
++) {
220 if (gnlh
->cmd
== wait
->cmds
[i
]) {
221 wait
->cmd
= gnlh
->cmd
;
228 static __u32
__listen_events(struct nl80211_state
*state
,
229 const int n_waits
, const __u32
*waits
,
230 struct print_event_args
*args
)
233 struct nl_cb
*cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
234 struct wait_event wait_ev
;
237 fprintf(stderr
, "failed to allocate netlink callbacks\n");
241 /* Configuration multicast group */
242 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "config");
246 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
250 /* Scan multicast group */
251 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "scan");
253 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
258 /* Regulatory multicast group */
259 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "regulatory");
261 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
266 /* MLME multicast group */
267 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "mlme");
269 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
274 /* no sequence checking for multicast messages */
275 nl_cb_set(cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
277 if (n_waits
&& waits
) {
278 wait_ev
.cmds
= waits
;
279 wait_ev
.n_cmds
= n_waits
;
280 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, wait_event
, &wait_ev
);
282 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_event
, args
);
288 nl_recvmsgs(state
->nl_sock
, cb
);
295 __u32
listen_events(struct nl80211_state
*state
,
296 const int n_waits
, const __u32
*waits
)
298 return __listen_events(state
, n_waits
, waits
, NULL
);
301 static int print_events(struct nl80211_state
*state
,
304 int argc
, char **argv
)
306 struct print_event_args args
;
308 memset(&args
, 0, sizeof(args
));
314 if (strcmp(argv
[0], "-f") == 0)
316 else if (strcmp(argv
[0], "-t") == 0)
327 return __listen_events(state
, 0, NULL
, &args
);
329 TOPLEVEL(event
, "[-t] [-f]", 0, 0, CIB_NONE
, print_events
,
330 "Monitor events from the kernel.\n"
331 "-t - print timestamp\n"
332 "-f - print full frame for auth/assoc etc.");