7 static int no_seq_check(struct nl_msg
*msg
, void *arg
)
12 static void print_frame(struct print_event_args
*args
, struct nlattr
*attr
)
21 printf(" [no frame]");
23 frame
= nla_data(attr
);
27 printf(" [invalid frame: ");
31 mac_addr_n2a(macbuf
, frame
+ 10);
32 printf(" %s -> ", macbuf
);
33 mac_addr_n2a(macbuf
, frame
+ 4);
36 switch (frame
[0] & 0xfc) {
37 case 0x10: /* assoc resp */
38 case 0x30: /* reassoc resp */
40 tmp
= (frame
[27] << 8) + frame
[26];
41 printf(" status: %d: %s", tmp
, get_status_str(tmp
));
43 case 0x00: /* assoc req */
44 case 0x20: /* reassoc req */
48 tmp
= (frame
[29] << 8) + frame
[28];
49 printf(" status: %d: %s", tmp
, get_status_str(tmp
));
52 case 0xa0: /* disassoc */
53 case 0xc0: /* deauth */
55 tmp
= (frame
[25] << 8) + frame
[24];
56 printf(" reason %d: %s", tmp
, get_reason_str(tmp
));
66 for (i
= 0; i
< len
; i
++)
67 printf(" %.02x", frame
[i
]);
71 static int print_event(struct nl_msg
*msg
, void *arg
)
73 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
74 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1], *nst
;
75 struct print_event_args
*args
= arg
;
84 gettimeofday(&tv
, NULL
);
85 printf("%ld.%06u: ", (long) tv
.tv_sec
, (unsigned int) tv
.tv_usec
);
88 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
89 genlmsg_attrlen(gnlh
, 0), NULL
);
91 if (tb
[NL80211_ATTR_IFINDEX
] && tb
[NL80211_ATTR_WIPHY
]) {
92 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
93 printf("%s (phy #%d): ", ifname
, nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
94 } else if (tb
[NL80211_ATTR_IFINDEX
]) {
95 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
96 printf("%s: ", ifname
);
97 } else if (tb
[NL80211_ATTR_WIPHY
]) {
98 printf("phy #%d: ", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
102 case NL80211_CMD_NEW_WIPHY
:
103 printf("renamed to %s\n", nla_get_string(tb
[NL80211_ATTR_WIPHY_NAME
]));
105 case NL80211_CMD_TRIGGER_SCAN
:
106 printf("scan started\n");
108 case NL80211_CMD_NEW_SCAN_RESULTS
:
109 printf("scan finished:");
110 case NL80211_CMD_SCAN_ABORTED
:
111 if (gnlh
->cmd
== NL80211_CMD_SCAN_ABORTED
)
112 printf("scan aborted:");
113 if (tb
[NL80211_ATTR_SCAN_FREQUENCIES
]) {
114 nla_for_each_nested(nst
, tb
[NL80211_ATTR_SCAN_FREQUENCIES
], rem_nst
)
115 printf(" %d", nla_get_u32(nst
));
118 if (tb
[NL80211_ATTR_SCAN_SSIDS
]) {
119 nla_for_each_nested(nst
, tb
[NL80211_ATTR_SCAN_SSIDS
], rem_nst
) {
121 print_ssid_escaped(nla_len(nst
), nla_data(nst
));
127 case NL80211_CMD_REG_CHANGE
:
128 printf("regulatory domain change: ");
130 reg_type
= nla_get_u8(tb
[NL80211_ATTR_REG_TYPE
]);
133 case NL80211_REGDOM_TYPE_COUNTRY
:
134 printf("set to %s by %s request",
135 nla_get_string(tb
[NL80211_ATTR_REG_ALPHA2
]),
136 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
137 if (tb
[NL80211_ATTR_WIPHY
])
138 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
140 case NL80211_REGDOM_TYPE_WORLD
:
141 printf("set to world roaming by %s request",
142 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
144 case NL80211_REGDOM_TYPE_CUSTOM_WORLD
:
145 printf("custom world roaming rules in place on phy%d by %s request",
146 nla_get_u32(tb
[NL80211_ATTR_WIPHY
]),
147 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
149 case NL80211_REGDOM_TYPE_INTERSECTION
:
150 printf("intersection used due to a request made by %s",
151 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
152 if (tb
[NL80211_ATTR_WIPHY
])
153 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
156 printf("unknown source (upgrade this utility)");
162 case NL80211_CMD_JOIN_IBSS
:
163 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
164 printf("IBSS %s joined\n", macbuf
);
166 case NL80211_CMD_AUTHENTICATE
:
168 if (tb
[NL80211_ATTR_FRAME
])
169 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
170 else if (tb
[NL80211_ATTR_TIMED_OUT
])
171 printf(": timed out");
173 printf(": unknown event");
176 case NL80211_CMD_ASSOCIATE
:
178 if (tb
[NL80211_ATTR_FRAME
])
179 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
180 else if (tb
[NL80211_ATTR_TIMED_OUT
])
181 printf(": timed out");
183 printf(": unknown event");
186 case NL80211_CMD_DEAUTHENTICATE
:
188 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
191 case NL80211_CMD_DISASSOCIATE
:
193 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
196 case NL80211_CMD_CONNECT
:
198 if (!tb
[NL80211_ATTR_STATUS_CODE
])
199 printf("unknown connect status");
200 else if (nla_get_u16(tb
[NL80211_ATTR_STATUS_CODE
]) == 0)
203 status
= nla_get_u16(tb
[NL80211_ATTR_STATUS_CODE
]);
204 printf("failed to connect");
206 if (tb
[NL80211_ATTR_MAC
]) {
207 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
208 printf(" to %s", macbuf
);
211 printf(", status: %d: %s", status
, get_status_str(status
));
214 case NL80211_CMD_ROAM
:
216 if (tb
[NL80211_ATTR_MAC
]) {
217 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
218 printf(" to %s", macbuf
);
222 case NL80211_CMD_DISCONNECT
:
223 printf("disconnected");
224 if (tb
[NL80211_ATTR_DISCONNECTED_BY_AP
])
227 printf(" (local request)");
228 if (tb
[NL80211_ATTR_REASON_CODE
])
229 printf(" reason: %d: %s", nla_get_u16(tb
[NL80211_ATTR_REASON_CODE
]),
230 get_reason_str(nla_get_u16(tb
[NL80211_ATTR_REASON_CODE
])));
234 printf("unknown event %d\n", gnlh
->cmd
);
245 struct print_event_args
*pargs
;
248 static int wait_event(struct nl_msg
*msg
, void *arg
)
250 struct wait_event
*wait
= arg
;
251 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
254 for (i
= 0; i
< wait
->n_cmds
; i
++) {
255 if (gnlh
->cmd
== wait
->cmds
[i
]) {
256 wait
->cmd
= gnlh
->cmd
;
258 print_event(msg
, wait
->pargs
);
265 __u32
__listen_events(struct nl80211_state
*state
,
266 const int n_waits
, const __u32
*waits
,
267 struct print_event_args
*args
)
270 struct nl_cb
*cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
271 struct wait_event wait_ev
;
274 fprintf(stderr
, "failed to allocate netlink callbacks\n");
278 /* Configuration multicast group */
279 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "config");
283 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
287 /* Scan multicast group */
288 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "scan");
290 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
295 /* Regulatory multicast group */
296 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "regulatory");
298 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
303 /* MLME multicast group */
304 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "mlme");
306 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
311 /* no sequence checking for multicast messages */
312 nl_cb_set(cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
314 if (n_waits
&& waits
) {
315 wait_ev
.cmds
= waits
;
316 wait_ev
.n_cmds
= n_waits
;
317 wait_ev
.pargs
= args
;
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
);
325 nl_recvmsgs(state
->nl_sock
, cb
);
332 __u32
listen_events(struct nl80211_state
*state
,
333 const int n_waits
, const __u32
*waits
)
335 return __listen_events(state
, n_waits
, waits
, NULL
);
338 static int print_events(struct nl80211_state
*state
,
341 int argc
, char **argv
)
343 struct print_event_args args
;
345 memset(&args
, 0, sizeof(args
));
351 if (strcmp(argv
[0], "-f") == 0)
353 else if (strcmp(argv
[0], "-t") == 0)
364 return __listen_events(state
, 0, NULL
, &args
);
366 TOPLEVEL(event
, "[-t] [-f]", 0, 0, CIB_NONE
, print_events
,
367 "Monitor events from the kernel.\n"
368 "-t - print timestamp\n"
369 "-f - print full frame for auth/assoc etc.");