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