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