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