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
);