mka: Get rid of struct ieee802_1x_cp_conf
[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         SM_ENTRY(CP, SECURED);
188
189         sm->chgd_server = FALSE;
190
191         sm->protect_frames = sm->kay->macsec_protect;
192         sm->replay_protect = sm->kay->macsec_replay_protect;
193         sm->validate_frames = sm->kay->macsec_validate;
194
195         /* NOTE: now no other than default cipher suite (AES-GCM-128) */
196         sm->current_cipher_suite = sm->cipher_suite;
197         secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite);
198
199         sm->confidentiality_offset = sm->cipher_offset;
200
201         sm->port_valid = TRUE;
202
203         secy_cp_control_confidentiality_offset(sm->kay,
204                                                sm->confidentiality_offset);
205         secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
206         secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
207         secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
208 }
209
210
211 SM_STATE(CP, RECEIVE)
212 {
213         SM_ENTRY(CP, RECEIVE);
214         /* RECEIVE state machine not keep with Figure 12-2 in
215          * IEEE Std 802.1X-2010 */
216         sm->oki = sm->lki;
217         sm->oan = sm->lan;
218         sm->otx = sm->ltx;
219         sm->orx = sm->lrx;
220         ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
221                                        sm->otx, sm->orx);
222
223         sm->lki = os_malloc(sizeof(*sm->lki));
224         if (!sm->lki) {
225                 wpa_printf(MSG_ERROR, "CP-%s: Out of memory", __func__);
226                 return;
227         }
228         os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki));
229         sm->lan = sm->distributed_an;
230         sm->ltx = FALSE;
231         sm->lrx = FALSE;
232         ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
233                                           sm->ltx, sm->lrx);
234         ieee802_1x_kay_create_sas(sm->kay, sm->lki);
235         ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki);
236         sm->new_sak = FALSE;
237         sm->all_receiving = FALSE;
238 }
239
240
241 SM_STATE(CP, RECEIVING)
242 {
243         SM_ENTRY(CP, RECEIVING);
244
245         sm->lrx = TRUE;
246         ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
247                                           sm->ltx, sm->lrx);
248         sm->transmit_when = sm->transmit_delay;
249         eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
250         eloop_register_timeout(sm->transmit_when / 1000, 0,
251                                ieee802_1x_cp_transmit_when_timeout, sm, NULL);
252         /* the electedSelf have been set before CP entering to RECEIVING
253          * but the CP will transmit from RECEIVING to READY under
254          * the !electedSelf when KaY is not key server */
255         ieee802_1x_cp_sm_step(sm);
256         sm->using_receive_sas = FALSE;
257         sm->server_transmitting = FALSE;
258 }
259
260
261 SM_STATE(CP, READY)
262 {
263         SM_ENTRY(CP, READY);
264
265         ieee802_1x_kay_enable_new_info(sm->kay);
266 }
267
268
269 SM_STATE(CP, TRANSMIT)
270 {
271         SM_ENTRY(CP, TRANSMIT);
272
273         sm->controlled_port_enabled = TRUE;
274         secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
275         sm->ltx = TRUE;
276         ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
277                                           sm->ltx, sm->lrx);
278         ieee802_1x_kay_enable_tx_sas(sm->kay,  sm->lki);
279         sm->all_receiving = FALSE;
280         sm->server_transmitting = FALSE;
281 }
282
283
284 SM_STATE(CP, TRANSMITTING)
285 {
286         SM_ENTRY(CP, TRANSMITTING);
287         sm->retire_when = sm->orx ? sm->retire_delay : 0;
288         sm->otx = FALSE;
289         ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
290                                        sm->otx, sm->orx);
291         ieee802_1x_kay_enable_new_info(sm->kay);
292         eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
293         eloop_register_timeout(sm->retire_when / 1000, 0,
294                                ieee802_1x_cp_retire_when_timeout, sm, NULL);
295         sm->using_transmit_sa = FALSE;
296 }
297
298
299 SM_STATE(CP, ABANDON)
300 {
301         SM_ENTRY(CP, ABANDON);
302         sm->lrx = FALSE;
303         ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
304                                           sm->ltx, sm->lrx);
305         ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
306
307         os_free(sm->lki);
308         sm->lki = NULL;
309         ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
310                                           sm->ltx, sm->lrx);
311         sm->new_sak = FALSE;
312 }
313
314
315 SM_STATE(CP, RETIRE)
316 {
317         SM_ENTRY(CP, RETIRE);
318         /* RETIRE state machine not keep with Figure 12-2 in
319          * IEEE Std 802.1X-2010 */
320         os_free(sm->oki);
321         sm->oki = NULL;
322         sm->orx = FALSE;
323         sm->otx = FALSE;
324         ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
325                                        sm->otx, sm->orx);
326 }
327
328
329 /**
330  * CP state machine handler entry
331  */
332 SM_STEP(CP)
333 {
334         if (!sm->port_enabled)
335                 SM_ENTER(CP, INIT);
336
337         switch (sm->CP_state) {
338         case CP_BEGIN:
339                 SM_ENTER(CP, INIT);
340                 break;
341
342         case CP_INIT:
343                 SM_ENTER(CP, CHANGE);
344                 break;
345
346         case CP_CHANGE:
347                 if (sm->connect == UNAUTHENTICATED)
348                         SM_ENTER(CP, ALLOWED);
349                 else if (sm->connect == AUTHENTICATED)
350                         SM_ENTER(CP, AUTHENTICATED);
351                 else if (sm->connect == SECURE)
352                         SM_ENTER(CP, SECURED);
353                 break;
354
355         case CP_ALLOWED:
356                 if (sm->connect != UNAUTHENTICATED)
357                         SM_ENTER(CP, CHANGE);
358                 break;
359
360         case CP_AUTHENTICATED:
361                 if (sm->connect != AUTHENTICATED)
362                         SM_ENTER(CP, CHANGE);
363                 break;
364
365         case CP_SECURED:
366                 if (changed_connect(sm))
367                         SM_ENTER(CP, CHANGE);
368                 else if (sm->new_sak)
369                         SM_ENTER(CP, RECEIVE);
370                 break;
371
372         case CP_RECEIVE:
373                 if (sm->using_receive_sas)
374                         SM_ENTER(CP, RECEIVING);
375                 break;
376
377         case CP_RECEIVING:
378                 if (sm->new_sak || changed_connect(sm))
379                         SM_ENTER(CP, ABANDON);
380                 if (!sm->elected_self)
381                         SM_ENTER(CP, READY);
382                 if (sm->elected_self &&
383                     (sm->all_receiving || !sm->transmit_when))
384                         SM_ENTER(CP, TRANSMIT);
385                 break;
386
387         case CP_TRANSMIT:
388                 if (sm->using_transmit_sa)
389                         SM_ENTER(CP, TRANSMITTING);
390                 break;
391
392         case CP_TRANSMITTING:
393                 if (!sm->retire_when || changed_connect(sm))
394                         SM_ENTER(CP, RETIRE);
395                 break;
396
397         case CP_RETIRE:
398                 if (changed_connect(sm))
399                         SM_ENTER(CP, CHANGE);
400                 else if (sm->new_sak)
401                         SM_ENTER(CP, RECEIVE);
402                 break;
403
404         case CP_READY:
405                 if (sm->new_sak || changed_connect(sm))
406                         SM_ENTER(CP, RECEIVE);
407                 if (sm->server_transmitting)
408                         SM_ENTER(CP, TRANSMIT);
409                 break;
410         case CP_ABANDON:
411                 if (changed_connect(sm))
412                         SM_ENTER(CP, RETIRE);
413                 else if (sm->new_sak)
414                         SM_ENTER(CP, RECEIVE);
415                 break;
416         default:
417                 wpa_printf(MSG_ERROR, "CP: the state machine is not defined");
418                 break;
419         }
420 }
421
422
423 /**
424  * ieee802_1x_cp_sm_init -
425  */
426 struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
427 {
428         struct ieee802_1x_cp_sm *sm;
429
430         sm = os_zalloc(sizeof(*sm));
431         if (sm == NULL) {
432                 wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
433                 return NULL;
434         }
435
436         sm->kay = kay;
437
438         sm->port_valid = FALSE;
439
440         sm->chgd_server = FALSE;
441
442         sm->protect_frames = kay->macsec_protect;
443         sm->validate_frames = kay->macsec_validate;
444         sm->replay_protect = kay->macsec_replay_protect;
445         sm->replay_window = kay->macsec_replay_window;
446
447         sm->controlled_port_enabled = FALSE;
448
449         sm->lki = NULL;
450         sm->lrx = FALSE;
451         sm->ltx = FALSE;
452         sm->oki = NULL;
453         sm->orx = FALSE;
454         sm->otx = FALSE;
455
456         sm->current_cipher_suite = default_cs_id;
457         sm->cipher_suite = default_cs_id;
458         sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
459         sm->confidentiality_offset = sm->cipher_offset;
460         sm->transmit_delay = MKA_LIFE_TIME;
461         sm->retire_delay = MKA_SAK_RETIRE_TIME;
462         sm->CP_state = CP_BEGIN;
463         sm->changed = FALSE;
464         sm->authorization_data = NULL;
465
466         wpa_printf(MSG_DEBUG, "CP: state machine created");
467
468         secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
469         secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
470         secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
471         secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
472         secy_cp_control_confidentiality_offset(sm->kay,
473                                                sm->confidentiality_offset);
474
475         SM_ENTER(CP, INIT);
476         SM_STEP_RUN(CP);
477
478         return sm;
479 }
480
481
482 static void ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm *sm)
483 {
484         enum cp_states prev_state;
485         int i;
486
487         for (i = 0; i < 100; i++) {
488                 prev_state = sm->CP_state;
489                 SM_STEP_RUN(CP);
490                 if (prev_state == sm->CP_state)
491                         break;
492         }
493 }
494
495
496 static void ieee802_1x_cp_step_cb(void *eloop_ctx, void *timeout_ctx)
497 {
498         struct ieee802_1x_cp_sm *sm = eloop_ctx;
499         ieee802_1x_cp_step_run(sm);
500 }
501
502
503 /**
504  * ieee802_1x_cp_sm_deinit -
505  */
506 void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm)
507 {
508         wpa_printf(MSG_DEBUG, "CP: state machine removed");
509         if (!sm)
510                 return;
511
512         eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
513         eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
514         eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
515         os_free(sm->lki);
516         os_free(sm->oki);
517         os_free(sm->authorization_data);
518         os_free(sm);
519 }
520
521
522 /**
523  * ieee802_1x_cp_connect_pending
524  */
525 void ieee802_1x_cp_connect_pending(void *cp_ctx)
526 {
527         struct ieee802_1x_cp_sm *sm = cp_ctx;
528
529         sm->connect = PENDING;
530 }
531
532
533 /**
534  * ieee802_1x_cp_connect_unauthenticated
535  */
536 void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx)
537 {
538         struct ieee802_1x_cp_sm *sm = (struct ieee802_1x_cp_sm *)cp_ctx;
539
540         sm->connect = UNAUTHENTICATED;
541 }
542
543
544 /**
545  * ieee802_1x_cp_connect_authenticated
546  */
547 void ieee802_1x_cp_connect_authenticated(void *cp_ctx)
548 {
549         struct ieee802_1x_cp_sm *sm = cp_ctx;
550
551         sm->connect = AUTHENTICATED;
552 }
553
554
555 /**
556  * ieee802_1x_cp_connect_secure
557  */
558 void ieee802_1x_cp_connect_secure(void *cp_ctx)
559 {
560         struct ieee802_1x_cp_sm *sm = cp_ctx;
561
562         sm->connect = SECURE;
563 }
564
565
566 /**
567  * ieee802_1x_cp_set_chgdserver -
568  */
569 void ieee802_1x_cp_signal_chgdserver(void *cp_ctx)
570 {
571         struct ieee802_1x_cp_sm *sm = cp_ctx;
572
573         sm->chgd_server = TRUE;
574 }
575
576
577 /**
578  * ieee802_1x_cp_set_electedself -
579  */
580 void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status)
581 {
582         struct ieee802_1x_cp_sm *sm = cp_ctx;
583         sm->elected_self = status;
584 }
585
586
587 /**
588  * ieee802_1x_cp_set_authorizationdata -
589  */
590 void ieee802_1x_cp_set_authorizationdata(void *cp_ctx, u8 *pdata, int len)
591 {
592         struct ieee802_1x_cp_sm *sm = cp_ctx;
593         os_free(sm->authorization_data);
594         sm->authorization_data = os_zalloc(len);
595         if (sm->authorization_data)
596                 os_memcpy(sm->authorization_data, pdata, len);
597 }
598
599
600 /**
601  * ieee802_1x_cp_set_ciphersuite -
602  */
603 void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
604 {
605         struct ieee802_1x_cp_sm *sm = cp_ctx;
606         sm->cipher_suite = cs;
607 }
608
609
610 /**
611  * ieee802_1x_cp_set_offset -
612  */
613 void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset)
614 {
615         struct ieee802_1x_cp_sm *sm = cp_ctx;
616         sm->cipher_offset = offset;
617 }
618
619
620 /**
621  * ieee802_1x_cp_signal_newsak -
622  */
623 void ieee802_1x_cp_signal_newsak(void *cp_ctx)
624 {
625         struct ieee802_1x_cp_sm *sm = cp_ctx;
626         sm->new_sak = TRUE;
627 }
628
629
630 /**
631  * ieee802_1x_cp_set_distributedki -
632  */
633 void ieee802_1x_cp_set_distributedki(void *cp_ctx,
634                                      const struct ieee802_1x_mka_ki *dki)
635 {
636         struct ieee802_1x_cp_sm *sm = cp_ctx;
637         os_memcpy(&sm->distributed_ki, dki, sizeof(struct ieee802_1x_mka_ki));
638 }
639
640
641 /**
642  * ieee802_1x_cp_set_distributedan -
643  */
644 void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an)
645 {
646         struct ieee802_1x_cp_sm *sm = cp_ctx;
647         sm->distributed_an = an;
648 }
649
650
651 /**
652  * ieee802_1x_cp_set_usingreceivesas -
653  */
654 void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status)
655 {
656         struct ieee802_1x_cp_sm *sm = cp_ctx;
657         sm->using_receive_sas = status;
658 }
659
660
661 /**
662  * ieee802_1x_cp_set_allreceiving -
663  */
664 void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status)
665 {
666         struct ieee802_1x_cp_sm *sm = cp_ctx;
667         sm->all_receiving = status;
668 }
669
670
671 /**
672  * ieee802_1x_cp_set_servertransmitting -
673  */
674 void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status)
675 {
676         struct ieee802_1x_cp_sm *sm = cp_ctx;
677         sm->server_transmitting = status;
678 }
679
680
681 /**
682  * ieee802_1x_cp_set_usingtransmitsas -
683  */
684 void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status)
685 {
686         struct ieee802_1x_cp_sm *sm = cp_ctx;
687         sm->using_transmit_sa = status;
688 }
689
690
691 /**
692  * ieee802_1x_cp_sm_step - Advance EAPOL state machines
693  * @sm: EAPOL state machine
694  *
695  * This function is called to advance CP state machines after any change
696  * that could affect their state.
697  */
698 void ieee802_1x_cp_sm_step(void *cp_ctx)
699 {
700         /*
701          * Run ieee802_1x_cp_step_run from a registered timeout
702          * to make sure that other possible timeouts/events are processed
703          * and to avoid long function call chains.
704          */
705         struct ieee802_1x_cp_sm *sm = cp_ctx;
706         eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
707         eloop_register_timeout(0, 0, ieee802_1x_cp_step_cb, sm, NULL);
708 }
709
710
711 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
712                                               void *timeout_ctx)
713 {
714         struct ieee802_1x_cp_sm *sm = eloop_ctx;
715         sm->retire_when = 0;
716         ieee802_1x_cp_step_run(sm);
717 }
718
719
720 static void
721 ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, void *timeout_ctx)
722 {
723         struct ieee802_1x_cp_sm *sm = eloop_ctx;
724         sm->transmit_when = 0;
725         ieee802_1x_cp_step_run(sm);
726 }