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_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 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
171 case NL80211_CMD_ASSOCIATE
:
173 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
176 case NL80211_CMD_DEAUTHENTICATE
:
178 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
181 case NL80211_CMD_DISASSOCIATE
:
183 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
187 printf("unknown event %d\n", gnlh
->cmd
);
200 static int wait_event(struct nl_msg
*msg
, void *arg
)
202 struct wait_event
*wait
= arg
;
203 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
206 for (i
= 0; i
< wait
->n_cmds
; i
++) {
207 if (gnlh
->cmd
== wait
->cmds
[i
]) {
208 wait
->cmd
= gnlh
->cmd
;
215 static __u32
__listen_events(struct nl80211_state
*state
,
216 const int n_waits
, const __u32
*waits
,
217 struct print_event_args
*args
)
220 struct nl_cb
*cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
221 struct wait_event wait_ev
;
224 fprintf(stderr
, "failed to allocate netlink callbacks\n");
228 /* Configuration multicast group */
229 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "config");
233 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
237 /* Scan multicast group */
238 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "scan");
240 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
245 /* Regulatory multicast group */
246 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "regulatory");
248 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
253 /* MLME multicast group */
254 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "mlme");
256 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
261 /* no sequence checking for multicast messages */
262 nl_cb_set(cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
264 if (n_waits
&& waits
) {
265 wait_ev
.cmds
= waits
;
266 wait_ev
.n_cmds
= n_waits
;
267 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, wait_event
, &wait_ev
);
269 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_event
, args
);
275 nl_recvmsgs(state
->nl_sock
, cb
);
282 __u32
listen_events(struct nl80211_state
*state
,
283 const int n_waits
, const __u32
*waits
)
285 return __listen_events(state
, n_waits
, waits
, NULL
);
288 static int print_events(struct nl80211_state
*state
,
291 int argc
, char **argv
)
293 struct print_event_args args
;
295 memset(&args
, 0, sizeof(args
));
301 if (strcmp(argv
[0], "-f") == 0)
303 else if (strcmp(argv
[0], "-t") == 0)
314 return __listen_events(state
, 0, NULL
, &args
);
316 TOPLEVEL(event
, "[-t] [-f]", 0, 0, CIB_NONE
, print_events
,
317 "Monitor events from the kernel.\n"
318 "-t - print timestamp\n"
319 "-f - print full frame for auth/assoc etc.");