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 
42 	/* KaY -> CP */
43 	Boolean chgd_server; /* clear by CP */
44 	Boolean elected_self;
45 	enum confidentiality_offset cipher_offset;
46 	u64 cipher_suite;
47 	Boolean new_sak; /* clear by CP */
48 	struct ieee802_1x_mka_ki distributed_ki;
49 	u8 distributed_an;
50 	Boolean using_receive_sas;
51 	Boolean all_receiving;
52 	Boolean server_transmitting;
53 	Boolean using_transmit_sa;
54 
55 	/* CP -> KaY */
56 	struct ieee802_1x_mka_ki *lki;
57 	u8 lan;
58 	Boolean ltx;
59 	Boolean lrx;
60 	struct ieee802_1x_mka_ki *oki;
61 	u8 oan;
62 	Boolean otx;
63 	Boolean orx;
64 
65 	/* CP -> SecY */
66 	Boolean protect_frames;
67 	enum validate_frames validate_frames;
68 
69 	Boolean replay_protect;
70 	u32 replay_window;
71 
72 	u64 current_cipher_suite;
73 	enum confidentiality_offset confidentiality_offset;
74 	Boolean controlled_port_enabled;
75 
76 	/* SecY -> CP */
77 	Boolean port_enabled; /* SecY->CP */
78 
79 	/* private */
80 	u32 transmit_when;
81 	u32 transmit_delay;
82 	u32 retire_when;
83 	u32 retire_delay;
84 
85 	/* not defined IEEE Std 802.1X-2010 */
86 	struct ieee802_1x_kay *kay;
87 };
88 
89 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
90 					      void *timeout_ctx);
91 static void ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx,
92 						void *timeout_ctx);
93 
94 
95 static int changed_cipher(struct ieee802_1x_cp_sm *sm)
96 {
97 	return sm->confidentiality_offset != sm->cipher_offset ||
98 		sm->current_cipher_suite != sm->cipher_suite;
99 }
100 
101 
102 static int changed_connect(struct ieee802_1x_cp_sm *sm)
103 {
104 	return sm->connect != SECURE || sm->chgd_server || changed_cipher(sm);
105 }
106 
107 
108 SM_STATE(CP, INIT)
109 {
110 	SM_ENTRY(CP, INIT);
111 
112 	sm->controlled_port_enabled = FALSE;
113 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
114 
115 	sm->port_valid = FALSE;
116 
117 	os_free(sm->lki);
118 	sm->lki = NULL;
119 	sm->ltx = FALSE;
120 	sm->lrx = FALSE;
121 
122 	os_free(sm->oki);
123 	sm->oki = NULL;
124 	sm->otx = FALSE;
125 	sm->orx = FALSE;
126 
127 	sm->port_enabled = TRUE;
128 	sm->chgd_server = FALSE;
129 }
130 
131 
132 SM_STATE(CP, CHANGE)
133 {
134 	SM_ENTRY(CP, CHANGE);
135 
136 	sm->port_valid = FALSE;
137 	sm->controlled_port_enabled = FALSE;
138 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
139 
140 	if (sm->lki)
141 		ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
142 	if (sm->oki)
143 		ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
144 }
145 
146 
147 SM_STATE(CP, ALLOWED)
148 {
149 	SM_ENTRY(CP, ALLOWED);
150 
151 	sm->protect_frames = FALSE;
152 	sm->replay_protect = FALSE;
153 	sm->validate_frames = Checked;
154 
155 	sm->port_valid = FALSE;
156 	sm->controlled_port_enabled = TRUE;
157 
158 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
159 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
160 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
161 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
162 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
163 }
164 
165 
166 SM_STATE(CP, AUTHENTICATED)
167 {
168 	SM_ENTRY(CP, AUTHENTICATED);
169 
170 	sm->protect_frames = FALSE;
171 	sm->replay_protect = FALSE;
172 	sm->validate_frames = Checked;
173 
174 	sm->port_valid = FALSE;
175 	sm->controlled_port_enabled = TRUE;
176 
177 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
178 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
179 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
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_encrypt(sm->kay, sm->kay->macsec_encrypt);
207 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
208 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
209 }
210 
211 
212 SM_STATE(CP, RECEIVE)
213 {
214 	SM_ENTRY(CP, RECEIVE);
215 	/* RECEIVE state machine not keep with Figure 12-2 in
216 	 * IEEE Std 802.1X-2010 */
217 	if (sm->oki) {
218 		ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
219 		os_free(sm->oki);
220 	}
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 	if (sm->oki) {
326 		ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
327 		os_free(sm->oki);
328 		sm->oki = NULL;
329 	}
330 	sm->orx = FALSE;
331 	sm->otx = FALSE;
332 	ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
333 				       sm->otx, sm->orx);
334 }
335 
336 
337 /**
338  * CP state machine handler entry
339  */
340 SM_STEP(CP)
341 {
342 	if (!sm->port_enabled)
343 		SM_ENTER(CP, INIT);
344 
345 	switch (sm->CP_state) {
346 	case CP_BEGIN:
347 		SM_ENTER(CP, INIT);
348 		break;
349 
350 	case CP_INIT:
351 		SM_ENTER(CP, CHANGE);
352 		break;
353 
354 	case CP_CHANGE:
355 		if (sm->connect == UNAUTHENTICATED)
356 			SM_ENTER(CP, ALLOWED);
357 		else if (sm->connect == AUTHENTICATED)
358 			SM_ENTER(CP, AUTHENTICATED);
359 		else if (sm->connect == SECURE)
360 			SM_ENTER(CP, SECURED);
361 		break;
362 
363 	case CP_ALLOWED:
364 		if (sm->connect != UNAUTHENTICATED)
365 			SM_ENTER(CP, CHANGE);
366 		break;
367 
368 	case CP_AUTHENTICATED:
369 		if (sm->connect != AUTHENTICATED)
370 			SM_ENTER(CP, CHANGE);
371 		break;
372 
373 	case CP_SECURED:
374 		if (changed_connect(sm))
375 			SM_ENTER(CP, CHANGE);
376 		else if (sm->new_sak)
377 			SM_ENTER(CP, RECEIVE);
378 		break;
379 
380 	case CP_RECEIVE:
381 		if (sm->using_receive_sas)
382 			SM_ENTER(CP, RECEIVING);
383 		break;
384 
385 	case CP_RECEIVING:
386 		if (sm->new_sak || changed_connect(sm))
387 			SM_ENTER(CP, ABANDON);
388 		if (!sm->elected_self)
389 			SM_ENTER(CP, READY);
390 		if (sm->elected_self &&
391 		    (sm->all_receiving || !sm->controlled_port_enabled ||
392 		     !sm->transmit_when))
393 			SM_ENTER(CP, TRANSMIT);
394 		break;
395 
396 	case CP_TRANSMIT:
397 		if (sm->using_transmit_sa)
398 			SM_ENTER(CP, TRANSMITTING);
399 		break;
400 
401 	case CP_TRANSMITTING:
402 		if (!sm->retire_when || changed_connect(sm))
403 			SM_ENTER(CP, RETIRE);
404 		break;
405 
406 	case CP_RETIRE:
407 		if (changed_connect(sm))
408 			SM_ENTER(CP, CHANGE);
409 		else if (sm->new_sak)
410 			SM_ENTER(CP, RECEIVE);
411 		break;
412 
413 	case CP_READY:
414 		if (sm->new_sak || changed_connect(sm))
415 			SM_ENTER(CP, ABANDON);
416 		if (sm->server_transmitting || !sm->controlled_port_enabled)
417 			SM_ENTER(CP, TRANSMIT);
418 		break;
419 	case CP_ABANDON:
420 		if (changed_connect(sm))
421 			SM_ENTER(CP, RETIRE);
422 		else if (sm->new_sak)
423 			SM_ENTER(CP, RECEIVE);
424 		break;
425 	default:
426 		wpa_printf(MSG_ERROR, "CP: the state machine is not defined");
427 		break;
428 	}
429 }
430 
431 
432 /**
433  * ieee802_1x_cp_sm_init -
434  */
435 struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
436 {
437 	struct ieee802_1x_cp_sm *sm;
438 
439 	sm = os_zalloc(sizeof(*sm));
440 	if (sm == NULL) {
441 		wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
442 		return NULL;
443 	}
444 
445 	sm->kay = kay;
446 
447 	sm->port_valid = FALSE;
448 
449 	sm->chgd_server = FALSE;
450 
451 	sm->protect_frames = kay->macsec_protect;
452 	sm->validate_frames = kay->macsec_validate;
453 	sm->replay_protect = kay->macsec_replay_protect;
454 	sm->replay_window = kay->macsec_replay_window;
455 
456 	sm->controlled_port_enabled = FALSE;
457 
458 	sm->lki = NULL;
459 	sm->lrx = FALSE;
460 	sm->ltx = FALSE;
461 	sm->oki = NULL;
462 	sm->orx = FALSE;
463 	sm->otx = FALSE;
464 
465 	sm->current_cipher_suite = default_cs_id;
466 	sm->cipher_suite = default_cs_id;
467 	sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
468 	sm->confidentiality_offset = sm->cipher_offset;
469 	sm->transmit_delay = MKA_LIFE_TIME;
470 	sm->retire_delay = MKA_SAK_RETIRE_TIME;
471 	sm->CP_state = CP_BEGIN;
472 	sm->changed = FALSE;
473 
474 	wpa_printf(MSG_DEBUG, "CP: state machine created");
475 
476 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
477 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
478 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
479 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
480 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
481 	secy_cp_control_confidentiality_offset(sm->kay,
482 					       sm->confidentiality_offset);
483 
484 	SM_STEP_RUN(CP);
485 
486 	return sm;
487 }
488 
489 
490 static void ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm *sm)
491 {
492 	enum cp_states prev_state;
493 	int i;
494 
495 	for (i = 0; i < 100; i++) {
496 		prev_state = sm->CP_state;
497 		SM_STEP_RUN(CP);
498 		if (prev_state == sm->CP_state)
499 			break;
500 	}
501 }
502 
503 
504 static void ieee802_1x_cp_step_cb(void *eloop_ctx, void *timeout_ctx)
505 {
506 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
507 	ieee802_1x_cp_step_run(sm);
508 }
509 
510 
511 /**
512  * ieee802_1x_cp_sm_deinit -
513  */
514 void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm)
515 {
516 	wpa_printf(MSG_DEBUG, "CP: state machine removed");
517 	if (!sm)
518 		return;
519 
520 	eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
521 	eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
522 	eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
523 	os_free(sm->lki);
524 	os_free(sm->oki);
525 	os_free(sm);
526 }
527 
528 
529 /**
530  * ieee802_1x_cp_connect_pending
531  */
532 void ieee802_1x_cp_connect_pending(void *cp_ctx)
533 {
534 	struct ieee802_1x_cp_sm *sm = cp_ctx;
535 
536 	sm->connect = PENDING;
537 }
538 
539 
540 /**
541  * ieee802_1x_cp_connect_unauthenticated
542  */
543 void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx)
544 {
545 	struct ieee802_1x_cp_sm *sm = (struct ieee802_1x_cp_sm *)cp_ctx;
546 
547 	sm->connect = UNAUTHENTICATED;
548 }
549 
550 
551 /**
552  * ieee802_1x_cp_connect_authenticated
553  */
554 void ieee802_1x_cp_connect_authenticated(void *cp_ctx)
555 {
556 	struct ieee802_1x_cp_sm *sm = cp_ctx;
557 
558 	sm->connect = AUTHENTICATED;
559 }
560 
561 
562 /**
563  * ieee802_1x_cp_connect_secure
564  */
565 void ieee802_1x_cp_connect_secure(void *cp_ctx)
566 {
567 	struct ieee802_1x_cp_sm *sm = cp_ctx;
568 
569 	sm->connect = SECURE;
570 }
571 
572 
573 /**
574  * ieee802_1x_cp_set_chgdserver -
575  */
576 void ieee802_1x_cp_signal_chgdserver(void *cp_ctx)
577 {
578 	struct ieee802_1x_cp_sm *sm = cp_ctx;
579 
580 	sm->chgd_server = TRUE;
581 }
582 
583 
584 /**
585  * ieee802_1x_cp_set_electedself -
586  */
587 void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status)
588 {
589 	struct ieee802_1x_cp_sm *sm = cp_ctx;
590 	sm->elected_self = status;
591 }
592 
593 
594 /**
595  * ieee802_1x_cp_set_ciphersuite -
596  */
597 void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
598 {
599 	struct ieee802_1x_cp_sm *sm = cp_ctx;
600 	sm->cipher_suite = cs;
601 }
602 
603 
604 /**
605  * ieee802_1x_cp_set_offset -
606  */
607 void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset)
608 {
609 	struct ieee802_1x_cp_sm *sm = cp_ctx;
610 	sm->cipher_offset = offset;
611 }
612 
613 
614 /**
615  * ieee802_1x_cp_signal_newsak -
616  */
617 void ieee802_1x_cp_signal_newsak(void *cp_ctx)
618 {
619 	struct ieee802_1x_cp_sm *sm = cp_ctx;
620 	sm->new_sak = TRUE;
621 }
622 
623 
624 /**
625  * ieee802_1x_cp_set_distributedki -
626  */
627 void ieee802_1x_cp_set_distributedki(void *cp_ctx,
628 				     const struct ieee802_1x_mka_ki *dki)
629 {
630 	struct ieee802_1x_cp_sm *sm = cp_ctx;
631 	os_memcpy(&sm->distributed_ki, dki, sizeof(struct ieee802_1x_mka_ki));
632 }
633 
634 
635 /**
636  * ieee802_1x_cp_set_distributedan -
637  */
638 void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an)
639 {
640 	struct ieee802_1x_cp_sm *sm = cp_ctx;
641 	sm->distributed_an = an;
642 }
643 
644 
645 /**
646  * ieee802_1x_cp_set_usingreceivesas -
647  */
648 void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status)
649 {
650 	struct ieee802_1x_cp_sm *sm = cp_ctx;
651 	sm->using_receive_sas = status;
652 }
653 
654 
655 /**
656  * ieee802_1x_cp_set_allreceiving -
657  */
658 void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status)
659 {
660 	struct ieee802_1x_cp_sm *sm = cp_ctx;
661 	sm->all_receiving = status;
662 }
663 
664 
665 /**
666  * ieee802_1x_cp_set_servertransmitting -
667  */
668 void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status)
669 {
670 	struct ieee802_1x_cp_sm *sm = cp_ctx;
671 	sm->server_transmitting = status;
672 }
673 
674 
675 /**
676  * ieee802_1x_cp_set_usingtransmitsas -
677  */
678 void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status)
679 {
680 	struct ieee802_1x_cp_sm *sm = cp_ctx;
681 	sm->using_transmit_sa = status;
682 }
683 
684 
685 /**
686  * ieee802_1x_cp_sm_step - Advance EAPOL state machines
687  * @sm: EAPOL state machine
688  *
689  * This function is called to advance CP state machines after any change
690  * that could affect their state.
691  */
692 void ieee802_1x_cp_sm_step(void *cp_ctx)
693 {
694 	/*
695 	 * Run ieee802_1x_cp_step_run from a registered timeout
696 	 * to make sure that other possible timeouts/events are processed
697 	 * and to avoid long function call chains.
698 	 */
699 	struct ieee802_1x_cp_sm *sm = cp_ctx;
700 	eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
701 	eloop_register_timeout(0, 0, ieee802_1x_cp_step_cb, sm, NULL);
702 }
703 
704 
705 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
706 					      void *timeout_ctx)
707 {
708 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
709 	sm->retire_when = 0;
710 	ieee802_1x_cp_step_run(sm);
711 }
712 
713 
714 static void
715 ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, void *timeout_ctx)
716 {
717 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
718 	sm->transmit_when = 0;
719 	ieee802_1x_cp_step_run(sm);
720 }
721