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