18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS client 3203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius_client.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Defaults for RADIUS retransmit values (exponential backoff) */ 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_CLIENT_FIRST_WAIT 3 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_CLIENT_MAX_WAIT 120 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_CLIENT_MAX_RETRIES - RADIUS client maximum retries 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Maximum number of retransmit attempts before the entry is removed from 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * retransmit list. 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_CLIENT_MAX_RETRIES 10 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Maximum number of entries in retransmit list (oldest entries will be 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * removed, if this limit is exceeded). 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_CLIENT_MAX_ENTRIES 30 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The number of failed retry attempts after which the RADIUS server will be 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * changed (if one of more backup servers are configured). 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_CLIENT_NUM_FAILOVER 4 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct radius_rx_handler - RADIUS client RX handler 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This data structure is used internally inside the RADIUS client module to 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * store registered RX handlers. These handlers are registered by calls to 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_register() and unregistered when the RADIUS client is 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deinitialized with a call to radius_client_deinit(). 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_rx_handler { 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handler - Received RADIUS message handler 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RadiusRxResult (*handler)(struct radius_msg *msg, 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *req, 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len, 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *data); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data - Context data for the handler 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *data; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct radius_msg_list - RADIUS client message retransmit list 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This data structure is used internally inside the RADIUS client module to 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * store pending RADIUS requests that may still need to be retransmitted. 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_msg_list { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * addr - STA/client address 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is used to find RADIUS messages for the same STA. 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr[ETH_ALEN]; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * msg - RADIUS message 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * msg_type - Message type 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RadiusType msg_type; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * first_try - Time of the first transmission attempt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t first_try; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * next_try - Time for the next transmission attempt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t next_try; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * attempts - Number of transmission attempts 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attempts; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * next_wait - Next retransmission wait time in seconds 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int next_wait; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * last_attempt - Time of the last transmission attempt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 125fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime last_attempt; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * shared_secret - Shared secret with the target RADIUS server 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * shared_secret_len - shared_secret length in octets 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: server config with failover to backup server(s) */ 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * next - Next message in the list 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *next; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct radius_client_data - Internal RADIUS client data 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This data structure is used internally inside the RADIUS client module. 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * External users allocate this by calling radius_client_init() and free it by 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * calling radius_client_deinit(). The pointer to this opaque data is used in 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * calls to other functions as an identifier for the RADIUS client instance. 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_client_data { 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ctx - Context pointer for hostapd_logger() callbacks 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * conf - RADIUS client configuration (list of RADIUS servers to use) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * auth_serv_sock - IPv4 socket for RADIUS authentication messages 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_serv_sock; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * acct_serv_sock - IPv4 socket for RADIUS accounting messages 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int acct_serv_sock; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_serv_sock6; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int acct_serv_sock6; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * auth_sock - Currently used socket for RADIUS authentication server 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_sock; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * acct_sock - Currently used socket for RADIUS accounting server 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int acct_sock; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * auth_handlers - Authentication message handlers 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_rx_handler *auth_handlers; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * num_auth_handlers - Number of handlers in auth_handlers 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_auth_handlers; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * acct_handlers - Accounting message handlers 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_rx_handler *acct_handlers; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * num_acct_handlers - Number of handlers in acct_handlers 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_acct_handlers; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * msgs - Pending outgoing RADIUS messages 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *msgs; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * num_msgs - Number of pending messages in the msgs list 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_msgs; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * next_radius_identifier - Next RADIUS message identifier to use 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 next_radius_identifier; 2299c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 2309c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt /** 2319c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * interim_error_cb - Interim accounting error callback 2329c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt */ 2339c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt void (*interim_error_cb)(const u8 *addr, void *ctx); 2349c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 2359c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt /** 2369c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * interim_error_cb_ctx - interim_error_cb() context data 2379c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt */ 2389c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt void *interim_error_cb_ctx; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_change_server(struct radius_client_data *radius, 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *nserv, 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *oserv, 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock, int sock6, int auth); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_init_acct(struct radius_client_data *radius); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_init_auth(struct radius_client_data *radius); 249203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidtstatic void radius_client_auth_failover(struct radius_client_data *radius); 250203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidtstatic void radius_client_acct_failover(struct radius_client_data *radius); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_client_msg_free(struct radius_msg_list *req) 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(req->msg); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(req); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_register - Register a RADIUS client RX handler 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT) 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @handler: Handler for received RADIUS messages 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Context pointer for handler callbacks 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to register a handler for processing received RADIUS 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication and accounting messages. The handler() callback function will 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be called whenever a RADIUS message is received from the active server. 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * There can be multiple registered RADIUS message handlers. The handlers will 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be called in order until one of them indicates that it has processed or 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * queued the message. 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint radius_client_register(struct radius_client_data *radius, 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RadiusType msg_type, 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RadiusRxResult (*handler)(struct radius_msg *msg, 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *req, 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len, 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *data), 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *data) 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_rx_handler **handlers, *newh; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *num; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg_type == RADIUS_ACCT) { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handlers = &radius->acct_handlers; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num = &radius->num_acct_handlers; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handlers = &radius->auth_handlers; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num = &radius->num_auth_handlers; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt newh = os_realloc_array(*handlers, *num + 1, 29761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(struct radius_rx_handler)); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (newh == NULL) 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newh[*num].handler = handler; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt newh[*num].data = data; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*num)++; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *handlers = newh; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3109c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt/** 3119c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * radius_client_set_interim_erro_cb - Register an interim acct error callback 3129c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 3139c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * @addr: Station address from the failed message 3149c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * @cb: Handler for interim accounting errors 3159c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * @ctx: Context pointer for handler callbacks 3169c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * 3179c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * This function is used to register a handler for processing failed 3189c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * transmission attempts of interim accounting update messages. 3199c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt */ 3209c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidtvoid radius_client_set_interim_error_cb(struct radius_client_data *radius, 3219c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt void (*cb)(const u8 *addr, void *ctx), 3229c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt void *ctx) 3239c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt{ 3249c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt radius->interim_error_cb = cb; 3259c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt radius->interim_error_cb_ctx = ctx; 3269c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt} 3279c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 3289c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 329717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt/* 330717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt * Returns >0 if message queue was flushed (i.e., the message that triggered 331717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt * the error is not available anymore) 332717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt */ 333717574375e969e8272c6d1a26137286eac158abbDmitry Shmidtstatic int radius_client_handle_send_error(struct radius_client_data *radius, 334717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt int s, RadiusType msg_type) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int _errno = errno; 338203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno)); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || 340014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt _errno == EBADF || _errno == ENETUNREACH || _errno == EACCES) { 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Send failed - maybe interface status changed -" 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " try to connect again"); 345717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (msg_type == RADIUS_ACCT || 346717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt msg_type == RADIUS_ACCT_INTERIM) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_init_acct(radius); 348717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt return 0; 349717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } else { 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_init_auth(radius); 351717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt return 1; 352717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 355717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 356717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt return 0; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_retransmit(struct radius_client_data *radius, 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry, 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t now) 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int s; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 367203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt size_t prev_num_msgs; 3689c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt u8 *acct_delay_time; 3699c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt size_t acct_delay_time_len; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->msg_type == RADIUS_ACCT || 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->msg_type == RADIUS_ACCT_INTERIM) { 373203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (radius->acct_sock < 0) 374203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_init_acct(radius); 375203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (radius->acct_sock < 0 && conf->num_acct_servers > 1) { 376203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt prev_num_msgs = radius->num_msgs; 377203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_acct_failover(radius); 378203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (prev_num_msgs != radius->num_msgs) 379203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt return 0; 380203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt } 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = radius->acct_sock; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->attempts == 0) 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->acct_server->requests++; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->acct_server->timeouts++; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->acct_server->retransmissions++; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 389203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (radius->auth_sock < 0) 390203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_init_auth(radius); 391203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (radius->auth_sock < 0 && conf->num_auth_servers > 1) { 392203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt prev_num_msgs = radius->num_msgs; 393203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_auth_failover(radius); 394203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (prev_num_msgs != radius->num_msgs) 395203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt return 0; 396203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt } 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = radius->auth_sock; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->attempts == 0) 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->auth_server->requests++; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->auth_server->timeouts++; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->auth_server->retransmissions++; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4059c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 4069c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (entry->msg_type == RADIUS_ACCT_INTERIM) { 4079c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, 4089c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt "RADIUS: Failed to transmit interim accounting update to " 4099c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt MACSTR " - drop message and request a new update", 4109c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt MAC2STR(entry->addr)); 4119c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (radius->interim_error_cb) 4129c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt radius->interim_error_cb(entry->addr, 4139c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt radius->interim_error_cb_ctx); 4149c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt return 1; 4159c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt } 4169c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 417203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (s < 0) { 418203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt wpa_printf(MSG_INFO, 419203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt "RADIUS: No valid socket for retransmission"); 420203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt return 1; 421203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt } 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4239c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (entry->msg_type == RADIUS_ACCT && 4249c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME, 4259c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt &acct_delay_time, &acct_delay_time_len, 4269c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt NULL) == 0 && 4279c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt acct_delay_time_len == 4) { 4289c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt struct radius_hdr *hdr; 4299c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt u32 delay_time; 4309c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 4319c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt /* 4329c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * Need to assign a new identifier since attribute contents 4339c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * changes. 4349c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt */ 4359c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt hdr = radius_msg_get_hdr(entry->msg); 4369c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt hdr->identifier = radius_client_get_id(radius); 4379c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 4389c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt /* Update Acct-Delay-Time to show wait time in queue */ 4399c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt delay_time = now - entry->first_try; 4409c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt WPA_PUT_BE32(acct_delay_time, delay_time); 4419c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 4429c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt wpa_printf(MSG_DEBUG, 4439c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt "RADIUS: Updated Acct-Delay-Time to %u for retransmission", 4449c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt delay_time); 4459c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt radius_msg_finish_acct(entry->msg, entry->shared_secret, 4469c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt entry->shared_secret_len); 4479c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt if (radius->conf->msg_dumps) 4489c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt radius_msg_dump(entry->msg); 4499c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt } 4509c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* retransmit; remove entry if too many attempts */ 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->attempts++; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_hdr(entry->msg)->identifier); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 457fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&entry->last_attempt); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = radius_msg_get_buf(entry->msg); 459717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { 460717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (radius_client_handle_send_error(radius, s, entry->msg_type) 461717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt > 0) 462717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt return 0; 463717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next_try = now + entry->next_wait; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next_wait *= 2; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { 470cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Removing un-ACKed message due to too many failed retransmit attempts"); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_client_timer(void *eloop_ctx, void *timeout_ctx) 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client_data *radius = eloop_ctx; 481fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t first; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry, *prev, *tmp; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_failover = 0, acct_failover = 0; 485717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt size_t prev_num_msgs; 486717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt int s; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = radius->msgs; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!entry) 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 492fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = 0; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 497717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt prev_num_msgs = radius->num_msgs; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (now.sec >= entry->next_try && 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_retransmit(radius, entry, now.sec)) { 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry->next; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->msgs = entry->next; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = entry; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_msg_free(tmp); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->num_msgs--; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 512717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (prev_num_msgs != radius->num_msgs) { 513717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt wpa_printf(MSG_DEBUG, 514717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt "RADIUS: Message removed from queue - restart from beginning"); 515717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt entry = radius->msgs; 516717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt prev = NULL; 517717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt continue; 518717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 519717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 520717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt s = entry->msg_type == RADIUS_AUTH ? radius->auth_sock : 521717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius->acct_sock; 522717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER || 523717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt (s < 0 && entry->attempts > 0)) { 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->msg_type == RADIUS_ACCT || 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->msg_type == RADIUS_ACCT_INTERIM) 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt acct_failover++; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_failover++; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (first == 0 || entry->next_try < first) 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = entry->next_try; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->msgs) { 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (first < now.sec) 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = now.sec; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(first - now.sec, 0, 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_timer, radius, NULL); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "retransmit in %ld seconds", 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long int) (first - now.sec)); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 549d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (auth_failover) 550203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_auth_failover(radius); 551203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 552d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (acct_failover) 553203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_acct_failover(radius); 554203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt} 555203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 556203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 557203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidtstatic void radius_client_auth_failover(struct radius_client_data *radius) 558203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt{ 559203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 560203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt struct hostapd_radius_server *next, *old; 561203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt struct radius_msg_list *entry; 562203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt char abuf[50]; 563203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 564203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt old = conf->auth_server; 565203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 566203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt HOSTAPD_LEVEL_NOTICE, 567203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt "No response from Authentication server %s:%d - failover", 568203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 569203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt old->port); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 571203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 572203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (entry->msg_type == RADIUS_AUTH) 573203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt old->timeouts++; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 576203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt next = old + 1; 577203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) 578203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt next = conf->auth_servers; 579203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt conf->auth_server = next; 580203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_change_server(radius, next, old, 581203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->auth_serv_sock, 582203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->auth_serv_sock6, 1); 583203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt} 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 586203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidtstatic void radius_client_acct_failover(struct radius_client_data *radius) 587203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt{ 588203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 589203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt struct hostapd_radius_server *next, *old; 590203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt struct radius_msg_list *entry; 591203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt char abuf[50]; 592203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 593203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt old = conf->acct_server; 594203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 595203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt HOSTAPD_LEVEL_NOTICE, 596203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt "No response from Accounting server %s:%d - failover", 597203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 598203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt old->port); 599203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 600203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 601203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (entry->msg_type == RADIUS_ACCT || 602203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt entry->msg_type == RADIUS_ACCT_INTERIM) 603203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt old->timeouts++; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 605203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 606203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt next = old + 1; 607203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (next > &conf->acct_servers[conf->num_acct_servers - 1]) 608203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt next = conf->acct_servers; 609203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt conf->acct_server = next; 610203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_change_server(radius, next, old, 611203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->acct_serv_sock, 612203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->acct_serv_sock6, 0); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_client_update_timeout(struct radius_client_data *radius) 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 618fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t first; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_client_timer, radius, NULL); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->msgs == NULL) { 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = 0; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (first == 0 || entry->next_try < first) 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = entry->next_try; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 634fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (first < now.sec) 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt first = now.sec; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" 64104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt " %ld seconds", (long int) (first - now.sec)); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_client_list_add(struct radius_client_data *radius, 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg, 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RadiusType msg_type, 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len, const u8 *addr) 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry, *prev; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_terminated()) { 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No point in adding entries to retransmit queue since event 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * loop has already been terminated. */ 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = os_zalloc(sizeof(*entry)); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry == NULL) { 662cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Failed to add packet into retransmit list"); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->addr, addr, ETH_ALEN); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->msg = msg; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->msg_type = msg_type; 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->shared_secret = shared_secret; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->shared_secret_len = shared_secret_len; 673fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&entry->last_attempt); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->first_try = entry->last_attempt.sec; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->attempts = 1; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next = radius->msgs; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->msgs = entry; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_update_timeout(radius); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { 683cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Removing the oldest un-ACKed packet due to retransmit list limits"); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry->next) { 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) { 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = NULL; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_msg_free(entry); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->num_msgs++; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_send - Send a RADIUS request 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: RADIUS message to be sent 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM) 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: MAC address of the device related to this message or %NULL 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * between accounting and interim accounting messages is that the interim 7099c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * message will not be retransmitted. Instead, a callback is used to indicate 7109c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * that the transmission failed for the specific station @addr so that a new 7119c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * interim accounting update message can be generated with up-to-date session 7129c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * data instead of trying to resend old information. 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The message is added on the retransmission queue and will be retransmitted 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * automatically until a response is received or maximum number of retries 7169c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * (RADIUS_CLIENT_MAX_RETRIES) is reached. No such retries are used with 7179c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * RADIUS_ACCT_INTERIM, i.e., such a pending message is removed from the queue 7189c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * automatically on transmission failure. 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The related device MAC address can be used to identify pending messages that 7219c17526f86859e2b6aebac0ed4f2561601816103Dmitry Shmidt * can be removed with radius_client_flush_auth(). 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint radius_client_send(struct radius_client_data *radius, 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg, RadiusType msg_type, 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *name; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int s, res; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { 735203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (conf->acct_server && radius->acct_sock < 0) 736203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_init_acct(radius); 737203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 7382f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (conf->acct_server == NULL || radius->acct_sock < 0 || 7392f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt conf->acct_server->shared_secret == NULL) { 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_RADIUS, 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "No accounting server configured"); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret = conf->acct_server->shared_secret; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len = conf->acct_server->shared_secret_len; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_finish_acct(msg, shared_secret, shared_secret_len); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name = "accounting"; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = radius->acct_sock; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->acct_server->requests++; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 753203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (conf->auth_server && radius->auth_sock < 0) 754203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_client_init_auth(radius); 755203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt 7562f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (conf->auth_server == NULL || radius->auth_sock < 0 || 7572f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt conf->auth_server->shared_secret == NULL) { 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_RADIUS, 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "No authentication server configured"); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret = conf->auth_server->shared_secret; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len = conf->auth_server->shared_secret_len; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_finish(msg, shared_secret, shared_secret_len); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name = "authentication"; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = radius->auth_sock; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->auth_server->requests++; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "server", name); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->msg_dumps) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_dump(msg); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = radius_msg_get_buf(msg); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_handle_send_error(radius, s, msg_type); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_list_add(radius, msg, msg_type, shared_secret, 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len, addr); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 78604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client_data *radius = eloop_ctx; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RadiusType msg_type = (RadiusType) sock_ctx; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len, roundtrip; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char buf[3000]; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_hdr *hdr; 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_rx_handler *handlers; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_handlers, i; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *req, *prev_req; 802fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *rconf; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int invalid_authenticator = 0; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg_type == RADIUS_ACCT) { 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handlers = radius->acct_handlers; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_handlers = radius->num_acct_handlers; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf = conf->acct_server; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handlers = radius->auth_handlers; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_handlers = radius->num_auth_handlers; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf = conf->auth_server; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 0) { 818cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "recv[RADIUS]: %s", strerror(errno)); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "server", len); 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len == sizeof(buf)) { 825cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Possibly too long UDP frame for our buffer - dropping it"); 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = radius_msg_parse(buf, len); 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 831cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Parsing incoming frame failed"); 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->malformed_responses++; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = radius_msg_get_hdr(msg); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->msg_dumps) 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_dump(msg); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_ACCEPT: 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->access_accepts++; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_REJECT: 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->access_rejects++; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCESS_CHALLENGE: 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->access_challenges++; 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_CODE_ACCOUNTING_RESPONSE: 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->responses++; 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev_req = NULL; 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = radius->msgs; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (req) { 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: also match by src addr:port of the packet when using 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * alternative RADIUS servers (?) */ 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((req->msg_type == msg_type || 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (req->msg_type == RADIUS_ACCT_INTERIM && 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg_type == RADIUS_ACCT)) && 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_get_hdr(req->msg)->identifier == 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->identifier) 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev_req = req; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = req->next; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "No matching RADIUS request found (type=%d " 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "id=%d) - dropping packet", 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg_type, hdr->identifier); 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 882fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt roundtrip = (now.sec - req->last_attempt.sec) * 100 + 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (now.usec - req->last_attempt.usec) / 10000; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Received RADIUS packet matched with a pending " 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request, round trip time %d.%02d sec", 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt roundtrip / 100, roundtrip % 100); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->round_trip_time = roundtrip; 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remove ACKed RADIUS packet from retransmit list */ 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev_req) 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev_req->next = req->next; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->msgs = req->next; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->num_msgs--; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_handlers; i++) { 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RadiusRxResult res; 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = handlers[i].handler(msg, req->msg, req->shared_secret, 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->shared_secret_len, 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handlers[i].data); 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (res) { 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_RX_PROCESSED: 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* continue */ 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_RX_QUEUED: 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_msg_free(req); 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_RX_INVALID_AUTHENTICATOR: 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt invalid_authenticator++; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* continue */ 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RADIUS_RX_UNKNOWN: 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* continue with next handler */ 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (invalid_authenticator) 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->bad_authenticators++; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rconf->unknown_types++; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(type=%d code=%d id=%d)%s - dropping packet", 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg_type, hdr->code, hdr->identifier, 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt invalid_authenticator ? " [INVALID AUTHENTICATOR]" : 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ""); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_msg_free(req); 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fail: 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_get_id - Get an identifier for a new RADIUS message 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Allocated identifier 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to fetch a unique (among pending requests) identifier 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for a new RADIUS message. 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 radius_client_get_id(struct radius_client_data *radius) 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry, *prev, *_remove; 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id = radius->next_radius_identifier++; 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* remove entries with matching id from retransmit list to avoid 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * using new reply from the RADIUS server with an old request */ 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = radius->msgs; 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_hdr(entry->msg)->identifier == id) { 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, entry->addr, 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_RADIUS, 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Removing pending RADIUS message, " 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "since its id (%d) is reused", id); 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry->next; 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->msgs = entry->next; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _remove = entry; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _remove = NULL; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_remove) 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_msg_free(_remove); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return id; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_flush - Flush all pending RADIUS client messages 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @only_auth: Whether only authentication messages are removed 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid radius_client_flush(struct radius_client_data *radius, int only_auth) 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry, *prev, *tmp; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius) 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = radius->msgs; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!only_auth || entry->msg_type == RADIUS_AUTH) { 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry->next; 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->msgs = entry->next; 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = entry; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_msg_free(tmp); 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->num_msgs--; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->msgs == NULL) 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_client_timer, radius, NULL); 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_client_update_acct_msgs(struct radius_client_data *radius, 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t shared_secret_len) 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius) 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->msg_type == RADIUS_ACCT) { 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->shared_secret = shared_secret; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->shared_secret_len = shared_secret_len; 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_finish_acct(entry->msg, shared_secret, 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared_secret_len); 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_change_server(struct radius_client_data *radius, 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *nserv, 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *oserv, 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock, int sock6, int auth) 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in serv, claddr; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in6 serv6, claddr6; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr *addr, *cl_addr; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t addrlen, claddrlen; 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char abuf[50]; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sel_sock; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 1053d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt struct sockaddr_in disconnect_addr = { 1054d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt .sin_family = AF_UNSPEC, 1055d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt }; 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s server %s:%d", 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth ? "Authentication" : "Accounting", 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nserv->port); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1064d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (oserv && oserv == nserv) { 1065d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* Reconnect to same server, flush */ 1066d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (auth) 1067d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt radius_client_flush(radius, 1); 1068d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1069d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1070717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (oserv && oserv != nserv && 1071717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt (nserv->shared_secret_len != oserv->shared_secret_len || 1072717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt os_memcmp(nserv->shared_secret, oserv->shared_secret, 1073717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt nserv->shared_secret_len) != 0)) { 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Pending RADIUS packets used different shared secret, so 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * they need to be modified. Update accounting message 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authenticators here. Authentication messages are removed 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * since they would require more changes and the new RADIUS 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * server may not be prepared to receive them anyway due to 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * missing state information. Client will likely retry 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication, so this should not be an issue. */ 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth) 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_flush(radius, 1); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_update_acct_msgs( 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius, nserv->shared_secret, 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nserv->shared_secret_len); 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Reset retry counters for the new server */ 1091717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt for (entry = radius->msgs; oserv && oserv != nserv && entry; 1092717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt entry = entry->next) { 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((auth && entry->msg_type != RADIUS_AUTH) || 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (!auth && entry->msg_type != RADIUS_ACCT)) 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->attempts = 0; 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->msgs) { 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_client_timer, radius, NULL); 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_timer, radius, NULL); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (nserv->addr.af) { 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AF_INET: 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&serv, 0, sizeof(serv)); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv.sin_family = AF_INET; 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv.sin_port = htons(nserv->port); 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = (struct sockaddr *) &serv; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addrlen = sizeof(serv); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sel_sock = sock; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AF_INET6: 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&serv6, 0, sizeof(serv6)); 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv6.sin6_family = AF_INET6; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct in6_addr)); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv6.sin6_port = htons(nserv->port); 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = (struct sockaddr *) &serv6; 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addrlen = sizeof(serv6); 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sel_sock = sock6; 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sel_sock < 0) { 11346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, 11356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "RADIUS: No server socket available (af=%d sock=%d sock6=%d auth=%d", 11366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nserv->addr.af, sock, sock6, auth); 11376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 11386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 11396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->force_client_addr) { 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (conf->client_addr.af) { 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AF_INET: 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&claddr, 0, sizeof(claddr)); 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddr.sin_family = AF_INET; 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddr.sin_port = htons(0); 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cl_addr = (struct sockaddr *) &claddr; 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddrlen = sizeof(claddr); 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AF_INET6: 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&claddr6, 0, sizeof(claddr6)); 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddr6.sin6_family = AF_INET6; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct in6_addr)); 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddr6.sin6_port = htons(0); 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cl_addr = (struct sockaddr *) &claddr6; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddrlen = sizeof(claddr6); 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(sel_sock, cl_addr, claddrlen) < 0) { 1166cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "bind[radius]: %s", 1167cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1172d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* Force a reconnect by disconnecting the socket first */ 1173d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (connect(sel_sock, (struct sockaddr *) &disconnect_addr, 1174d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt sizeof(disconnect_addr)) < 0) 1175d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt wpa_printf(MSG_INFO, "disconnect[radius]: %s", strerror(errno)); 1176d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (connect(sel_sock, addr, addrlen) < 0) { 1178cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno)); 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (nserv->addr.af) { 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AF_INET: 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddrlen = sizeof(claddr); 1186661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (getsockname(sel_sock, (struct sockaddr *) &claddr, 1187661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt &claddrlen) == 0) { 1188661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1189661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt inet_ntoa(claddr.sin_addr), 1190661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ntohs(claddr.sin_port)); 1191661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AF_INET6: { 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt claddrlen = sizeof(claddr6); 1196661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (getsockname(sel_sock, (struct sockaddr *) &claddr6, 1197661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt &claddrlen) == 0) { 1198661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 1199661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt inet_ntop(AF_INET6, &claddr6.sin6_addr, 1200661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt abuf, sizeof(abuf)), 1201661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ntohs(claddr6.sin6_port)); 1202661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth) 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->auth_sock = sel_sock; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->acct_sock = sel_sock; 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client_data *radius = eloop_ctx; 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *oserv; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->auth_sock >= 0 && conf->auth_servers && 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->auth_server != conf->auth_servers) { 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oserv = conf->auth_server; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->auth_server = conf->auth_servers; 1228203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (radius_change_server(radius, conf->auth_server, oserv, 1229203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->auth_serv_sock, 1230203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->auth_serv_sock6, 1) < 0) { 1231203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt conf->auth_server = oserv; 1232203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_change_server(radius, oserv, conf->auth_server, 1233203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->auth_serv_sock, 1234203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->auth_serv_sock6, 1); 1235203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt } 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->acct_sock >= 0 && conf->acct_servers && 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->acct_server != conf->acct_servers) { 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oserv = conf->acct_server; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->acct_server = conf->acct_servers; 1242203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (radius_change_server(radius, conf->acct_server, oserv, 1243203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->acct_serv_sock, 1244203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->acct_serv_sock6, 0) < 0) { 1245203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt conf->acct_server = oserv; 1246203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius_change_server(radius, oserv, conf->acct_server, 1247203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->acct_serv_sock, 1248203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt radius->acct_serv_sock6, 0); 1249203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt } 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->retry_primary_interval) 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(conf->retry_primary_interval, 0, 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_retry_primary_timer, radius, 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_disable_pmtu_discovery(int s) 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int r = -1; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int action = IP_PMTUDISC_DONT; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(action)); 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (r == -1) 1268cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_ERROR, "RADIUS: Failed to set IP_MTU_DISCOVER: %s", 1269cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return r; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1275717574375e969e8272c6d1a26137286eac158abbDmitry Shmidtstatic void radius_close_auth_sockets(struct radius_client_data *radius) 1276717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt{ 1277717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius->auth_sock = -1; 1278717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 1279717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (radius->auth_serv_sock >= 0) { 1280717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt eloop_unregister_read_sock(radius->auth_serv_sock); 1281717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt close(radius->auth_serv_sock); 1282717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius->auth_serv_sock = -1; 1283717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 1284717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt#ifdef CONFIG_IPV6 1285717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (radius->auth_serv_sock6 >= 0) { 1286717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt eloop_unregister_read_sock(radius->auth_serv_sock6); 1287717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt close(radius->auth_serv_sock6); 1288717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius->auth_serv_sock6 = -1; 1289717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 1290717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt#endif /* CONFIG_IPV6 */ 1291717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt} 1292717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 1293717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 1294717574375e969e8272c6d1a26137286eac158abbDmitry Shmidtstatic void radius_close_acct_sockets(struct radius_client_data *radius) 1295717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt{ 1296717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius->acct_sock = -1; 1297717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 1298717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (radius->acct_serv_sock >= 0) { 1299717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt eloop_unregister_read_sock(radius->acct_serv_sock); 1300717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt close(radius->acct_serv_sock); 1301717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius->acct_serv_sock = -1; 1302717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 1303717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt#ifdef CONFIG_IPV6 1304717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (radius->acct_serv_sock6 >= 0) { 1305717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt eloop_unregister_read_sock(radius->acct_serv_sock6); 1306717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt close(radius->acct_serv_sock6); 1307717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius->acct_serv_sock6 = -1; 1308717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt } 1309717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt#endif /* CONFIG_IPV6 */ 1310717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt} 1311717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 1312717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_init_auth(struct radius_client_data *radius) 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_auth_sockets(radius); 1319717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->auth_serv_sock < 0) 1322cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s", 1323cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_disable_pmtu_discovery(radius->auth_serv_sock); 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok++; 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->auth_serv_sock6 < 0) 1332cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s", 1333cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok++; 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ok == 0) 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_change_server(radius, conf->auth_server, NULL, 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->auth_serv_sock, radius->auth_serv_sock6, 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1); 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->auth_serv_sock >= 0 && 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(radius->auth_serv_sock, 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_receive, radius, 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) RADIUS_AUTH)) { 1349cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server"); 1350717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_auth_sockets(radius); 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->auth_serv_sock6 >= 0 && 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(radius->auth_serv_sock6, 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_receive, radius, 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) RADIUS_AUTH)) { 1359cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for authentication server"); 1360717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_auth_sockets(radius); 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_init_acct(struct radius_client_data *radius) 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ok = 0; 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1374717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_acct_sockets(radius); 1375717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->acct_serv_sock < 0) 1378cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET,SOCK_DGRAM]: %s", 1379cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_disable_pmtu_discovery(radius->acct_serv_sock); 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok++; 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->acct_serv_sock6 < 0) 1388cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: socket[PF_INET6,SOCK_DGRAM]: %s", 1389cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ok++; 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ok == 0) 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_change_server(radius, conf->acct_server, NULL, 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->acct_serv_sock, radius->acct_serv_sock6, 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->acct_serv_sock >= 0 && 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(radius->acct_serv_sock, 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_receive, radius, 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) RADIUS_ACCT)) { 1405cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server"); 1406717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_acct_sockets(radius); 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius->acct_serv_sock6 >= 0 && 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(radius->acct_serv_sock6, 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_receive, radius, 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void *) RADIUS_ACCT)) { 1415cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "RADIUS: Could not register read socket for accounting server"); 1416717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_acct_sockets(radius); 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_init - Initialize RADIUS client 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Callback context to be used in hostapd_logger() calls 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conf: RADIUS client configuration (RADIUS servers) 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to private RADIUS client context or %NULL on failure 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The caller is responsible for keeping the configuration data available for 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * called for the returned context pointer. 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct radius_client_data * 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtradius_client_init(void *ctx, struct hostapd_radius_servers *conf) 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client_data *radius; 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius = os_zalloc(sizeof(struct radius_client_data)); 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius == NULL) 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->ctx = ctx; 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->conf = conf; 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->auth_serv_sock = radius->acct_serv_sock = 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->auth_serv_sock6 = radius->acct_serv_sock6 = 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->auth_sock = radius->acct_sock = -1; 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->auth_server && radius_client_init_auth(radius)) { 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_deinit(radius); 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->acct_server && radius_client_init_acct(radius)) { 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_deinit(radius); 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->retry_primary_interval) 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(conf->retry_primary_interval, 0, 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_retry_primary_timer, radius, 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return radius; 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_deinit - Deinitialize RADIUS client 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid radius_client_deinit(struct radius_client_data *radius) 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius) 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_auth_sockets(radius); 1479717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt radius_close_acct_sockets(radius); 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_flush(radius, 0); 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(radius->auth_handlers); 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(radius->acct_handlers); 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(radius); 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_flush_auth - Flush pending RADIUS messages for an address 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: MAC address of the related device 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to remove pending RADIUS authentication messages 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that are related to a specific device. The addr parameter is matched with 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the one used in radius_client_send() call that was used to transmit the 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication request. 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid radius_client_flush_auth(struct radius_client_data *radius, 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *entry, *prev, *tmp; 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = radius->msgs; 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->msg_type == RADIUS_AUTH && 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(radius->ctx, addr, 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_MODULE_RADIUS, 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Removing pending RADIUS authentication" 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " message for removed client"); 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry->next; 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->msgs = entry->next; 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = entry; 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_msg_free(tmp); 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->num_msgs--; 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_dump_auth_server(char *buf, size_t buflen, 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *serv, 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client_data *cli) 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pending = 0; 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *msg; 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char abuf[50]; 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cli) { 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (msg = cli->msgs; msg; msg = msg->next) { 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg->msg_type == RADIUS_AUTH) 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pending++; 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return os_snprintf(buf, buflen, 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServerIndex=%d\n" 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthServerAddress=%s\n" 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientServerPortNumber=%d\n" 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientRoundTripTime=%d\n" 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientAccessRequests=%u\n" 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientAccessRetransmissions=%u\n" 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientAccessAccepts=%u\n" 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientAccessRejects=%u\n" 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientAccessChallenges=%u\n" 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientMalformedAccessResponses=%u\n" 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientBadAuthenticators=%u\n" 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientPendingRequests=%u\n" 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientTimeouts=%u\n" 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientUnknownTypes=%u\n" 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAuthClientPacketsDropped=%u\n", 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->index, 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->port, 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->round_trip_time, 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->requests, 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->retransmissions, 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->access_accepts, 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->access_rejects, 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->access_challenges, 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->malformed_responses, 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->bad_authenticators, 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pending, 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->timeouts, 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->unknown_types, 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->packets_dropped); 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int radius_client_dump_acct_server(char *buf, size_t buflen, 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *serv, 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_client_data *cli) 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pending = 0; 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg_list *msg; 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char abuf[50]; 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cli) { 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (msg = cli->msgs; msg; msg = msg->next) { 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg->msg_type == RADIUS_ACCT || 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg->msg_type == RADIUS_ACCT_INTERIM) 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pending++; 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return os_snprintf(buf, buflen, 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccServerIndex=%d\n" 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccServerAddress=%s\n" 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientServerPortNumber=%d\n" 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientRoundTripTime=%d\n" 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientRequests=%u\n" 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientRetransmissions=%u\n" 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientResponses=%u\n" 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientMalformedResponses=%u\n" 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientBadAuthenticators=%u\n" 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientPendingRequests=%u\n" 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientTimeouts=%u\n" 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientUnknownTypes=%u\n" 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "radiusAccClientPacketsDropped=%u\n", 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->index, 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->port, 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->round_trip_time, 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->requests, 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->retransmissions, 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->responses, 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->malformed_responses, 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->bad_authenticators, 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pending, 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->timeouts, 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->unknown_types, 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv->packets_dropped); 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * radius_client_get_mib - Get RADIUS client MIB information 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @radius: RADIUS client context from radius_client_init() 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for returning MIB data in text format 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buf length in octets 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of octets written into the buffer 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint radius_client_get_mib(struct radius_client_data *radius, char *buf, 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen) 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_server *serv; 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count = 0; 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->auth_servers) { 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < conf->num_auth_servers; i++) { 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv = &conf->auth_servers[i]; 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count += radius_client_dump_auth_server( 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + count, buflen - count, serv, 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv == conf->auth_server ? 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius : NULL); 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->acct_servers) { 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < conf->num_acct_servers; i++) { 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv = &conf->acct_servers[i]; 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count += radius_client_dump_acct_server( 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + count, buflen - count, serv, 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt serv == conf->acct_server ? 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius : NULL); 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return count; 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid radius_client_reconfig(struct radius_client_data *radius, 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_radius_servers *conf) 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius) 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius->conf = conf; 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1674