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