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