2
* hostapd / RADIUS client
3
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation.
9
* Alternatively, this software may be distributed under the terms of BSD
12
* See README and COPYING for more details.
19
#include "radius_client.h"
22
/* Defaults for RADIUS retransmit values (exponential backoff) */
23
#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */
24
#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
25
#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
26
* before entry is removed from retransmit
28
#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit
29
* list (oldest will be removed, if this
30
* limit is exceeded) */
31
#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this
32
* many failed retry attempts */
35
struct radius_rx_handler {
36
RadiusRxResult (*handler)(struct radius_msg *msg,
37
struct radius_msg *req,
38
u8 *shared_secret, size_t shared_secret_len,
44
/* RADIUS message retransmit list */
45
struct radius_msg_list {
46
u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages
47
* for the same STA. */
48
struct radius_msg *msg;
54
struct os_time last_attempt;
57
size_t shared_secret_len;
59
/* TODO: server config with failover to backup server(s) */
61
struct radius_msg_list *next;
65
struct radius_client_data {
67
struct hostapd_radius_servers *conf;
69
int auth_serv_sock; /* socket for authentication RADIUS messages */
70
int acct_serv_sock; /* socket for accounting RADIUS messages */
73
int auth_sock; /* currently used socket */
74
int acct_sock; /* currently used socket */
76
struct radius_rx_handler *auth_handlers;
77
size_t num_auth_handlers;
78
struct radius_rx_handler *acct_handlers;
79
size_t num_acct_handlers;
81
struct radius_msg_list *msgs;
84
u8 next_radius_identifier;
89
radius_change_server(struct radius_client_data *radius,
90
struct hostapd_radius_server *nserv,
91
struct hostapd_radius_server *oserv,
92
int sock, int sock6, int auth);
93
static int radius_client_init_acct(struct radius_client_data *radius);
94
static int radius_client_init_auth(struct radius_client_data *radius);
97
static void radius_client_msg_free(struct radius_msg_list *req)
99
radius_msg_free(req->msg);
105
int radius_client_register(struct radius_client_data *radius,
107
RadiusRxResult (*handler)(struct radius_msg *msg,
108
struct radius_msg *req,
110
size_t shared_secret_len,
114
struct radius_rx_handler **handlers, *newh;
117
if (msg_type == RADIUS_ACCT) {
118
handlers = &radius->acct_handlers;
119
num = &radius->num_acct_handlers;
121
handlers = &radius->auth_handlers;
122
num = &radius->num_auth_handlers;
125
newh = os_realloc(*handlers,
126
(*num + 1) * sizeof(struct radius_rx_handler));
130
newh[*num].handler = handler;
131
newh[*num].data = data;
139
static void radius_client_handle_send_error(struct radius_client_data *radius,
140
int s, RadiusType msg_type)
142
#ifndef CONFIG_NATIVE_WINDOWS
144
perror("send[RADIUS]");
145
if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL) {
146
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
148
"Send failed - maybe interface status changed -"
149
" try to connect again");
150
eloop_unregister_read_sock(s);
152
if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM)
153
radius_client_init_acct(radius);
155
radius_client_init_auth(radius);
157
#endif /* CONFIG_NATIVE_WINDOWS */
161
static int radius_client_retransmit(struct radius_client_data *radius,
162
struct radius_msg_list *entry,
165
struct hostapd_radius_servers *conf = radius->conf;
168
if (entry->msg_type == RADIUS_ACCT ||
169
entry->msg_type == RADIUS_ACCT_INTERIM) {
170
s = radius->acct_sock;
171
if (entry->attempts == 0)
172
conf->acct_server->requests++;
174
conf->acct_server->timeouts++;
175
conf->acct_server->retransmissions++;
178
s = radius->auth_sock;
179
if (entry->attempts == 0)
180
conf->auth_server->requests++;
182
conf->auth_server->timeouts++;
183
conf->auth_server->retransmissions++;
187
/* retransmit; remove entry if too many attempts */
189
hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
190
HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
191
entry->msg->hdr->identifier);
193
os_get_time(&entry->last_attempt);
194
if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
195
radius_client_handle_send_error(radius, s, entry->msg_type);
197
entry->next_try = now + entry->next_wait;
198
entry->next_wait *= 2;
199
if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
200
entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
201
if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
202
printf("Removing un-ACKed RADIUS message due to too many "
203
"failed retransmit attempts\n");
211
static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
213
struct radius_client_data *radius = eloop_ctx;
214
struct hostapd_radius_servers *conf = radius->conf;
217
struct radius_msg_list *entry, *prev, *tmp;
218
int auth_failover = 0, acct_failover = 0;
221
entry = radius->msgs;
230
if (now.sec >= entry->next_try &&
231
radius_client_retransmit(radius, entry, now.sec)) {
233
prev->next = entry->next;
235
radius->msgs = entry->next;
239
radius_client_msg_free(tmp);
244
if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) {
245
if (entry->msg_type == RADIUS_ACCT ||
246
entry->msg_type == RADIUS_ACCT_INTERIM)
252
if (first == 0 || entry->next_try < first)
253
first = entry->next_try;
262
eloop_register_timeout(first - now.sec, 0,
263
radius_client_timer, radius, NULL);
264
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
265
HOSTAPD_LEVEL_DEBUG, "Next RADIUS client "
266
"retransmit in %ld seconds",
267
(long int) (first - now.sec));
270
if (auth_failover && conf->num_auth_servers > 1) {
271
struct hostapd_radius_server *next, *old;
272
old = conf->auth_server;
273
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
274
HOSTAPD_LEVEL_NOTICE,
275
"No response from Authentication server "
277
hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
280
for (entry = radius->msgs; entry; entry = entry->next) {
281
if (entry->msg_type == RADIUS_AUTH)
286
if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
287
next = conf->auth_servers;
288
conf->auth_server = next;
289
radius_change_server(radius, next, old,
290
radius->auth_serv_sock,
291
radius->auth_serv_sock6, 1);
294
if (acct_failover && conf->num_acct_servers > 1) {
295
struct hostapd_radius_server *next, *old;
296
old = conf->acct_server;
297
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
298
HOSTAPD_LEVEL_NOTICE,
299
"No response from Accounting server "
301
hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
304
for (entry = radius->msgs; entry; entry = entry->next) {
305
if (entry->msg_type == RADIUS_ACCT ||
306
entry->msg_type == RADIUS_ACCT_INTERIM)
311
if (next > &conf->acct_servers[conf->num_acct_servers - 1])
312
next = conf->acct_servers;
313
conf->acct_server = next;
314
radius_change_server(radius, next, old,
315
radius->acct_serv_sock,
316
radius->acct_serv_sock6, 0);
321
static void radius_client_update_timeout(struct radius_client_data *radius)
325
struct radius_msg_list *entry;
327
eloop_cancel_timeout(radius_client_timer, radius, NULL);
329
if (radius->msgs == NULL) {
334
for (entry = radius->msgs; entry; entry = entry->next) {
335
if (first == 0 || entry->next_try < first)
336
first = entry->next_try;
342
eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
344
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
345
HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
346
" %ld seconds\n", (long int) (first - now.sec));
350
static void radius_client_list_add(struct radius_client_data *radius,
351
struct radius_msg *msg,
352
RadiusType msg_type, u8 *shared_secret,
353
size_t shared_secret_len, const u8 *addr)
355
struct radius_msg_list *entry, *prev;
357
if (eloop_terminated()) {
358
/* No point in adding entries to retransmit queue since event
359
* loop has already been terminated. */
360
radius_msg_free(msg);
365
entry = wpa_zalloc(sizeof(*entry));
367
printf("Failed to add RADIUS packet into retransmit list\n");
368
radius_msg_free(msg);
374
os_memcpy(entry->addr, addr, ETH_ALEN);
376
entry->msg_type = msg_type;
377
entry->shared_secret = shared_secret;
378
entry->shared_secret_len = shared_secret_len;
379
os_get_time(&entry->last_attempt);
380
entry->first_try = entry->last_attempt.sec;
381
entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
383
entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
384
entry->next = radius->msgs;
385
radius->msgs = entry;
386
radius_client_update_timeout(radius);
388
if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
389
printf("Removing the oldest un-ACKed RADIUS packet due to "
390
"retransmit list limits.\n");
392
while (entry->next) {
398
radius_client_msg_free(entry);
405
static void radius_client_list_del(struct radius_client_data *radius,
406
RadiusType msg_type, const u8 *addr)
408
struct radius_msg_list *entry, *prev, *tmp;
413
entry = radius->msgs;
416
if (entry->msg_type == msg_type &&
417
os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
419
prev->next = entry->next;
421
radius->msgs = entry->next;
424
hostapd_logger(radius->ctx, addr,
425
HOSTAPD_MODULE_RADIUS,
427
"Removing matching RADIUS message");
428
radius_client_msg_free(tmp);
438
int radius_client_send(struct radius_client_data *radius,
439
struct radius_msg *msg, RadiusType msg_type,
442
struct hostapd_radius_servers *conf = radius->conf;
444
size_t shared_secret_len;
448
if (msg_type == RADIUS_ACCT_INTERIM) {
449
/* Remove any pending interim acct update for the same STA. */
450
radius_client_list_del(radius, msg_type, addr);
453
if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
454
shared_secret = conf->acct_server->shared_secret;
455
shared_secret_len = conf->acct_server->shared_secret_len;
456
radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
458
s = radius->acct_sock;
459
conf->acct_server->requests++;
461
shared_secret = conf->auth_server->shared_secret;
462
shared_secret_len = conf->auth_server->shared_secret_len;
463
radius_msg_finish(msg, shared_secret, shared_secret_len);
464
name = "authentication";
465
s = radius->auth_sock;
466
conf->auth_server->requests++;
469
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
470
HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s "
473
radius_msg_dump(msg);
475
res = send(s, msg->buf, msg->buf_used, 0);
477
radius_client_handle_send_error(radius, s, msg_type);
479
radius_client_list_add(radius, msg, msg_type, shared_secret,
480
shared_secret_len, addr);
486
static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
488
struct radius_client_data *radius = eloop_ctx;
489
struct hostapd_radius_servers *conf = radius->conf;
490
RadiusType msg_type = (RadiusType) sock_ctx;
492
unsigned char buf[3000];
493
struct radius_msg *msg;
494
struct radius_rx_handler *handlers;
495
size_t num_handlers, i;
496
struct radius_msg_list *req, *prev_req;
498
struct hostapd_radius_server *rconf;
499
int invalid_authenticator = 0;
501
if (msg_type == RADIUS_ACCT) {
502
handlers = radius->acct_handlers;
503
num_handlers = radius->num_acct_handlers;
504
rconf = conf->acct_server;
506
handlers = radius->auth_handlers;
507
num_handlers = radius->num_auth_handlers;
508
rconf = conf->auth_server;
511
len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
513
perror("recv[RADIUS]");
516
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
517
HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS "
519
if (len == sizeof(buf)) {
520
printf("Possibly too long UDP frame for our buffer - "
525
msg = radius_msg_parse(buf, len);
527
printf("Parsing incoming RADIUS frame failed\n");
528
rconf->malformed_responses++;
532
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
533
HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
535
radius_msg_dump(msg);
537
switch (msg->hdr->code) {
538
case RADIUS_CODE_ACCESS_ACCEPT:
539
rconf->access_accepts++;
541
case RADIUS_CODE_ACCESS_REJECT:
542
rconf->access_rejects++;
544
case RADIUS_CODE_ACCESS_CHALLENGE:
545
rconf->access_challenges++;
547
case RADIUS_CODE_ACCOUNTING_RESPONSE:
555
/* TODO: also match by src addr:port of the packet when using
556
* alternative RADIUS servers (?) */
557
if ((req->msg_type == msg_type ||
558
(req->msg_type == RADIUS_ACCT_INTERIM &&
559
msg_type == RADIUS_ACCT)) &&
560
req->msg->hdr->identifier == msg->hdr->identifier)
568
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
570
"No matching RADIUS request found (type=%d "
571
"id=%d) - dropping packet",
572
msg_type, msg->hdr->identifier);
577
roundtrip = (now.sec - req->last_attempt.sec) * 100 +
578
(now.usec - req->last_attempt.usec) / 10000;
579
hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
581
"Received RADIUS packet matched with a pending "
582
"request, round trip time %d.%02d sec",
583
roundtrip / 100, roundtrip % 100);
584
rconf->round_trip_time = roundtrip;
586
/* Remove ACKed RADIUS packet from retransmit list */
588
prev_req->next = req->next;
590
radius->msgs = req->next;
593
for (i = 0; i < num_handlers; i++) {
595
res = handlers[i].handler(msg, req->msg, req->shared_secret,
596
req->shared_secret_len,
599
case RADIUS_RX_PROCESSED:
600
radius_msg_free(msg);
603
case RADIUS_RX_QUEUED:
604
radius_client_msg_free(req);
606
case RADIUS_RX_INVALID_AUTHENTICATOR:
607
invalid_authenticator++;
609
case RADIUS_RX_UNKNOWN:
610
/* continue with next handler */
615
if (invalid_authenticator)
616
rconf->bad_authenticators++;
618
rconf->unknown_types++;
619
hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
620
HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
621
"(type=%d code=%d id=%d)%s - dropping packet",
622
msg_type, msg->hdr->code, msg->hdr->identifier,
623
invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
625
radius_client_msg_free(req);
628
radius_msg_free(msg);
633
u8 radius_client_get_id(struct radius_client_data *radius)
635
struct radius_msg_list *entry, *prev, *_remove;
636
u8 id = radius->next_radius_identifier++;
638
/* remove entries with matching id from retransmit list to avoid
639
* using new reply from the RADIUS server with an old request */
640
entry = radius->msgs;
643
if (entry->msg->hdr->identifier == id) {
644
hostapd_logger(radius->ctx, entry->addr,
645
HOSTAPD_MODULE_RADIUS,
647
"Removing pending RADIUS message, "
648
"since its id (%d) is reused", id);
650
prev->next = entry->next;
652
radius->msgs = entry->next;
661
radius_client_msg_free(_remove);
668
void radius_client_flush(struct radius_client_data *radius, int only_auth)
670
struct radius_msg_list *entry, *prev, *tmp;
676
entry = radius->msgs;
679
if (!only_auth || entry->msg_type == RADIUS_AUTH) {
681
prev->next = entry->next;
683
radius->msgs = entry->next;
687
radius_client_msg_free(tmp);
695
if (radius->msgs == NULL)
696
eloop_cancel_timeout(radius_client_timer, radius, NULL);
700
void radius_client_update_acct_msgs(struct radius_client_data *radius,
702
size_t shared_secret_len)
704
struct radius_msg_list *entry;
709
for (entry = radius->msgs; entry; entry = entry->next) {
710
if (entry->msg_type == RADIUS_ACCT) {
711
entry->shared_secret = shared_secret;
712
entry->shared_secret_len = shared_secret_len;
713
radius_msg_finish_acct(entry->msg, shared_secret,
721
radius_change_server(struct radius_client_data *radius,
722
struct hostapd_radius_server *nserv,
723
struct hostapd_radius_server *oserv,
724
int sock, int sock6, int auth)
726
struct sockaddr_in serv;
728
struct sockaddr_in6 serv6;
729
#endif /* CONFIG_IPV6 */
730
struct sockaddr *addr;
734
struct radius_msg_list *entry;
736
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
739
auth ? "Authentication" : "Accounting",
740
hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
743
if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len ||
744
os_memcmp(nserv->shared_secret, oserv->shared_secret,
745
nserv->shared_secret_len) != 0) {
746
/* Pending RADIUS packets used different shared secret, so
747
* they need to be modified. Update accounting message
748
* authenticators here. Authentication messages are removed
749
* since they would require more changes and the new RADIUS
750
* server may not be prepared to receive them anyway due to
751
* missing state information. Client will likely retry
752
* authentication, so this should not be an issue. */
754
radius_client_flush(radius, 1);
756
radius_client_update_acct_msgs(
757
radius, nserv->shared_secret,
758
nserv->shared_secret_len);
762
/* Reset retry counters for the new server */
763
for (entry = radius->msgs; entry; entry = entry->next) {
764
if ((auth && entry->msg_type != RADIUS_AUTH) ||
765
(!auth && entry->msg_type != RADIUS_ACCT))
767
entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
769
entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
773
eloop_cancel_timeout(radius_client_timer, radius, NULL);
774
eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
775
radius_client_timer, radius, NULL);
778
switch (nserv->addr.af) {
780
os_memset(&serv, 0, sizeof(serv));
781
serv.sin_family = AF_INET;
782
serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
783
serv.sin_port = htons(nserv->port);
784
addr = (struct sockaddr *) &serv;
785
addrlen = sizeof(serv);
790
os_memset(&serv6, 0, sizeof(serv6));
791
serv6.sin6_family = AF_INET6;
792
os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
793
sizeof(struct in6_addr));
794
serv6.sin6_port = htons(nserv->port);
795
addr = (struct sockaddr *) &serv6;
796
addrlen = sizeof(serv6);
799
#endif /* CONFIG_IPV6 */
804
if (connect(sel_sock, addr, addrlen) < 0) {
805
perror("connect[radius]");
810
radius->auth_sock = sel_sock;
812
radius->acct_sock = sel_sock;
818
static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
820
struct radius_client_data *radius = eloop_ctx;
821
struct hostapd_radius_servers *conf = radius->conf;
822
struct hostapd_radius_server *oserv;
824
if (radius->auth_sock >= 0 && conf->auth_servers &&
825
conf->auth_server != conf->auth_servers) {
826
oserv = conf->auth_server;
827
conf->auth_server = conf->auth_servers;
828
radius_change_server(radius, conf->auth_server, oserv,
829
radius->auth_serv_sock,
830
radius->auth_serv_sock6, 1);
833
if (radius->acct_sock >= 0 && conf->acct_servers &&
834
conf->acct_server != conf->acct_servers) {
835
oserv = conf->acct_server;
836
conf->acct_server = conf->acct_servers;
837
radius_change_server(radius, conf->acct_server, oserv,
838
radius->acct_serv_sock,
839
radius->acct_serv_sock6, 0);
842
if (conf->retry_primary_interval)
843
eloop_register_timeout(conf->retry_primary_interval, 0,
844
radius_retry_primary_timer, radius,
849
static int radius_client_init_auth(struct radius_client_data *radius)
851
struct hostapd_radius_servers *conf = radius->conf;
854
radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
855
if (radius->auth_serv_sock < 0)
856
perror("socket[PF_INET,SOCK_DGRAM]");
861
radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
862
if (radius->auth_serv_sock6 < 0)
863
perror("socket[PF_INET6,SOCK_DGRAM]");
866
#endif /* CONFIG_IPV6 */
871
radius_change_server(radius, conf->auth_server, NULL,
872
radius->auth_serv_sock, radius->auth_serv_sock6,
875
if (radius->auth_serv_sock >= 0 &&
876
eloop_register_read_sock(radius->auth_serv_sock,
877
radius_client_receive, radius,
878
(void *) RADIUS_AUTH)) {
879
printf("Could not register read socket for authentication "
885
if (radius->auth_serv_sock6 >= 0 &&
886
eloop_register_read_sock(radius->auth_serv_sock6,
887
radius_client_receive, radius,
888
(void *) RADIUS_AUTH)) {
889
printf("Could not register read socket for authentication "
893
#endif /* CONFIG_IPV6 */
899
static int radius_client_init_acct(struct radius_client_data *radius)
901
struct hostapd_radius_servers *conf = radius->conf;
904
radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
905
if (radius->acct_serv_sock < 0)
906
perror("socket[PF_INET,SOCK_DGRAM]");
911
radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
912
if (radius->acct_serv_sock6 < 0)
913
perror("socket[PF_INET6,SOCK_DGRAM]");
916
#endif /* CONFIG_IPV6 */
921
radius_change_server(radius, conf->acct_server, NULL,
922
radius->acct_serv_sock, radius->acct_serv_sock6,
925
if (radius->acct_serv_sock >= 0 &&
926
eloop_register_read_sock(radius->acct_serv_sock,
927
radius_client_receive, radius,
928
(void *) RADIUS_ACCT)) {
929
printf("Could not register read socket for accounting "
935
if (radius->acct_serv_sock6 >= 0 &&
936
eloop_register_read_sock(radius->acct_serv_sock6,
937
radius_client_receive, radius,
938
(void *) RADIUS_ACCT)) {
939
printf("Could not register read socket for accounting "
943
#endif /* CONFIG_IPV6 */
949
struct radius_client_data *
950
radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
952
struct radius_client_data *radius;
954
radius = wpa_zalloc(sizeof(struct radius_client_data));
960
radius->auth_serv_sock = radius->acct_serv_sock =
961
radius->auth_serv_sock6 = radius->acct_serv_sock6 =
962
radius->auth_sock = radius->acct_sock = -1;
964
if (conf->auth_server && radius_client_init_auth(radius)) {
965
radius_client_deinit(radius);
969
if (conf->acct_server && radius_client_init_acct(radius)) {
970
radius_client_deinit(radius);
974
if (conf->retry_primary_interval)
975
eloop_register_timeout(conf->retry_primary_interval, 0,
976
radius_retry_primary_timer, radius,
983
void radius_client_deinit(struct radius_client_data *radius)
988
if (radius->auth_serv_sock >= 0)
989
eloop_unregister_read_sock(radius->auth_serv_sock);
990
if (radius->acct_serv_sock >= 0)
991
eloop_unregister_read_sock(radius->acct_serv_sock);
993
eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
995
radius_client_flush(radius, 0);
996
os_free(radius->auth_handlers);
997
os_free(radius->acct_handlers);
1002
void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr)
1004
struct radius_msg_list *entry, *prev, *tmp;
1007
entry = radius->msgs;
1009
if (entry->msg_type == RADIUS_AUTH &&
1010
os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
1011
hostapd_logger(radius->ctx, addr,
1012
HOSTAPD_MODULE_RADIUS,
1013
HOSTAPD_LEVEL_DEBUG,
1014
"Removing pending RADIUS authentication"
1015
" message for removed client");
1018
prev->next = entry->next;
1020
radius->msgs = entry->next;
1023
entry = entry->next;
1024
radius_client_msg_free(tmp);
1030
entry = entry->next;
1035
static int radius_client_dump_auth_server(char *buf, size_t buflen,
1036
struct hostapd_radius_server *serv,
1037
struct radius_client_data *cli)
1040
struct radius_msg_list *msg;
1044
for (msg = cli->msgs; msg; msg = msg->next) {
1045
if (msg->msg_type == RADIUS_AUTH)
1050
return os_snprintf(buf, buflen,
1051
"radiusAuthServerIndex=%d\n"
1052
"radiusAuthServerAddress=%s\n"
1053
"radiusAuthClientServerPortNumber=%d\n"
1054
"radiusAuthClientRoundTripTime=%d\n"
1055
"radiusAuthClientAccessRequests=%u\n"
1056
"radiusAuthClientAccessRetransmissions=%u\n"
1057
"radiusAuthClientAccessAccepts=%u\n"
1058
"radiusAuthClientAccessRejects=%u\n"
1059
"radiusAuthClientAccessChallenges=%u\n"
1060
"radiusAuthClientMalformedAccessResponses=%u\n"
1061
"radiusAuthClientBadAuthenticators=%u\n"
1062
"radiusAuthClientPendingRequests=%u\n"
1063
"radiusAuthClientTimeouts=%u\n"
1064
"radiusAuthClientUnknownTypes=%u\n"
1065
"radiusAuthClientPacketsDropped=%u\n",
1067
hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
1069
serv->round_trip_time,
1071
serv->retransmissions,
1072
serv->access_accepts,
1073
serv->access_rejects,
1074
serv->access_challenges,
1075
serv->malformed_responses,
1076
serv->bad_authenticators,
1079
serv->unknown_types,
1080
serv->packets_dropped);
1084
static int radius_client_dump_acct_server(char *buf, size_t buflen,
1085
struct hostapd_radius_server *serv,
1086
struct radius_client_data *cli)
1089
struct radius_msg_list *msg;
1093
for (msg = cli->msgs; msg; msg = msg->next) {
1094
if (msg->msg_type == RADIUS_ACCT ||
1095
msg->msg_type == RADIUS_ACCT_INTERIM)
1100
return os_snprintf(buf, buflen,
1101
"radiusAccServerIndex=%d\n"
1102
"radiusAccServerAddress=%s\n"
1103
"radiusAccClientServerPortNumber=%d\n"
1104
"radiusAccClientRoundTripTime=%d\n"
1105
"radiusAccClientRequests=%u\n"
1106
"radiusAccClientRetransmissions=%u\n"
1107
"radiusAccClientResponses=%u\n"
1108
"radiusAccClientMalformedResponses=%u\n"
1109
"radiusAccClientBadAuthenticators=%u\n"
1110
"radiusAccClientPendingRequests=%u\n"
1111
"radiusAccClientTimeouts=%u\n"
1112
"radiusAccClientUnknownTypes=%u\n"
1113
"radiusAccClientPacketsDropped=%u\n",
1115
hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
1117
serv->round_trip_time,
1119
serv->retransmissions,
1121
serv->malformed_responses,
1122
serv->bad_authenticators,
1125
serv->unknown_types,
1126
serv->packets_dropped);
1130
int radius_client_get_mib(struct radius_client_data *radius, char *buf,
1133
struct hostapd_radius_servers *conf = radius->conf;
1135
struct hostapd_radius_server *serv;
1138
if (conf->auth_servers) {
1139
for (i = 0; i < conf->num_auth_servers; i++) {
1140
serv = &conf->auth_servers[i];
1141
count += radius_client_dump_auth_server(
1142
buf + count, buflen - count, serv,
1143
serv == conf->auth_server ?
1148
if (conf->acct_servers) {
1149
for (i = 0; i < conf->num_acct_servers; i++) {
1150
serv = &conf->acct_servers[i];
1151
count += radius_client_dump_acct_server(
1152
buf + count, buflen - count, serv,
1153
serv == conf->acct_server ?
1162
static int radius_servers_diff(struct hostapd_radius_server *nserv,
1163
struct hostapd_radius_server *oserv,
1168
for (i = 0; i < num; i++) {
1169
if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) ||
1170
nserv[i].port != oserv[i].port ||
1171
nserv[i].shared_secret_len != oserv[i].shared_secret_len ||
1172
memcmp(nserv[i].shared_secret, oserv[i].shared_secret,
1173
nserv[i].shared_secret_len) != 0)
1181
struct radius_client_data *
1182
radius_client_reconfig(struct radius_client_data *old, void *ctx,
1183
struct hostapd_radius_servers *oldconf,
1184
struct hostapd_radius_servers *newconf)
1186
radius_client_flush(old, 0);
1188
if (newconf->retry_primary_interval !=
1189
oldconf->retry_primary_interval ||
1190
newconf->num_auth_servers != oldconf->num_auth_servers ||
1191
newconf->num_acct_servers != oldconf->num_acct_servers ||
1192
radius_servers_diff(newconf->auth_servers, oldconf->auth_servers,
1193
newconf->num_auth_servers) ||
1194
radius_servers_diff(newconf->acct_servers, oldconf->acct_servers,
1195
newconf->num_acct_servers)) {
1196
hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS,
1197
HOSTAPD_LEVEL_DEBUG,
1198
"Reconfiguring RADIUS client");
1199
radius_client_deinit(old);
1200
return radius_client_init(ctx, newconf);