2 * Host AP (software wireless LAN access point) user space daemon for
3 * Host AP kernel driver / RADIUS client
4 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
21 #include <sys/types.h>
24 #ifndef CONFIG_NATIVE_WINDOWS
25 #include <netinet/in.h>
26 #include <sys/socket.h>
27 #include <arpa/inet.h>
28 #endif /* CONFIG_NATIVE_WINDOWS */
32 #include "radius_client.h"
35 /* Defaults for RADIUS retransmit values (exponential backoff) */
36 #define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */
37 #define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
38 #define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
39 * before entry is removed from retransmit
41 #define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit
42 * list (oldest will be removed, if this
43 * limit is exceeded) */
44 #define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this
45 * many failed retry attempts */
48 struct radius_rx_handler
{
49 RadiusRxResult (*handler
)(struct radius_msg
*msg
,
50 struct radius_msg
*req
,
51 u8
*shared_secret
, size_t shared_secret_len
,
57 /* RADIUS message retransmit list */
58 struct radius_msg_list
{
59 u8 addr
[ETH_ALEN
]; /* STA/client address; used to find RADIUS messages
60 * for the same STA. */
61 struct radius_msg
*msg
;
67 struct timeval last_attempt
;
70 size_t shared_secret_len
;
72 /* TODO: server config with failover to backup server(s) */
74 struct radius_msg_list
*next
;
78 struct radius_client_data
{
80 struct hostapd_radius_servers
*conf
;
82 int auth_serv_sock
; /* socket for authentication RADIUS messages */
83 int acct_serv_sock
; /* socket for accounting RADIUS messages */
86 int auth_sock
; /* currently used socket */
87 int acct_sock
; /* currently used socket */
89 struct radius_rx_handler
*auth_handlers
;
90 size_t num_auth_handlers
;
91 struct radius_rx_handler
*acct_handlers
;
92 size_t num_acct_handlers
;
94 struct radius_msg_list
*msgs
;
97 u8 next_radius_identifier
;
102 radius_change_server(struct radius_client_data
*radius
,
103 struct hostapd_radius_server
*nserv
,
104 struct hostapd_radius_server
*oserv
,
105 int sock
, int sock6
, int auth
);
106 static int radius_client_init_acct(struct radius_client_data
*radius
);
107 static int radius_client_init_auth(struct radius_client_data
*radius
);
110 static void radius_client_msg_free(struct radius_msg_list
*req
)
112 radius_msg_free(req
->msg
);
118 int radius_client_register(struct radius_client_data
*radius
,
120 RadiusRxResult (*handler
)(struct radius_msg
*msg
,
121 struct radius_msg
*req
,
123 size_t shared_secret_len
,
127 struct radius_rx_handler
**handlers
, *newh
;
130 if (msg_type
== RADIUS_ACCT
) {
131 handlers
= &radius
->acct_handlers
;
132 num
= &radius
->num_acct_handlers
;
134 handlers
= &radius
->auth_handlers
;
135 num
= &radius
->num_auth_handlers
;
138 newh
= (struct radius_rx_handler
*)
140 (*num
+ 1) * sizeof(struct radius_rx_handler
));
144 newh
[*num
].handler
= handler
;
145 newh
[*num
].data
= data
;
153 static void radius_client_handle_send_error(struct radius_client_data
*radius
,
154 int s
, RadiusType msg_type
)
156 #ifndef CONFIG_NATIVE_WINDOWS
158 perror("send[RADIUS]");
159 if (_errno
== ENOTCONN
|| _errno
== EDESTADDRREQ
|| _errno
== EINVAL
) {
160 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
162 "Send failed - maybe interface status changed -"
163 " try to connect again");
164 eloop_unregister_read_sock(s
);
166 if (msg_type
== RADIUS_ACCT
|| msg_type
== RADIUS_ACCT_INTERIM
)
167 radius_client_init_acct(radius
);
169 radius_client_init_auth(radius
);
171 #endif /* CONFIG_NATIVE_WINDOWS */
175 static int radius_client_retransmit(struct radius_client_data
*radius
,
176 struct radius_msg_list
*entry
, time_t now
)
178 struct hostapd_radius_servers
*conf
= radius
->conf
;
181 if (entry
->msg_type
== RADIUS_ACCT
||
182 entry
->msg_type
== RADIUS_ACCT_INTERIM
) {
183 s
= radius
->acct_sock
;
184 if (entry
->attempts
== 0)
185 conf
->acct_server
->requests
++;
187 conf
->acct_server
->timeouts
++;
188 conf
->acct_server
->retransmissions
++;
191 s
= radius
->auth_sock
;
192 if (entry
->attempts
== 0)
193 conf
->auth_server
->requests
++;
195 conf
->auth_server
->timeouts
++;
196 conf
->auth_server
->retransmissions
++;
200 /* retransmit; remove entry if too many attempts */
202 hostapd_logger(radius
->ctx
, entry
->addr
, HOSTAPD_MODULE_RADIUS
,
203 HOSTAPD_LEVEL_DEBUG
, "Resending RADIUS message (id=%d)",
204 entry
->msg
->hdr
->identifier
);
206 gettimeofday(&entry
->last_attempt
, NULL
);
207 if (send(s
, entry
->msg
->buf
, entry
->msg
->buf_used
, 0) < 0)
208 radius_client_handle_send_error(radius
, s
, entry
->msg_type
);
210 entry
->next_try
= now
+ entry
->next_wait
;
211 entry
->next_wait
*= 2;
212 if (entry
->next_wait
> RADIUS_CLIENT_MAX_WAIT
)
213 entry
->next_wait
= RADIUS_CLIENT_MAX_WAIT
;
214 if (entry
->attempts
>= RADIUS_CLIENT_MAX_RETRIES
) {
215 printf("Removing un-ACKed RADIUS message due to too many "
216 "failed retransmit attempts\n");
224 static void radius_client_timer(void *eloop_ctx
, void *timeout_ctx
)
226 struct radius_client_data
*radius
= eloop_ctx
;
227 struct hostapd_radius_servers
*conf
= radius
->conf
;
229 struct radius_msg_list
*entry
, *prev
, *tmp
;
230 int auth_failover
= 0, acct_failover
= 0;
233 entry
= radius
->msgs
;
242 if (now
>= entry
->next_try
&&
243 radius_client_retransmit(radius
, entry
, now
)) {
245 prev
->next
= entry
->next
;
247 radius
->msgs
= entry
->next
;
251 radius_client_msg_free(tmp
);
256 if (entry
->attempts
> RADIUS_CLIENT_NUM_FAILOVER
) {
257 if (entry
->msg_type
== RADIUS_ACCT
||
258 entry
->msg_type
== RADIUS_ACCT_INTERIM
)
264 if (first
== 0 || entry
->next_try
< first
)
265 first
= entry
->next_try
;
274 eloop_register_timeout(first
- now
, 0,
275 radius_client_timer
, radius
, NULL
);
276 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
277 HOSTAPD_LEVEL_DEBUG
, "Next RADIUS client "
278 "retransmit in %ld seconds",
279 (long int) (first
- now
));
282 if (auth_failover
&& conf
->num_auth_servers
> 1) {
283 struct hostapd_radius_server
*next
, *old
;
284 old
= conf
->auth_server
;
285 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
286 HOSTAPD_LEVEL_NOTICE
,
287 "No response from Authentication server "
289 hostapd_ip_txt(&old
->addr
, abuf
, sizeof(abuf
)),
292 for (entry
= radius
->msgs
; entry
; entry
= entry
->next
) {
293 if (entry
->msg_type
== RADIUS_AUTH
)
298 if (next
> &(conf
->auth_servers
[conf
->num_auth_servers
- 1]))
299 next
= conf
->auth_servers
;
300 conf
->auth_server
= next
;
301 radius_change_server(radius
, next
, old
,
302 radius
->auth_serv_sock
,
303 radius
->auth_serv_sock6
, 1);
306 if (acct_failover
&& conf
->num_acct_servers
> 1) {
307 struct hostapd_radius_server
*next
, *old
;
308 old
= conf
->acct_server
;
309 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
310 HOSTAPD_LEVEL_NOTICE
,
311 "No response from Accounting server "
313 hostapd_ip_txt(&old
->addr
, abuf
, sizeof(abuf
)),
316 for (entry
= radius
->msgs
; entry
; entry
= entry
->next
) {
317 if (entry
->msg_type
== RADIUS_ACCT
||
318 entry
->msg_type
== RADIUS_ACCT_INTERIM
)
323 if (next
> &conf
->acct_servers
[conf
->num_acct_servers
- 1])
324 next
= conf
->acct_servers
;
325 conf
->acct_server
= next
;
326 radius_change_server(radius
, next
, old
,
327 radius
->acct_serv_sock
,
328 radius
->acct_serv_sock6
, 0);
333 static void radius_client_update_timeout(struct radius_client_data
*radius
)
336 struct radius_msg_list
*entry
;
338 eloop_cancel_timeout(radius_client_timer
, radius
, NULL
);
340 if (radius
->msgs
== NULL
) {
345 for (entry
= radius
->msgs
; entry
; entry
= entry
->next
) {
346 if (first
== 0 || entry
->next_try
< first
)
347 first
= entry
->next_try
;
353 eloop_register_timeout(first
- now
, 0, radius_client_timer
, radius
,
355 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
356 HOSTAPD_LEVEL_DEBUG
, "Next RADIUS client retransmit in"
357 " %ld seconds\n", (long int) (first
- now
));
361 static void radius_client_list_add(struct radius_client_data
*radius
,
362 struct radius_msg
*msg
,
363 RadiusType msg_type
, u8
*shared_secret
,
364 size_t shared_secret_len
, u8
*addr
)
366 struct radius_msg_list
*entry
, *prev
;
368 if (eloop_terminated()) {
369 /* No point in adding entries to retransmit queue since event
370 * loop has already been terminated. */
371 radius_msg_free(msg
);
376 entry
= malloc(sizeof(*entry
));
378 printf("Failed to add RADIUS packet into retransmit list\n");
379 radius_msg_free(msg
);
384 memset(entry
, 0, sizeof(*entry
));
386 memcpy(entry
->addr
, addr
, ETH_ALEN
);
388 entry
->msg_type
= msg_type
;
389 entry
->shared_secret
= shared_secret
;
390 entry
->shared_secret_len
= shared_secret_len
;
391 time(&entry
->first_try
);
392 entry
->next_try
= entry
->first_try
+ RADIUS_CLIENT_FIRST_WAIT
;
394 gettimeofday(&entry
->last_attempt
, NULL
);
395 entry
->next_wait
= RADIUS_CLIENT_FIRST_WAIT
* 2;
396 entry
->next
= radius
->msgs
;
397 radius
->msgs
= entry
;
398 radius_client_update_timeout(radius
);
400 if (radius
->num_msgs
>= RADIUS_CLIENT_MAX_ENTRIES
) {
401 printf("Removing the oldest un-ACKed RADIUS packet due to "
402 "retransmit list limits.\n");
404 while (entry
->next
) {
410 radius_client_msg_free(entry
);
417 static void radius_client_list_del(struct radius_client_data
*radius
,
418 RadiusType msg_type
, u8
*addr
)
420 struct radius_msg_list
*entry
, *prev
, *tmp
;
425 entry
= radius
->msgs
;
428 if (entry
->msg_type
== msg_type
&&
429 memcmp(entry
->addr
, addr
, ETH_ALEN
) == 0) {
431 prev
->next
= entry
->next
;
433 radius
->msgs
= entry
->next
;
436 hostapd_logger(radius
->ctx
, addr
,
437 HOSTAPD_MODULE_RADIUS
,
439 "Removing matching RADIUS message");
440 radius_client_msg_free(tmp
);
450 int radius_client_send(struct radius_client_data
*radius
,
451 struct radius_msg
*msg
, RadiusType msg_type
, u8
*addr
)
453 struct hostapd_radius_servers
*conf
= radius
->conf
;
455 size_t shared_secret_len
;
459 if (msg_type
== RADIUS_ACCT_INTERIM
) {
460 /* Remove any pending interim acct update for the same STA. */
461 radius_client_list_del(radius
, msg_type
, addr
);
464 if (msg_type
== RADIUS_ACCT
|| msg_type
== RADIUS_ACCT_INTERIM
) {
465 shared_secret
= conf
->acct_server
->shared_secret
;
466 shared_secret_len
= conf
->acct_server
->shared_secret_len
;
467 radius_msg_finish_acct(msg
, shared_secret
, shared_secret_len
);
469 s
= radius
->acct_sock
;
470 conf
->acct_server
->requests
++;
472 shared_secret
= conf
->auth_server
->shared_secret
;
473 shared_secret_len
= conf
->auth_server
->shared_secret_len
;
474 radius_msg_finish(msg
, shared_secret
, shared_secret_len
);
475 name
= "authentication";
476 s
= radius
->auth_sock
;
477 conf
->auth_server
->requests
++;
480 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
481 HOSTAPD_LEVEL_DEBUG
, "Sending RADIUS message to %s "
484 radius_msg_dump(msg
);
486 res
= send(s
, msg
->buf
, msg
->buf_used
, 0);
488 radius_client_handle_send_error(radius
, s
, msg_type
);
490 radius_client_list_add(radius
, msg
, msg_type
, shared_secret
,
491 shared_secret_len
, addr
);
497 static void radius_client_receive(int sock
, void *eloop_ctx
, void *sock_ctx
)
499 struct radius_client_data
*radius
= eloop_ctx
;
500 struct hostapd_radius_servers
*conf
= radius
->conf
;
501 RadiusType msg_type
= (RadiusType
) sock_ctx
;
502 int len
, i
, roundtrip
;
503 unsigned char buf
[3000];
504 struct radius_msg
*msg
;
505 struct radius_rx_handler
*handlers
;
507 struct radius_msg_list
*req
, *prev_req
;
509 struct hostapd_radius_server
*rconf
;
510 int invalid_authenticator
= 0;
512 if (msg_type
== RADIUS_ACCT
) {
513 handlers
= radius
->acct_handlers
;
514 num_handlers
= radius
->num_acct_handlers
;
515 rconf
= conf
->acct_server
;
517 handlers
= radius
->auth_handlers
;
518 num_handlers
= radius
->num_auth_handlers
;
519 rconf
= conf
->auth_server
;
522 len
= recv(sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
524 perror("recv[RADIUS]");
527 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
528 HOSTAPD_LEVEL_DEBUG
, "Received %d bytes from RADIUS "
530 if (len
== sizeof(buf
)) {
531 printf("Possibly too long UDP frame for our buffer - "
536 msg
= radius_msg_parse(buf
, len
);
538 printf("Parsing incoming RADIUS frame failed\n");
539 rconf
->malformed_responses
++;
543 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
544 HOSTAPD_LEVEL_DEBUG
, "Received RADIUS message");
546 radius_msg_dump(msg
);
548 switch (msg
->hdr
->code
) {
549 case RADIUS_CODE_ACCESS_ACCEPT
:
550 rconf
->access_accepts
++;
552 case RADIUS_CODE_ACCESS_REJECT
:
553 rconf
->access_rejects
++;
555 case RADIUS_CODE_ACCESS_CHALLENGE
:
556 rconf
->access_challenges
++;
558 case RADIUS_CODE_ACCOUNTING_RESPONSE
:
566 /* TODO: also match by src addr:port of the packet when using
567 * alternative RADIUS servers (?) */
568 if ((req
->msg_type
== msg_type
||
569 (req
->msg_type
== RADIUS_ACCT_INTERIM
&&
570 msg_type
== RADIUS_ACCT
)) &&
571 req
->msg
->hdr
->identifier
== msg
->hdr
->identifier
)
579 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
581 "No matching RADIUS request found (type=%d "
582 "id=%d) - dropping packet",
583 msg_type
, msg
->hdr
->identifier
);
587 gettimeofday(&tv
, NULL
);
588 roundtrip
= (tv
.tv_sec
- req
->last_attempt
.tv_sec
) * 100 +
589 (tv
.tv_usec
- req
->last_attempt
.tv_usec
) / 10000;
590 hostapd_logger(radius
->ctx
, req
->addr
, HOSTAPD_MODULE_RADIUS
,
592 "Received RADIUS packet matched with a pending "
593 "request, round trip time %d.%02d sec",
594 roundtrip
/ 100, roundtrip
% 100);
595 rconf
->round_trip_time
= roundtrip
;
597 /* Remove ACKed RADIUS packet from retransmit list */
599 prev_req
->next
= req
->next
;
601 radius
->msgs
= req
->next
;
604 for (i
= 0; i
< num_handlers
; i
++) {
606 res
= handlers
[i
].handler(msg
, req
->msg
, req
->shared_secret
,
607 req
->shared_secret_len
,
610 case RADIUS_RX_PROCESSED
:
611 radius_msg_free(msg
);
614 case RADIUS_RX_QUEUED
:
615 radius_client_msg_free(req
);
617 case RADIUS_RX_INVALID_AUTHENTICATOR
:
618 invalid_authenticator
++;
620 case RADIUS_RX_UNKNOWN
:
621 /* continue with next handler */
626 if (invalid_authenticator
)
627 rconf
->bad_authenticators
++;
629 rconf
->unknown_types
++;
630 hostapd_logger(radius
->ctx
, req
->addr
, HOSTAPD_MODULE_RADIUS
,
631 HOSTAPD_LEVEL_DEBUG
, "No RADIUS RX handler found "
632 "(type=%d code=%d id=%d)%s - dropping packet",
633 msg_type
, msg
->hdr
->code
, msg
->hdr
->identifier
,
634 invalid_authenticator
? " [INVALID AUTHENTICATOR]" :
636 radius_client_msg_free(req
);
639 radius_msg_free(msg
);
644 u8
radius_client_get_id(struct radius_client_data
*radius
)
646 struct radius_msg_list
*entry
, *prev
, *remove
;
647 u8 id
= radius
->next_radius_identifier
++;
649 /* remove entries with matching id from retransmit list to avoid
650 * using new reply from the RADIUS server with an old request */
651 entry
= radius
->msgs
;
654 if (entry
->msg
->hdr
->identifier
== id
) {
655 hostapd_logger(radius
->ctx
, entry
->addr
,
656 HOSTAPD_MODULE_RADIUS
,
658 "Removing pending RADIUS message, "
659 "since its id (%d) is reused", id
);
661 prev
->next
= entry
->next
;
663 radius
->msgs
= entry
->next
;
672 radius_client_msg_free(remove
);
679 void radius_client_flush(struct radius_client_data
*radius
)
681 struct radius_msg_list
*entry
, *prev
;
686 eloop_cancel_timeout(radius_client_timer
, radius
, NULL
);
688 entry
= radius
->msgs
;
690 radius
->num_msgs
= 0;
694 radius_client_msg_free(prev
);
700 radius_change_server(struct radius_client_data
*radius
,
701 struct hostapd_radius_server
*nserv
,
702 struct hostapd_radius_server
*oserv
,
703 int sock
, int sock6
, int auth
)
705 struct sockaddr_in serv
;
707 struct sockaddr_in6 serv6
;
708 #endif /* CONFIG_IPV6 */
709 struct sockaddr
*addr
;
714 hostapd_logger(radius
->ctx
, NULL
, HOSTAPD_MODULE_RADIUS
,
717 auth
? "Authentication" : "Accounting",
718 hostapd_ip_txt(&nserv
->addr
, abuf
, sizeof(abuf
)),
721 if (!oserv
|| nserv
->shared_secret_len
!= oserv
->shared_secret_len
||
722 memcmp(nserv
->shared_secret
, oserv
->shared_secret
,
723 nserv
->shared_secret_len
) != 0) {
724 /* Pending RADIUS packets used different shared
725 * secret, so they would need to be modified. Could
726 * update all message authenticators and
727 * User-Passwords, etc. and retry with new server. For
728 * now, just drop all pending packets. */
729 radius_client_flush(radius
);
731 /* Reset retry counters for the new server */
732 struct radius_msg_list
*entry
;
733 entry
= radius
->msgs
;
735 entry
->next_try
= entry
->first_try
+
736 RADIUS_CLIENT_FIRST_WAIT
;
738 entry
->next_wait
= RADIUS_CLIENT_FIRST_WAIT
* 2;
742 eloop_cancel_timeout(radius_client_timer
, radius
,
744 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT
, 0,
745 radius_client_timer
, radius
,
750 switch (nserv
->addr
.af
) {
752 memset(&serv
, 0, sizeof(serv
));
753 serv
.sin_family
= AF_INET
;
754 serv
.sin_addr
.s_addr
= nserv
->addr
.u
.v4
.s_addr
;
755 serv
.sin_port
= htons(nserv
->port
);
756 addr
= (struct sockaddr
*) &serv
;
757 addrlen
= sizeof(serv
);
762 memset(&serv6
, 0, sizeof(serv6
));
763 serv6
.sin6_family
= AF_INET6
;
764 memcpy(&serv6
.sin6_addr
, &nserv
->addr
.u
.v6
,
765 sizeof(struct in6_addr
));
766 serv6
.sin6_port
= htons(nserv
->port
);
767 addr
= (struct sockaddr
*) &serv6
;
768 addrlen
= sizeof(serv6
);
771 #endif /* CONFIG_IPV6 */
776 if (connect(sel_sock
, addr
, addrlen
) < 0) {
777 perror("connect[radius]");
782 radius
->auth_sock
= sel_sock
;
784 radius
->acct_sock
= sel_sock
;
790 static void radius_retry_primary_timer(void *eloop_ctx
, void *timeout_ctx
)
792 struct radius_client_data
*radius
= eloop_ctx
;
793 struct hostapd_radius_servers
*conf
= radius
->conf
;
794 struct hostapd_radius_server
*oserv
;
796 if (radius
->auth_sock
>= 0 && conf
->auth_servers
&&
797 conf
->auth_server
!= conf
->auth_servers
) {
798 oserv
= conf
->auth_server
;
799 conf
->auth_server
= conf
->auth_servers
;
800 radius_change_server(radius
, conf
->auth_server
, oserv
,
801 radius
->auth_serv_sock
,
802 radius
->auth_serv_sock6
, 1);
805 if (radius
->acct_sock
>= 0 && conf
->acct_servers
&&
806 conf
->acct_server
!= conf
->acct_servers
) {
807 oserv
= conf
->acct_server
;
808 conf
->acct_server
= conf
->acct_servers
;
809 radius_change_server(radius
, conf
->acct_server
, oserv
,
810 radius
->acct_serv_sock
,
811 radius
->acct_serv_sock6
, 0);
814 if (conf
->retry_primary_interval
)
815 eloop_register_timeout(conf
->retry_primary_interval
, 0,
816 radius_retry_primary_timer
, radius
,
821 static int radius_client_init_auth(struct radius_client_data
*radius
)
823 struct hostapd_radius_servers
*conf
= radius
->conf
;
826 radius
->auth_serv_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
827 if (radius
->auth_serv_sock
< 0)
828 perror("socket[PF_INET,SOCK_DGRAM]");
833 radius
->auth_serv_sock6
= socket(PF_INET6
, SOCK_DGRAM
, 0);
834 if (radius
->auth_serv_sock6
< 0)
835 perror("socket[PF_INET6,SOCK_DGRAM]");
838 #endif /* CONFIG_IPV6 */
843 radius_change_server(radius
, conf
->auth_server
, NULL
,
844 radius
->auth_serv_sock
, radius
->auth_serv_sock6
,
847 if (radius
->auth_serv_sock
>= 0 &&
848 eloop_register_read_sock(radius
->auth_serv_sock
,
849 radius_client_receive
, radius
,
850 (void *) RADIUS_AUTH
)) {
851 printf("Could not register read socket for authentication "
857 if (radius
->auth_serv_sock6
>= 0 &&
858 eloop_register_read_sock(radius
->auth_serv_sock6
,
859 radius_client_receive
, radius
,
860 (void *) RADIUS_AUTH
)) {
861 printf("Could not register read socket for authentication "
865 #endif /* CONFIG_IPV6 */
871 static int radius_client_init_acct(struct radius_client_data
*radius
)
873 struct hostapd_radius_servers
*conf
= radius
->conf
;
876 radius
->acct_serv_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
877 if (radius
->acct_serv_sock
< 0)
878 perror("socket[PF_INET,SOCK_DGRAM]");
882 radius_change_server(radius
, conf
->acct_server
, NULL
,
883 radius
->acct_serv_sock
, radius
->acct_serv_sock6
,
886 if (radius
->acct_serv_sock
>= 0 &&
887 eloop_register_read_sock(radius
->acct_serv_sock
,
888 radius_client_receive
, radius
,
889 (void *) RADIUS_ACCT
)) {
890 printf("Could not register read socket for accounting "
896 if (radius
->acct_serv_sock6
>= 0 &&
897 eloop_register_read_sock(radius
->acct_serv_sock6
,
898 radius_client_receive
, radius
,
899 (void *) RADIUS_ACCT
)) {
900 printf("Could not register read socket for accounting "
904 #endif /* CONFIG_IPV6 */
910 struct radius_client_data
*
911 radius_client_init(void *ctx
, struct hostapd_radius_servers
*conf
)
913 struct radius_client_data
*radius
;
915 radius
= malloc(sizeof(struct radius_client_data
));
919 memset(radius
, 0, sizeof(struct radius_client_data
));
922 radius
->auth_serv_sock
= radius
->acct_serv_sock
=
923 radius
->auth_serv_sock6
= radius
->acct_serv_sock6
=
924 radius
->auth_sock
= radius
->acct_sock
= -1;
926 if (conf
->auth_server
&& radius_client_init_auth(radius
)) {
927 radius_client_deinit(radius
);
931 if (conf
->acct_server
&& radius_client_init_acct(radius
)) {
932 radius_client_deinit(radius
);
936 if (conf
->retry_primary_interval
)
937 eloop_register_timeout(conf
->retry_primary_interval
, 0,
938 radius_retry_primary_timer
, radius
,
945 void radius_client_deinit(struct radius_client_data
*radius
)
950 eloop_cancel_timeout(radius_retry_primary_timer
, radius
, NULL
);
952 radius_client_flush(radius
);
953 free(radius
->auth_handlers
);
954 free(radius
->acct_handlers
);
959 void radius_client_flush_auth(struct radius_client_data
*radius
, u8
*addr
)
961 struct radius_msg_list
*entry
, *prev
, *tmp
;
964 entry
= radius
->msgs
;
966 if (entry
->msg_type
== RADIUS_AUTH
&&
967 memcmp(entry
->addr
, addr
, ETH_ALEN
) == 0) {
968 hostapd_logger(radius
->ctx
, addr
,
969 HOSTAPD_MODULE_RADIUS
,
971 "Removing pending RADIUS authentication"
972 " message for removed client");
975 prev
->next
= entry
->next
;
977 radius
->msgs
= entry
->next
;
981 radius_client_msg_free(tmp
);
992 static int radius_client_dump_auth_server(char *buf
, size_t buflen
,
993 struct hostapd_radius_server
*serv
,
994 struct radius_client_data
*cli
)
997 struct radius_msg_list
*msg
;
1001 for (msg
= cli
->msgs
; msg
; msg
= msg
->next
) {
1002 if (msg
->msg_type
== RADIUS_AUTH
)
1007 return snprintf(buf
, buflen
,
1008 "radiusAuthServerIndex=%d\n"
1009 "radiusAuthServerAddress=%s\n"
1010 "radiusAuthClientServerPortNumber=%d\n"
1011 "radiusAuthClientRoundTripTime=%d\n"
1012 "radiusAuthClientAccessRequests=%u\n"
1013 "radiusAuthClientAccessRetransmissions=%u\n"
1014 "radiusAuthClientAccessAccepts=%u\n"
1015 "radiusAuthClientAccessRejects=%u\n"
1016 "radiusAuthClientAccessChallenges=%u\n"
1017 "radiusAuthClientMalformedAccessResponses=%u\n"
1018 "radiusAuthClientBadAuthenticators=%u\n"
1019 "radiusAuthClientPendingRequests=%u\n"
1020 "radiusAuthClientTimeouts=%u\n"
1021 "radiusAuthClientUnknownTypes=%u\n"
1022 "radiusAuthClientPacketsDropped=%u\n",
1024 hostapd_ip_txt(&serv
->addr
, abuf
, sizeof(abuf
)),
1026 serv
->round_trip_time
,
1028 serv
->retransmissions
,
1029 serv
->access_accepts
,
1030 serv
->access_rejects
,
1031 serv
->access_challenges
,
1032 serv
->malformed_responses
,
1033 serv
->bad_authenticators
,
1036 serv
->unknown_types
,
1037 serv
->packets_dropped
);
1041 static int radius_client_dump_acct_server(char *buf
, size_t buflen
,
1042 struct hostapd_radius_server
*serv
,
1043 struct radius_client_data
*cli
)
1046 struct radius_msg_list
*msg
;
1050 for (msg
= cli
->msgs
; msg
; msg
= msg
->next
) {
1051 if (msg
->msg_type
== RADIUS_ACCT
||
1052 msg
->msg_type
== RADIUS_ACCT_INTERIM
)
1057 return snprintf(buf
, buflen
,
1058 "radiusAccServerIndex=%d\n"
1059 "radiusAccServerAddress=%s\n"
1060 "radiusAccClientServerPortNumber=%d\n"
1061 "radiusAccClientRoundTripTime=%d\n"
1062 "radiusAccClientRequests=%u\n"
1063 "radiusAccClientRetransmissions=%u\n"
1064 "radiusAccClientResponses=%u\n"
1065 "radiusAccClientMalformedResponses=%u\n"
1066 "radiusAccClientBadAuthenticators=%u\n"
1067 "radiusAccClientPendingRequests=%u\n"
1068 "radiusAccClientTimeouts=%u\n"
1069 "radiusAccClientUnknownTypes=%u\n"
1070 "radiusAccClientPacketsDropped=%u\n",
1072 hostapd_ip_txt(&serv
->addr
, abuf
, sizeof(abuf
)),
1074 serv
->round_trip_time
,
1076 serv
->retransmissions
,
1078 serv
->malformed_responses
,
1079 serv
->bad_authenticators
,
1082 serv
->unknown_types
,
1083 serv
->packets_dropped
);
1087 int radius_client_get_mib(struct radius_client_data
*radius
, char *buf
,
1090 struct hostapd_radius_servers
*conf
= radius
->conf
;
1092 struct hostapd_radius_server
*serv
;
1095 if (conf
->auth_servers
) {
1096 for (i
= 0; i
< conf
->num_auth_servers
; i
++) {
1097 serv
= &conf
->auth_servers
[i
];
1098 count
+= radius_client_dump_auth_server(
1099 buf
+ count
, buflen
- count
, serv
,
1100 serv
== conf
->auth_server
?
1105 if (conf
->acct_servers
) {
1106 for (i
= 0; i
< conf
->num_acct_servers
; i
++) {
1107 serv
= &conf
->acct_servers
[i
];
1108 count
+= radius_client_dump_acct_server(
1109 buf
+ count
, buflen
- count
, serv
,
1110 serv
== conf
->acct_server
?