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 ?