xref: /freebsd/contrib/wpa/src/pae/ieee802_1x_cp.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
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 	bool changed;
35 
36 	/* CP -> Client */
37 	bool port_valid;
38 
39 	/* Logon -> CP */
40 	enum connect_type connect;
41 
42 	/* KaY -> CP */
43 	bool chgd_server; /* clear by CP */
44 	bool elected_self;
45 	enum confidentiality_offset cipher_offset;
46 	u64 cipher_suite;
47 	bool new_sak; /* clear by CP */
48 	struct ieee802_1x_mka_ki distributed_ki;
49 	u8 distributed_an;
50 	bool using_receive_sas;
51 	bool all_receiving;
52 	bool server_transmitting;
53 	bool using_transmit_sa;
54 
55 	/* CP -> KaY */
56 	struct ieee802_1x_mka_ki *lki;
57 	u8 lan;
58 	bool ltx;
59 	bool lrx;
60 	struct ieee802_1x_mka_ki *oki;
61 	u8 oan;
62 	bool otx;
63 	bool orx;
64 
65 	/* CP -> SecY */
66 	bool protect_frames;
67 	enum validate_frames validate_frames;
68 
69 	bool replay_protect;
70 	u32 replay_window;
71 
72 	u64 current_cipher_suite;
73 	enum confidentiality_offset confidentiality_offset;
74 	bool controlled_port_enabled;
75 
76 	/* SecY -> CP */
77 	bool 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 	/* The standard doesn't say it but we should clear out the latest
145 	 * and old key values. Why would we keep advertising them if
146 	 * they've been deleted and the key server has been changed?
147 	 */
148 	os_free(sm->oki);
149 	sm->oki = NULL;
150 	sm->otx = false;
151 	sm->orx = false;
152 	sm->oan = 0;
153 	ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
154 				       sm->otx, sm->orx);
155 	os_free(sm->lki);
156 	sm->lki = NULL;
157 	sm->lrx = false;
158 	sm->ltx = false;
159 	sm->lan = 0;
160 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
161 					  sm->ltx, sm->lrx);
162 }
163 
164 
165 SM_STATE(CP, ALLOWED)
166 {
167 	SM_ENTRY(CP, ALLOWED);
168 
169 	sm->protect_frames = false;
170 	sm->replay_protect = false;
171 	sm->validate_frames = Checked;
172 
173 	sm->port_valid = false;
174 	sm->controlled_port_enabled = true;
175 
176 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
177 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
178 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
179 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
180 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
181 }
182 
183 
184 SM_STATE(CP, AUTHENTICATED)
185 {
186 	SM_ENTRY(CP, AUTHENTICATED);
187 
188 	sm->protect_frames = false;
189 	sm->replay_protect = false;
190 	sm->validate_frames = Checked;
191 
192 	sm->port_valid = false;
193 	sm->controlled_port_enabled = true;
194 
195 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
196 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
197 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
198 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
199 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
200 }
201 
202 
203 SM_STATE(CP, SECURED)
204 {
205 	SM_ENTRY(CP, SECURED);
206 
207 	sm->chgd_server = false;
208 
209 	sm->protect_frames = sm->kay->macsec_protect;
210 	sm->replay_protect = sm->kay->macsec_replay_protect;
211 	sm->validate_frames = sm->kay->macsec_validate;
212 
213 	/* NOTE: now no other than default cipher suite (AES-GCM-128) */
214 	sm->current_cipher_suite = sm->cipher_suite;
215 	secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite);
216 
217 	sm->confidentiality_offset = sm->cipher_offset;
218 
219 	sm->port_valid = true;
220 
221 	secy_cp_control_confidentiality_offset(sm->kay,
222 					       sm->confidentiality_offset);
223 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
224 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
225 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
226 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
227 }
228 
229 
230 SM_STATE(CP, RECEIVE)
231 {
232 	SM_ENTRY(CP, RECEIVE);
233 
234 	sm->lki = os_malloc(sizeof(*sm->lki));
235 	if (!sm->lki) {
236 		wpa_printf(MSG_ERROR, "CP-%s: Out of memory", __func__);
237 		return;
238 	}
239 	os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki));
240 	sm->lan = sm->distributed_an;
241 	sm->ltx = false;
242 	sm->lrx = false;
243 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
244 					  sm->ltx, sm->lrx);
245 	ieee802_1x_kay_create_sas(sm->kay, sm->lki);
246 	ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki);
247 	sm->new_sak = false;
248 	sm->all_receiving = false;
249 }
250 
251 
252 SM_STATE(CP, RECEIVING)
253 {
254 	SM_ENTRY(CP, RECEIVING);
255 
256 	sm->lrx = true;
257 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
258 					  sm->ltx, sm->lrx);
259 	sm->transmit_when = sm->transmit_delay;
260 	eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
261 	eloop_register_timeout(sm->transmit_when / 1000, 0,
262 			       ieee802_1x_cp_transmit_when_timeout, sm, NULL);
263 	/* the electedSelf have been set before CP entering to RECEIVING
264 	 * but the CP will transmit from RECEIVING to READY under
265 	 * the !electedSelf when KaY is not key server */
266 	ieee802_1x_cp_sm_step(sm);
267 	sm->using_receive_sas = false;
268 	sm->server_transmitting = false;
269 }
270 
271 
272 SM_STATE(CP, READY)
273 {
274 	SM_ENTRY(CP, READY);
275 
276 	ieee802_1x_kay_enable_new_info(sm->kay);
277 }
278 
279 
280 SM_STATE(CP, TRANSMIT)
281 {
282 	SM_ENTRY(CP, TRANSMIT);
283 
284 	sm->controlled_port_enabled = true;
285 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
286 	sm->ltx = true;
287 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
288 					  sm->ltx, sm->lrx);
289 	ieee802_1x_kay_enable_tx_sas(sm->kay,  sm->lki);
290 	sm->all_receiving = false;
291 	sm->server_transmitting = false;
292 }
293 
294 
295 SM_STATE(CP, TRANSMITTING)
296 {
297 	SM_ENTRY(CP, TRANSMITTING);
298 	sm->retire_when = sm->orx ? sm->retire_delay : 0;
299 	sm->otx = false;
300 	ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
301 				       sm->otx, sm->orx);
302 	ieee802_1x_kay_enable_new_info(sm->kay);
303 	eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
304 	eloop_register_timeout(sm->retire_when / 1000, 0,
305 			       ieee802_1x_cp_retire_when_timeout, sm, NULL);
306 	sm->using_transmit_sa = false;
307 }
308 
309 
310 SM_STATE(CP, ABANDON)
311 {
312 	SM_ENTRY(CP, ABANDON);
313 	sm->lrx = false;
314 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
315 					  sm->ltx, sm->lrx);
316 	ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
317 
318 	os_free(sm->lki);
319 	sm->lki = NULL;
320 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
321 					  sm->ltx, sm->lrx);
322 }
323 
324 
325 SM_STATE(CP, RETIRE)
326 {
327 	SM_ENTRY(CP, RETIRE);
328 	if (sm->oki) {
329 		ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
330 		os_free(sm->oki);
331 		sm->oki = NULL;
332 	}
333 	sm->oki = sm->lki;
334 	sm->otx = sm->ltx;
335 	sm->orx = sm->lrx;
336 	sm->oan = sm->lan;
337 	ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
338 				       sm->otx, sm->orx);
339 	sm->lki = NULL;
340 	sm->ltx = false;
341 	sm->lrx = false;
342 	sm->lan = 0;
343 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
344 					  sm->ltx, sm->lrx);
345 }
346 
347 
348 /**
349  * CP state machine handler entry
350  */
351 SM_STEP(CP)
352 {
353 	if (!sm->port_enabled)
354 		SM_ENTER(CP, INIT);
355 
356 	switch (sm->CP_state) {
357 	case CP_BEGIN:
358 		SM_ENTER(CP, INIT);
359 		break;
360 
361 	case CP_INIT:
362 		SM_ENTER(CP, CHANGE);
363 		break;
364 
365 	case CP_CHANGE:
366 		if (sm->connect == UNAUTHENTICATED)
367 			SM_ENTER(CP, ALLOWED);
368 		else if (sm->connect == AUTHENTICATED)
369 			SM_ENTER(CP, AUTHENTICATED);
370 		else if (sm->connect == SECURE)
371 			SM_ENTER(CP, SECURED);
372 		break;
373 
374 	case CP_ALLOWED:
375 		if (sm->connect != UNAUTHENTICATED)
376 			SM_ENTER(CP, CHANGE);
377 		break;
378 
379 	case CP_AUTHENTICATED:
380 		if (sm->connect != AUTHENTICATED)
381 			SM_ENTER(CP, CHANGE);
382 		break;
383 
384 	case CP_SECURED:
385 		if (changed_connect(sm))
386 			SM_ENTER(CP, CHANGE);
387 		else if (sm->new_sak)
388 			SM_ENTER(CP, RECEIVE);
389 		break;
390 
391 	case CP_RECEIVE:
392 		if (sm->using_receive_sas)
393 			SM_ENTER(CP, RECEIVING);
394 		break;
395 
396 	case CP_RECEIVING:
397 		if (sm->new_sak || changed_connect(sm))
398 			SM_ENTER(CP, ABANDON);
399 		if (!sm->elected_self)
400 			SM_ENTER(CP, READY);
401 		if (sm->elected_self &&
402 		    (sm->all_receiving || !sm->controlled_port_enabled ||
403 		     !sm->transmit_when))
404 			SM_ENTER(CP, TRANSMIT);
405 		break;
406 
407 	case CP_TRANSMIT:
408 		if (sm->using_transmit_sa)
409 			SM_ENTER(CP, TRANSMITTING);
410 		break;
411 
412 	case CP_TRANSMITTING:
413 		if (!sm->retire_when || changed_connect(sm))
414 			SM_ENTER(CP, RETIRE);
415 		break;
416 
417 	case CP_RETIRE:
418 		if (changed_connect(sm))
419 			SM_ENTER(CP, CHANGE);
420 		else if (sm->new_sak)
421 			SM_ENTER(CP, RECEIVE);
422 		break;
423 
424 	case CP_READY:
425 		if (sm->new_sak || changed_connect(sm))
426 			SM_ENTER(CP, ABANDON);
427 		if (sm->server_transmitting || !sm->controlled_port_enabled)
428 			SM_ENTER(CP, TRANSMIT);
429 		break;
430 	case CP_ABANDON:
431 		if (changed_connect(sm))
432 			SM_ENTER(CP, RETIRE);
433 		else if (sm->new_sak)
434 			SM_ENTER(CP, RECEIVE);
435 		break;
436 	default:
437 		wpa_printf(MSG_ERROR, "CP: the state machine is not defined");
438 		break;
439 	}
440 }
441 
442 
443 /**
444  * ieee802_1x_cp_sm_init -
445  */
446 struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
447 {
448 	struct ieee802_1x_cp_sm *sm;
449 
450 	sm = os_zalloc(sizeof(*sm));
451 	if (sm == NULL) {
452 		wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
453 		return NULL;
454 	}
455 
456 	sm->kay = kay;
457 
458 	sm->port_valid = false;
459 
460 	sm->chgd_server = false;
461 
462 	sm->protect_frames = kay->macsec_protect;
463 	sm->validate_frames = kay->macsec_validate;
464 	sm->replay_protect = kay->macsec_replay_protect;
465 	sm->replay_window = kay->macsec_replay_window;
466 
467 	sm->controlled_port_enabled = false;
468 
469 	sm->lki = NULL;
470 	sm->lrx = false;
471 	sm->ltx = false;
472 	sm->oki = NULL;
473 	sm->orx = false;
474 	sm->otx = false;
475 
476 	sm->current_cipher_suite = default_cs_id;
477 	sm->cipher_suite = default_cs_id;
478 	sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
479 	sm->confidentiality_offset = sm->cipher_offset;
480 	sm->transmit_delay = MKA_LIFE_TIME;
481 	sm->retire_delay = MKA_SAK_RETIRE_TIME;
482 	sm->CP_state = CP_BEGIN;
483 	sm->changed = false;
484 
485 	wpa_printf(MSG_DEBUG, "CP: state machine created");
486 
487 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
488 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
489 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
490 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
491 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
492 	secy_cp_control_confidentiality_offset(sm->kay,
493 					       sm->confidentiality_offset);
494 
495 	SM_STEP_RUN(CP);
496 
497 	return sm;
498 }
499 
500 
501 static void ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm *sm)
502 {
503 	enum cp_states prev_state;
504 	int i;
505 
506 	for (i = 0; i < 100; i++) {
507 		prev_state = sm->CP_state;
508 		SM_STEP_RUN(CP);
509 		if (prev_state == sm->CP_state)
510 			break;
511 	}
512 }
513 
514 
515 static void ieee802_1x_cp_step_cb(void *eloop_ctx, void *timeout_ctx)
516 {
517 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
518 	ieee802_1x_cp_step_run(sm);
519 }
520 
521 
522 /**
523  * ieee802_1x_cp_sm_deinit -
524  */
525 void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm)
526 {
527 	wpa_printf(MSG_DEBUG, "CP: state machine removed");
528 	if (!sm)
529 		return;
530 
531 	eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
532 	eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
533 	eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
534 	os_free(sm->lki);
535 	os_free(sm->oki);
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, bool 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_ciphersuite -
607  */
608 void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
609 {
610 	struct ieee802_1x_cp_sm *sm = cp_ctx;
611 	sm->cipher_suite = cs;
612 }
613 
614 
615 /**
616  * ieee802_1x_cp_set_offset -
617  */
618 void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset)
619 {
620 	struct ieee802_1x_cp_sm *sm = cp_ctx;
621 	sm->cipher_offset = offset;
622 }
623 
624 
625 /**
626  * ieee802_1x_cp_signal_newsak -
627  */
628 void ieee802_1x_cp_signal_newsak(void *cp_ctx)
629 {
630 	struct ieee802_1x_cp_sm *sm = cp_ctx;
631 	sm->new_sak = true;
632 }
633 
634 
635 /**
636  * ieee802_1x_cp_set_distributedki -
637  */
638 void ieee802_1x_cp_set_distributedki(void *cp_ctx,
639 				     const struct ieee802_1x_mka_ki *dki)
640 {
641 	struct ieee802_1x_cp_sm *sm = cp_ctx;
642 	os_memcpy(&sm->distributed_ki, dki, sizeof(struct ieee802_1x_mka_ki));
643 }
644 
645 
646 /**
647  * ieee802_1x_cp_set_distributedan -
648  */
649 void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an)
650 {
651 	struct ieee802_1x_cp_sm *sm = cp_ctx;
652 	sm->distributed_an = an;
653 }
654 
655 
656 /**
657  * ieee802_1x_cp_set_usingreceivesas -
658  */
659 void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, bool status)
660 {
661 	struct ieee802_1x_cp_sm *sm = cp_ctx;
662 	sm->using_receive_sas = status;
663 }
664 
665 
666 /**
667  * ieee802_1x_cp_set_allreceiving -
668  */
669 void ieee802_1x_cp_set_allreceiving(void *cp_ctx, bool status)
670 {
671 	struct ieee802_1x_cp_sm *sm = cp_ctx;
672 	sm->all_receiving = status;
673 }
674 
675 
676 /**
677  * ieee802_1x_cp_set_servertransmitting -
678  */
679 void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, bool status)
680 {
681 	struct ieee802_1x_cp_sm *sm = cp_ctx;
682 	sm->server_transmitting = status;
683 }
684 
685 
686 /**
687  * ieee802_1x_cp_set_usingtransmitsas -
688  */
689 void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, bool status)
690 {
691 	struct ieee802_1x_cp_sm *sm = cp_ctx;
692 	sm->using_transmit_sa = status;
693 }
694 
695 
696 /**
697  * ieee802_1x_cp_sm_step - Advance EAPOL state machines
698  * @sm: EAPOL state machine
699  *
700  * This function is called to advance CP state machines after any change
701  * that could affect their state.
702  */
703 void ieee802_1x_cp_sm_step(void *cp_ctx)
704 {
705 	/*
706 	 * Run ieee802_1x_cp_step_run from a registered timeout
707 	 * to make sure that other possible timeouts/events are processed
708 	 * and to avoid long function call chains.
709 	 */
710 	struct ieee802_1x_cp_sm *sm = cp_ctx;
711 	eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
712 	eloop_register_timeout(0, 0, ieee802_1x_cp_step_cb, sm, NULL);
713 }
714 
715 
716 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
717 					      void *timeout_ctx)
718 {
719 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
720 	sm->retire_when = 0;
721 	ieee802_1x_cp_step_run(sm);
722 }
723 
724 
725 static void
726 ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, void *timeout_ctx)
727 {
728 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
729 	sm->transmit_when = 0;
730 	ieee802_1x_cp_step_run(sm);
731 }
732