2 * WPA Supplicant - Basic mesh peer management
3 * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/ieee802_11_defs.h"
14 #include "ap/hostapd.h"
15 #include "ap/sta_info.h"
16 #include "ap/ieee802_11.h"
17 #include "wpa_supplicant_i.h"
21 /* TODO make configurable */
22 #define dot11MeshMaxRetries 10
23 #define dot11MeshRetryTimeout 1
24 #define dot11MeshConfirmTimeout 1
25 #define dot11MeshHoldingTimeout 1
27 struct mesh_peer_mgmt_ie {
35 static void plink_timer(void *eloop_ctx, void *user_data);
50 static const char * const mplstate[] = {
51 [PLINK_LISTEN] = "LISTEN",
52 [PLINK_OPEN_SENT] = "OPEN_SENT",
53 [PLINK_OPEN_RCVD] = "OPEN_RCVD",
54 [PLINK_CNF_RCVD] = "CNF_RCVD",
55 [PLINK_ESTAB] = "ESTAB",
56 [PLINK_HOLDING] = "HOLDING",
57 [PLINK_BLOCKED] = "BLOCKED"
60 static const char * const mplevent[] = {
61 [PLINK_UNDEFINED] = "UNDEFINED",
62 [OPN_ACPT] = "OPN_ACPT",
63 [OPN_RJCT] = "OPN_RJCT",
64 [OPN_IGNR] = "OPN_IGNR",
65 [CNF_ACPT] = "CNF_ACPT",
66 [CNF_RJCT] = "CNF_RJCT",
67 [CNF_IGNR] = "CNF_IGNR",
68 [CLS_ACPT] = "CLS_ACPT",
69 [CLS_IGNR] = "CLS_IGNR"
73 static int mesh_mpm_parse_peer_mgmt(struct wpa_supplicant *wpa_s,
75 const u8 *ie, size_t len,
76 struct mesh_peer_mgmt_ie *mpm_ie)
78 os_memset(mpm_ie, 0, sizeof(*mpm_ie));
80 /* remove optional PMK at end */
83 mpm_ie->pmk = ie + len - 16;
86 if ((action_field == PLINK_OPEN && len != 4) ||
87 (action_field == PLINK_CONFIRM && len != 6) ||
88 (action_field == PLINK_CLOSE && len != 6 && len != 8)) {
89 wpa_msg(wpa_s, MSG_DEBUG, "MPM: Invalid peer mgmt ie");
96 mpm_ie->proto_id = ie;
97 mpm_ie->llid = ie + 2;
101 /* close reason is always present at end for close */
102 if (action_field == PLINK_CLOSE) {
105 mpm_ie->reason = ie + len - 2;
109 /* plid, present for confirm, and possibly close */
117 static int plink_free_count(struct hostapd_data *hapd)
119 if (hapd->max_plinks > hapd->num_plinks)
120 return hapd->max_plinks - hapd->num_plinks;
125 static u16 copy_supp_rates(struct wpa_supplicant *wpa_s,
126 struct sta_info *sta,
127 struct ieee802_11_elems *elems)
129 if (!elems->supp_rates) {
130 wpa_msg(wpa_s, MSG_ERROR, "no supported rates from " MACSTR,
132 return WLAN_STATUS_UNSPECIFIED_FAILURE;
135 if (elems->supp_rates_len + elems->ext_supp_rates_len >
136 sizeof(sta->supported_rates)) {
137 wpa_msg(wpa_s, MSG_ERROR,
138 "Invalid supported rates element length " MACSTR
139 " %d+%d", MAC2STR(sta->addr), elems->supp_rates_len,
140 elems->ext_supp_rates_len);
141 return WLAN_STATUS_UNSPECIFIED_FAILURE;
144 sta->supported_rates_len = merge_byte_arrays(
145 sta->supported_rates, sizeof(sta->supported_rates),
146 elems->supp_rates, elems->supp_rates_len,
147 elems->ext_supp_rates, elems->ext_supp_rates_len);
149 return WLAN_STATUS_SUCCESS;
153 /* return true if elems from a neighbor match this MBSS */
154 static Boolean matches_local(struct wpa_supplicant *wpa_s,
155 struct ieee802_11_elems *elems)
157 struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
159 if (elems->mesh_config_len < 5)
162 return (mconf->meshid_len == elems->mesh_id_len &&
163 os_memcmp(mconf->meshid, elems->mesh_id,
164 elems->mesh_id_len) == 0 &&
165 mconf->mesh_pp_id == elems->mesh_config[0] &&
166 mconf->mesh_pm_id == elems->mesh_config[1] &&
167 mconf->mesh_cc_id == elems->mesh_config[2] &&
168 mconf->mesh_sp_id == elems->mesh_config[3] &&
169 mconf->mesh_auth_id == elems->mesh_config[4]);
173 /* check if local link id is already used with another peer */
174 static Boolean llid_in_use(struct wpa_supplicant *wpa_s, u16 llid)
176 struct sta_info *sta;
177 struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
179 for (sta = hapd->sta_list; sta; sta = sta->next) {
180 if (sta->my_lid == llid)
188 /* generate an llid for a link and set to initial state */
189 static void mesh_mpm_init_link(struct wpa_supplicant *wpa_s,
190 struct sta_info *sta)
195 if (os_get_random((u8 *) &llid, sizeof(llid)) < 0)
197 } while (!llid || llid_in_use(wpa_s, llid));
201 sta->plink_state = PLINK_LISTEN;
205 static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
206 struct sta_info *sta,
207 enum plink_action_field type,
211 struct hostapd_iface *ifmsh = wpa_s->ifmsh;
212 struct hostapd_data *bss = ifmsh->bss[0];
213 struct mesh_conf *conf = ifmsh->mconf;
214 u8 supp_rates[2 + 2 + 32];
216 u8 ie_len, add_plid = 0;
218 int ampe = conf->security & MESH_CONF_SEC_AMPE;
223 buf = wpabuf_alloc(2 + /* capability info */
225 2 + 8 + /* supported rates */
227 2 + 32 + /* mesh ID */
228 2 + 7 + /* mesh config */
229 2 + 26 + /* HT capabilities */
230 2 + 22 + /* HT operation */
231 2 + 23 + /* peering management */
237 wpabuf_put_u8(buf, WLAN_ACTION_SELF_PROTECTED);
238 wpabuf_put_u8(buf, type);
240 if (type != PLINK_CLOSE) {
241 /* capability info */
242 wpabuf_put_le16(buf, ampe ? IEEE80211_CAP_PRIVACY : 0);
244 if (type == PLINK_CONFIRM)
245 wpabuf_put_le16(buf, sta->peer_lid);
247 /* IE: supp + ext. supp rates */
248 pos = hostapd_eid_supp_rates(bss, supp_rates);
249 pos = hostapd_eid_ext_supp_rates(bss, pos);
250 wpabuf_put_data(buf, supp_rates, pos - supp_rates);
253 wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
254 wpabuf_put_u8(buf, conf->meshid_len);
255 wpabuf_put_data(buf, conf->meshid, conf->meshid_len);
258 wpabuf_put_u8(buf, WLAN_EID_MESH_CONFIG);
259 wpabuf_put_u8(buf, 7);
260 wpabuf_put_u8(buf, conf->mesh_pp_id);
261 wpabuf_put_u8(buf, conf->mesh_pm_id);
262 wpabuf_put_u8(buf, conf->mesh_cc_id);
263 wpabuf_put_u8(buf, conf->mesh_sp_id);
264 wpabuf_put_u8(buf, conf->mesh_auth_id);
265 /* TODO: formation info */
266 wpabuf_put_u8(buf, 0);
267 /* always forwarding & accepting plinks for now */
268 wpabuf_put_u8(buf, 0x1 | 0x8);
269 } else { /* Peer closing frame */
271 wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
272 wpabuf_put_u8(buf, conf->meshid_len);
273 wpabuf_put_data(buf, conf->meshid, conf->meshid_len);
276 /* IE: Mesh Peering Management element */
290 ie_len += 2; /* reason code */
294 wpabuf_put_u8(buf, WLAN_EID_PEER_MGMT);
295 wpabuf_put_u8(buf, ie_len);
296 /* peering protocol */
298 wpabuf_put_le16(buf, 1);
300 wpabuf_put_le16(buf, 0);
301 wpabuf_put_le16(buf, sta->my_lid);
303 wpabuf_put_le16(buf, sta->peer_lid);
304 if (type == PLINK_CLOSE)
305 wpabuf_put_le16(buf, close_reason);
309 ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0,
310 sta->addr, wpa_s->own_addr, wpa_s->own_addr,
311 wpabuf_head(buf), wpabuf_len(buf), 0);
313 wpa_msg(wpa_s, MSG_INFO,
314 "Mesh MPM: failed to send peering frame");
320 /* configure peering state in ours and driver's station entry */
322 wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s, struct sta_info *sta,
323 enum mesh_plink_state state)
325 struct hostapd_sta_add_params params;
328 sta->plink_state = state;
330 os_memset(¶ms, 0, sizeof(params));
331 params.addr = sta->addr;
332 params.plink_state = state;
335 wpa_msg(wpa_s, MSG_DEBUG, "MPM set " MACSTR " into %s",
336 MAC2STR(sta->addr), mplstate[state]);
337 ret = wpa_drv_sta_add(wpa_s, ¶ms);
339 wpa_msg(wpa_s, MSG_ERROR, "Driver failed to set " MACSTR
340 ": %d", MAC2STR(sta->addr), ret);
345 static void mesh_mpm_fsm_restart(struct wpa_supplicant *wpa_s,
346 struct sta_info *sta)
348 struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
350 eloop_cancel_timeout(plink_timer, wpa_s, sta);
352 if (sta->mpm_close_reason == WLAN_REASON_MESH_CLOSE_RCVD) {
353 ap_free_sta(hapd, sta);
357 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_LISTEN);
358 sta->my_lid = sta->peer_lid = sta->mpm_close_reason = 0;
359 sta->mpm_retries = 0;
363 static void plink_timer(void *eloop_ctx, void *user_data)
365 struct wpa_supplicant *wpa_s = eloop_ctx;
366 struct sta_info *sta = user_data;
369 switch (sta->plink_state) {
370 case PLINK_OPEN_RCVD:
371 case PLINK_OPEN_SENT:
373 if (sta->mpm_retries < dot11MeshMaxRetries) {
374 eloop_register_timeout(dot11MeshRetryTimeout, 0,
375 plink_timer, wpa_s, sta);
376 mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0);
380 reason = WLAN_REASON_MESH_MAX_RETRIES;
381 /* fall through on else */
386 reason = WLAN_REASON_MESH_CONFIRM_TIMEOUT;
387 sta->plink_state = PLINK_HOLDING;
388 eloop_register_timeout(dot11MeshHoldingTimeout, 0,
389 plink_timer, wpa_s, sta);
390 mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason);
394 mesh_mpm_fsm_restart(wpa_s, sta);
402 /* initiate peering with station */
404 mesh_mpm_plink_open(struct wpa_supplicant *wpa_s, struct sta_info *sta,
405 enum mesh_plink_state next_state)
407 eloop_cancel_timeout(plink_timer, wpa_s, sta);
408 eloop_register_timeout(dot11MeshRetryTimeout, 0, plink_timer,
410 mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0);
411 wpa_mesh_set_plink_state(wpa_s, sta, next_state);
415 int mesh_mpm_plink_close(struct hostapd_data *hapd,
416 struct sta_info *sta, void *ctx)
418 struct wpa_supplicant *wpa_s = ctx;
419 int reason = WLAN_REASON_MESH_PEERING_CANCELLED;
422 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
423 mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason);
424 wpa_printf(MSG_DEBUG, "MPM closing plink sta=" MACSTR,
426 eloop_cancel_timeout(plink_timer, wpa_s, sta);
434 void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh)
436 struct hostapd_data *hapd = ifmsh->bss[0];
438 /* notify peers we're leaving */
439 ap_for_each_sta(hapd, mesh_mpm_plink_close, wpa_s);
441 hapd->num_plinks = 0;
442 hostapd_free_stas(hapd);
446 /* for mesh_rsn to indicate this peer has completed authentication, and we're
447 * ready to start AMPE */
448 void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr)
450 struct hostapd_data *data = wpa_s->ifmsh->bss[0];
451 struct hostapd_sta_add_params params;
452 struct sta_info *sta;
455 sta = ap_get_sta(data, addr);
457 wpa_msg(wpa_s, MSG_DEBUG, "no such mesh peer");
461 /* TODO: Should do nothing if this STA is already authenticated, but
462 * the AP code already sets this flag. */
463 sta->flags |= WLAN_STA_AUTH;
465 os_memset(¶ms, 0, sizeof(params));
466 params.addr = sta->addr;
467 params.flags = WPA_STA_AUTHENTICATED | WPA_STA_AUTHORIZED;
470 wpa_msg(wpa_s, MSG_DEBUG, "MPM authenticating " MACSTR,
472 ret = wpa_drv_sta_add(wpa_s, ¶ms);
474 wpa_msg(wpa_s, MSG_ERROR,
475 "Driver failed to set " MACSTR ": %d",
476 MAC2STR(sta->addr), ret);
480 mesh_mpm_init_link(wpa_s, sta);
482 mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
486 void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
487 struct ieee802_11_elems *elems)
489 struct hostapd_sta_add_params params;
490 struct mesh_conf *conf = wpa_s->ifmsh->mconf;
491 struct hostapd_data *data = wpa_s->ifmsh->bss[0];
492 struct sta_info *sta;
493 struct wpa_ssid *ssid = wpa_s->current_ssid;
496 sta = ap_get_sta(data, addr);
498 sta = ap_sta_add(data, addr);
504 if (copy_supp_rates(wpa_s, sta, elems))
507 mesh_mpm_init_link(wpa_s, sta);
509 /* insert into driver */
510 os_memset(¶ms, 0, sizeof(params));
511 params.supp_rates = sta->supported_rates;
512 params.supp_rates_len = sta->supported_rates_len;
514 params.plink_state = sta->plink_state;
515 params.aid = sta->peer_lid;
516 params.listen_interval = 100;
517 /* TODO: HT capabilities */
518 params.flags |= WPA_STA_WMM;
519 params.flags_mask |= WPA_STA_AUTHENTICATED;
520 if (conf->security == MESH_CONF_SEC_NONE) {
521 params.flags |= WPA_STA_AUTHORIZED;
522 params.flags |= WPA_STA_AUTHENTICATED;
524 sta->flags |= WLAN_STA_MFP;
525 params.flags |= WPA_STA_MFP;
528 ret = wpa_drv_sta_add(wpa_s, ¶ms);
530 wpa_msg(wpa_s, MSG_ERROR,
531 "Driver failed to insert " MACSTR ": %d",
536 if (ssid && ssid->no_auto_peer) {
537 wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
538 MACSTR " because of no_auto_peer", MAC2STR(addr));
542 mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
546 void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, struct rx_mgmt *rx_mgmt)
548 struct hostapd_frame_info fi;
550 os_memset(&fi, 0, sizeof(fi));
551 fi.datarate = rx_mgmt->datarate;
552 fi.ssi_signal = rx_mgmt->ssi_signal;
553 ieee802_11_mgmt(wpa_s->ifmsh->bss[0], rx_mgmt->frame,
554 rx_mgmt->frame_len, &fi);
558 static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
559 struct sta_info *sta)
561 struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
563 wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR " established",
566 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_ESTAB);
569 sta->flags |= WLAN_STA_ASSOC;
571 eloop_cancel_timeout(plink_timer, wpa_s, sta);
573 /* Send ctrl event */
574 wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_PEER_CONNECTED MACSTR,
579 static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta,
580 enum plink_event event)
582 struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
585 wpa_msg(wpa_s, MSG_DEBUG, "MPM " MACSTR " state %s event %s",
586 MAC2STR(sta->addr), mplstate[sta->plink_state],
589 switch (sta->plink_state) {
593 mesh_mpm_fsm_restart(wpa_s, sta);
596 mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_RCVD);
597 mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CONFIRM,
604 case PLINK_OPEN_SENT:
608 reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
611 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
613 reason = WLAN_REASON_MESH_CLOSE_RCVD;
614 eloop_register_timeout(dot11MeshHoldingTimeout, 0,
615 plink_timer, wpa_s, sta);
616 mesh_mpm_send_plink_action(wpa_s, sta,
617 PLINK_CLOSE, reason);
620 /* retry timer is left untouched */
621 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPEN_RCVD);
622 mesh_mpm_send_plink_action(wpa_s, sta,
626 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_CNF_RCVD);
627 eloop_register_timeout(dot11MeshConfirmTimeout, 0,
628 plink_timer, wpa_s, sta);
634 case PLINK_OPEN_RCVD:
638 reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
641 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
643 reason = WLAN_REASON_MESH_CLOSE_RCVD;
644 eloop_register_timeout(dot11MeshHoldingTimeout, 0,
645 plink_timer, wpa_s, sta);
646 sta->mpm_close_reason = reason;
647 mesh_mpm_send_plink_action(wpa_s, sta,
648 PLINK_CLOSE, reason);
651 mesh_mpm_send_plink_action(wpa_s, sta,
655 mesh_mpm_plink_estab(wpa_s, sta);
665 reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
668 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
670 reason = WLAN_REASON_MESH_CLOSE_RCVD;
671 eloop_register_timeout(dot11MeshHoldingTimeout, 0,
672 plink_timer, wpa_s, sta);
673 sta->mpm_close_reason = reason;
674 mesh_mpm_send_plink_action(wpa_s, sta,
675 PLINK_CLOSE, reason);
678 mesh_mpm_plink_estab(wpa_s, sta);
679 mesh_mpm_send_plink_action(wpa_s, sta,
689 wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
690 reason = WLAN_REASON_MESH_CLOSE_RCVD;
692 eloop_register_timeout(dot11MeshHoldingTimeout, 0,
693 plink_timer, wpa_s, sta);
694 sta->mpm_close_reason = reason;
696 wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR
697 " closed with reason %d",
698 MAC2STR(sta->addr), reason);
700 wpa_msg_ctrl(wpa_s, MSG_INFO,
701 MESH_PEER_DISCONNECTED MACSTR,
706 mesh_mpm_send_plink_action(wpa_s, sta,
707 PLINK_CLOSE, reason);
710 mesh_mpm_send_plink_action(wpa_s, sta,
720 mesh_mpm_fsm_restart(wpa_s, sta);
726 reason = sta->mpm_close_reason;
727 mesh_mpm_send_plink_action(wpa_s, sta,
728 PLINK_CLOSE, reason);
735 wpa_msg(wpa_s, MSG_DEBUG,
736 "Unsupported MPM event %s for state %s",
737 mplevent[event], mplstate[sta->plink_state]);
743 void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s,
744 const struct ieee80211_mgmt *mgmt, size_t len)
747 struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
748 struct sta_info *sta;
749 u16 plid = 0, llid = 0;
750 enum plink_event event;
751 struct ieee802_11_elems elems;
752 struct mesh_peer_mgmt_ie peer_mgmt_ie;
757 if (mgmt->u.action.category != WLAN_ACTION_SELF_PROTECTED)
760 action_field = mgmt->u.action.u.slf_prot_action.action;
762 ies = mgmt->u.action.u.slf_prot_action.variable;
763 ie_len = (const u8 *) mgmt + len -
764 mgmt->u.action.u.slf_prot_action.variable;
766 /* at least expect mesh id and peering mgmt */
770 if (action_field == PLINK_OPEN || action_field == PLINK_CONFIRM) {
771 ies += 2; /* capability */
774 if (action_field == PLINK_CONFIRM) {
779 /* check for mesh peering, mesh id and mesh config IEs */
780 if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed)
782 if (!elems.peer_mgmt)
784 if ((action_field != PLINK_CLOSE) &&
785 (!elems.mesh_id || !elems.mesh_config))
788 if (action_field != PLINK_CLOSE && !matches_local(wpa_s, &elems))
791 ret = mesh_mpm_parse_peer_mgmt(wpa_s, action_field,
798 /* the sender's llid is our plid and vice-versa */
799 plid = WPA_GET_LE16(peer_mgmt_ie.llid);
800 if (peer_mgmt_ie.plid)
801 llid = WPA_GET_LE16(peer_mgmt_ie.plid);
803 sta = ap_get_sta(hapd, mgmt->sa);
808 mesh_mpm_init_link(wpa_s, sta);
810 if (sta->plink_state == PLINK_BLOCKED)
813 /* Now we will figure out the appropriate event... */
814 switch (action_field) {
816 if (!plink_free_count(hapd) ||
817 (sta->peer_lid && sta->peer_lid != plid)) {
820 sta->peer_lid = plid;
825 if (!plink_free_count(hapd) ||
826 sta->my_lid != llid ||
827 (sta->peer_lid && sta->peer_lid != plid)) {
831 sta->peer_lid = plid;
836 if (sta->plink_state == PLINK_ESTAB)
837 /* Do not check for llid or plid. This does not
838 * follow the standard but since multiple plinks
839 * per cand are not supported, it is necessary in
840 * order to avoid a livelock when MP A sees an
841 * establish peer link to MP B but MP B does not
842 * see it. This can be caused by a timeout in
843 * B's peer link establishment or B being
847 else if (sta->peer_lid != plid)
849 else if (peer_mgmt_ie.plid && sta->my_lid != llid)
855 wpa_msg(wpa_s, MSG_ERROR,
856 "Mesh plink: unknown frame subtype");
859 mesh_mpm_fsm(wpa_s, sta, event);