1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * hostapd / RADIUS client 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "radius.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "radius_client.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Defaults for RADIUS retransmit values (exponential backoff) */ 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */ 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */ 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * before entry is removed from retransmit 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * list */ 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * list (oldest will be removed, if this 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * limit is exceeded) */ 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * many failed retry attempts */ 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_rx_handler { 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusRxResult (*handler)(struct radius_msg *msg, 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *req, 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *shared_secret, 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t shared_secret_len, 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *data); 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *data; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* RADIUS message retransmit list */ 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_msg_list { 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * for the same STA. */ 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg; 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusType msg_type; 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_time_t first_try; 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_time_t next_try; 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int attempts; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int next_wait; 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time last_attempt; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *shared_secret; 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t shared_secret_len; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: server config with failover to backup server(s) */ 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *next; 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_client_data { 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *ctx; 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf; 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int auth_serv_sock; /* socket for authentication RADIUS messages */ 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int acct_serv_sock; /* socket for accounting RADIUS messages */ 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int auth_serv_sock6; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int acct_serv_sock6; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int auth_sock; /* currently used socket */ 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int acct_sock; /* currently used socket */ 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_rx_handler *auth_handlers; 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t num_auth_handlers; 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_rx_handler *acct_handlers; 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t num_acct_handlers; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *msgs; 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t num_msgs; 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 next_radius_identifier; 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_change_server(struct radius_client_data *radius, 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *nserv, 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *oserv, 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int sock, int sock6, int auth); 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_client_init_acct(struct radius_client_data *radius); 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_client_init_auth(struct radius_client_data *radius); 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_msg_free(struct radius_msg_list *req) 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(req->msg); 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(req->msg); 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(req); 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint radius_client_register(struct radius_client_data *radius, 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusType msg_type, 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusRxResult (*handler)(struct radius_msg *msg, 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *req, 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *shared_secret, 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t shared_secret_len, 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *data), 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt void *data) 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_rx_handler **handlers, *newh; 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t *num; 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg_type == RADIUS_ACCT) { 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt handlers = &radius->acct_handlers; 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt num = &radius->num_acct_handlers; 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt handlers = &radius->auth_handlers; 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt num = &radius->num_auth_handlers; 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt newh = os_realloc(*handlers, 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (*num + 1) * sizeof(struct radius_rx_handler)); 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (newh == NULL) 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt newh[*num].handler = handler; 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt newh[*num].data = data; 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (*num)++; 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *handlers = newh; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_handle_send_error(struct radius_client_data *radius, 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int s, RadiusType msg_type) 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int _errno = errno; 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("send[RADIUS]"); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _errno == EBADF) { 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_INFO, 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Send failed - maybe interface status changed -" 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " try to connect again"); 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_unregister_read_sock(s); 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt close(s); 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_init_acct(radius); 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_init_auth(radius); 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_client_retransmit(struct radius_client_data *radius, 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry, 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_time_t now) 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int s; 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg_type == RADIUS_ACCT || 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->msg_type == RADIUS_ACCT_INTERIM) { 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt s = radius->acct_sock; 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->attempts == 0) 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->acct_server->requests++; 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->acct_server->timeouts++; 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->acct_server->retransmissions++; 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt s = radius->auth_sock; 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->attempts == 0) 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->auth_server->requests++; 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->auth_server->timeouts++; 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->auth_server->retransmissions++; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* retransmit; remove entry if too many attempts */ 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->attempts++; 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->msg->hdr->identifier); 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&entry->last_attempt); 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0) 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_handle_send_error(radius, s, entry->msg_type); 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next_try = now + entry->next_wait; 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next_wait *= 2; 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next_wait = RADIUS_CLIENT_MAX_WAIT; 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Removing un-ACKed RADIUS message due to too many " 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "failed retransmit attempts\n"); 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 1; 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_timer(void *eloop_ctx, void *timeout_ctx) 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client_data *radius = eloop_ctx; 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_time_t first; 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry, *prev, *tmp; 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int auth_failover = 0, acct_failover = 0; 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char abuf[50]; 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = radius->msgs; 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!entry) 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&now); 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt first = 0; 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = NULL; 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (entry) { 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (now.sec >= entry->next_try && 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_retransmit(radius, entry, now.sec)) { 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev) 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = entry->next; 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->msgs = entry->next; 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tmp = entry; 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(tmp); 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->num_msgs--; 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) { 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg_type == RADIUS_ACCT || 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->msg_type == RADIUS_ACCT_INTERIM) 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt acct_failover++; 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_failover++; 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (first == 0 || entry->next_try < first) 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt first = entry->next_try; 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = entry; 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->msgs) { 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (first < now.sec) 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt first = now.sec; 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(first - now.sec, 0, 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_timer, radius, NULL); 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "retransmit in %ld seconds", 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (long int) (first - now.sec)); 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (auth_failover && conf->num_auth_servers > 1) { 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *next, *old; 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt old = conf->auth_server; 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_NOTICE, 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "No response from Authentication server " 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%s:%d - failover", 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt old->port); 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg_type == RADIUS_AUTH) 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt old->timeouts++; 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next = old + 1; 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next = conf->auth_servers; 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->auth_server = next; 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_change_server(radius, next, old, 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock, 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock6, 1); 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (acct_failover && conf->num_acct_servers > 1) { 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *next, *old; 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt old = conf->acct_server; 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_NOTICE, 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "No response from Accounting server " 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%s:%d - failover", 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt old->port); 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg_type == RADIUS_ACCT || 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->msg_type == RADIUS_ACCT_INTERIM) 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt old->timeouts++; 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next = old + 1; 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (next > &conf->acct_servers[conf->num_acct_servers - 1]) 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt next = conf->acct_servers; 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->acct_server = next; 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_change_server(radius, next, old, 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_serv_sock, 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_serv_sock6, 0); 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_update_timeout(struct radius_client_data *radius) 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_time_t first; 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry; 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(radius_client_timer, radius, NULL); 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->msgs == NULL) { 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt first = 0; 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (first == 0 || entry->next_try < first) 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt first = entry->next_try; 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&now); 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (first < now.sec) 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt first = now.sec; 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt NULL); 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " %ld seconds\n", (long int) (first - now.sec)); 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_list_add(struct radius_client_data *radius, 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg, 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusType msg_type, u8 *shared_secret, 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t shared_secret_len, const u8 *addr) 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry, *prev; 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eloop_terminated()) { 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* No point in adding entries to retransmit queue since event 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * loop has already been terminated. */ 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = os_zalloc(sizeof(*entry)); 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry == NULL) { 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Failed to add RADIUS packet into retransmit list\n"); 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (addr) 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(entry->addr, addr, ETH_ALEN); 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->msg = msg; 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->msg_type = msg_type; 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->shared_secret = shared_secret; 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->shared_secret_len = shared_secret_len; 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&entry->last_attempt); 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->first_try = entry->last_attempt.sec; 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->attempts = 1; 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next = radius->msgs; 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->msgs = entry; 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_update_timeout(radius); 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Removing the oldest un-ACKed RADIUS packet due to " 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "retransmit list limits.\n"); 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = NULL; 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (entry->next) { 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = entry; 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev) { 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = NULL; 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(entry); 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->num_msgs++; 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_list_del(struct radius_client_data *radius, 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusType msg_type, const u8 *addr) 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry, *prev, *tmp; 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (addr == NULL) 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = radius->msgs; 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = NULL; 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (entry) { 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg_type == msg_type && 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev) 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = entry->next; 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->msgs = entry->next; 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tmp = entry; 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, addr, 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_MODULE_RADIUS, 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Removing matching RADIUS message"); 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(tmp); 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->num_msgs--; 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = entry; 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint radius_client_send(struct radius_client_data *radius, 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg, RadiusType msg_type, 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *addr) 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *shared_secret; 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t shared_secret_len; 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *name; 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int s, res; 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg_type == RADIUS_ACCT_INTERIM) { 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Remove any pending interim acct update for the same STA. */ 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_list_del(radius, msg_type, addr); 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->acct_server == NULL) { 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_MODULE_RADIUS, 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_INFO, 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "No accounting server configured"); 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared_secret = conf->acct_server->shared_secret; 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared_secret_len = conf->acct_server->shared_secret_len; 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_finish_acct(msg, shared_secret, shared_secret_len); 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt name = "accounting"; 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt s = radius->acct_sock; 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->acct_server->requests++; 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->auth_server == NULL) { 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_MODULE_RADIUS, 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_INFO, 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "No authentication server configured"); 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared_secret = conf->auth_server->shared_secret; 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared_secret_len = conf->auth_server->shared_secret_len; 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_finish(msg, shared_secret, shared_secret_len); 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt name = "authentication"; 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt s = radius->auth_sock; 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->auth_server->requests++; 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "server", name); 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->msg_dumps) 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_dump(msg); 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = send(s, msg->buf, msg->buf_used, 0); 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (res < 0) 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_handle_send_error(radius, s, msg_type); 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_list_add(radius, msg, msg_type, shared_secret, 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared_secret_len, addr); 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return res; 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client_data *radius = eloop_ctx; 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusType msg_type = (RadiusType) sock_ctx; 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int len, roundtrip; 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt unsigned char buf[3000]; 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg *msg; 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_rx_handler *handlers; 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t num_handlers, i; 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *req, *prev_req; 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct os_time now; 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *rconf; 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int invalid_authenticator = 0; 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg_type == RADIUS_ACCT) { 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt handlers = radius->acct_handlers; 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt num_handlers = radius->num_acct_handlers; 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf = conf->acct_server; 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt handlers = radius->auth_handlers; 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt num_handlers = radius->num_auth_handlers; 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf = conf->auth_server; 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len < 0) { 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("recv[RADIUS]"); 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "server", len); 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len == sizeof(buf)) { 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Possibly too long UDP frame for our buffer - " 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "dropping it\n"); 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = radius_msg_parse(buf, len); 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg == NULL) { 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Parsing incoming RADIUS frame failed\n"); 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->malformed_responses++; 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->msg_dumps) 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_dump(msg); 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (msg->hdr->code) { 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_CODE_ACCESS_ACCEPT: 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->access_accepts++; 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_CODE_ACCESS_REJECT: 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->access_rejects++; 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_CODE_ACCESS_CHALLENGE: 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->access_challenges++; 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_CODE_ACCOUNTING_RESPONSE: 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->responses++; 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev_req = NULL; 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = radius->msgs; 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (req) { 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: also match by src addr:port of the packet when using 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * alternative RADIUS servers (?) */ 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((req->msg_type == msg_type || 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (req->msg_type == RADIUS_ACCT_INTERIM && 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg_type == RADIUS_ACCT)) && 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req->msg->hdr->identifier == msg->hdr->identifier) 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev_req = req; 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = req->next; 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req == NULL) { 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "No matching RADIUS request found (type=%d " 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "id=%d) - dropping packet", 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg_type, msg->hdr->identifier); 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_get_time(&now); 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt roundtrip = (now.sec - req->last_attempt.sec) * 100 + 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (now.usec - req->last_attempt.usec) / 10000; 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Received RADIUS packet matched with a pending " 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "request, round trip time %d.%02d sec", 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt roundtrip / 100, roundtrip % 100); 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->round_trip_time = roundtrip; 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Remove ACKed RADIUS packet from retransmit list */ 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev_req) 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev_req->next = req->next; 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->msgs = req->next; 607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->num_msgs--; 608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < num_handlers; i++) { 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt RadiusRxResult res; 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = handlers[i].handler(msg, req->msg, req->shared_secret, 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req->shared_secret_len, 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt handlers[i].data); 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (res) { 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_RX_PROCESSED: 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* continue */ 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_RX_QUEUED: 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(req); 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_RX_INVALID_AUTHENTICATOR: 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt invalid_authenticator++; 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* continue */ 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case RADIUS_RX_UNKNOWN: 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* continue with next handler */ 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (invalid_authenticator) 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->bad_authenticators++; 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt rconf->unknown_types++; 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(type=%d code=%d id=%d)%s - dropping packet", 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg_type, msg->hdr->code, msg->hdr->identifier, 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt invalid_authenticator ? " [INVALID AUTHENTICATOR]" : 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ""); 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(req); 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt fail: 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_free(msg); 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(msg); 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtu8 radius_client_get_id(struct radius_client_data *radius) 650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry, *prev, *_remove; 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 id = radius->next_radius_identifier++; 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* remove entries with matching id from retransmit list to avoid 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * using new reply from the RADIUS server with an old request */ 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = radius->msgs; 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = NULL; 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (entry) { 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg->hdr->identifier == id) { 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, entry->addr, 661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_MODULE_RADIUS, 662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Removing pending RADIUS message, " 664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "since its id (%d) is reused", id); 665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev) 666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = entry->next; 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->msgs = entry->next; 669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _remove = entry; 670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt _remove = NULL; 672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = entry; 673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (_remove) 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(_remove); 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return id; 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid radius_client_flush(struct radius_client_data *radius, int only_auth) 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry, *prev, *tmp; 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!radius) 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = NULL; 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = radius->msgs; 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (entry) { 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!only_auth || entry->msg_type == RADIUS_AUTH) { 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev) 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = entry->next; 698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->msgs = entry->next; 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tmp = entry; 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(tmp); 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->num_msgs--; 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = entry; 707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->msgs == NULL) 712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(radius_client_timer, radius, NULL); 713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_client_update_acct_msgs(struct radius_client_data *radius, 717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *shared_secret, 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t shared_secret_len) 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry; 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!radius) 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg_type == RADIUS_ACCT) { 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->shared_secret = shared_secret; 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->shared_secret_len = shared_secret_len; 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_msg_finish_acct(entry->msg, shared_secret, 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt shared_secret_len); 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_change_server(struct radius_client_data *radius, 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *nserv, 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *oserv, 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int sock, int sock6, int auth) 741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_in serv, claddr; 743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr_in6 serv6, claddr6; 745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct sockaddr *addr, *cl_addr; 747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt socklen_t addrlen, claddrlen; 748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char abuf[50]; 749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int sel_sock; 750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry; 751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, 754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_INFO, 755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%s server %s:%d", 756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth ? "Authentication" : "Accounting", 757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), 758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nserv->port); 759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len || 761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(nserv->shared_secret, oserv->shared_secret, 762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nserv->shared_secret_len) != 0) { 763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Pending RADIUS packets used different shared secret, so 764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * they need to be modified. Update accounting message 765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * authenticators here. Authentication messages are removed 766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * since they would require more changes and the new RADIUS 767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * server may not be prepared to receive them anyway due to 768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * missing state information. Client will likely retry 769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * authentication, so this should not be an issue. */ 770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (auth) 771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_flush(radius, 1); 772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_update_acct_msgs( 774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius, nserv->shared_secret, 775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nserv->shared_secret_len); 776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Reset retry counters for the new server */ 780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (entry = radius->msgs; entry; entry = entry->next) { 781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((auth && entry->msg_type != RADIUS_AUTH) || 782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (!auth && entry->msg_type != RADIUS_ACCT)) 783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; 785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->attempts = 0; 786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; 787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->msgs) { 790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(radius_client_timer, radius, NULL); 791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, 792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_timer, radius, NULL); 793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (nserv->addr.af) { 796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AF_INET: 797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&serv, 0, sizeof(serv)); 798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv.sin_family = AF_INET; 799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; 800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv.sin_port = htons(nserv->port); 801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr = (struct sockaddr *) &serv; 802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addrlen = sizeof(serv); 803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sel_sock = sock; 804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AF_INET6: 807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&serv6, 0, sizeof(serv6)); 808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv6.sin6_family = AF_INET6; 809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, 810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(struct in6_addr)); 811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv6.sin6_port = htons(nserv->port); 812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addr = (struct sockaddr *) &serv6; 813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt addrlen = sizeof(serv6); 814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sel_sock = sock6; 815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->force_client_addr) { 822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (conf->client_addr.af) { 823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AF_INET: 824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&claddr, 0, sizeof(claddr)); 825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddr.sin_family = AF_INET; 826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; 827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddr.sin_port = htons(0); 828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cl_addr = (struct sockaddr *) &claddr; 829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddrlen = sizeof(claddr); 830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AF_INET6: 833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&claddr6, 0, sizeof(claddr6)); 834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddr6.sin6_family = AF_INET6; 835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, 836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sizeof(struct in6_addr)); 837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddr6.sin6_port = htons(0); 838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cl_addr = (struct sockaddr *) &claddr6; 839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddrlen = sizeof(claddr6); 840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (bind(sel_sock, cl_addr, claddrlen) < 0) { 847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("bind[radius]"); 848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (connect(sel_sock, addr, addrlen) < 0) { 853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("connect[radius]"); 854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS 858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (nserv->addr.af) { 859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AF_INET: 860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddrlen = sizeof(claddr); 861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen); 862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port)); 864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case AF_INET6: { 867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt claddrlen = sizeof(claddr6); 868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt getsockname(sel_sock, (struct sockaddr *) &claddr6, 869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &claddrlen); 870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", 871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt inet_ntop(AF_INET6, &claddr6.sin6_addr, 872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt abuf, sizeof(abuf)), 873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ntohs(claddr6.sin6_port)); 874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (auth) 881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_sock = sel_sock; 882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_sock = sel_sock; 884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) 890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client_data *radius = eloop_ctx; 892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *oserv; 894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->auth_sock >= 0 && conf->auth_servers && 896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->auth_server != conf->auth_servers) { 897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt oserv = conf->auth_server; 898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->auth_server = conf->auth_servers; 899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_change_server(radius, conf->auth_server, oserv, 900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock, 901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock6, 1); 902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->acct_sock >= 0 && conf->acct_servers && 905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->acct_server != conf->acct_servers) { 906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt oserv = conf->acct_server; 907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt conf->acct_server = conf->acct_servers; 908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_change_server(radius, conf->acct_server, oserv, 909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_serv_sock, 910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_serv_sock6, 0); 911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->retry_primary_interval) 914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(conf->retry_primary_interval, 0, 915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_retry_primary_timer, radius, 916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt NULL); 917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 920dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidtstatic int radius_client_disable_pmtu_discovery(int s) 921dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt{ 922dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt int r = -1; 923dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 924dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt /* Turn off Path MTU discovery on IPv4/UDP sockets. */ 925dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt int action = IP_PMTUDISC_DONT; 926dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, 927dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt sizeof(action)); 928dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (r == -1) 929dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " 930dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt "%s", strerror(errno)); 931dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#endif 932dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt return r; 933dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt} 934dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 935dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt 936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_client_init_auth(struct radius_client_data *radius) 937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ok = 0; 940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->auth_serv_sock < 0) 943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket[PF_INET,SOCK_DGRAM]"); 944dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt else { 945dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt radius_client_disable_pmtu_discovery(radius->auth_serv_sock); 946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ok++; 947dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } 948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->auth_serv_sock6 < 0) 952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket[PF_INET6,SOCK_DGRAM]"); 953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ok++; 955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ok == 0) 958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_change_server(radius, conf->auth_server, NULL, 961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock, radius->auth_serv_sock6, 962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1); 963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->auth_serv_sock >= 0 && 965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_read_sock(radius->auth_serv_sock, 966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_receive, radius, 967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) RADIUS_AUTH)) { 968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Could not register read socket for authentication " 969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "server\n"); 970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->auth_serv_sock6 >= 0 && 975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_read_sock(radius->auth_serv_sock6, 976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_receive, radius, 977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) RADIUS_AUTH)) { 978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Could not register read socket for authentication " 979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "server\n"); 980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 981526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 982526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 983526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 984526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 985526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 986526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 987526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 988526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_client_init_acct(struct radius_client_data *radius) 989526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 990526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 991526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ok = 0; 992526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 993526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); 994526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->acct_serv_sock < 0) 995526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket[PF_INET,SOCK_DGRAM]"); 996dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt else { 997dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt radius_client_disable_pmtu_discovery(radius->acct_serv_sock); 998526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ok++; 999dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt } 1000526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1001526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 1002526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); 1003526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->acct_serv_sock6 < 0) 1004526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("socket[PF_INET6,SOCK_DGRAM]"); 1005526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 1006526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ok++; 1007526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 1008526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1009526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ok == 0) 1010526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1011526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1012526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_change_server(radius, conf->acct_server, NULL, 1013526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->acct_serv_sock, radius->acct_serv_sock6, 1014526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0); 1015526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1016526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->acct_serv_sock >= 0 && 1017526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_read_sock(radius->acct_serv_sock, 1018526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_receive, radius, 1019526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) RADIUS_ACCT)) { 1020526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Could not register read socket for accounting " 1021526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "server\n"); 1022526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1023526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1024526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1025526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IPV6 1026526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->acct_serv_sock6 >= 0 && 1027526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_read_sock(radius->acct_serv_sock6, 1028526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_receive, radius, 1029526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (void *) RADIUS_ACCT)) { 1030526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt printf("Could not register read socket for accounting " 1031526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "server\n"); 1032526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 1033526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1034526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IPV6 */ 1035526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1036526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1037526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1038526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1039526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1040526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_client_data * 1041526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_client_init(void *ctx, struct hostapd_radius_servers *conf) 1042526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1043526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client_data *radius; 1044526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1045526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius = os_zalloc(sizeof(struct radius_client_data)); 1046526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius == NULL) 1047526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1048526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1049526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->ctx = ctx; 1050526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->conf = conf; 1051526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock = radius->acct_serv_sock = 1052526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_serv_sock6 = radius->acct_serv_sock6 = 1053526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->auth_sock = radius->acct_sock = -1; 1054526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1055526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->auth_server && radius_client_init_auth(radius)) { 1056526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_deinit(radius); 1057526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1058526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1059526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1060526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->acct_server && radius_client_init_acct(radius)) { 1061526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_deinit(radius); 1062526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 1063526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1064526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1065526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->retry_primary_interval) 1066526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(conf->retry_primary_interval, 0, 1067526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_retry_primary_timer, radius, 1068526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt NULL); 1069526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1070526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return radius; 1071526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1072526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1073526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1074526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid radius_client_deinit(struct radius_client_data *radius) 1075526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1076526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!radius) 1077526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 1078526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1079526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->auth_serv_sock >= 0) 1080526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_unregister_read_sock(radius->auth_serv_sock); 1081526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (radius->acct_serv_sock >= 0) 1082526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_unregister_read_sock(radius->acct_serv_sock); 1083dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#ifdef CONFIG_IPV6 1084dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (radius->auth_serv_sock6 >= 0) 1085dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt eloop_unregister_read_sock(radius->auth_serv_sock6); 1086dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt if (radius->acct_serv_sock6 >= 0) 1087dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt eloop_unregister_read_sock(radius->acct_serv_sock6); 1088dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#endif /* CONFIG_IPV6 */ 1089526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1090526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); 1091526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1092526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_flush(radius, 0); 1093526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(radius->auth_handlers); 1094526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(radius->acct_handlers); 1095526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(radius); 1096526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1097526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1098526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1099526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid radius_client_flush_auth(struct radius_client_data *radius, u8 *addr) 1100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *entry, *prev, *tmp; 1102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = NULL; 1104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = radius->msgs; 1105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (entry) { 1106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (entry->msg_type == RADIUS_AUTH && 1107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 1108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(radius->ctx, addr, 1109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_MODULE_RADIUS, 1110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 1111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Removing pending RADIUS authentication" 1112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " message for removed client"); 1113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (prev) 1115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev->next = entry->next; 1116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 1117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->msgs = entry->next; 1118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt tmp = entry; 1120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 1121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_msg_free(tmp); 1122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius->num_msgs--; 1123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt continue; 1124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt prev = entry; 1127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt entry = entry->next; 1128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_client_dump_auth_server(char *buf, size_t buflen, 1133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *serv, 1134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client_data *cli) 1135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pending = 0; 1137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *msg; 1138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char abuf[50]; 1139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cli) { 1141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (msg = cli->msgs; msg; msg = msg->next) { 1142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg->msg_type == RADIUS_AUTH) 1143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pending++; 1144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return os_snprintf(buf, buflen, 1148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServerIndex=%d\n" 1149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthServerAddress=%s\n" 1150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientServerPortNumber=%d\n" 1151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientRoundTripTime=%d\n" 1152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientAccessRequests=%u\n" 1153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientAccessRetransmissions=%u\n" 1154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientAccessAccepts=%u\n" 1155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientAccessRejects=%u\n" 1156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientAccessChallenges=%u\n" 1157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientMalformedAccessResponses=%u\n" 1158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientBadAuthenticators=%u\n" 1159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientPendingRequests=%u\n" 1160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientTimeouts=%u\n" 1161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientUnknownTypes=%u\n" 1162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAuthClientPacketsDropped=%u\n", 1163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->index, 1164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->port, 1166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->round_trip_time, 1167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->requests, 1168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->retransmissions, 1169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->access_accepts, 1170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->access_rejects, 1171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->access_challenges, 1172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->malformed_responses, 1173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->bad_authenticators, 1174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pending, 1175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->timeouts, 1176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->unknown_types, 1177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->packets_dropped); 1178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_client_dump_acct_server(char *buf, size_t buflen, 1182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *serv, 1183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_client_data *cli) 1184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pending = 0; 1186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct radius_msg_list *msg; 1187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char abuf[50]; 1188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cli) { 1190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (msg = cli->msgs; msg; msg = msg->next) { 1191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (msg->msg_type == RADIUS_ACCT || 1192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg->msg_type == RADIUS_ACCT_INTERIM) 1193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pending++; 1194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return os_snprintf(buf, buflen, 1198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccServerIndex=%d\n" 1199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccServerAddress=%s\n" 1200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientServerPortNumber=%d\n" 1201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientRoundTripTime=%d\n" 1202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientRequests=%u\n" 1203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientRetransmissions=%u\n" 1204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientResponses=%u\n" 1205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientMalformedResponses=%u\n" 1206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientBadAuthenticators=%u\n" 1207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientPendingRequests=%u\n" 1208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientTimeouts=%u\n" 1209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientUnknownTypes=%u\n" 1210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "radiusAccClientPacketsDropped=%u\n", 1211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->index, 1212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), 1213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->port, 1214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->round_trip_time, 1215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->requests, 1216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->retransmissions, 1217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->responses, 1218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->malformed_responses, 1219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->bad_authenticators, 1220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pending, 1221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->timeouts, 1222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->unknown_types, 1223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv->packets_dropped); 1224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint radius_client_get_mib(struct radius_client_data *radius, char *buf, 1228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t buflen) 1229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *conf = radius->conf; 1231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int i; 1232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *serv; 1233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int count = 0; 1234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->auth_servers) { 1236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < conf->num_auth_servers; i++) { 1237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv = &conf->auth_servers[i]; 1238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count += radius_client_dump_auth_server( 1239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf + count, buflen - count, serv, 1240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv == conf->auth_server ? 1241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius : NULL); 1242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (conf->acct_servers) { 1246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < conf->num_acct_servers; i++) { 1247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv = &conf->acct_servers[i]; 1248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt count += radius_client_dump_acct_server( 1249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf + count, buflen - count, serv, 1250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt serv == conf->acct_server ? 1251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius : NULL); 1252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return count; 1256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int radius_servers_diff(struct hostapd_radius_server *nserv, 1260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_server *oserv, 1261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int num) 1262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int i; 1264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < num; i++) { 1266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) || 1267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nserv[i].port != oserv[i].port || 1268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nserv[i].shared_secret_len != oserv[i].shared_secret_len || 1269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(nserv[i].shared_secret, oserv[i].shared_secret, 1270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nserv[i].shared_secret_len) != 0) 1271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 1; 1272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 1275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct radius_client_data * 1279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtradius_client_reconfig(struct radius_client_data *old, void *ctx, 1280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *oldconf, 1281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct hostapd_radius_servers *newconf) 1282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 1283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_flush(old, 0); 1284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (newconf->retry_primary_interval != 1286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt oldconf->retry_primary_interval || 1287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt newconf->num_auth_servers != oldconf->num_auth_servers || 1288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt newconf->num_acct_servers != oldconf->num_acct_servers || 1289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_servers_diff(newconf->auth_servers, oldconf->auth_servers, 1290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt newconf->num_auth_servers) || 1291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_servers_diff(newconf->acct_servers, oldconf->acct_servers, 1292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt newconf->num_acct_servers)) { 1293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS, 1294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt HOSTAPD_LEVEL_DEBUG, 1295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Reconfiguring RADIUS client"); 1296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt radius_client_deinit(old); 1297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return radius_client_init(ctx, newconf); 1298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 1299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 1300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return old; 1301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 1302