xref: /freebsd/contrib/wpa/src/pae/ieee802_1x_cp.c (revision 780fb4a2)
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 }
727