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];
79 struct print_event_args
*args
= arg
;
86 gettimeofday(&tv
, NULL
);
87 printf("%ld.%06u: ", (long) tv
.tv_sec
, (unsigned int) tv
.tv_usec
);
90 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
91 genlmsg_attrlen(gnlh
, 0), NULL
);
93 if (tb
[NL80211_ATTR_IFINDEX
] && tb
[NL80211_ATTR_WIPHY
]) {
94 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
95 printf("%s (phy #%d): ", ifname
, nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
96 } else if (tb
[NL80211_ATTR_IFINDEX
]) {
97 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), ifname
);
98 printf("%s: ", ifname
);
99 } else if (tb
[NL80211_ATTR_WIPHY
]) {
100 printf("phy #%d: ", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
104 case NL80211_CMD_NEW_WIPHY
:
105 printf("renamed to %s\n", nla_get_string(tb
[NL80211_ATTR_WIPHY_NAME
]));
107 case NL80211_CMD_NEW_SCAN_RESULTS
:
108 printf("scan finished\n");
110 case NL80211_CMD_SCAN_ABORTED
:
111 printf("scan aborted\n");
113 case NL80211_CMD_REG_CHANGE
:
114 printf("regulatory domain change: ");
116 reg_type
= nla_get_u8(tb
[NL80211_ATTR_REG_TYPE
]);
119 case NL80211_REGDOM_TYPE_COUNTRY
:
120 printf("set to %s by %s request",
121 nla_get_string(tb
[NL80211_ATTR_REG_ALPHA2
]),
122 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
123 if (tb
[NL80211_ATTR_WIPHY
])
124 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
126 case NL80211_REGDOM_TYPE_WORLD
:
127 printf("set to world roaming by %s request",
128 reg_initiator_to_string(nla_get_u8(tb
[NL80211_ATTR_REG_INITIATOR
])));
130 case NL80211_REGDOM_TYPE_CUSTOM_WORLD
:
131 printf("custom world roaming rules in place on phy%d by %s request",
132 nla_get_u32(tb
[NL80211_ATTR_WIPHY
]),
133 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
135 case NL80211_REGDOM_TYPE_INTERSECTION
:
136 printf("intersection used due to a request made by %s",
137 reg_initiator_to_string(nla_get_u32(tb
[NL80211_ATTR_REG_INITIATOR
])));
138 if (tb
[NL80211_ATTR_WIPHY
])
139 printf(" on phy%d", nla_get_u32(tb
[NL80211_ATTR_WIPHY
]));
142 printf("unknown source (upgrade this utility)");
148 case NL80211_CMD_JOIN_IBSS
:
149 mac_addr_n2a(macbuf
, nla_data(tb
[NL80211_ATTR_MAC
]));
150 printf("IBSS %s joined\n", macbuf
);
152 case NL80211_CMD_AUTHENTICATE
:
154 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
157 case NL80211_CMD_ASSOCIATE
:
159 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
162 case NL80211_CMD_DEAUTHENTICATE
:
164 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
167 case NL80211_CMD_DISASSOCIATE
:
169 print_frame(args
, tb
[NL80211_ATTR_FRAME
]);
173 printf("unknown event %d\n", gnlh
->cmd
);
186 static int wait_event(struct nl_msg
*msg
, void *arg
)
188 struct wait_event
*wait
= arg
;
189 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
192 for (i
= 0; i
< wait
->n_cmds
; i
++) {
193 if (gnlh
->cmd
== wait
->cmds
[i
]) {
194 wait
->cmd
= gnlh
->cmd
;
201 static __u32
__listen_events(struct nl80211_state
*state
,
202 const int n_waits
, const __u32
*waits
,
203 struct print_event_args
*args
)
206 struct nl_cb
*cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
207 struct wait_event wait_ev
;
210 fprintf(stderr
, "failed to allocate netlink callbacks\n");
214 /* Configuration multicast group */
215 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "config");
219 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
223 /* Scan multicast group */
224 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "scan");
226 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
231 /* Regulatory multicast group */
232 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "regulatory");
234 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
239 /* MLME multicast group */
240 mcid
= nl_get_multicast_id(state
->nl_sock
, "nl80211", "mlme");
242 ret
= nl_socket_add_membership(state
->nl_sock
, mcid
);
247 /* no sequence checking for multicast messages */
248 nl_cb_set(cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
250 if (n_waits
&& waits
) {
251 wait_ev
.cmds
= waits
;
252 wait_ev
.n_cmds
= n_waits
;
253 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, wait_event
, &wait_ev
);
255 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_event
, args
);
261 nl_recvmsgs(state
->nl_sock
, cb
);
268 __u32
listen_events(struct nl80211_state
*state
,
269 const int n_waits
, const __u32
*waits
)
271 return __listen_events(state
, n_waits
, waits
, NULL
);
274 static int print_events(struct nl80211_state
*state
,
277 int argc
, char **argv
)
279 struct print_event_args args
;
281 memset(&args
, 0, sizeof(args
));
287 if (strcmp(argv
[0], "-f") == 0)
289 else if (strcmp(argv
[0], "-t") == 0)
300 return __listen_events(state
, 0, NULL
, &args
);
302 TOPLEVEL(event
, "[-t] [-f]", 0, 0, CIB_NONE
, print_events
);