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