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 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 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 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 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 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 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 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 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 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 276 SM_STATE(CP, READY) 277 { 278 SM_ENTRY(CP, READY); 279 280 ieee802_1x_kay_enable_new_info(sm->kay); 281 } 282 283 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 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 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 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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