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
changed_cipher(struct ieee802_1x_cp_sm * sm)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
changed_connect(struct ieee802_1x_cp_sm * sm)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
SM_STATE(CP,INIT)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
SM_STATE(CP,CHANGE)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
SM_STATE(CP,ALLOWED)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
SM_STATE(CP,AUTHENTICATED)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
SM_STATE(CP,SECURED)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
SM_STATE(CP,RECEIVE)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
SM_STATE(CP,RECEIVING)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
SM_STATE(CP,READY)272 SM_STATE(CP, READY)
273 {
274 SM_ENTRY(CP, READY);
275
276 ieee802_1x_kay_enable_new_info(sm->kay);
277 }
278
279
SM_STATE(CP,TRANSMIT)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
SM_STATE(CP,TRANSMITTING)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
SM_STATE(CP,ABANDON)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
SM_STATE(CP,RETIRE)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 */
SM_STEP(CP)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 */
ieee802_1x_cp_sm_init(struct ieee802_1x_kay * kay)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
ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm * sm)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
ieee802_1x_cp_step_cb(void * eloop_ctx,void * timeout_ctx)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 */
ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm * sm)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 */
ieee802_1x_cp_connect_pending(void * cp_ctx)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 */
ieee802_1x_cp_connect_unauthenticated(void * cp_ctx)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 */
ieee802_1x_cp_connect_authenticated(void * cp_ctx)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 */
ieee802_1x_cp_connect_secure(void * cp_ctx)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 */
ieee802_1x_cp_signal_chgdserver(void * cp_ctx)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 */
ieee802_1x_cp_set_electedself(void * cp_ctx,bool status)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 */
ieee802_1x_cp_set_ciphersuite(void * cp_ctx,u64 cs)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 */
ieee802_1x_cp_set_offset(void * cp_ctx,enum confidentiality_offset offset)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 */
ieee802_1x_cp_signal_newsak(void * cp_ctx)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 */
ieee802_1x_cp_set_distributedki(void * cp_ctx,const struct ieee802_1x_mka_ki * dki)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 */
ieee802_1x_cp_set_distributedan(void * cp_ctx,u8 an)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 */
ieee802_1x_cp_set_usingreceivesas(void * cp_ctx,bool status)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 */
ieee802_1x_cp_set_allreceiving(void * cp_ctx,bool status)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 */
ieee802_1x_cp_set_servertransmitting(void * cp_ctx,bool status)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 */
ieee802_1x_cp_set_usingtransmitas(void * cp_ctx,bool status)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 */
ieee802_1x_cp_sm_step(void * cp_ctx)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
ieee802_1x_cp_retire_when_timeout(void * eloop_ctx,void * timeout_ctx)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
ieee802_1x_cp_transmit_when_timeout(void * eloop_ctx,void * timeout_ctx)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