1*a1157835SDaniel Fojt /*
2*a1157835SDaniel Fojt * IEEE 802.1X-2010 Controlled Port of PAE state machine - CP state machine
3*a1157835SDaniel Fojt * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
4*a1157835SDaniel Fojt *
5*a1157835SDaniel Fojt * This software may be distributed under the terms of the BSD license.
6*a1157835SDaniel Fojt * See README for more details.
7*a1157835SDaniel Fojt */
8*a1157835SDaniel Fojt
9*a1157835SDaniel Fojt #include "utils/includes.h"
10*a1157835SDaniel Fojt
11*a1157835SDaniel Fojt #include "utils/common.h"
12*a1157835SDaniel Fojt #include "utils/eloop.h"
13*a1157835SDaniel Fojt #include "common/defs.h"
14*a1157835SDaniel Fojt #include "common/ieee802_1x_defs.h"
15*a1157835SDaniel Fojt #include "utils/state_machine.h"
16*a1157835SDaniel Fojt #include "ieee802_1x_kay.h"
17*a1157835SDaniel Fojt #include "ieee802_1x_secy_ops.h"
18*a1157835SDaniel Fojt #include "pae/ieee802_1x_cp.h"
19*a1157835SDaniel Fojt
20*a1157835SDaniel Fojt #define STATE_MACHINE_DATA struct ieee802_1x_cp_sm
21*a1157835SDaniel Fojt #define STATE_MACHINE_DEBUG_PREFIX "CP"
22*a1157835SDaniel Fojt
23*a1157835SDaniel Fojt static u64 default_cs_id = CS_ID_GCM_AES_128;
24*a1157835SDaniel Fojt
25*a1157835SDaniel Fojt /* The variable defined in clause 12 in IEEE Std 802.1X-2010 */
26*a1157835SDaniel Fojt enum connect_type { PENDING, UNAUTHENTICATED, AUTHENTICATED, SECURE };
27*a1157835SDaniel Fojt
28*a1157835SDaniel Fojt struct ieee802_1x_cp_sm {
29*a1157835SDaniel Fojt enum cp_states {
30*a1157835SDaniel Fojt CP_BEGIN, CP_INIT, CP_CHANGE, CP_ALLOWED, CP_AUTHENTICATED,
31*a1157835SDaniel Fojt CP_SECURED, CP_RECEIVE, CP_RECEIVING, CP_READY, CP_TRANSMIT,
32*a1157835SDaniel Fojt CP_TRANSMITTING, CP_ABANDON, CP_RETIRE
33*a1157835SDaniel Fojt } CP_state;
34*a1157835SDaniel Fojt Boolean changed;
35*a1157835SDaniel Fojt
36*a1157835SDaniel Fojt /* CP -> Client */
37*a1157835SDaniel Fojt Boolean port_valid;
38*a1157835SDaniel Fojt
39*a1157835SDaniel Fojt /* Logon -> CP */
40*a1157835SDaniel Fojt enum connect_type connect;
41*a1157835SDaniel Fojt
42*a1157835SDaniel Fojt /* KaY -> CP */
43*a1157835SDaniel Fojt Boolean chgd_server; /* clear by CP */
44*a1157835SDaniel Fojt Boolean elected_self;
45*a1157835SDaniel Fojt enum confidentiality_offset cipher_offset;
46*a1157835SDaniel Fojt u64 cipher_suite;
47*a1157835SDaniel Fojt Boolean new_sak; /* clear by CP */
48*a1157835SDaniel Fojt struct ieee802_1x_mka_ki distributed_ki;
49*a1157835SDaniel Fojt u8 distributed_an;
50*a1157835SDaniel Fojt Boolean using_receive_sas;
51*a1157835SDaniel Fojt Boolean all_receiving;
52*a1157835SDaniel Fojt Boolean server_transmitting;
53*a1157835SDaniel Fojt Boolean using_transmit_sa;
54*a1157835SDaniel Fojt
55*a1157835SDaniel Fojt /* CP -> KaY */
56*a1157835SDaniel Fojt struct ieee802_1x_mka_ki *lki;
57*a1157835SDaniel Fojt u8 lan;
58*a1157835SDaniel Fojt Boolean ltx;
59*a1157835SDaniel Fojt Boolean lrx;
60*a1157835SDaniel Fojt struct ieee802_1x_mka_ki *oki;
61*a1157835SDaniel Fojt u8 oan;
62*a1157835SDaniel Fojt Boolean otx;
63*a1157835SDaniel Fojt Boolean orx;
64*a1157835SDaniel Fojt
65*a1157835SDaniel Fojt /* CP -> SecY */
66*a1157835SDaniel Fojt Boolean protect_frames;
67*a1157835SDaniel Fojt enum validate_frames validate_frames;
68*a1157835SDaniel Fojt
69*a1157835SDaniel Fojt Boolean replay_protect;
70*a1157835SDaniel Fojt u32 replay_window;
71*a1157835SDaniel Fojt
72*a1157835SDaniel Fojt u64 current_cipher_suite;
73*a1157835SDaniel Fojt enum confidentiality_offset confidentiality_offset;
74*a1157835SDaniel Fojt Boolean controlled_port_enabled;
75*a1157835SDaniel Fojt
76*a1157835SDaniel Fojt /* SecY -> CP */
77*a1157835SDaniel Fojt Boolean port_enabled; /* SecY->CP */
78*a1157835SDaniel Fojt
79*a1157835SDaniel Fojt /* private */
80*a1157835SDaniel Fojt u32 transmit_when;
81*a1157835SDaniel Fojt u32 transmit_delay;
82*a1157835SDaniel Fojt u32 retire_when;
83*a1157835SDaniel Fojt u32 retire_delay;
84*a1157835SDaniel Fojt
85*a1157835SDaniel Fojt /* not defined IEEE Std 802.1X-2010 */
86*a1157835SDaniel Fojt struct ieee802_1x_kay *kay;
87*a1157835SDaniel Fojt };
88*a1157835SDaniel Fojt
89*a1157835SDaniel Fojt static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
90*a1157835SDaniel Fojt void *timeout_ctx);
91*a1157835SDaniel Fojt static void ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx,
92*a1157835SDaniel Fojt void *timeout_ctx);
93*a1157835SDaniel Fojt
94*a1157835SDaniel Fojt
changed_cipher(struct ieee802_1x_cp_sm * sm)95*a1157835SDaniel Fojt static int changed_cipher(struct ieee802_1x_cp_sm *sm)
96*a1157835SDaniel Fojt {
97*a1157835SDaniel Fojt return sm->confidentiality_offset != sm->cipher_offset ||
98*a1157835SDaniel Fojt sm->current_cipher_suite != sm->cipher_suite;
99*a1157835SDaniel Fojt }
100*a1157835SDaniel Fojt
101*a1157835SDaniel Fojt
changed_connect(struct ieee802_1x_cp_sm * sm)102*a1157835SDaniel Fojt static int changed_connect(struct ieee802_1x_cp_sm *sm)
103*a1157835SDaniel Fojt {
104*a1157835SDaniel Fojt return sm->connect != SECURE || sm->chgd_server || changed_cipher(sm);
105*a1157835SDaniel Fojt }
106*a1157835SDaniel Fojt
107*a1157835SDaniel Fojt
SM_STATE(CP,INIT)108*a1157835SDaniel Fojt SM_STATE(CP, INIT)
109*a1157835SDaniel Fojt {
110*a1157835SDaniel Fojt SM_ENTRY(CP, INIT);
111*a1157835SDaniel Fojt
112*a1157835SDaniel Fojt sm->controlled_port_enabled = FALSE;
113*a1157835SDaniel Fojt secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
114*a1157835SDaniel Fojt
115*a1157835SDaniel Fojt sm->port_valid = FALSE;
116*a1157835SDaniel Fojt
117*a1157835SDaniel Fojt os_free(sm->lki);
118*a1157835SDaniel Fojt sm->lki = NULL;
119*a1157835SDaniel Fojt sm->ltx = FALSE;
120*a1157835SDaniel Fojt sm->lrx = FALSE;
121*a1157835SDaniel Fojt
122*a1157835SDaniel Fojt os_free(sm->oki);
123*a1157835SDaniel Fojt sm->oki = NULL;
124*a1157835SDaniel Fojt sm->otx = FALSE;
125*a1157835SDaniel Fojt sm->orx = FALSE;
126*a1157835SDaniel Fojt
127*a1157835SDaniel Fojt sm->port_enabled = TRUE;
128*a1157835SDaniel Fojt sm->chgd_server = FALSE;
129*a1157835SDaniel Fojt }
130*a1157835SDaniel Fojt
131*a1157835SDaniel Fojt
SM_STATE(CP,CHANGE)132*a1157835SDaniel Fojt SM_STATE(CP, CHANGE)
133*a1157835SDaniel Fojt {
134*a1157835SDaniel Fojt SM_ENTRY(CP, CHANGE);
135*a1157835SDaniel Fojt
136*a1157835SDaniel Fojt sm->port_valid = FALSE;
137*a1157835SDaniel Fojt sm->controlled_port_enabled = FALSE;
138*a1157835SDaniel Fojt secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
139*a1157835SDaniel Fojt
140*a1157835SDaniel Fojt if (sm->lki)
141*a1157835SDaniel Fojt ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
142*a1157835SDaniel Fojt if (sm->oki)
143*a1157835SDaniel Fojt ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
144*a1157835SDaniel Fojt }
145*a1157835SDaniel Fojt
146*a1157835SDaniel Fojt
SM_STATE(CP,ALLOWED)147*a1157835SDaniel Fojt SM_STATE(CP, ALLOWED)
148*a1157835SDaniel Fojt {
149*a1157835SDaniel Fojt SM_ENTRY(CP, ALLOWED);
150*a1157835SDaniel Fojt
151*a1157835SDaniel Fojt sm->protect_frames = FALSE;
152*a1157835SDaniel Fojt sm->replay_protect = FALSE;
153*a1157835SDaniel Fojt sm->validate_frames = Checked;
154*a1157835SDaniel Fojt
155*a1157835SDaniel Fojt sm->port_valid = FALSE;
156*a1157835SDaniel Fojt sm->controlled_port_enabled = TRUE;
157*a1157835SDaniel Fojt
158*a1157835SDaniel Fojt secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
159*a1157835SDaniel Fojt secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
160*a1157835SDaniel Fojt secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
161*a1157835SDaniel Fojt secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
162*a1157835SDaniel Fojt secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
163*a1157835SDaniel Fojt }
164*a1157835SDaniel Fojt
165*a1157835SDaniel Fojt
SM_STATE(CP,AUTHENTICATED)166*a1157835SDaniel Fojt SM_STATE(CP, AUTHENTICATED)
167*a1157835SDaniel Fojt {
168*a1157835SDaniel Fojt SM_ENTRY(CP, AUTHENTICATED);
169*a1157835SDaniel Fojt
170*a1157835SDaniel Fojt sm->protect_frames = FALSE;
171*a1157835SDaniel Fojt sm->replay_protect = FALSE;
172*a1157835SDaniel Fojt sm->validate_frames = Checked;
173*a1157835SDaniel Fojt
174*a1157835SDaniel Fojt sm->port_valid = FALSE;
175*a1157835SDaniel Fojt sm->controlled_port_enabled = TRUE;
176*a1157835SDaniel Fojt
177*a1157835SDaniel Fojt secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
178*a1157835SDaniel Fojt secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
179*a1157835SDaniel Fojt secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
180*a1157835SDaniel Fojt secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
181*a1157835SDaniel Fojt secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
182*a1157835SDaniel Fojt }
183*a1157835SDaniel Fojt
184*a1157835SDaniel Fojt
SM_STATE(CP,SECURED)185*a1157835SDaniel Fojt SM_STATE(CP, SECURED)
186*a1157835SDaniel Fojt {
187*a1157835SDaniel Fojt SM_ENTRY(CP, SECURED);
188*a1157835SDaniel Fojt
189*a1157835SDaniel Fojt sm->chgd_server = FALSE;
190*a1157835SDaniel Fojt
191*a1157835SDaniel Fojt sm->protect_frames = sm->kay->macsec_protect;
192*a1157835SDaniel Fojt sm->replay_protect = sm->kay->macsec_replay_protect;
193*a1157835SDaniel Fojt sm->validate_frames = sm->kay->macsec_validate;
194*a1157835SDaniel Fojt
195*a1157835SDaniel Fojt /* NOTE: now no other than default cipher suite (AES-GCM-128) */
196*a1157835SDaniel Fojt sm->current_cipher_suite = sm->cipher_suite;
197*a1157835SDaniel Fojt secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite);
198*a1157835SDaniel Fojt
199*a1157835SDaniel Fojt sm->confidentiality_offset = sm->cipher_offset;
200*a1157835SDaniel Fojt
201*a1157835SDaniel Fojt sm->port_valid = TRUE;
202*a1157835SDaniel Fojt
203*a1157835SDaniel Fojt secy_cp_control_confidentiality_offset(sm->kay,
204*a1157835SDaniel Fojt sm->confidentiality_offset);
205*a1157835SDaniel Fojt secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
206*a1157835SDaniel Fojt secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
207*a1157835SDaniel Fojt secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
208*a1157835SDaniel Fojt secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
209*a1157835SDaniel Fojt }
210*a1157835SDaniel Fojt
211*a1157835SDaniel Fojt
SM_STATE(CP,RECEIVE)212*a1157835SDaniel Fojt SM_STATE(CP, RECEIVE)
213*a1157835SDaniel Fojt {
214*a1157835SDaniel Fojt SM_ENTRY(CP, RECEIVE);
215*a1157835SDaniel Fojt /* RECEIVE state machine not keep with Figure 12-2 in
216*a1157835SDaniel Fojt * IEEE Std 802.1X-2010 */
217*a1157835SDaniel Fojt if (sm->oki) {
218*a1157835SDaniel Fojt ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
219*a1157835SDaniel Fojt os_free(sm->oki);
220*a1157835SDaniel Fojt }
221*a1157835SDaniel Fojt sm->oki = sm->lki;
222*a1157835SDaniel Fojt sm->oan = sm->lan;
223*a1157835SDaniel Fojt sm->otx = sm->ltx;
224*a1157835SDaniel Fojt sm->orx = sm->lrx;
225*a1157835SDaniel Fojt ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
226*a1157835SDaniel Fojt sm->otx, sm->orx);
227*a1157835SDaniel Fojt
228*a1157835SDaniel Fojt sm->lki = os_malloc(sizeof(*sm->lki));
229*a1157835SDaniel Fojt if (!sm->lki) {
230*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "CP-%s: Out of memory", __func__);
231*a1157835SDaniel Fojt return;
232*a1157835SDaniel Fojt }
233*a1157835SDaniel Fojt os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki));
234*a1157835SDaniel Fojt sm->lan = sm->distributed_an;
235*a1157835SDaniel Fojt sm->ltx = FALSE;
236*a1157835SDaniel Fojt sm->lrx = FALSE;
237*a1157835SDaniel Fojt ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
238*a1157835SDaniel Fojt sm->ltx, sm->lrx);
239*a1157835SDaniel Fojt ieee802_1x_kay_create_sas(sm->kay, sm->lki);
240*a1157835SDaniel Fojt ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki);
241*a1157835SDaniel Fojt sm->new_sak = FALSE;
242*a1157835SDaniel Fojt sm->all_receiving = FALSE;
243*a1157835SDaniel Fojt }
244*a1157835SDaniel Fojt
245*a1157835SDaniel Fojt
SM_STATE(CP,RECEIVING)246*a1157835SDaniel Fojt SM_STATE(CP, RECEIVING)
247*a1157835SDaniel Fojt {
248*a1157835SDaniel Fojt SM_ENTRY(CP, RECEIVING);
249*a1157835SDaniel Fojt
250*a1157835SDaniel Fojt sm->lrx = TRUE;
251*a1157835SDaniel Fojt ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
252*a1157835SDaniel Fojt sm->ltx, sm->lrx);
253*a1157835SDaniel Fojt sm->transmit_when = sm->transmit_delay;
254*a1157835SDaniel Fojt eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
255*a1157835SDaniel Fojt eloop_register_timeout(sm->transmit_when / 1000, 0,
256*a1157835SDaniel Fojt ieee802_1x_cp_transmit_when_timeout, sm, NULL);
257*a1157835SDaniel Fojt /* the electedSelf have been set before CP entering to RECEIVING
258*a1157835SDaniel Fojt * but the CP will transmit from RECEIVING to READY under
259*a1157835SDaniel Fojt * the !electedSelf when KaY is not key server */
260*a1157835SDaniel Fojt ieee802_1x_cp_sm_step(sm);
261*a1157835SDaniel Fojt sm->using_receive_sas = FALSE;
262*a1157835SDaniel Fojt sm->server_transmitting = FALSE;
263*a1157835SDaniel Fojt }
264*a1157835SDaniel Fojt
265*a1157835SDaniel Fojt
SM_STATE(CP,READY)266*a1157835SDaniel Fojt SM_STATE(CP, READY)
267*a1157835SDaniel Fojt {
268*a1157835SDaniel Fojt SM_ENTRY(CP, READY);
269*a1157835SDaniel Fojt
270*a1157835SDaniel Fojt ieee802_1x_kay_enable_new_info(sm->kay);
271*a1157835SDaniel Fojt }
272*a1157835SDaniel Fojt
273*a1157835SDaniel Fojt
SM_STATE(CP,TRANSMIT)274*a1157835SDaniel Fojt SM_STATE(CP, TRANSMIT)
275*a1157835SDaniel Fojt {
276*a1157835SDaniel Fojt SM_ENTRY(CP, TRANSMIT);
277*a1157835SDaniel Fojt
278*a1157835SDaniel Fojt sm->controlled_port_enabled = TRUE;
279*a1157835SDaniel Fojt secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
280*a1157835SDaniel Fojt sm->ltx = TRUE;
281*a1157835SDaniel Fojt ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
282*a1157835SDaniel Fojt sm->ltx, sm->lrx);
283*a1157835SDaniel Fojt ieee802_1x_kay_enable_tx_sas(sm->kay, sm->lki);
284*a1157835SDaniel Fojt sm->all_receiving = FALSE;
285*a1157835SDaniel Fojt sm->server_transmitting = FALSE;
286*a1157835SDaniel Fojt }
287*a1157835SDaniel Fojt
288*a1157835SDaniel Fojt
SM_STATE(CP,TRANSMITTING)289*a1157835SDaniel Fojt SM_STATE(CP, TRANSMITTING)
290*a1157835SDaniel Fojt {
291*a1157835SDaniel Fojt SM_ENTRY(CP, TRANSMITTING);
292*a1157835SDaniel Fojt sm->retire_when = sm->orx ? sm->retire_delay : 0;
293*a1157835SDaniel Fojt sm->otx = FALSE;
294*a1157835SDaniel Fojt ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
295*a1157835SDaniel Fojt sm->otx, sm->orx);
296*a1157835SDaniel Fojt ieee802_1x_kay_enable_new_info(sm->kay);
297*a1157835SDaniel Fojt eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
298*a1157835SDaniel Fojt eloop_register_timeout(sm->retire_when / 1000, 0,
299*a1157835SDaniel Fojt ieee802_1x_cp_retire_when_timeout, sm, NULL);
300*a1157835SDaniel Fojt sm->using_transmit_sa = FALSE;
301*a1157835SDaniel Fojt }
302*a1157835SDaniel Fojt
303*a1157835SDaniel Fojt
SM_STATE(CP,ABANDON)304*a1157835SDaniel Fojt SM_STATE(CP, ABANDON)
305*a1157835SDaniel Fojt {
306*a1157835SDaniel Fojt SM_ENTRY(CP, ABANDON);
307*a1157835SDaniel Fojt sm->lrx = FALSE;
308*a1157835SDaniel Fojt ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
309*a1157835SDaniel Fojt sm->ltx, sm->lrx);
310*a1157835SDaniel Fojt ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
311*a1157835SDaniel Fojt
312*a1157835SDaniel Fojt os_free(sm->lki);
313*a1157835SDaniel Fojt sm->lki = NULL;
314*a1157835SDaniel Fojt ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
315*a1157835SDaniel Fojt sm->ltx, sm->lrx);
316*a1157835SDaniel Fojt sm->new_sak = FALSE;
317*a1157835SDaniel Fojt }
318*a1157835SDaniel Fojt
319*a1157835SDaniel Fojt
SM_STATE(CP,RETIRE)320*a1157835SDaniel Fojt SM_STATE(CP, RETIRE)
321*a1157835SDaniel Fojt {
322*a1157835SDaniel Fojt SM_ENTRY(CP, RETIRE);
323*a1157835SDaniel Fojt /* RETIRE state machine not keep with Figure 12-2 in
324*a1157835SDaniel Fojt * IEEE Std 802.1X-2010 */
325*a1157835SDaniel Fojt if (sm->oki) {
326*a1157835SDaniel Fojt ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
327*a1157835SDaniel Fojt os_free(sm->oki);
328*a1157835SDaniel Fojt sm->oki = NULL;
329*a1157835SDaniel Fojt }
330*a1157835SDaniel Fojt sm->orx = FALSE;
331*a1157835SDaniel Fojt sm->otx = FALSE;
332*a1157835SDaniel Fojt ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
333*a1157835SDaniel Fojt sm->otx, sm->orx);
334*a1157835SDaniel Fojt }
335*a1157835SDaniel Fojt
336*a1157835SDaniel Fojt
337*a1157835SDaniel Fojt /**
338*a1157835SDaniel Fojt * CP state machine handler entry
339*a1157835SDaniel Fojt */
SM_STEP(CP)340*a1157835SDaniel Fojt SM_STEP(CP)
341*a1157835SDaniel Fojt {
342*a1157835SDaniel Fojt if (!sm->port_enabled)
343*a1157835SDaniel Fojt SM_ENTER(CP, INIT);
344*a1157835SDaniel Fojt
345*a1157835SDaniel Fojt switch (sm->CP_state) {
346*a1157835SDaniel Fojt case CP_BEGIN:
347*a1157835SDaniel Fojt SM_ENTER(CP, INIT);
348*a1157835SDaniel Fojt break;
349*a1157835SDaniel Fojt
350*a1157835SDaniel Fojt case CP_INIT:
351*a1157835SDaniel Fojt SM_ENTER(CP, CHANGE);
352*a1157835SDaniel Fojt break;
353*a1157835SDaniel Fojt
354*a1157835SDaniel Fojt case CP_CHANGE:
355*a1157835SDaniel Fojt if (sm->connect == UNAUTHENTICATED)
356*a1157835SDaniel Fojt SM_ENTER(CP, ALLOWED);
357*a1157835SDaniel Fojt else if (sm->connect == AUTHENTICATED)
358*a1157835SDaniel Fojt SM_ENTER(CP, AUTHENTICATED);
359*a1157835SDaniel Fojt else if (sm->connect == SECURE)
360*a1157835SDaniel Fojt SM_ENTER(CP, SECURED);
361*a1157835SDaniel Fojt break;
362*a1157835SDaniel Fojt
363*a1157835SDaniel Fojt case CP_ALLOWED:
364*a1157835SDaniel Fojt if (sm->connect != UNAUTHENTICATED)
365*a1157835SDaniel Fojt SM_ENTER(CP, CHANGE);
366*a1157835SDaniel Fojt break;
367*a1157835SDaniel Fojt
368*a1157835SDaniel Fojt case CP_AUTHENTICATED:
369*a1157835SDaniel Fojt if (sm->connect != AUTHENTICATED)
370*a1157835SDaniel Fojt SM_ENTER(CP, CHANGE);
371*a1157835SDaniel Fojt break;
372*a1157835SDaniel Fojt
373*a1157835SDaniel Fojt case CP_SECURED:
374*a1157835SDaniel Fojt if (changed_connect(sm))
375*a1157835SDaniel Fojt SM_ENTER(CP, CHANGE);
376*a1157835SDaniel Fojt else if (sm->new_sak)
377*a1157835SDaniel Fojt SM_ENTER(CP, RECEIVE);
378*a1157835SDaniel Fojt break;
379*a1157835SDaniel Fojt
380*a1157835SDaniel Fojt case CP_RECEIVE:
381*a1157835SDaniel Fojt if (sm->using_receive_sas)
382*a1157835SDaniel Fojt SM_ENTER(CP, RECEIVING);
383*a1157835SDaniel Fojt break;
384*a1157835SDaniel Fojt
385*a1157835SDaniel Fojt case CP_RECEIVING:
386*a1157835SDaniel Fojt if (sm->new_sak || changed_connect(sm))
387*a1157835SDaniel Fojt SM_ENTER(CP, ABANDON);
388*a1157835SDaniel Fojt if (!sm->elected_self)
389*a1157835SDaniel Fojt SM_ENTER(CP, READY);
390*a1157835SDaniel Fojt if (sm->elected_self &&
391*a1157835SDaniel Fojt (sm->all_receiving || !sm->controlled_port_enabled ||
392*a1157835SDaniel Fojt !sm->transmit_when))
393*a1157835SDaniel Fojt SM_ENTER(CP, TRANSMIT);
394*a1157835SDaniel Fojt break;
395*a1157835SDaniel Fojt
396*a1157835SDaniel Fojt case CP_TRANSMIT:
397*a1157835SDaniel Fojt if (sm->using_transmit_sa)
398*a1157835SDaniel Fojt SM_ENTER(CP, TRANSMITTING);
399*a1157835SDaniel Fojt break;
400*a1157835SDaniel Fojt
401*a1157835SDaniel Fojt case CP_TRANSMITTING:
402*a1157835SDaniel Fojt if (!sm->retire_when || changed_connect(sm))
403*a1157835SDaniel Fojt SM_ENTER(CP, RETIRE);
404*a1157835SDaniel Fojt break;
405*a1157835SDaniel Fojt
406*a1157835SDaniel Fojt case CP_RETIRE:
407*a1157835SDaniel Fojt if (changed_connect(sm))
408*a1157835SDaniel Fojt SM_ENTER(CP, CHANGE);
409*a1157835SDaniel Fojt else if (sm->new_sak)
410*a1157835SDaniel Fojt SM_ENTER(CP, RECEIVE);
411*a1157835SDaniel Fojt break;
412*a1157835SDaniel Fojt
413*a1157835SDaniel Fojt case CP_READY:
414*a1157835SDaniel Fojt if (sm->new_sak || changed_connect(sm))
415*a1157835SDaniel Fojt SM_ENTER(CP, ABANDON);
416*a1157835SDaniel Fojt if (sm->server_transmitting || !sm->controlled_port_enabled)
417*a1157835SDaniel Fojt SM_ENTER(CP, TRANSMIT);
418*a1157835SDaniel Fojt break;
419*a1157835SDaniel Fojt case CP_ABANDON:
420*a1157835SDaniel Fojt if (changed_connect(sm))
421*a1157835SDaniel Fojt SM_ENTER(CP, RETIRE);
422*a1157835SDaniel Fojt else if (sm->new_sak)
423*a1157835SDaniel Fojt SM_ENTER(CP, RECEIVE);
424*a1157835SDaniel Fojt break;
425*a1157835SDaniel Fojt default:
426*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "CP: the state machine is not defined");
427*a1157835SDaniel Fojt break;
428*a1157835SDaniel Fojt }
429*a1157835SDaniel Fojt }
430*a1157835SDaniel Fojt
431*a1157835SDaniel Fojt
432*a1157835SDaniel Fojt /**
433*a1157835SDaniel Fojt * ieee802_1x_cp_sm_init -
434*a1157835SDaniel Fojt */
ieee802_1x_cp_sm_init(struct ieee802_1x_kay * kay)435*a1157835SDaniel Fojt struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
436*a1157835SDaniel Fojt {
437*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm;
438*a1157835SDaniel Fojt
439*a1157835SDaniel Fojt sm = os_zalloc(sizeof(*sm));
440*a1157835SDaniel Fojt if (sm == NULL) {
441*a1157835SDaniel Fojt wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
442*a1157835SDaniel Fojt return NULL;
443*a1157835SDaniel Fojt }
444*a1157835SDaniel Fojt
445*a1157835SDaniel Fojt sm->kay = kay;
446*a1157835SDaniel Fojt
447*a1157835SDaniel Fojt sm->port_valid = FALSE;
448*a1157835SDaniel Fojt
449*a1157835SDaniel Fojt sm->chgd_server = FALSE;
450*a1157835SDaniel Fojt
451*a1157835SDaniel Fojt sm->protect_frames = kay->macsec_protect;
452*a1157835SDaniel Fojt sm->validate_frames = kay->macsec_validate;
453*a1157835SDaniel Fojt sm->replay_protect = kay->macsec_replay_protect;
454*a1157835SDaniel Fojt sm->replay_window = kay->macsec_replay_window;
455*a1157835SDaniel Fojt
456*a1157835SDaniel Fojt sm->controlled_port_enabled = FALSE;
457*a1157835SDaniel Fojt
458*a1157835SDaniel Fojt sm->lki = NULL;
459*a1157835SDaniel Fojt sm->lrx = FALSE;
460*a1157835SDaniel Fojt sm->ltx = FALSE;
461*a1157835SDaniel Fojt sm->oki = NULL;
462*a1157835SDaniel Fojt sm->orx = FALSE;
463*a1157835SDaniel Fojt sm->otx = FALSE;
464*a1157835SDaniel Fojt
465*a1157835SDaniel Fojt sm->current_cipher_suite = default_cs_id;
466*a1157835SDaniel Fojt sm->cipher_suite = default_cs_id;
467*a1157835SDaniel Fojt sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
468*a1157835SDaniel Fojt sm->confidentiality_offset = sm->cipher_offset;
469*a1157835SDaniel Fojt sm->transmit_delay = MKA_LIFE_TIME;
470*a1157835SDaniel Fojt sm->retire_delay = MKA_SAK_RETIRE_TIME;
471*a1157835SDaniel Fojt sm->CP_state = CP_BEGIN;
472*a1157835SDaniel Fojt sm->changed = FALSE;
473*a1157835SDaniel Fojt
474*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "CP: state machine created");
475*a1157835SDaniel Fojt
476*a1157835SDaniel Fojt secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
477*a1157835SDaniel Fojt secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
478*a1157835SDaniel Fojt secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
479*a1157835SDaniel Fojt secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
480*a1157835SDaniel Fojt secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
481*a1157835SDaniel Fojt secy_cp_control_confidentiality_offset(sm->kay,
482*a1157835SDaniel Fojt sm->confidentiality_offset);
483*a1157835SDaniel Fojt
484*a1157835SDaniel Fojt SM_STEP_RUN(CP);
485*a1157835SDaniel Fojt
486*a1157835SDaniel Fojt return sm;
487*a1157835SDaniel Fojt }
488*a1157835SDaniel Fojt
489*a1157835SDaniel Fojt
ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm * sm)490*a1157835SDaniel Fojt static void ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm *sm)
491*a1157835SDaniel Fojt {
492*a1157835SDaniel Fojt enum cp_states prev_state;
493*a1157835SDaniel Fojt int i;
494*a1157835SDaniel Fojt
495*a1157835SDaniel Fojt for (i = 0; i < 100; i++) {
496*a1157835SDaniel Fojt prev_state = sm->CP_state;
497*a1157835SDaniel Fojt SM_STEP_RUN(CP);
498*a1157835SDaniel Fojt if (prev_state == sm->CP_state)
499*a1157835SDaniel Fojt break;
500*a1157835SDaniel Fojt }
501*a1157835SDaniel Fojt }
502*a1157835SDaniel Fojt
503*a1157835SDaniel Fojt
ieee802_1x_cp_step_cb(void * eloop_ctx,void * timeout_ctx)504*a1157835SDaniel Fojt static void ieee802_1x_cp_step_cb(void *eloop_ctx, void *timeout_ctx)
505*a1157835SDaniel Fojt {
506*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = eloop_ctx;
507*a1157835SDaniel Fojt ieee802_1x_cp_step_run(sm);
508*a1157835SDaniel Fojt }
509*a1157835SDaniel Fojt
510*a1157835SDaniel Fojt
511*a1157835SDaniel Fojt /**
512*a1157835SDaniel Fojt * ieee802_1x_cp_sm_deinit -
513*a1157835SDaniel Fojt */
ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm * sm)514*a1157835SDaniel Fojt void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm)
515*a1157835SDaniel Fojt {
516*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "CP: state machine removed");
517*a1157835SDaniel Fojt if (!sm)
518*a1157835SDaniel Fojt return;
519*a1157835SDaniel Fojt
520*a1157835SDaniel Fojt eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
521*a1157835SDaniel Fojt eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
522*a1157835SDaniel Fojt eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
523*a1157835SDaniel Fojt os_free(sm->lki);
524*a1157835SDaniel Fojt os_free(sm->oki);
525*a1157835SDaniel Fojt os_free(sm);
526*a1157835SDaniel Fojt }
527*a1157835SDaniel Fojt
528*a1157835SDaniel Fojt
529*a1157835SDaniel Fojt /**
530*a1157835SDaniel Fojt * ieee802_1x_cp_connect_pending
531*a1157835SDaniel Fojt */
ieee802_1x_cp_connect_pending(void * cp_ctx)532*a1157835SDaniel Fojt void ieee802_1x_cp_connect_pending(void *cp_ctx)
533*a1157835SDaniel Fojt {
534*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
535*a1157835SDaniel Fojt
536*a1157835SDaniel Fojt sm->connect = PENDING;
537*a1157835SDaniel Fojt }
538*a1157835SDaniel Fojt
539*a1157835SDaniel Fojt
540*a1157835SDaniel Fojt /**
541*a1157835SDaniel Fojt * ieee802_1x_cp_connect_unauthenticated
542*a1157835SDaniel Fojt */
ieee802_1x_cp_connect_unauthenticated(void * cp_ctx)543*a1157835SDaniel Fojt void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx)
544*a1157835SDaniel Fojt {
545*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = (struct ieee802_1x_cp_sm *)cp_ctx;
546*a1157835SDaniel Fojt
547*a1157835SDaniel Fojt sm->connect = UNAUTHENTICATED;
548*a1157835SDaniel Fojt }
549*a1157835SDaniel Fojt
550*a1157835SDaniel Fojt
551*a1157835SDaniel Fojt /**
552*a1157835SDaniel Fojt * ieee802_1x_cp_connect_authenticated
553*a1157835SDaniel Fojt */
ieee802_1x_cp_connect_authenticated(void * cp_ctx)554*a1157835SDaniel Fojt void ieee802_1x_cp_connect_authenticated(void *cp_ctx)
555*a1157835SDaniel Fojt {
556*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
557*a1157835SDaniel Fojt
558*a1157835SDaniel Fojt sm->connect = AUTHENTICATED;
559*a1157835SDaniel Fojt }
560*a1157835SDaniel Fojt
561*a1157835SDaniel Fojt
562*a1157835SDaniel Fojt /**
563*a1157835SDaniel Fojt * ieee802_1x_cp_connect_secure
564*a1157835SDaniel Fojt */
ieee802_1x_cp_connect_secure(void * cp_ctx)565*a1157835SDaniel Fojt void ieee802_1x_cp_connect_secure(void *cp_ctx)
566*a1157835SDaniel Fojt {
567*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
568*a1157835SDaniel Fojt
569*a1157835SDaniel Fojt sm->connect = SECURE;
570*a1157835SDaniel Fojt }
571*a1157835SDaniel Fojt
572*a1157835SDaniel Fojt
573*a1157835SDaniel Fojt /**
574*a1157835SDaniel Fojt * ieee802_1x_cp_set_chgdserver -
575*a1157835SDaniel Fojt */
ieee802_1x_cp_signal_chgdserver(void * cp_ctx)576*a1157835SDaniel Fojt void ieee802_1x_cp_signal_chgdserver(void *cp_ctx)
577*a1157835SDaniel Fojt {
578*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
579*a1157835SDaniel Fojt
580*a1157835SDaniel Fojt sm->chgd_server = TRUE;
581*a1157835SDaniel Fojt }
582*a1157835SDaniel Fojt
583*a1157835SDaniel Fojt
584*a1157835SDaniel Fojt /**
585*a1157835SDaniel Fojt * ieee802_1x_cp_set_electedself -
586*a1157835SDaniel Fojt */
ieee802_1x_cp_set_electedself(void * cp_ctx,Boolean status)587*a1157835SDaniel Fojt void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status)
588*a1157835SDaniel Fojt {
589*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
590*a1157835SDaniel Fojt sm->elected_self = status;
591*a1157835SDaniel Fojt }
592*a1157835SDaniel Fojt
593*a1157835SDaniel Fojt
594*a1157835SDaniel Fojt /**
595*a1157835SDaniel Fojt * ieee802_1x_cp_set_ciphersuite -
596*a1157835SDaniel Fojt */
ieee802_1x_cp_set_ciphersuite(void * cp_ctx,u64 cs)597*a1157835SDaniel Fojt void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
598*a1157835SDaniel Fojt {
599*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
600*a1157835SDaniel Fojt sm->cipher_suite = cs;
601*a1157835SDaniel Fojt }
602*a1157835SDaniel Fojt
603*a1157835SDaniel Fojt
604*a1157835SDaniel Fojt /**
605*a1157835SDaniel Fojt * ieee802_1x_cp_set_offset -
606*a1157835SDaniel Fojt */
ieee802_1x_cp_set_offset(void * cp_ctx,enum confidentiality_offset offset)607*a1157835SDaniel Fojt void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset)
608*a1157835SDaniel Fojt {
609*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
610*a1157835SDaniel Fojt sm->cipher_offset = offset;
611*a1157835SDaniel Fojt }
612*a1157835SDaniel Fojt
613*a1157835SDaniel Fojt
614*a1157835SDaniel Fojt /**
615*a1157835SDaniel Fojt * ieee802_1x_cp_signal_newsak -
616*a1157835SDaniel Fojt */
ieee802_1x_cp_signal_newsak(void * cp_ctx)617*a1157835SDaniel Fojt void ieee802_1x_cp_signal_newsak(void *cp_ctx)
618*a1157835SDaniel Fojt {
619*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
620*a1157835SDaniel Fojt sm->new_sak = TRUE;
621*a1157835SDaniel Fojt }
622*a1157835SDaniel Fojt
623*a1157835SDaniel Fojt
624*a1157835SDaniel Fojt /**
625*a1157835SDaniel Fojt * ieee802_1x_cp_set_distributedki -
626*a1157835SDaniel Fojt */
ieee802_1x_cp_set_distributedki(void * cp_ctx,const struct ieee802_1x_mka_ki * dki)627*a1157835SDaniel Fojt void ieee802_1x_cp_set_distributedki(void *cp_ctx,
628*a1157835SDaniel Fojt const struct ieee802_1x_mka_ki *dki)
629*a1157835SDaniel Fojt {
630*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
631*a1157835SDaniel Fojt os_memcpy(&sm->distributed_ki, dki, sizeof(struct ieee802_1x_mka_ki));
632*a1157835SDaniel Fojt }
633*a1157835SDaniel Fojt
634*a1157835SDaniel Fojt
635*a1157835SDaniel Fojt /**
636*a1157835SDaniel Fojt * ieee802_1x_cp_set_distributedan -
637*a1157835SDaniel Fojt */
ieee802_1x_cp_set_distributedan(void * cp_ctx,u8 an)638*a1157835SDaniel Fojt void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an)
639*a1157835SDaniel Fojt {
640*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
641*a1157835SDaniel Fojt sm->distributed_an = an;
642*a1157835SDaniel Fojt }
643*a1157835SDaniel Fojt
644*a1157835SDaniel Fojt
645*a1157835SDaniel Fojt /**
646*a1157835SDaniel Fojt * ieee802_1x_cp_set_usingreceivesas -
647*a1157835SDaniel Fojt */
ieee802_1x_cp_set_usingreceivesas(void * cp_ctx,Boolean status)648*a1157835SDaniel Fojt void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status)
649*a1157835SDaniel Fojt {
650*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
651*a1157835SDaniel Fojt sm->using_receive_sas = status;
652*a1157835SDaniel Fojt }
653*a1157835SDaniel Fojt
654*a1157835SDaniel Fojt
655*a1157835SDaniel Fojt /**
656*a1157835SDaniel Fojt * ieee802_1x_cp_set_allreceiving -
657*a1157835SDaniel Fojt */
ieee802_1x_cp_set_allreceiving(void * cp_ctx,Boolean status)658*a1157835SDaniel Fojt void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status)
659*a1157835SDaniel Fojt {
660*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
661*a1157835SDaniel Fojt sm->all_receiving = status;
662*a1157835SDaniel Fojt }
663*a1157835SDaniel Fojt
664*a1157835SDaniel Fojt
665*a1157835SDaniel Fojt /**
666*a1157835SDaniel Fojt * ieee802_1x_cp_set_servertransmitting -
667*a1157835SDaniel Fojt */
ieee802_1x_cp_set_servertransmitting(void * cp_ctx,Boolean status)668*a1157835SDaniel Fojt void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status)
669*a1157835SDaniel Fojt {
670*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
671*a1157835SDaniel Fojt sm->server_transmitting = status;
672*a1157835SDaniel Fojt }
673*a1157835SDaniel Fojt
674*a1157835SDaniel Fojt
675*a1157835SDaniel Fojt /**
676*a1157835SDaniel Fojt * ieee802_1x_cp_set_usingtransmitsas -
677*a1157835SDaniel Fojt */
ieee802_1x_cp_set_usingtransmitas(void * cp_ctx,Boolean status)678*a1157835SDaniel Fojt void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status)
679*a1157835SDaniel Fojt {
680*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
681*a1157835SDaniel Fojt sm->using_transmit_sa = status;
682*a1157835SDaniel Fojt }
683*a1157835SDaniel Fojt
684*a1157835SDaniel Fojt
685*a1157835SDaniel Fojt /**
686*a1157835SDaniel Fojt * ieee802_1x_cp_sm_step - Advance EAPOL state machines
687*a1157835SDaniel Fojt * @sm: EAPOL state machine
688*a1157835SDaniel Fojt *
689*a1157835SDaniel Fojt * This function is called to advance CP state machines after any change
690*a1157835SDaniel Fojt * that could affect their state.
691*a1157835SDaniel Fojt */
ieee802_1x_cp_sm_step(void * cp_ctx)692*a1157835SDaniel Fojt void ieee802_1x_cp_sm_step(void *cp_ctx)
693*a1157835SDaniel Fojt {
694*a1157835SDaniel Fojt /*
695*a1157835SDaniel Fojt * Run ieee802_1x_cp_step_run from a registered timeout
696*a1157835SDaniel Fojt * to make sure that other possible timeouts/events are processed
697*a1157835SDaniel Fojt * and to avoid long function call chains.
698*a1157835SDaniel Fojt */
699*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = cp_ctx;
700*a1157835SDaniel Fojt eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
701*a1157835SDaniel Fojt eloop_register_timeout(0, 0, ieee802_1x_cp_step_cb, sm, NULL);
702*a1157835SDaniel Fojt }
703*a1157835SDaniel Fojt
704*a1157835SDaniel Fojt
ieee802_1x_cp_retire_when_timeout(void * eloop_ctx,void * timeout_ctx)705*a1157835SDaniel Fojt static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
706*a1157835SDaniel Fojt void *timeout_ctx)
707*a1157835SDaniel Fojt {
708*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = eloop_ctx;
709*a1157835SDaniel Fojt sm->retire_when = 0;
710*a1157835SDaniel Fojt ieee802_1x_cp_step_run(sm);
711*a1157835SDaniel Fojt }
712*a1157835SDaniel Fojt
713*a1157835SDaniel Fojt
714*a1157835SDaniel Fojt static void
ieee802_1x_cp_transmit_when_timeout(void * eloop_ctx,void * timeout_ctx)715*a1157835SDaniel Fojt ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, void *timeout_ctx)
716*a1157835SDaniel Fojt {
717*a1157835SDaniel Fojt struct ieee802_1x_cp_sm *sm = eloop_ctx;
718*a1157835SDaniel Fojt sm->transmit_when = 0;
719*a1157835SDaniel Fojt ieee802_1x_cp_step_run(sm);
720*a1157835SDaniel Fojt }
721