1 /* 2 * RADIUS client 3 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "radius.h" 13 #include "radius_client.h" 14 #include "eloop.h" 15 16 /* Defaults for RADIUS retransmit values (exponential backoff) */ 17 18 /** 19 * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds 20 */ 21 #define RADIUS_CLIENT_FIRST_WAIT 3 22 23 /** 24 * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds 25 */ 26 #define RADIUS_CLIENT_MAX_WAIT 120 27 28 /** 29 * RADIUS_CLIENT_MAX_RETRIES - RADIUS client maximum retries 30 * 31 * Maximum number of retransmit attempts before the entry is removed from 32 * retransmit list. 33 */ 34 #define RADIUS_CLIENT_MAX_RETRIES 10 35 36 /** 37 * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages 38 * 39 * Maximum number of entries in retransmit list (oldest entries will be 40 * removed, if this limit is exceeded). 41 */ 42 #define RADIUS_CLIENT_MAX_ENTRIES 30 43 44 /** 45 * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point 46 * 47 * The number of failed retry attempts after which the RADIUS server will be 48 * changed (if one of more backup servers are configured). 49 */ 50 #define RADIUS_CLIENT_NUM_FAILOVER 4 51 52 53 /** 54 * struct radius_rx_handler - RADIUS client RX handler 55 * 56 * This data structure is used internally inside the RADIUS client module to 57 * store registered RX handlers. These handlers are registered by calls to 58 * radius_client_register() and unregistered when the RADIUS client is 59 * deinitialized with a call to radius_client_deinit(). 60 */ 61 struct radius_rx_handler { 62 /** 63 * handler - Received RADIUS message handler 64 */ 65 RadiusRxResult (*handler)(struct radius_msg *msg, 66 struct radius_msg *req, 67 const u8 *shared_secret, 68 size_t shared_secret_len, 69 void *data); 70 71 /** 72 * data - Context data for the handler 73 */ 74 void *data; 75 }; 76 77 78 /** 79 * struct radius_msg_list - RADIUS client message retransmit list 80 * 81 * This data structure is used internally inside the RADIUS client module to 82 * store pending RADIUS requests that may still need to be retransmitted. 83 */ 84 struct radius_msg_list { 85 /** 86 * addr - STA/client address 87 * 88 * This is used to find RADIUS messages for the same STA. 89 */ 90 u8 addr[ETH_ALEN]; 91 92 /** 93 * msg - RADIUS message 94 */ 95 struct radius_msg *msg; 96 97 /** 98 * msg_type - Message type 99 */ 100 RadiusType msg_type; 101 102 /** 103 * first_try - Time of the first transmission attempt 104 */ 105 os_time_t first_try; 106 107 /** 108 * next_try - Time for the next transmission attempt 109 */ 110 os_time_t next_try; 111 112 /** 113 * attempts - Number of transmission attempts 114 */ 115 int attempts; 116 117 /** 118 * next_wait - Next retransmission wait time in seconds 119 */ 120 int next_wait; 121 122 /** 123 * last_attempt - Time of the last transmission attempt 124 */ 125 struct os_reltime last_attempt; 126 127 /** 128 * shared_secret - Shared secret with the target RADIUS server 129 */ 130 const u8 *shared_secret; 131 132 /** 133 * shared_secret_len - shared_secret length in octets 134 */ 135 size_t shared_secret_len; 136 137 /* TODO: server config with failover to backup server(s) */ 138 139 /** 140 * next - Next message in the list 141 */ 142 struct radius_msg_list *next; 143 }; 144 145 146 /** 147 * struct radius_client_data - Internal RADIUS client data 148 * 149 * This data structure is used internally inside the RADIUS client module. 150 * External users allocate this by calling radius_client_init() and free it by 151 * calling radius_client_deinit(). The pointer to this opaque data is used in 152 * calls to other functions as an identifier for the RADIUS client instance. 153 */ 154 struct radius_client_data { 155 /** 156 * ctx - Context pointer for hostapd_logger() callbacks 157 */ 158 void *ctx; 159 160 /** 161 * conf - RADIUS client configuration (list of RADIUS servers to use) 162 */ 163 struct hostapd_radius_servers *conf; 164 165 /** 166 * auth_serv_sock - IPv4 socket for RADIUS authentication messages 167 */ 168 int auth_serv_sock; 169 170 /** 171 * acct_serv_sock - IPv4 socket for RADIUS accounting messages 172 */ 173 int acct_serv_sock; 174 175 /** 176 * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages 177 */ 178 int auth_serv_sock6; 179 180 /** 181 * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages 182 */ 183 int acct_serv_sock6; 184 185 /** 186 * auth_sock - Currently used socket for RADIUS authentication server 187 */ 188 int auth_sock; 189 190 /** 191 * acct_sock - Currently used socket for RADIUS accounting server 192 */ 193 int acct_sock; 194 195 /** 196 * auth_handlers - Authentication message handlers 197 */ 198 struct radius_rx_handler *auth_handlers; 199 200 /** 201 * num_auth_handlers - Number of handlers in auth_handlers 202 */ 203 size_t num_auth_handlers; 204 205 /** 206 * acct_handlers - Accounting message handlers 207 */ 208 struct radius_rx_handler *acct_handlers; 209 210 /** 211 * num_acct_handlers - Number of handlers in acct_handlers 212 */ 213 size_t num_acct_handlers; 214 215 /** 216 * msgs - Pending outgoing RADIUS messages 217 */ 218 struct radius_msg_list *msgs; 219 220 /** 221 * num_msgs - Number of pending messages in the msgs list 222 */ 223 size_t num_msgs; 224 225 /** 226 * next_radius_identifier - Next RADIUS message identifier to use 227 */ 228 u8 next_radius_identifier; 229 }; 230 231 232 static int 233 radius_change_server(struct radius_client_data *radius, 234 struct hostapd_radius_server *nserv, 235 struct hostapd_radius_server *oserv, 236 int sock, int sock6, int auth); 237 static int radius_client_init_acct(struct radius_client_data *radius); 238 static int radius_client_init_auth(struct radius_client_data *radius); 239 240 241 static void radius_client_msg_free(struct radius_msg_list *req) 242 { 243 radius_msg_free(req->msg); 244 os_free(req); 245 } 246 247 248 /** 249 * radius_client_register - Register a RADIUS client RX handler 250 * @radius: RADIUS client context from radius_client_init() 251 * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT) 252 * @handler: Handler for received RADIUS messages 253 * @data: Context pointer for handler callbacks 254 * Returns: 0 on success, -1 on failure 255 * 256 * This function is used to register a handler for processing received RADIUS 257 * authentication and accounting messages. The handler() callback function will 258 * be called whenever a RADIUS message is received from the active server. 259 * 260 * There can be multiple registered RADIUS message handlers. The handlers will 261 * be called in order until one of them indicates that it has processed or 262 * queued the message. 263 */ 264 int radius_client_register(struct radius_client_data *radius, 265 RadiusType msg_type, 266 RadiusRxResult (*handler)(struct radius_msg *msg, 267 struct radius_msg *req, 268 const u8 *shared_secret, 269 size_t shared_secret_len, 270 void *data), 271 void *data) 272 { 273 struct radius_rx_handler **handlers, *newh; 274 size_t *num; 275 276 if (msg_type == RADIUS_ACCT) { 277 handlers = &radius->acct_handlers; 278 num = &radius->num_acct_handlers; 279 } else { 280 handlers = &radius->auth_handlers; 281 num = &radius->num_auth_handlers; 282 } 283 284 newh = os_realloc_array(*handlers, *num + 1, 285 sizeof(struct radius_rx_handler)); 286 if (newh == NULL) 287 return -1; 288 289 newh[*num].handler = handler; 290 newh[*num].data = data; 291 (*num)++; 292 *handlers = newh; 293 294 return 0; 295 } 296 297 298 static void radius_client_handle_send_error(struct radius_client_data *radius, 299 int s, RadiusType msg_type) 300 { 301 #ifndef CONFIG_NATIVE_WINDOWS 302 int _errno = errno; 303 wpa_printf(MSG_INFO, "send[RADIUS]: %s", strerror(errno)); 304 if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || 305 _errno == EBADF) { 306 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 307 HOSTAPD_LEVEL_INFO, 308 "Send failed - maybe interface status changed -" 309 " try to connect again"); 310 eloop_unregister_read_sock(s); 311 close(s); 312 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) 313 radius_client_init_acct(radius); 314 else 315 radius_client_init_auth(radius); 316 } 317 #endif /* CONFIG_NATIVE_WINDOWS */ 318 } 319 320 321 static int radius_client_retransmit(struct radius_client_data *radius, 322 struct radius_msg_list *entry, 323 os_time_t now) 324 { 325 struct hostapd_radius_servers *conf = radius->conf; 326 int s; 327 struct wpabuf *buf; 328 329 if (entry->msg_type == RADIUS_ACCT || 330 entry->msg_type == RADIUS_ACCT_INTERIM) { 331 s = radius->acct_sock; 332 if (entry->attempts == 0) 333 conf->acct_server->requests++; 334 else { 335 conf->acct_server->timeouts++; 336 conf->acct_server->retransmissions++; 337 } 338 } else { 339 s = radius->auth_sock; 340 if (entry->attempts == 0) 341 conf->auth_server->requests++; 342 else { 343 conf->auth_server->timeouts++; 344 conf->auth_server->retransmissions++; 345 } 346 } 347 348 /* retransmit; remove entry if too many attempts */ 349 entry->attempts++; 350 hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, 351 HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", 352 radius_msg_get_hdr(entry->msg)->identifier); 353 354 os_get_reltime(&entry->last_attempt); 355 buf = radius_msg_get_buf(entry->msg); 356 if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) 357 radius_client_handle_send_error(radius, s, entry->msg_type); 358 359 entry->next_try = now + entry->next_wait; 360 entry->next_wait *= 2; 361 if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 362 entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 363 if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { 364 wpa_printf(MSG_INFO, "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts"); 365 return 1; 366 } 367 368 return 0; 369 } 370 371 372 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) 373 { 374 struct radius_client_data *radius = eloop_ctx; 375 struct hostapd_radius_servers *conf = radius->conf; 376 struct os_reltime now; 377 os_time_t first; 378 struct radius_msg_list *entry, *prev, *tmp; 379 int auth_failover = 0, acct_failover = 0; 380 char abuf[50]; 381 382 entry = radius->msgs; 383 if (!entry) 384 return; 385 386 os_get_reltime(&now); 387 first = 0; 388 389 prev = NULL; 390 while (entry) { 391 if (now.sec >= entry->next_try && 392 radius_client_retransmit(radius, entry, now.sec)) { 393 if (prev) 394 prev->next = entry->next; 395 else 396 radius->msgs = entry->next; 397 398 tmp = entry; 399 entry = entry->next; 400 radius_client_msg_free(tmp); 401 radius->num_msgs--; 402 continue; 403 } 404 405 if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) { 406 if (entry->msg_type == RADIUS_ACCT || 407 entry->msg_type == RADIUS_ACCT_INTERIM) 408 acct_failover++; 409 else 410 auth_failover++; 411 } 412 413 if (first == 0 || entry->next_try < first) 414 first = entry->next_try; 415 416 prev = entry; 417 entry = entry->next; 418 } 419 420 if (radius->msgs) { 421 if (first < now.sec) 422 first = now.sec; 423 eloop_register_timeout(first - now.sec, 0, 424 radius_client_timer, radius, NULL); 425 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 426 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " 427 "retransmit in %ld seconds", 428 (long int) (first - now.sec)); 429 } 430 431 if (auth_failover && conf->num_auth_servers > 1) { 432 struct hostapd_radius_server *next, *old; 433 old = conf->auth_server; 434 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 435 HOSTAPD_LEVEL_NOTICE, 436 "No response from Authentication server " 437 "%s:%d - failover", 438 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 439 old->port); 440 441 for (entry = radius->msgs; entry; entry = entry->next) { 442 if (entry->msg_type == RADIUS_AUTH) 443 old->timeouts++; 444 } 445 446 next = old + 1; 447 if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) 448 next = conf->auth_servers; 449 conf->auth_server = next; 450 radius_change_server(radius, next, old, 451 radius->auth_serv_sock, 452 radius->auth_serv_sock6, 1); 453 } 454 455 if (acct_failover && conf->num_acct_servers > 1) { 456 struct hostapd_radius_server *next, *old; 457 old = conf->acct_server; 458 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 459 HOSTAPD_LEVEL_NOTICE, 460 "No response from Accounting server " 461 "%s:%d - failover", 462 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 463 old->port); 464 465 for (entry = radius->msgs; entry; entry = entry->next) { 466 if (entry->msg_type == RADIUS_ACCT || 467 entry->msg_type == RADIUS_ACCT_INTERIM) 468 old->timeouts++; 469 } 470 471 next = old + 1; 472 if (next > &conf->acct_servers[conf->num_acct_servers - 1]) 473 next = conf->acct_servers; 474 conf->acct_server = next; 475 radius_change_server(radius, next, old, 476 radius->acct_serv_sock, 477 radius->acct_serv_sock6, 0); 478 } 479 } 480 481 482 static void radius_client_update_timeout(struct radius_client_data *radius) 483 { 484 struct os_reltime now; 485 os_time_t first; 486 struct radius_msg_list *entry; 487 488 eloop_cancel_timeout(radius_client_timer, radius, NULL); 489 490 if (radius->msgs == NULL) { 491 return; 492 } 493 494 first = 0; 495 for (entry = radius->msgs; entry; entry = entry->next) { 496 if (first == 0 || entry->next_try < first) 497 first = entry->next_try; 498 } 499 500 os_get_reltime(&now); 501 if (first < now.sec) 502 first = now.sec; 503 eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, 504 NULL); 505 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 506 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" 507 " %ld seconds", (long int) (first - now.sec)); 508 } 509 510 511 static void radius_client_list_add(struct radius_client_data *radius, 512 struct radius_msg *msg, 513 RadiusType msg_type, 514 const u8 *shared_secret, 515 size_t shared_secret_len, const u8 *addr) 516 { 517 struct radius_msg_list *entry, *prev; 518 519 if (eloop_terminated()) { 520 /* No point in adding entries to retransmit queue since event 521 * loop has already been terminated. */ 522 radius_msg_free(msg); 523 return; 524 } 525 526 entry = os_zalloc(sizeof(*entry)); 527 if (entry == NULL) { 528 wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list"); 529 radius_msg_free(msg); 530 return; 531 } 532 533 if (addr) 534 os_memcpy(entry->addr, addr, ETH_ALEN); 535 entry->msg = msg; 536 entry->msg_type = msg_type; 537 entry->shared_secret = shared_secret; 538 entry->shared_secret_len = shared_secret_len; 539 os_get_reltime(&entry->last_attempt); 540 entry->first_try = entry->last_attempt.sec; 541 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 542 entry->attempts = 1; 543 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 544 entry->next = radius->msgs; 545 radius->msgs = entry; 546 radius_client_update_timeout(radius); 547 548 if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { 549 wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits"); 550 prev = NULL; 551 while (entry->next) { 552 prev = entry; 553 entry = entry->next; 554 } 555 if (prev) { 556 prev->next = NULL; 557 radius_client_msg_free(entry); 558 } 559 } else 560 radius->num_msgs++; 561 } 562 563 564 static void radius_client_list_del(struct radius_client_data *radius, 565 RadiusType msg_type, const u8 *addr) 566 { 567 struct radius_msg_list *entry, *prev, *tmp; 568 569 if (addr == NULL) 570 return; 571 572 entry = radius->msgs; 573 prev = NULL; 574 while (entry) { 575 if (entry->msg_type == msg_type && 576 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 577 if (prev) 578 prev->next = entry->next; 579 else 580 radius->msgs = entry->next; 581 tmp = entry; 582 entry = entry->next; 583 hostapd_logger(radius->ctx, addr, 584 HOSTAPD_MODULE_RADIUS, 585 HOSTAPD_LEVEL_DEBUG, 586 "Removing matching RADIUS message"); 587 radius_client_msg_free(tmp); 588 radius->num_msgs--; 589 continue; 590 } 591 prev = entry; 592 entry = entry->next; 593 } 594 } 595 596 597 /** 598 * radius_client_send - Send a RADIUS request 599 * @radius: RADIUS client context from radius_client_init() 600 * @msg: RADIUS message to be sent 601 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM) 602 * @addr: MAC address of the device related to this message or %NULL 603 * Returns: 0 on success, -1 on failure 604 * 605 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or 606 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference 607 * between accounting and interim accounting messages is that the interim 608 * message will override any pending interim accounting updates while a new 609 * accounting message does not remove any pending messages. 610 * 611 * The message is added on the retransmission queue and will be retransmitted 612 * automatically until a response is received or maximum number of retries 613 * (RADIUS_CLIENT_MAX_RETRIES) is reached. 614 * 615 * The related device MAC address can be used to identify pending messages that 616 * can be removed with radius_client_flush_auth() or with interim accounting 617 * updates. 618 */ 619 int radius_client_send(struct radius_client_data *radius, 620 struct radius_msg *msg, RadiusType msg_type, 621 const u8 *addr) 622 { 623 struct hostapd_radius_servers *conf = radius->conf; 624 const u8 *shared_secret; 625 size_t shared_secret_len; 626 char *name; 627 int s, res; 628 struct wpabuf *buf; 629 630 if (msg_type == RADIUS_ACCT_INTERIM) { 631 /* Remove any pending interim acct update for the same STA. */ 632 radius_client_list_del(radius, msg_type, addr); 633 } 634 635 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { 636 if (conf->acct_server == NULL) { 637 hostapd_logger(radius->ctx, NULL, 638 HOSTAPD_MODULE_RADIUS, 639 HOSTAPD_LEVEL_INFO, 640 "No accounting server configured"); 641 return -1; 642 } 643 shared_secret = conf->acct_server->shared_secret; 644 shared_secret_len = conf->acct_server->shared_secret_len; 645 radius_msg_finish_acct(msg, shared_secret, shared_secret_len); 646 name = "accounting"; 647 s = radius->acct_sock; 648 conf->acct_server->requests++; 649 } else { 650 if (conf->auth_server == NULL) { 651 hostapd_logger(radius->ctx, NULL, 652 HOSTAPD_MODULE_RADIUS, 653 HOSTAPD_LEVEL_INFO, 654 "No authentication server configured"); 655 return -1; 656 } 657 shared_secret = conf->auth_server->shared_secret; 658 shared_secret_len = conf->auth_server->shared_secret_len; 659 radius_msg_finish(msg, shared_secret, shared_secret_len); 660 name = "authentication"; 661 s = radius->auth_sock; 662 conf->auth_server->requests++; 663 } 664 665 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 666 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " 667 "server", name); 668 if (conf->msg_dumps) 669 radius_msg_dump(msg); 670 671 buf = radius_msg_get_buf(msg); 672 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0); 673 if (res < 0) 674 radius_client_handle_send_error(radius, s, msg_type); 675 676 radius_client_list_add(radius, msg, msg_type, shared_secret, 677 shared_secret_len, addr); 678 679 return 0; 680 } 681 682 683 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) 684 { 685 struct radius_client_data *radius = eloop_ctx; 686 struct hostapd_radius_servers *conf = radius->conf; 687 RadiusType msg_type = (RadiusType) sock_ctx; 688 int len, roundtrip; 689 unsigned char buf[3000]; 690 struct radius_msg *msg; 691 struct radius_hdr *hdr; 692 struct radius_rx_handler *handlers; 693 size_t num_handlers, i; 694 struct radius_msg_list *req, *prev_req; 695 struct os_reltime now; 696 struct hostapd_radius_server *rconf; 697 int invalid_authenticator = 0; 698 699 if (msg_type == RADIUS_ACCT) { 700 handlers = radius->acct_handlers; 701 num_handlers = radius->num_acct_handlers; 702 rconf = conf->acct_server; 703 } else { 704 handlers = radius->auth_handlers; 705 num_handlers = radius->num_auth_handlers; 706 rconf = conf->auth_server; 707 } 708 709 len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); 710 if (len < 0) { 711 wpa_printf(MSG_INFO, "recv[RADIUS]: %s", strerror(errno)); 712 return; 713 } 714 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 715 HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " 716 "server", len); 717 if (len == sizeof(buf)) { 718 wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it"); 719 return; 720 } 721 722 msg = radius_msg_parse(buf, len); 723 if (msg == NULL) { 724 wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed"); 725 rconf->malformed_responses++; 726 return; 727 } 728 hdr = radius_msg_get_hdr(msg); 729 730 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 731 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); 732 if (conf->msg_dumps) 733 radius_msg_dump(msg); 734 735 switch (hdr->code) { 736 case RADIUS_CODE_ACCESS_ACCEPT: 737 rconf->access_accepts++; 738 break; 739 case RADIUS_CODE_ACCESS_REJECT: 740 rconf->access_rejects++; 741 break; 742 case RADIUS_CODE_ACCESS_CHALLENGE: 743 rconf->access_challenges++; 744 break; 745 case RADIUS_CODE_ACCOUNTING_RESPONSE: 746 rconf->responses++; 747 break; 748 } 749 750 prev_req = NULL; 751 req = radius->msgs; 752 while (req) { 753 /* TODO: also match by src addr:port of the packet when using 754 * alternative RADIUS servers (?) */ 755 if ((req->msg_type == msg_type || 756 (req->msg_type == RADIUS_ACCT_INTERIM && 757 msg_type == RADIUS_ACCT)) && 758 radius_msg_get_hdr(req->msg)->identifier == 759 hdr->identifier) 760 break; 761 762 prev_req = req; 763 req = req->next; 764 } 765 766 if (req == NULL) { 767 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 768 HOSTAPD_LEVEL_DEBUG, 769 "No matching RADIUS request found (type=%d " 770 "id=%d) - dropping packet", 771 msg_type, hdr->identifier); 772 goto fail; 773 } 774 775 os_get_reltime(&now); 776 roundtrip = (now.sec - req->last_attempt.sec) * 100 + 777 (now.usec - req->last_attempt.usec) / 10000; 778 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 779 HOSTAPD_LEVEL_DEBUG, 780 "Received RADIUS packet matched with a pending " 781 "request, round trip time %d.%02d sec", 782 roundtrip / 100, roundtrip % 100); 783 rconf->round_trip_time = roundtrip; 784 785 /* Remove ACKed RADIUS packet from retransmit list */ 786 if (prev_req) 787 prev_req->next = req->next; 788 else 789 radius->msgs = req->next; 790 radius->num_msgs--; 791 792 for (i = 0; i < num_handlers; i++) { 793 RadiusRxResult res; 794 res = handlers[i].handler(msg, req->msg, req->shared_secret, 795 req->shared_secret_len, 796 handlers[i].data); 797 switch (res) { 798 case RADIUS_RX_PROCESSED: 799 radius_msg_free(msg); 800 /* continue */ 801 case RADIUS_RX_QUEUED: 802 radius_client_msg_free(req); 803 return; 804 case RADIUS_RX_INVALID_AUTHENTICATOR: 805 invalid_authenticator++; 806 /* continue */ 807 case RADIUS_RX_UNKNOWN: 808 /* continue with next handler */ 809 break; 810 } 811 } 812 813 if (invalid_authenticator) 814 rconf->bad_authenticators++; 815 else 816 rconf->unknown_types++; 817 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 818 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " 819 "(type=%d code=%d id=%d)%s - dropping packet", 820 msg_type, hdr->code, hdr->identifier, 821 invalid_authenticator ? " [INVALID AUTHENTICATOR]" : 822 ""); 823 radius_client_msg_free(req); 824 825 fail: 826 radius_msg_free(msg); 827 } 828 829 830 /** 831 * radius_client_get_id - Get an identifier for a new RADIUS message 832 * @radius: RADIUS client context from radius_client_init() 833 * Returns: Allocated identifier 834 * 835 * This function is used to fetch a unique (among pending requests) identifier 836 * for a new RADIUS message. 837 */ 838 u8 radius_client_get_id(struct radius_client_data *radius) 839 { 840 struct radius_msg_list *entry, *prev, *_remove; 841 u8 id = radius->next_radius_identifier++; 842 843 /* remove entries with matching id from retransmit list to avoid 844 * using new reply from the RADIUS server with an old request */ 845 entry = radius->msgs; 846 prev = NULL; 847 while (entry) { 848 if (radius_msg_get_hdr(entry->msg)->identifier == id) { 849 hostapd_logger(radius->ctx, entry->addr, 850 HOSTAPD_MODULE_RADIUS, 851 HOSTAPD_LEVEL_DEBUG, 852 "Removing pending RADIUS message, " 853 "since its id (%d) is reused", id); 854 if (prev) 855 prev->next = entry->next; 856 else 857 radius->msgs = entry->next; 858 _remove = entry; 859 } else { 860 _remove = NULL; 861 prev = entry; 862 } 863 entry = entry->next; 864 865 if (_remove) 866 radius_client_msg_free(_remove); 867 } 868 869 return id; 870 } 871 872 873 /** 874 * radius_client_flush - Flush all pending RADIUS client messages 875 * @radius: RADIUS client context from radius_client_init() 876 * @only_auth: Whether only authentication messages are removed 877 */ 878 void radius_client_flush(struct radius_client_data *radius, int only_auth) 879 { 880 struct radius_msg_list *entry, *prev, *tmp; 881 882 if (!radius) 883 return; 884 885 prev = NULL; 886 entry = radius->msgs; 887 888 while (entry) { 889 if (!only_auth || entry->msg_type == RADIUS_AUTH) { 890 if (prev) 891 prev->next = entry->next; 892 else 893 radius->msgs = entry->next; 894 895 tmp = entry; 896 entry = entry->next; 897 radius_client_msg_free(tmp); 898 radius->num_msgs--; 899 } else { 900 prev = entry; 901 entry = entry->next; 902 } 903 } 904 905 if (radius->msgs == NULL) 906 eloop_cancel_timeout(radius_client_timer, radius, NULL); 907 } 908 909 910 static void radius_client_update_acct_msgs(struct radius_client_data *radius, 911 const u8 *shared_secret, 912 size_t shared_secret_len) 913 { 914 struct radius_msg_list *entry; 915 916 if (!radius) 917 return; 918 919 for (entry = radius->msgs; entry; entry = entry->next) { 920 if (entry->msg_type == RADIUS_ACCT) { 921 entry->shared_secret = shared_secret; 922 entry->shared_secret_len = shared_secret_len; 923 radius_msg_finish_acct(entry->msg, shared_secret, 924 shared_secret_len); 925 } 926 } 927 } 928 929 930 static int 931 radius_change_server(struct radius_client_data *radius, 932 struct hostapd_radius_server *nserv, 933 struct hostapd_radius_server *oserv, 934 int sock, int sock6, int auth) 935 { 936 struct sockaddr_in serv, claddr; 937 #ifdef CONFIG_IPV6 938 struct sockaddr_in6 serv6, claddr6; 939 #endif /* CONFIG_IPV6 */ 940 struct sockaddr *addr, *cl_addr; 941 socklen_t addrlen, claddrlen; 942 char abuf[50]; 943 int sel_sock; 944 struct radius_msg_list *entry; 945 struct hostapd_radius_servers *conf = radius->conf; 946 947 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 948 HOSTAPD_LEVEL_INFO, 949 "%s server %s:%d", 950 auth ? "Authentication" : "Accounting", 951 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), 952 nserv->port); 953 954 if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len || 955 os_memcmp(nserv->shared_secret, oserv->shared_secret, 956 nserv->shared_secret_len) != 0) { 957 /* Pending RADIUS packets used different shared secret, so 958 * they need to be modified. Update accounting message 959 * authenticators here. Authentication messages are removed 960 * since they would require more changes and the new RADIUS 961 * server may not be prepared to receive them anyway due to 962 * missing state information. Client will likely retry 963 * authentication, so this should not be an issue. */ 964 if (auth) 965 radius_client_flush(radius, 1); 966 else { 967 radius_client_update_acct_msgs( 968 radius, nserv->shared_secret, 969 nserv->shared_secret_len); 970 } 971 } 972 973 /* Reset retry counters for the new server */ 974 for (entry = radius->msgs; entry; entry = entry->next) { 975 if ((auth && entry->msg_type != RADIUS_AUTH) || 976 (!auth && entry->msg_type != RADIUS_ACCT)) 977 continue; 978 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 979 entry->attempts = 0; 980 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 981 } 982 983 if (radius->msgs) { 984 eloop_cancel_timeout(radius_client_timer, radius, NULL); 985 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, 986 radius_client_timer, radius, NULL); 987 } 988 989 switch (nserv->addr.af) { 990 case AF_INET: 991 os_memset(&serv, 0, sizeof(serv)); 992 serv.sin_family = AF_INET; 993 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; 994 serv.sin_port = htons(nserv->port); 995 addr = (struct sockaddr *) &serv; 996 addrlen = sizeof(serv); 997 sel_sock = sock; 998 break; 999 #ifdef CONFIG_IPV6 1000 case AF_INET6: 1001 os_memset(&serv6, 0, sizeof(serv6)); 1002 serv6.sin6_family = AF_INET6; 1003 os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, 1004 sizeof(struct in6_addr)); 1005 serv6.sin6_port = htons(nserv->port); 1006 addr = (struct sockaddr *) &serv6; 1007 addrlen = sizeof(serv6); 1008 sel_sock = sock6; 1009 break; 1010 #endif /* CONFIG_IPV6 */ 1011 default: 1012 return -1; 1013 } 1014 1015 if (conf->force_client_addr) { 1016 switch (conf->client_addr.af) { 1017 case AF_INET: 1018 os_memset(&claddr, 0, sizeof(claddr)); 1019 claddr.sin_family = AF_INET; 1020 claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; 1021 claddr.sin_port = htons(0); 1022 cl_addr = (struct sockaddr *) &claddr; 1023 claddrlen = sizeof(claddr); 1024 break; 1025 #ifdef CONFIG_IPV6 1026 case AF_INET6: 1027 os_memset(&claddr6, 0, sizeof(claddr6)); 1028 claddr6.sin6_family = AF_INET6; 1029 os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, 1030 sizeof(struct in6_addr)); 1031 claddr6.sin6_port = htons(0); 1032 cl_addr = (struct sockaddr *) &claddr6; 1033 claddrlen = sizeof(claddr6); 1034 break; 1035 #endif /* CONFIG_IPV6 */ 1036 default: 1037 return -1; 1038 } 1039 1040 if (bind(sel_sock, cl_addr, claddrlen) < 0) { 1041 wpa_printf(MSG_INFO, "bind[radius]: %s", 1042 strerror(errno)); 1043 return -1; 1044 } 1045 } 1046 1047 if (connect(sel_sock, addr, addrlen) < 0) { 1048 wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno)); 1049 return -1; 1050 } 1051 1052 #ifndef CONFIG_NATIVE_WINDOWS 1053 switch (nserv->addr.af) { 1054 case AF_INET: 1055 claddrlen = sizeof(claddr); 1056 getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen); 1057 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1058 inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port)); 1059 break; 1060 #ifdef CONFIG_IPV6 1061 case AF_INET6: { 1062 claddrlen = sizeof(claddr6); 1063 getsockname(sel_sock, (struct sockaddr *) &claddr6, 1064 &claddrlen); 1065 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1066 inet_ntop(AF_INET6, &claddr6.sin6_addr, 1067 abuf, sizeof(abuf)), 1068 ntohs(claddr6.sin6_port)); 1069 break; 1070 } 1071 #endif /* CONFIG_IPV6 */ 1072 } 1073 #endif /* CONFIG_NATIVE_WINDOWS */ 1074 1075 if (auth) 1076 radius->auth_sock = sel_sock; 1077 else 1078 radius->acct_sock = sel_sock; 1079 1080 return 0; 1081 } 1082 1083 1084 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) 1085 { 1086 struct radius_client_data *radius = eloop_ctx; 1087 struct hostapd_radius_servers *conf = radius->conf; 1088 struct hostapd_radius_server *oserv; 1089 1090 if (radius->auth_sock >= 0 && conf->auth_servers && 1091 conf->auth_server != conf->auth_servers) { 1092 oserv = conf->auth_server; 1093 conf->auth_server = conf->auth_servers; 1094 radius_change_server(radius, conf->auth_server, oserv, 1095 radius->auth_serv_sock, 1096 radius->auth_serv_sock6, 1); 1097 } 1098 1099 if (radius->acct_sock >= 0 && conf->acct_servers && 1100 conf->acct_server != conf->acct_servers) { 1101 oserv = conf->acct_server; 1102 conf->acct_server = conf->acct_servers; 1103 radius_change_server(radius, conf->acct_server, oserv, 1104 radius->acct_serv_sock, 1105 radius->acct_serv_sock6, 0); 1106 } 1107 1108 if (conf->retry_primary_interval) 1109 eloop_register_timeout(conf->retry_primary_interval, 0, 1110 radius_retry_primary_timer, radius, 1111 NULL); 1112 } 1113 1114 1115 static int radius_client_disable_pmtu_discovery(int s) 1116 { 1117 int r = -1; 1118 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 1119 /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 1120 int action = IP_PMTUDISC_DONT; 1121 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 1122 sizeof(action)); 1123 if (r == -1) 1124 wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s", 1125 strerror(errno)); 1126 #endif 1127 return r; 1128 } 1129 1130 1131 static int radius_client_init_auth(struct radius_client_data *radius) 1132 { 1133 struct hostapd_radius_servers *conf = radius->conf; 1134 int ok = 0; 1135 1136 radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 1137 if (radius->auth_serv_sock < 0) 1138 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s", 1139 strerror(errno)); 1140 else { 1141 radius_client_disable_pmtu_discovery(radius->auth_serv_sock); 1142 ok++; 1143 } 1144 1145 #ifdef CONFIG_IPV6 1146 radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 1147 if (radius->auth_serv_sock6 < 0) 1148 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s", 1149 strerror(errno)); 1150 else 1151 ok++; 1152 #endif /* CONFIG_IPV6 */ 1153 1154 if (ok == 0) 1155 return -1; 1156 1157 radius_change_server(radius, conf->auth_server, NULL, 1158 radius->auth_serv_sock, radius->auth_serv_sock6, 1159 1); 1160 1161 if (radius->auth_serv_sock >= 0 && 1162 eloop_register_read_sock(radius->auth_serv_sock, 1163 radius_client_receive, radius, 1164 (void *) RADIUS_AUTH)) { 1165 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server"); 1166 return -1; 1167 } 1168 1169 #ifdef CONFIG_IPV6 1170 if (radius->auth_serv_sock6 >= 0 && 1171 eloop_register_read_sock(radius->auth_serv_sock6, 1172 radius_client_receive, radius, 1173 (void *) RADIUS_AUTH)) { 1174 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server"); 1175 return -1; 1176 } 1177 #endif /* CONFIG_IPV6 */ 1178 1179 return 0; 1180 } 1181 1182 1183 static int radius_client_init_acct(struct radius_client_data *radius) 1184 { 1185 struct hostapd_radius_servers *conf = radius->conf; 1186 int ok = 0; 1187 1188 radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 1189 if (radius->acct_serv_sock < 0) 1190 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s", 1191 strerror(errno)); 1192 else { 1193 radius_client_disable_pmtu_discovery(radius->acct_serv_sock); 1194 ok++; 1195 } 1196 1197 #ifdef CONFIG_IPV6 1198 radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 1199 if (radius->acct_serv_sock6 < 0) 1200 wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s", 1201 strerror(errno)); 1202 else 1203 ok++; 1204 #endif /* CONFIG_IPV6 */ 1205 1206 if (ok == 0) 1207 return -1; 1208 1209 radius_change_server(radius, conf->acct_server, NULL, 1210 radius->acct_serv_sock, radius->acct_serv_sock6, 1211 0); 1212 1213 if (radius->acct_serv_sock >= 0 && 1214 eloop_register_read_sock(radius->acct_serv_sock, 1215 radius_client_receive, radius, 1216 (void *) RADIUS_ACCT)) { 1217 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server"); 1218 return -1; 1219 } 1220 1221 #ifdef CONFIG_IPV6 1222 if (radius->acct_serv_sock6 >= 0 && 1223 eloop_register_read_sock(radius->acct_serv_sock6, 1224 radius_client_receive, radius, 1225 (void *) RADIUS_ACCT)) { 1226 wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server"); 1227 return -1; 1228 } 1229 #endif /* CONFIG_IPV6 */ 1230 1231 return 0; 1232 } 1233 1234 1235 /** 1236 * radius_client_init - Initialize RADIUS client 1237 * @ctx: Callback context to be used in hostapd_logger() calls 1238 * @conf: RADIUS client configuration (RADIUS servers) 1239 * Returns: Pointer to private RADIUS client context or %NULL on failure 1240 * 1241 * The caller is responsible for keeping the configuration data available for 1242 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is 1243 * called for the returned context pointer. 1244 */ 1245 struct radius_client_data * 1246 radius_client_init(void *ctx, struct hostapd_radius_servers *conf) 1247 { 1248 struct radius_client_data *radius; 1249 1250 radius = os_zalloc(sizeof(struct radius_client_data)); 1251 if (radius == NULL) 1252 return NULL; 1253 1254 radius->ctx = ctx; 1255 radius->conf = conf; 1256 radius->auth_serv_sock = radius->acct_serv_sock = 1257 radius->auth_serv_sock6 = radius->acct_serv_sock6 = 1258 radius->auth_sock = radius->acct_sock = -1; 1259 1260 if (conf->auth_server && radius_client_init_auth(radius)) { 1261 radius_client_deinit(radius); 1262 return NULL; 1263 } 1264 1265 if (conf->acct_server && radius_client_init_acct(radius)) { 1266 radius_client_deinit(radius); 1267 return NULL; 1268 } 1269 1270 if (conf->retry_primary_interval) 1271 eloop_register_timeout(conf->retry_primary_interval, 0, 1272 radius_retry_primary_timer, radius, 1273 NULL); 1274 1275 return radius; 1276 } 1277 1278 1279 /** 1280 * radius_client_deinit - Deinitialize RADIUS client 1281 * @radius: RADIUS client context from radius_client_init() 1282 */ 1283 void radius_client_deinit(struct radius_client_data *radius) 1284 { 1285 if (!radius) 1286 return; 1287 1288 if (radius->auth_serv_sock >= 0) 1289 eloop_unregister_read_sock(radius->auth_serv_sock); 1290 if (radius->acct_serv_sock >= 0) 1291 eloop_unregister_read_sock(radius->acct_serv_sock); 1292 #ifdef CONFIG_IPV6 1293 if (radius->auth_serv_sock6 >= 0) 1294 eloop_unregister_read_sock(radius->auth_serv_sock6); 1295 if (radius->acct_serv_sock6 >= 0) 1296 eloop_unregister_read_sock(radius->acct_serv_sock6); 1297 #endif /* CONFIG_IPV6 */ 1298 1299 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); 1300 1301 radius_client_flush(radius, 0); 1302 os_free(radius->auth_handlers); 1303 os_free(radius->acct_handlers); 1304 os_free(radius); 1305 } 1306 1307 1308 /** 1309 * radius_client_flush_auth - Flush pending RADIUS messages for an address 1310 * @radius: RADIUS client context from radius_client_init() 1311 * @addr: MAC address of the related device 1312 * 1313 * This function can be used to remove pending RADIUS authentication messages 1314 * that are related to a specific device. The addr parameter is matched with 1315 * the one used in radius_client_send() call that was used to transmit the 1316 * authentication request. 1317 */ 1318 void radius_client_flush_auth(struct radius_client_data *radius, 1319 const u8 *addr) 1320 { 1321 struct radius_msg_list *entry, *prev, *tmp; 1322 1323 prev = NULL; 1324 entry = radius->msgs; 1325 while (entry) { 1326 if (entry->msg_type == RADIUS_AUTH && 1327 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 1328 hostapd_logger(radius->ctx, addr, 1329 HOSTAPD_MODULE_RADIUS, 1330 HOSTAPD_LEVEL_DEBUG, 1331 "Removing pending RADIUS authentication" 1332 " message for removed client"); 1333 1334 if (prev) 1335 prev->next = entry->next; 1336 else 1337 radius->msgs = entry->next; 1338 1339 tmp = entry; 1340 entry = entry->next; 1341 radius_client_msg_free(tmp); 1342 radius->num_msgs--; 1343 continue; 1344 } 1345 1346 prev = entry; 1347 entry = entry->next; 1348 } 1349 } 1350 1351 1352 static int radius_client_dump_auth_server(char *buf, size_t buflen, 1353 struct hostapd_radius_server *serv, 1354 struct radius_client_data *cli) 1355 { 1356 int pending = 0; 1357 struct radius_msg_list *msg; 1358 char abuf[50]; 1359 1360 if (cli) { 1361 for (msg = cli->msgs; msg; msg = msg->next) { 1362 if (msg->msg_type == RADIUS_AUTH) 1363 pending++; 1364 } 1365 } 1366 1367 return os_snprintf(buf, buflen, 1368 "radiusAuthServerIndex=%d\n" 1369 "radiusAuthServerAddress=%s\n" 1370 "radiusAuthClientServerPortNumber=%d\n" 1371 "radiusAuthClientRoundTripTime=%d\n" 1372 "radiusAuthClientAccessRequests=%u\n" 1373 "radiusAuthClientAccessRetransmissions=%u\n" 1374 "radiusAuthClientAccessAccepts=%u\n" 1375 "radiusAuthClientAccessRejects=%u\n" 1376 "radiusAuthClientAccessChallenges=%u\n" 1377 "radiusAuthClientMalformedAccessResponses=%u\n" 1378 "radiusAuthClientBadAuthenticators=%u\n" 1379 "radiusAuthClientPendingRequests=%u\n" 1380 "radiusAuthClientTimeouts=%u\n" 1381 "radiusAuthClientUnknownTypes=%u\n" 1382 "radiusAuthClientPacketsDropped=%u\n", 1383 serv->index, 1384 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1385 serv->port, 1386 serv->round_trip_time, 1387 serv->requests, 1388 serv->retransmissions, 1389 serv->access_accepts, 1390 serv->access_rejects, 1391 serv->access_challenges, 1392 serv->malformed_responses, 1393 serv->bad_authenticators, 1394 pending, 1395 serv->timeouts, 1396 serv->unknown_types, 1397 serv->packets_dropped); 1398 } 1399 1400 1401 static int radius_client_dump_acct_server(char *buf, size_t buflen, 1402 struct hostapd_radius_server *serv, 1403 struct radius_client_data *cli) 1404 { 1405 int pending = 0; 1406 struct radius_msg_list *msg; 1407 char abuf[50]; 1408 1409 if (cli) { 1410 for (msg = cli->msgs; msg; msg = msg->next) { 1411 if (msg->msg_type == RADIUS_ACCT || 1412 msg->msg_type == RADIUS_ACCT_INTERIM) 1413 pending++; 1414 } 1415 } 1416 1417 return os_snprintf(buf, buflen, 1418 "radiusAccServerIndex=%d\n" 1419 "radiusAccServerAddress=%s\n" 1420 "radiusAccClientServerPortNumber=%d\n" 1421 "radiusAccClientRoundTripTime=%d\n" 1422 "radiusAccClientRequests=%u\n" 1423 "radiusAccClientRetransmissions=%u\n" 1424 "radiusAccClientResponses=%u\n" 1425 "radiusAccClientMalformedResponses=%u\n" 1426 "radiusAccClientBadAuthenticators=%u\n" 1427 "radiusAccClientPendingRequests=%u\n" 1428 "radiusAccClientTimeouts=%u\n" 1429 "radiusAccClientUnknownTypes=%u\n" 1430 "radiusAccClientPacketsDropped=%u\n", 1431 serv->index, 1432 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1433 serv->port, 1434 serv->round_trip_time, 1435 serv->requests, 1436 serv->retransmissions, 1437 serv->responses, 1438 serv->malformed_responses, 1439 serv->bad_authenticators, 1440 pending, 1441 serv->timeouts, 1442 serv->unknown_types, 1443 serv->packets_dropped); 1444 } 1445 1446 1447 /** 1448 * radius_client_get_mib - Get RADIUS client MIB information 1449 * @radius: RADIUS client context from radius_client_init() 1450 * @buf: Buffer for returning MIB data in text format 1451 * @buflen: Maximum buf length in octets 1452 * Returns: Number of octets written into the buffer 1453 */ 1454 int radius_client_get_mib(struct radius_client_data *radius, char *buf, 1455 size_t buflen) 1456 { 1457 struct hostapd_radius_servers *conf = radius->conf; 1458 int i; 1459 struct hostapd_radius_server *serv; 1460 int count = 0; 1461 1462 if (conf->auth_servers) { 1463 for (i = 0; i < conf->num_auth_servers; i++) { 1464 serv = &conf->auth_servers[i]; 1465 count += radius_client_dump_auth_server( 1466 buf + count, buflen - count, serv, 1467 serv == conf->auth_server ? 1468 radius : NULL); 1469 } 1470 } 1471 1472 if (conf->acct_servers) { 1473 for (i = 0; i < conf->num_acct_servers; i++) { 1474 serv = &conf->acct_servers[i]; 1475 count += radius_client_dump_acct_server( 1476 buf + count, buflen - count, serv, 1477 serv == conf->acct_server ? 1478 radius : NULL); 1479 } 1480 } 1481 1482 return count; 1483 } 1484 1485 1486 void radius_client_reconfig(struct radius_client_data *radius, 1487 struct hostapd_radius_servers *conf) 1488 { 1489 if (radius) 1490 radius->conf = conf; 1491 } 1492