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
;
88 gettimeofday(&tv
, NULL
);
89 printf("%ld.%06u: ", (long) tv
.tv_sec
, (unsigned int) tv
.tv_usec
);
92 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
93 genlmsg_attrlen(gnlh
, 0), NULL
);
95 if (tb
[NL80211_ATTR_IFINDEX
] && tb
[NL80211_ATTR_WIPHY
]) {
96 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
97 printf("%s (phy #%d): ", ifname
, nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
98 } else if (tb
[NL80211_ATTR_IFINDEX
]) {
99 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
100 printf("%s: ", ifname
);
101 } else if (tb
[NL80211_ATTR_WIPHY
]) {
102 printf("phy #%d: ", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
106 case NL80211_CMD_NEW_WIPHY
:
107 printf("renamed to %s\n", nla_get_string(tb
[NL80211_ATTR_WIPHY_NAME
]));
109 case NL80211_CMD_TRIGGER_SCAN
:
110 printf("scan started\n");
112 case NL80211_CMD_NEW_SCAN_RESULTS
:
113 printf("scan finished:");
114 case NL80211_CMD_SCAN_ABORTED
:
115 if (gnlh
->cmd
== NL80211_CMD_SCAN_ABORTED
)
116 printf("scan aborted:");
117 if (tb
[NL80211_ATTR_SCAN_FREQUENCIES
]) {
118 nla_for_each_nested(nst
, tb
[NL80211_ATTR_SCAN_FREQUENCIES
], rem_nst
)
119 printf(" %d", nla_get_u32(nst
));
122 if (tb
[NL80211_ATTR_SCAN_SSIDS
]) {
123 nla_for_each_nested(nst
, tb
[NL80211_ATTR_SCAN_SSIDS
], rem_nst
) {
125 print_ssid_escaped(nla_len(nst
), nla_data(nst
));
131 case NL80211_CMD_REG_CHANGE
:
132 printf("regulatory domain change: ");
134 reg_type
= nla_get_u8(tb
[NL80211_ATTR_REG_TYPE
]);
137 case NL80211_REGDOM_TYPE_COUNTRY
:
138 printf("set to %s by %s request",
139 nla_get_string(tb
[NL80211_ATTR_REG_ALPHA2
]),
140 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
141 if (tb
[NL80211_ATTR_WIPHY
])
142 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
144 case NL80211_REGDOM_TYPE_WORLD
:
145 printf("set to world roaming by %s request",
146 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
148 case NL80211_REGDOM_TYPE_CUSTOM_WORLD
:
149 printf("custom world roaming rules in place on phy%d by %s request",
150 nla_get_u32(tb
[NL80211_ATTR_WIPHY
]),
151 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
153 case NL80211_REGDOM_TYPE_INTERSECTION
:
154 printf("intersection used due to a request made by %s",
155 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
156 if (tb
[NL80211_ATTR_WIPHY
])
157 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
160 printf("unknown source (upgrade this utility)");
166 case NL80211_CMD_JOIN_IBSS
:
167 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
168 printf("IBSS %s joined\n", macbuf
);
170 case NL80211_CMD_AUTHENTICATE
:
172 if (tb
[NL80211_ATTR_FRAME
])
173 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
174 else if (tb
[NL80211_ATTR_TIMED_OUT
])
175 printf(": timed out");
177 printf(": unknown event");
180 case NL80211_CMD_ASSOCIATE
:
182 if (tb
[NL80211_ATTR_FRAME
])
183 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
184 else if (tb
[NL80211_ATTR_TIMED_OUT
])
185 printf(": timed out");
187 printf(": unknown event");
190 case NL80211_CMD_DEAUTHENTICATE
:
192 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
195 case NL80211_CMD_DISASSOCIATE
:
197 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
200 case NL80211_CMD_CONNECT
:
202 if (!tb
[NL80211_ATTR_STATUS_CODE
])
203 printf("unknown connect status");
204 else if (nla_get_u16(tb
[NL80211_ATTR_STATUS_CODE
]) == 0)
207 status
= nla_get_u16(tb
[NL80211_ATTR_STATUS_CODE
]);
208 printf("failed to connect");
210 if (tb
[NL80211_ATTR_MAC
]) {
211 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
212 printf(" to %s", macbuf
);
215 printf(", status: %d: %s", status
, get_status_str(status
));
218 case NL80211_CMD_ROAM
:
220 if (tb
[NL80211_ATTR_MAC
]) {
221 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
222 printf(" to %s", macbuf
);
226 case NL80211_CMD_DISCONNECT
:
227 printf("disconnected");
228 if (tb
[NL80211_ATTR_DISCONNECTED_BY_AP
])
231 printf(" (local request)");
232 if (tb
[NL80211_ATTR_REASON_CODE
])
233 printf(" reason: %d: %s", nla_get_u16(tb
[NL80211_ATTR_REASON_CODE
]),
234 get_reason_str(nla_get_u16(tb
[NL80211_ATTR_REASON_CODE
])));
238 printf("unknown event %d\n", gnlh
->cmd
);
251 static int wait_event(struct nl_msg
*msg
, void *arg
)
253 struct wait_event
*wait
= arg
;
254 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
257 for (i
= 0; i
< wait
->n_cmds
; i
++) {
258 if (gnlh
->cmd
== wait
->cmds
[i
]) {
259 wait
->cmd
= gnlh
->cmd
;
266 static __u32
__listen_events(struct nl80211_state
*state
,
267 const int n_waits
, const __u32
*waits
,
268 struct print_event_args
*args
)
271 struct nl_cb
*cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
272 struct wait_event wait_ev
;
275 fprintf(stderr
, "failed to allocate netlink callbacks\n");
279 /* Configuration multicast group */
280 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "config");
284 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
288 /* Scan multicast group */
289 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "scan");
291 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
296 /* Regulatory multicast group */
297 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "regulatory");
299 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
304 /* MLME multicast group */
305 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "mlme");
307 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
312 /* no sequence checking for multicast messages */
313 nl_cb_set(cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
315 if (n_waits
&& waits
) {
316 wait_ev
.cmds
= waits
;
317 wait_ev
.n_cmds
= n_waits
;
318 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, wait_event
, &wait_ev
);
320 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_event
, args
);
326 nl_recvmsgs(state
->nl_sock
, cb
);
333 __u32
listen_events(struct nl80211_state
*state
,
334 const int n_waits
, const __u32
*waits
)
336 return __listen_events(state
, n_waits
, waits
, NULL
);
339 static int print_events(struct nl80211_state
*state
,
342 int argc
, char **argv
)
344 struct print_event_args args
;
346 memset(&args
, 0, sizeof(args
));
352 if (strcmp(argv
[0], "-f") == 0)
354 else if (strcmp(argv
[0], "-t") == 0)
365 return __listen_events(state
, 0, NULL
, &args
);
367 TOPLEVEL(event
, "[-t] [-f]", 0, 0, CIB_NONE
, print_events
,
368 "Monitor events from the kernel.\n"
369 "-t - print timestamp\n"
370 "-f - print full frame for auth/assoc etc.");