radius_client.c revision 04949598a23f501be6eec21697465fd46a28840a
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 */ 61struct 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 */ 84struct 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_time 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 */ 154struct 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 232static int 233radius_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); 237static int radius_client_init_acct(struct radius_client_data *radius); 238static int radius_client_init_auth(struct radius_client_data *radius); 239 240 241static 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 */ 264int 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(*handlers, 285 (*num + 1) * 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 298static 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 perror("send[RADIUS]"); 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 321static 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_time(&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 printf("Removing un-ACKed RADIUS message due to too many " 365 "failed retransmit attempts\n"); 366 return 1; 367 } 368 369 return 0; 370} 371 372 373static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) 374{ 375 struct radius_client_data *radius = eloop_ctx; 376 struct hostapd_radius_servers *conf = radius->conf; 377 struct os_time now; 378 os_time_t first; 379 struct radius_msg_list *entry, *prev, *tmp; 380 int auth_failover = 0, acct_failover = 0; 381 char abuf[50]; 382 383 entry = radius->msgs; 384 if (!entry) 385 return; 386 387 os_get_time(&now); 388 first = 0; 389 390 prev = NULL; 391 while (entry) { 392 if (now.sec >= entry->next_try && 393 radius_client_retransmit(radius, entry, now.sec)) { 394 if (prev) 395 prev->next = entry->next; 396 else 397 radius->msgs = entry->next; 398 399 tmp = entry; 400 entry = entry->next; 401 radius_client_msg_free(tmp); 402 radius->num_msgs--; 403 continue; 404 } 405 406 if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) { 407 if (entry->msg_type == RADIUS_ACCT || 408 entry->msg_type == RADIUS_ACCT_INTERIM) 409 acct_failover++; 410 else 411 auth_failover++; 412 } 413 414 if (first == 0 || entry->next_try < first) 415 first = entry->next_try; 416 417 prev = entry; 418 entry = entry->next; 419 } 420 421 if (radius->msgs) { 422 if (first < now.sec) 423 first = now.sec; 424 eloop_register_timeout(first - now.sec, 0, 425 radius_client_timer, radius, NULL); 426 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 427 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " 428 "retransmit in %ld seconds", 429 (long int) (first - now.sec)); 430 } 431 432 if (auth_failover && conf->num_auth_servers > 1) { 433 struct hostapd_radius_server *next, *old; 434 old = conf->auth_server; 435 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 436 HOSTAPD_LEVEL_NOTICE, 437 "No response from Authentication server " 438 "%s:%d - failover", 439 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 440 old->port); 441 442 for (entry = radius->msgs; entry; entry = entry->next) { 443 if (entry->msg_type == RADIUS_AUTH) 444 old->timeouts++; 445 } 446 447 next = old + 1; 448 if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) 449 next = conf->auth_servers; 450 conf->auth_server = next; 451 radius_change_server(radius, next, old, 452 radius->auth_serv_sock, 453 radius->auth_serv_sock6, 1); 454 } 455 456 if (acct_failover && conf->num_acct_servers > 1) { 457 struct hostapd_radius_server *next, *old; 458 old = conf->acct_server; 459 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 460 HOSTAPD_LEVEL_NOTICE, 461 "No response from Accounting server " 462 "%s:%d - failover", 463 hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 464 old->port); 465 466 for (entry = radius->msgs; entry; entry = entry->next) { 467 if (entry->msg_type == RADIUS_ACCT || 468 entry->msg_type == RADIUS_ACCT_INTERIM) 469 old->timeouts++; 470 } 471 472 next = old + 1; 473 if (next > &conf->acct_servers[conf->num_acct_servers - 1]) 474 next = conf->acct_servers; 475 conf->acct_server = next; 476 radius_change_server(radius, next, old, 477 radius->acct_serv_sock, 478 radius->acct_serv_sock6, 0); 479 } 480} 481 482 483static void radius_client_update_timeout(struct radius_client_data *radius) 484{ 485 struct os_time now; 486 os_time_t first; 487 struct radius_msg_list *entry; 488 489 eloop_cancel_timeout(radius_client_timer, radius, NULL); 490 491 if (radius->msgs == NULL) { 492 return; 493 } 494 495 first = 0; 496 for (entry = radius->msgs; entry; entry = entry->next) { 497 if (first == 0 || entry->next_try < first) 498 first = entry->next_try; 499 } 500 501 os_get_time(&now); 502 if (first < now.sec) 503 first = now.sec; 504 eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, 505 NULL); 506 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 507 HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" 508 " %ld seconds", (long int) (first - now.sec)); 509} 510 511 512static void radius_client_list_add(struct radius_client_data *radius, 513 struct radius_msg *msg, 514 RadiusType msg_type, 515 const u8 *shared_secret, 516 size_t shared_secret_len, const u8 *addr) 517{ 518 struct radius_msg_list *entry, *prev; 519 520 if (eloop_terminated()) { 521 /* No point in adding entries to retransmit queue since event 522 * loop has already been terminated. */ 523 radius_msg_free(msg); 524 return; 525 } 526 527 entry = os_zalloc(sizeof(*entry)); 528 if (entry == NULL) { 529 printf("Failed to add RADIUS packet into retransmit list\n"); 530 radius_msg_free(msg); 531 return; 532 } 533 534 if (addr) 535 os_memcpy(entry->addr, addr, ETH_ALEN); 536 entry->msg = msg; 537 entry->msg_type = msg_type; 538 entry->shared_secret = shared_secret; 539 entry->shared_secret_len = shared_secret_len; 540 os_get_time(&entry->last_attempt); 541 entry->first_try = entry->last_attempt.sec; 542 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 543 entry->attempts = 1; 544 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 545 entry->next = radius->msgs; 546 radius->msgs = entry; 547 radius_client_update_timeout(radius); 548 549 if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { 550 printf("Removing the oldest un-ACKed RADIUS packet due to " 551 "retransmit list limits.\n"); 552 prev = NULL; 553 while (entry->next) { 554 prev = entry; 555 entry = entry->next; 556 } 557 if (prev) { 558 prev->next = NULL; 559 radius_client_msg_free(entry); 560 } 561 } else 562 radius->num_msgs++; 563} 564 565 566static void radius_client_list_del(struct radius_client_data *radius, 567 RadiusType msg_type, const u8 *addr) 568{ 569 struct radius_msg_list *entry, *prev, *tmp; 570 571 if (addr == NULL) 572 return; 573 574 entry = radius->msgs; 575 prev = NULL; 576 while (entry) { 577 if (entry->msg_type == msg_type && 578 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 579 if (prev) 580 prev->next = entry->next; 581 else 582 radius->msgs = entry->next; 583 tmp = entry; 584 entry = entry->next; 585 hostapd_logger(radius->ctx, addr, 586 HOSTAPD_MODULE_RADIUS, 587 HOSTAPD_LEVEL_DEBUG, 588 "Removing matching RADIUS message"); 589 radius_client_msg_free(tmp); 590 radius->num_msgs--; 591 continue; 592 } 593 prev = entry; 594 entry = entry->next; 595 } 596} 597 598 599/** 600 * radius_client_send - Send a RADIUS request 601 * @radius: RADIUS client context from radius_client_init() 602 * @msg: RADIUS message to be sent 603 * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM) 604 * @addr: MAC address of the device related to this message or %NULL 605 * Returns: 0 on success, -1 on failure 606 * 607 * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or 608 * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference 609 * between accounting and interim accounting messages is that the interim 610 * message will override any pending interim accounting updates while a new 611 * accounting message does not remove any pending messages. 612 * 613 * The message is added on the retransmission queue and will be retransmitted 614 * automatically until a response is received or maximum number of retries 615 * (RADIUS_CLIENT_MAX_RETRIES) is reached. 616 * 617 * The related device MAC address can be used to identify pending messages that 618 * can be removed with radius_client_flush_auth() or with interim accounting 619 * updates. 620 */ 621int radius_client_send(struct radius_client_data *radius, 622 struct radius_msg *msg, RadiusType msg_type, 623 const u8 *addr) 624{ 625 struct hostapd_radius_servers *conf = radius->conf; 626 const u8 *shared_secret; 627 size_t shared_secret_len; 628 char *name; 629 int s, res; 630 struct wpabuf *buf; 631 632 if (msg_type == RADIUS_ACCT_INTERIM) { 633 /* Remove any pending interim acct update for the same STA. */ 634 radius_client_list_del(radius, msg_type, addr); 635 } 636 637 if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { 638 if (conf->acct_server == NULL) { 639 hostapd_logger(radius->ctx, NULL, 640 HOSTAPD_MODULE_RADIUS, 641 HOSTAPD_LEVEL_INFO, 642 "No accounting server configured"); 643 return -1; 644 } 645 shared_secret = conf->acct_server->shared_secret; 646 shared_secret_len = conf->acct_server->shared_secret_len; 647 radius_msg_finish_acct(msg, shared_secret, shared_secret_len); 648 name = "accounting"; 649 s = radius->acct_sock; 650 conf->acct_server->requests++; 651 } else { 652 if (conf->auth_server == NULL) { 653 hostapd_logger(radius->ctx, NULL, 654 HOSTAPD_MODULE_RADIUS, 655 HOSTAPD_LEVEL_INFO, 656 "No authentication server configured"); 657 return -1; 658 } 659 shared_secret = conf->auth_server->shared_secret; 660 shared_secret_len = conf->auth_server->shared_secret_len; 661 radius_msg_finish(msg, shared_secret, shared_secret_len); 662 name = "authentication"; 663 s = radius->auth_sock; 664 conf->auth_server->requests++; 665 } 666 667 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 668 HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " 669 "server", name); 670 if (conf->msg_dumps) 671 radius_msg_dump(msg); 672 673 buf = radius_msg_get_buf(msg); 674 res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0); 675 if (res < 0) 676 radius_client_handle_send_error(radius, s, msg_type); 677 678 radius_client_list_add(radius, msg, msg_type, shared_secret, 679 shared_secret_len, addr); 680 681 return 0; 682} 683 684 685static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) 686{ 687 struct radius_client_data *radius = eloop_ctx; 688 struct hostapd_radius_servers *conf = radius->conf; 689 RadiusType msg_type = (RadiusType) sock_ctx; 690 int len, roundtrip; 691 unsigned char buf[3000]; 692 struct radius_msg *msg; 693 struct radius_hdr *hdr; 694 struct radius_rx_handler *handlers; 695 size_t num_handlers, i; 696 struct radius_msg_list *req, *prev_req; 697 struct os_time now; 698 struct hostapd_radius_server *rconf; 699 int invalid_authenticator = 0; 700 701 if (msg_type == RADIUS_ACCT) { 702 handlers = radius->acct_handlers; 703 num_handlers = radius->num_acct_handlers; 704 rconf = conf->acct_server; 705 } else { 706 handlers = radius->auth_handlers; 707 num_handlers = radius->num_auth_handlers; 708 rconf = conf->auth_server; 709 } 710 711 len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); 712 if (len < 0) { 713 perror("recv[RADIUS]"); 714 return; 715 } 716 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 717 HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " 718 "server", len); 719 if (len == sizeof(buf)) { 720 printf("Possibly too long UDP frame for our buffer - " 721 "dropping it\n"); 722 return; 723 } 724 725 msg = radius_msg_parse(buf, len); 726 if (msg == NULL) { 727 printf("Parsing incoming RADIUS frame failed\n"); 728 rconf->malformed_responses++; 729 return; 730 } 731 hdr = radius_msg_get_hdr(msg); 732 733 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 734 HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); 735 if (conf->msg_dumps) 736 radius_msg_dump(msg); 737 738 switch (hdr->code) { 739 case RADIUS_CODE_ACCESS_ACCEPT: 740 rconf->access_accepts++; 741 break; 742 case RADIUS_CODE_ACCESS_REJECT: 743 rconf->access_rejects++; 744 break; 745 case RADIUS_CODE_ACCESS_CHALLENGE: 746 rconf->access_challenges++; 747 break; 748 case RADIUS_CODE_ACCOUNTING_RESPONSE: 749 rconf->responses++; 750 break; 751 } 752 753 prev_req = NULL; 754 req = radius->msgs; 755 while (req) { 756 /* TODO: also match by src addr:port of the packet when using 757 * alternative RADIUS servers (?) */ 758 if ((req->msg_type == msg_type || 759 (req->msg_type == RADIUS_ACCT_INTERIM && 760 msg_type == RADIUS_ACCT)) && 761 radius_msg_get_hdr(req->msg)->identifier == 762 hdr->identifier) 763 break; 764 765 prev_req = req; 766 req = req->next; 767 } 768 769 if (req == NULL) { 770 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 771 HOSTAPD_LEVEL_DEBUG, 772 "No matching RADIUS request found (type=%d " 773 "id=%d) - dropping packet", 774 msg_type, hdr->identifier); 775 goto fail; 776 } 777 778 os_get_time(&now); 779 roundtrip = (now.sec - req->last_attempt.sec) * 100 + 780 (now.usec - req->last_attempt.usec) / 10000; 781 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 782 HOSTAPD_LEVEL_DEBUG, 783 "Received RADIUS packet matched with a pending " 784 "request, round trip time %d.%02d sec", 785 roundtrip / 100, roundtrip % 100); 786 rconf->round_trip_time = roundtrip; 787 788 /* Remove ACKed RADIUS packet from retransmit list */ 789 if (prev_req) 790 prev_req->next = req->next; 791 else 792 radius->msgs = req->next; 793 radius->num_msgs--; 794 795 for (i = 0; i < num_handlers; i++) { 796 RadiusRxResult res; 797 res = handlers[i].handler(msg, req->msg, req->shared_secret, 798 req->shared_secret_len, 799 handlers[i].data); 800 switch (res) { 801 case RADIUS_RX_PROCESSED: 802 radius_msg_free(msg); 803 /* continue */ 804 case RADIUS_RX_QUEUED: 805 radius_client_msg_free(req); 806 return; 807 case RADIUS_RX_INVALID_AUTHENTICATOR: 808 invalid_authenticator++; 809 /* continue */ 810 case RADIUS_RX_UNKNOWN: 811 /* continue with next handler */ 812 break; 813 } 814 } 815 816 if (invalid_authenticator) 817 rconf->bad_authenticators++; 818 else 819 rconf->unknown_types++; 820 hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 821 HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " 822 "(type=%d code=%d id=%d)%s - dropping packet", 823 msg_type, hdr->code, hdr->identifier, 824 invalid_authenticator ? " [INVALID AUTHENTICATOR]" : 825 ""); 826 radius_client_msg_free(req); 827 828 fail: 829 radius_msg_free(msg); 830} 831 832 833/** 834 * radius_client_get_id - Get an identifier for a new RADIUS message 835 * @radius: RADIUS client context from radius_client_init() 836 * Returns: Allocated identifier 837 * 838 * This function is used to fetch a unique (among pending requests) identifier 839 * for a new RADIUS message. 840 */ 841u8 radius_client_get_id(struct radius_client_data *radius) 842{ 843 struct radius_msg_list *entry, *prev, *_remove; 844 u8 id = radius->next_radius_identifier++; 845 846 /* remove entries with matching id from retransmit list to avoid 847 * using new reply from the RADIUS server with an old request */ 848 entry = radius->msgs; 849 prev = NULL; 850 while (entry) { 851 if (radius_msg_get_hdr(entry->msg)->identifier == id) { 852 hostapd_logger(radius->ctx, entry->addr, 853 HOSTAPD_MODULE_RADIUS, 854 HOSTAPD_LEVEL_DEBUG, 855 "Removing pending RADIUS message, " 856 "since its id (%d) is reused", id); 857 if (prev) 858 prev->next = entry->next; 859 else 860 radius->msgs = entry->next; 861 _remove = entry; 862 } else { 863 _remove = NULL; 864 prev = entry; 865 } 866 entry = entry->next; 867 868 if (_remove) 869 radius_client_msg_free(_remove); 870 } 871 872 return id; 873} 874 875 876/** 877 * radius_client_flush - Flush all pending RADIUS client messages 878 * @radius: RADIUS client context from radius_client_init() 879 * @only_auth: Whether only authentication messages are removed 880 */ 881void radius_client_flush(struct radius_client_data *radius, int only_auth) 882{ 883 struct radius_msg_list *entry, *prev, *tmp; 884 885 if (!radius) 886 return; 887 888 prev = NULL; 889 entry = radius->msgs; 890 891 while (entry) { 892 if (!only_auth || entry->msg_type == RADIUS_AUTH) { 893 if (prev) 894 prev->next = entry->next; 895 else 896 radius->msgs = entry->next; 897 898 tmp = entry; 899 entry = entry->next; 900 radius_client_msg_free(tmp); 901 radius->num_msgs--; 902 } else { 903 prev = entry; 904 entry = entry->next; 905 } 906 } 907 908 if (radius->msgs == NULL) 909 eloop_cancel_timeout(radius_client_timer, radius, NULL); 910} 911 912 913static void radius_client_update_acct_msgs(struct radius_client_data *radius, 914 const u8 *shared_secret, 915 size_t shared_secret_len) 916{ 917 struct radius_msg_list *entry; 918 919 if (!radius) 920 return; 921 922 for (entry = radius->msgs; entry; entry = entry->next) { 923 if (entry->msg_type == RADIUS_ACCT) { 924 entry->shared_secret = shared_secret; 925 entry->shared_secret_len = shared_secret_len; 926 radius_msg_finish_acct(entry->msg, shared_secret, 927 shared_secret_len); 928 } 929 } 930} 931 932 933static int 934radius_change_server(struct radius_client_data *radius, 935 struct hostapd_radius_server *nserv, 936 struct hostapd_radius_server *oserv, 937 int sock, int sock6, int auth) 938{ 939 struct sockaddr_in serv, claddr; 940#ifdef CONFIG_IPV6 941 struct sockaddr_in6 serv6, claddr6; 942#endif /* CONFIG_IPV6 */ 943 struct sockaddr *addr, *cl_addr; 944 socklen_t addrlen, claddrlen; 945 char abuf[50]; 946 int sel_sock; 947 struct radius_msg_list *entry; 948 struct hostapd_radius_servers *conf = radius->conf; 949 950 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 951 HOSTAPD_LEVEL_INFO, 952 "%s server %s:%d", 953 auth ? "Authentication" : "Accounting", 954 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), 955 nserv->port); 956 957 if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len || 958 os_memcmp(nserv->shared_secret, oserv->shared_secret, 959 nserv->shared_secret_len) != 0) { 960 /* Pending RADIUS packets used different shared secret, so 961 * they need to be modified. Update accounting message 962 * authenticators here. Authentication messages are removed 963 * since they would require more changes and the new RADIUS 964 * server may not be prepared to receive them anyway due to 965 * missing state information. Client will likely retry 966 * authentication, so this should not be an issue. */ 967 if (auth) 968 radius_client_flush(radius, 1); 969 else { 970 radius_client_update_acct_msgs( 971 radius, nserv->shared_secret, 972 nserv->shared_secret_len); 973 } 974 } 975 976 /* Reset retry counters for the new server */ 977 for (entry = radius->msgs; entry; entry = entry->next) { 978 if ((auth && entry->msg_type != RADIUS_AUTH) || 979 (!auth && entry->msg_type != RADIUS_ACCT)) 980 continue; 981 entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 982 entry->attempts = 0; 983 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 984 } 985 986 if (radius->msgs) { 987 eloop_cancel_timeout(radius_client_timer, radius, NULL); 988 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, 989 radius_client_timer, radius, NULL); 990 } 991 992 switch (nserv->addr.af) { 993 case AF_INET: 994 os_memset(&serv, 0, sizeof(serv)); 995 serv.sin_family = AF_INET; 996 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; 997 serv.sin_port = htons(nserv->port); 998 addr = (struct sockaddr *) &serv; 999 addrlen = sizeof(serv); 1000 sel_sock = sock; 1001 break; 1002#ifdef CONFIG_IPV6 1003 case AF_INET6: 1004 os_memset(&serv6, 0, sizeof(serv6)); 1005 serv6.sin6_family = AF_INET6; 1006 os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, 1007 sizeof(struct in6_addr)); 1008 serv6.sin6_port = htons(nserv->port); 1009 addr = (struct sockaddr *) &serv6; 1010 addrlen = sizeof(serv6); 1011 sel_sock = sock6; 1012 break; 1013#endif /* CONFIG_IPV6 */ 1014 default: 1015 return -1; 1016 } 1017 1018 if (conf->force_client_addr) { 1019 switch (conf->client_addr.af) { 1020 case AF_INET: 1021 os_memset(&claddr, 0, sizeof(claddr)); 1022 claddr.sin_family = AF_INET; 1023 claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; 1024 claddr.sin_port = htons(0); 1025 cl_addr = (struct sockaddr *) &claddr; 1026 claddrlen = sizeof(claddr); 1027 break; 1028#ifdef CONFIG_IPV6 1029 case AF_INET6: 1030 os_memset(&claddr6, 0, sizeof(claddr6)); 1031 claddr6.sin6_family = AF_INET6; 1032 os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, 1033 sizeof(struct in6_addr)); 1034 claddr6.sin6_port = htons(0); 1035 cl_addr = (struct sockaddr *) &claddr6; 1036 claddrlen = sizeof(claddr6); 1037 break; 1038#endif /* CONFIG_IPV6 */ 1039 default: 1040 return -1; 1041 } 1042 1043 if (bind(sel_sock, cl_addr, claddrlen) < 0) { 1044 perror("bind[radius]"); 1045 return -1; 1046 } 1047 } 1048 1049 if (connect(sel_sock, addr, addrlen) < 0) { 1050 perror("connect[radius]"); 1051 return -1; 1052 } 1053 1054#ifndef CONFIG_NATIVE_WINDOWS 1055 switch (nserv->addr.af) { 1056 case AF_INET: 1057 claddrlen = sizeof(claddr); 1058 getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen); 1059 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1060 inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port)); 1061 break; 1062#ifdef CONFIG_IPV6 1063 case AF_INET6: { 1064 claddrlen = sizeof(claddr6); 1065 getsockname(sel_sock, (struct sockaddr *) &claddr6, 1066 &claddrlen); 1067 wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1068 inet_ntop(AF_INET6, &claddr6.sin6_addr, 1069 abuf, sizeof(abuf)), 1070 ntohs(claddr6.sin6_port)); 1071 break; 1072 } 1073#endif /* CONFIG_IPV6 */ 1074 } 1075#endif /* CONFIG_NATIVE_WINDOWS */ 1076 1077 if (auth) 1078 radius->auth_sock = sel_sock; 1079 else 1080 radius->acct_sock = sel_sock; 1081 1082 return 0; 1083} 1084 1085 1086static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) 1087{ 1088 struct radius_client_data *radius = eloop_ctx; 1089 struct hostapd_radius_servers *conf = radius->conf; 1090 struct hostapd_radius_server *oserv; 1091 1092 if (radius->auth_sock >= 0 && conf->auth_servers && 1093 conf->auth_server != conf->auth_servers) { 1094 oserv = conf->auth_server; 1095 conf->auth_server = conf->auth_servers; 1096 radius_change_server(radius, conf->auth_server, oserv, 1097 radius->auth_serv_sock, 1098 radius->auth_serv_sock6, 1); 1099 } 1100 1101 if (radius->acct_sock >= 0 && conf->acct_servers && 1102 conf->acct_server != conf->acct_servers) { 1103 oserv = conf->acct_server; 1104 conf->acct_server = conf->acct_servers; 1105 radius_change_server(radius, conf->acct_server, oserv, 1106 radius->acct_serv_sock, 1107 radius->acct_serv_sock6, 0); 1108 } 1109 1110 if (conf->retry_primary_interval) 1111 eloop_register_timeout(conf->retry_primary_interval, 0, 1112 radius_retry_primary_timer, radius, 1113 NULL); 1114} 1115 1116 1117static int radius_client_disable_pmtu_discovery(int s) 1118{ 1119 int r = -1; 1120#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 1121 /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 1122 int action = IP_PMTUDISC_DONT; 1123 r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 1124 sizeof(action)); 1125 if (r == -1) 1126 wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " 1127 "%s", strerror(errno)); 1128#endif 1129 return r; 1130} 1131 1132 1133static int radius_client_init_auth(struct radius_client_data *radius) 1134{ 1135 struct hostapd_radius_servers *conf = radius->conf; 1136 int ok = 0; 1137 1138 radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 1139 if (radius->auth_serv_sock < 0) 1140 perror("socket[PF_INET,SOCK_DGRAM]"); 1141 else { 1142 radius_client_disable_pmtu_discovery(radius->auth_serv_sock); 1143 ok++; 1144 } 1145 1146#ifdef CONFIG_IPV6 1147 radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 1148 if (radius->auth_serv_sock6 < 0) 1149 perror("socket[PF_INET6,SOCK_DGRAM]"); 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 printf("Could not register read socket for authentication " 1166 "server\n"); 1167 return -1; 1168 } 1169 1170#ifdef CONFIG_IPV6 1171 if (radius->auth_serv_sock6 >= 0 && 1172 eloop_register_read_sock(radius->auth_serv_sock6, 1173 radius_client_receive, radius, 1174 (void *) RADIUS_AUTH)) { 1175 printf("Could not register read socket for authentication " 1176 "server\n"); 1177 return -1; 1178 } 1179#endif /* CONFIG_IPV6 */ 1180 1181 return 0; 1182} 1183 1184 1185static int radius_client_init_acct(struct radius_client_data *radius) 1186{ 1187 struct hostapd_radius_servers *conf = radius->conf; 1188 int ok = 0; 1189 1190 radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 1191 if (radius->acct_serv_sock < 0) 1192 perror("socket[PF_INET,SOCK_DGRAM]"); 1193 else { 1194 radius_client_disable_pmtu_discovery(radius->acct_serv_sock); 1195 ok++; 1196 } 1197 1198#ifdef CONFIG_IPV6 1199 radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 1200 if (radius->acct_serv_sock6 < 0) 1201 perror("socket[PF_INET6,SOCK_DGRAM]"); 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 printf("Could not register read socket for accounting " 1218 "server\n"); 1219 return -1; 1220 } 1221 1222#ifdef CONFIG_IPV6 1223 if (radius->acct_serv_sock6 >= 0 && 1224 eloop_register_read_sock(radius->acct_serv_sock6, 1225 radius_client_receive, radius, 1226 (void *) RADIUS_ACCT)) { 1227 printf("Could not register read socket for accounting " 1228 "server\n"); 1229 return -1; 1230 } 1231#endif /* CONFIG_IPV6 */ 1232 1233 return 0; 1234} 1235 1236 1237/** 1238 * radius_client_init - Initialize RADIUS client 1239 * @ctx: Callback context to be used in hostapd_logger() calls 1240 * @conf: RADIUS client configuration (RADIUS servers) 1241 * Returns: Pointer to private RADIUS client context or %NULL on failure 1242 * 1243 * The caller is responsible for keeping the configuration data available for 1244 * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is 1245 * called for the returned context pointer. 1246 */ 1247struct radius_client_data * 1248radius_client_init(void *ctx, struct hostapd_radius_servers *conf) 1249{ 1250 struct radius_client_data *radius; 1251 1252 radius = os_zalloc(sizeof(struct radius_client_data)); 1253 if (radius == NULL) 1254 return NULL; 1255 1256 radius->ctx = ctx; 1257 radius->conf = conf; 1258 radius->auth_serv_sock = radius->acct_serv_sock = 1259 radius->auth_serv_sock6 = radius->acct_serv_sock6 = 1260 radius->auth_sock = radius->acct_sock = -1; 1261 1262 if (conf->auth_server && radius_client_init_auth(radius)) { 1263 radius_client_deinit(radius); 1264 return NULL; 1265 } 1266 1267 if (conf->acct_server && radius_client_init_acct(radius)) { 1268 radius_client_deinit(radius); 1269 return NULL; 1270 } 1271 1272 if (conf->retry_primary_interval) 1273 eloop_register_timeout(conf->retry_primary_interval, 0, 1274 radius_retry_primary_timer, radius, 1275 NULL); 1276 1277 return radius; 1278} 1279 1280 1281/** 1282 * radius_client_deinit - Deinitialize RADIUS client 1283 * @radius: RADIUS client context from radius_client_init() 1284 */ 1285void radius_client_deinit(struct radius_client_data *radius) 1286{ 1287 if (!radius) 1288 return; 1289 1290 if (radius->auth_serv_sock >= 0) 1291 eloop_unregister_read_sock(radius->auth_serv_sock); 1292 if (radius->acct_serv_sock >= 0) 1293 eloop_unregister_read_sock(radius->acct_serv_sock); 1294#ifdef CONFIG_IPV6 1295 if (radius->auth_serv_sock6 >= 0) 1296 eloop_unregister_read_sock(radius->auth_serv_sock6); 1297 if (radius->acct_serv_sock6 >= 0) 1298 eloop_unregister_read_sock(radius->acct_serv_sock6); 1299#endif /* CONFIG_IPV6 */ 1300 1301 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); 1302 1303 radius_client_flush(radius, 0); 1304 os_free(radius->auth_handlers); 1305 os_free(radius->acct_handlers); 1306 os_free(radius); 1307} 1308 1309 1310/** 1311 * radius_client_flush_auth - Flush pending RADIUS messages for an address 1312 * @radius: RADIUS client context from radius_client_init() 1313 * @addr: MAC address of the related device 1314 * 1315 * This function can be used to remove pending RADIUS authentication messages 1316 * that are related to a specific device. The addr parameter is matched with 1317 * the one used in radius_client_send() call that was used to transmit the 1318 * authentication request. 1319 */ 1320void radius_client_flush_auth(struct radius_client_data *radius, 1321 const u8 *addr) 1322{ 1323 struct radius_msg_list *entry, *prev, *tmp; 1324 1325 prev = NULL; 1326 entry = radius->msgs; 1327 while (entry) { 1328 if (entry->msg_type == RADIUS_AUTH && 1329 os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 1330 hostapd_logger(radius->ctx, addr, 1331 HOSTAPD_MODULE_RADIUS, 1332 HOSTAPD_LEVEL_DEBUG, 1333 "Removing pending RADIUS authentication" 1334 " message for removed client"); 1335 1336 if (prev) 1337 prev->next = entry->next; 1338 else 1339 radius->msgs = entry->next; 1340 1341 tmp = entry; 1342 entry = entry->next; 1343 radius_client_msg_free(tmp); 1344 radius->num_msgs--; 1345 continue; 1346 } 1347 1348 prev = entry; 1349 entry = entry->next; 1350 } 1351} 1352 1353 1354static int radius_client_dump_auth_server(char *buf, size_t buflen, 1355 struct hostapd_radius_server *serv, 1356 struct radius_client_data *cli) 1357{ 1358 int pending = 0; 1359 struct radius_msg_list *msg; 1360 char abuf[50]; 1361 1362 if (cli) { 1363 for (msg = cli->msgs; msg; msg = msg->next) { 1364 if (msg->msg_type == RADIUS_AUTH) 1365 pending++; 1366 } 1367 } 1368 1369 return os_snprintf(buf, buflen, 1370 "radiusAuthServerIndex=%d\n" 1371 "radiusAuthServerAddress=%s\n" 1372 "radiusAuthClientServerPortNumber=%d\n" 1373 "radiusAuthClientRoundTripTime=%d\n" 1374 "radiusAuthClientAccessRequests=%u\n" 1375 "radiusAuthClientAccessRetransmissions=%u\n" 1376 "radiusAuthClientAccessAccepts=%u\n" 1377 "radiusAuthClientAccessRejects=%u\n" 1378 "radiusAuthClientAccessChallenges=%u\n" 1379 "radiusAuthClientMalformedAccessResponses=%u\n" 1380 "radiusAuthClientBadAuthenticators=%u\n" 1381 "radiusAuthClientPendingRequests=%u\n" 1382 "radiusAuthClientTimeouts=%u\n" 1383 "radiusAuthClientUnknownTypes=%u\n" 1384 "radiusAuthClientPacketsDropped=%u\n", 1385 serv->index, 1386 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1387 serv->port, 1388 serv->round_trip_time, 1389 serv->requests, 1390 serv->retransmissions, 1391 serv->access_accepts, 1392 serv->access_rejects, 1393 serv->access_challenges, 1394 serv->malformed_responses, 1395 serv->bad_authenticators, 1396 pending, 1397 serv->timeouts, 1398 serv->unknown_types, 1399 serv->packets_dropped); 1400} 1401 1402 1403static int radius_client_dump_acct_server(char *buf, size_t buflen, 1404 struct hostapd_radius_server *serv, 1405 struct radius_client_data *cli) 1406{ 1407 int pending = 0; 1408 struct radius_msg_list *msg; 1409 char abuf[50]; 1410 1411 if (cli) { 1412 for (msg = cli->msgs; msg; msg = msg->next) { 1413 if (msg->msg_type == RADIUS_ACCT || 1414 msg->msg_type == RADIUS_ACCT_INTERIM) 1415 pending++; 1416 } 1417 } 1418 1419 return os_snprintf(buf, buflen, 1420 "radiusAccServerIndex=%d\n" 1421 "radiusAccServerAddress=%s\n" 1422 "radiusAccClientServerPortNumber=%d\n" 1423 "radiusAccClientRoundTripTime=%d\n" 1424 "radiusAccClientRequests=%u\n" 1425 "radiusAccClientRetransmissions=%u\n" 1426 "radiusAccClientResponses=%u\n" 1427 "radiusAccClientMalformedResponses=%u\n" 1428 "radiusAccClientBadAuthenticators=%u\n" 1429 "radiusAccClientPendingRequests=%u\n" 1430 "radiusAccClientTimeouts=%u\n" 1431 "radiusAccClientUnknownTypes=%u\n" 1432 "radiusAccClientPacketsDropped=%u\n", 1433 serv->index, 1434 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1435 serv->port, 1436 serv->round_trip_time, 1437 serv->requests, 1438 serv->retransmissions, 1439 serv->responses, 1440 serv->malformed_responses, 1441 serv->bad_authenticators, 1442 pending, 1443 serv->timeouts, 1444 serv->unknown_types, 1445 serv->packets_dropped); 1446} 1447 1448 1449/** 1450 * radius_client_get_mib - Get RADIUS client MIB information 1451 * @radius: RADIUS client context from radius_client_init() 1452 * @buf: Buffer for returning MIB data in text format 1453 * @buflen: Maximum buf length in octets 1454 * Returns: Number of octets written into the buffer 1455 */ 1456int radius_client_get_mib(struct radius_client_data *radius, char *buf, 1457 size_t buflen) 1458{ 1459 struct hostapd_radius_servers *conf = radius->conf; 1460 int i; 1461 struct hostapd_radius_server *serv; 1462 int count = 0; 1463 1464 if (conf->auth_servers) { 1465 for (i = 0; i < conf->num_auth_servers; i++) { 1466 serv = &conf->auth_servers[i]; 1467 count += radius_client_dump_auth_server( 1468 buf + count, buflen - count, serv, 1469 serv == conf->auth_server ? 1470 radius : NULL); 1471 } 1472 } 1473 1474 if (conf->acct_servers) { 1475 for (i = 0; i < conf->num_acct_servers; i++) { 1476 serv = &conf->acct_servers[i]; 1477 count += radius_client_dump_acct_server( 1478 buf + count, buflen - count, serv, 1479 serv == conf->acct_server ? 1480 radius : NULL); 1481 } 1482 } 1483 1484 return count; 1485} 1486 1487 1488void radius_client_reconfig(struct radius_client_data *radius, 1489 struct hostapd_radius_servers *conf) 1490{ 1491 if (radius) 1492 radius->conf = conf; 1493} 1494