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 u64 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 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 89static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx, 90 void *timeout_ctx); 91static void ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, 92 void *timeout_ctx); 93 94 95static 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 102static int changed_connect(struct ieee802_1x_cp_sm *sm) 103{ 104 return sm->connect != SECURE || sm->chgd_server || changed_cipher(sm); 105} 106 107 108SM_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 132SM_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 165SM_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 184SM_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 203SM_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 230SM_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 252SM_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 272SM_STATE(CP, READY) 273{ 274 SM_ENTRY(CP, READY); 275 276 ieee802_1x_kay_enable_new_info(sm->kay); 277} 278 279 280SM_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 295SM_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 310SM_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 325SM_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 */ 351SM_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 */ 446struct 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 501static 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 515static 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 */ 525void 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 */ 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, 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 */ 608void 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 */ 618void 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 */ 628void 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 */ 638void 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 */ 649void 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 */ 659void 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 */ 669void 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 */ 679void 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 */ 689void 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 */ 703void 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 716static 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 725static void 726ieee802_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