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;
671 radius_client_msg_free(remove);
678 void radius_client_flush(struct radius_client_data *radius)
680 struct radius_msg_list *entry, *prev;
685 eloop_cancel_timeout(radius_client_timer, radius, NULL);
687 entry = radius->msgs;
689 radius->num_msgs = 0;
693 radius_client_msg_free(prev);
699 radius_change_server(struct radius_client_data *radius,
700 struct hostapd_radius_server *nserv,
701 struct hostapd_radius_server *oserv,
702 int sock, int sock6, int auth)
704 struct sockaddr_in serv;
706 struct sockaddr_in6 serv6;
707 #endif /* CONFIG_IPV6 */
708 struct sockaddr *addr;
713 hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
716 auth ? "Authentication" : "Accounting",
717 hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
720 if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len ||
721 memcmp(nserv->shared_secret, oserv->shared_secret,
722 nserv->shared_secret_len) != 0) {
723 /* Pending RADIUS packets used different shared
724 * secret, so they would need to be modified. Could
725 * update all message authenticators and
726 * User-Passwords, etc. and retry with new server. For
727 * now, just drop all pending packets. */
728 radius_client_flush(radius);
730 /* Reset retry counters for the new server */
731 struct radius_msg_list *entry;
732 entry = radius->msgs;
734 entry->next_try = entry->first_try +
735 RADIUS_CLIENT_FIRST_WAIT;
737 entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
741 eloop_cancel_timeout(radius_client_timer, radius,
743 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
744 radius_client_timer, radius,
749 switch (nserv->addr.af) {
751 memset(&serv, 0, sizeof(serv));
752 serv.sin_family = AF_INET;
753 serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
754 serv.sin_port = htons(nserv->port);
755 addr = (struct sockaddr *) &serv;
756 addrlen = sizeof(serv);
761 memset(&serv6, 0, sizeof(serv6));
762 serv6.sin6_family = AF_INET6;
763 memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
764 sizeof(struct in6_addr));
765 serv6.sin6_port = htons(nserv->port);
766 addr = (struct sockaddr *) &serv6;
767 addrlen = sizeof(serv6);
770 #endif /* CONFIG_IPV6 */
775 if (connect(sel_sock, addr, addrlen) < 0) {
776 perror("connect[radius]");
781 radius->auth_sock = sel_sock;
783 radius->acct_sock = sel_sock;
789 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
791 struct radius_client_data *radius = eloop_ctx;
792 struct hostapd_radius_servers *conf = radius->conf;
793 struct hostapd_radius_server *oserv;
795 if (radius->auth_sock >= 0 && conf->auth_servers &&
796 conf->auth_server != conf->auth_servers) {
797 oserv = conf->auth_server;
798 conf->auth_server = conf->auth_servers;
799 radius_change_server(radius, conf->auth_server, oserv,
800 radius->auth_serv_sock,
801 radius->auth_serv_sock6, 1);
804 if (radius->acct_sock >= 0 && conf->acct_servers &&
805 conf->acct_server != conf->acct_servers) {
806 oserv = conf->acct_server;
807 conf->acct_server = conf->acct_servers;
808 radius_change_server(radius, conf->acct_server, oserv,
809 radius->acct_serv_sock,
810 radius->acct_serv_sock6, 0);
813 if (conf->retry_primary_interval)
814 eloop_register_timeout(conf->retry_primary_interval, 0,
815 radius_retry_primary_timer, radius,
820 static int radius_client_init_auth(struct radius_client_data *radius)
822 struct hostapd_radius_servers *conf = radius->conf;
825 radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
826 if (radius->auth_serv_sock < 0)
827 perror("socket[PF_INET,SOCK_DGRAM]");
832 radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
833 if (radius->auth_serv_sock6 < 0)
834 perror("socket[PF_INET6,SOCK_DGRAM]");
837 #endif /* CONFIG_IPV6 */
842 radius_change_server(radius, conf->auth_server, NULL,
843 radius->auth_serv_sock, radius->auth_serv_sock6,
846 if (radius->auth_serv_sock >= 0 &&
847 eloop_register_read_sock(radius->auth_serv_sock,
848 radius_client_receive, radius,
849 (void *) RADIUS_AUTH)) {
850 printf("Could not register read socket for authentication "
856 if (radius->auth_serv_sock6 >= 0 &&
857 eloop_register_read_sock(radius->auth_serv_sock6,
858 radius_client_receive, radius,
859 (void *) RADIUS_AUTH)) {
860 printf("Could not register read socket for authentication "
864 #endif /* CONFIG_IPV6 */
870 static int radius_client_init_acct(struct radius_client_data *radius)
872 struct hostapd_radius_servers *conf = radius->conf;
875 radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
876 if (radius->acct_serv_sock < 0)
877 perror("socket[PF_INET,SOCK_DGRAM]");
881 radius_change_server(radius, conf->acct_server, NULL,
882 radius->acct_serv_sock, radius->acct_serv_sock6,
885 if (radius->acct_serv_sock >= 0 &&
886 eloop_register_read_sock(radius->acct_serv_sock,
887 radius_client_receive, radius,
888 (void *) RADIUS_ACCT)) {
889 printf("Could not register read socket for accounting "
895 if (radius->acct_serv_sock6 >= 0 &&
896 eloop_register_read_sock(radius->acct_serv_sock6,
897 radius_client_receive, radius,
898 (void *) RADIUS_ACCT)) {
899 printf("Could not register read socket for accounting "
903 #endif /* CONFIG_IPV6 */
909 struct radius_client_data *
910 radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
912 struct radius_client_data *radius;
914 radius = malloc(sizeof(struct radius_client_data));
918 memset(radius, 0, sizeof(struct radius_client_data));
921 radius->auth_serv_sock = radius->acct_serv_sock =
922 radius->auth_serv_sock6 = radius->acct_serv_sock6 =
923 radius->auth_sock = radius->acct_sock = -1;
925 if (conf->auth_server && radius_client_init_auth(radius)) {
926 radius_client_deinit(radius);
930 if (conf->acct_server && radius_client_init_acct(radius)) {
931 radius_client_deinit(radius);
935 if (conf->retry_primary_interval)
936 eloop_register_timeout(conf->retry_primary_interval, 0,
937 radius_retry_primary_timer, radius,
944 void radius_client_deinit(struct radius_client_data *radius)
949 eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
951 radius_client_flush(radius);
952 free(radius->auth_handlers);
953 free(radius->acct_handlers);
958 void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr)
960 struct radius_msg_list *entry, *prev, *tmp;
963 entry = radius->msgs;
965 if (entry->msg_type == RADIUS_AUTH &&
966 memcmp(entry->addr, addr, ETH_ALEN) == 0) {
967 hostapd_logger(radius->ctx, addr,
968 HOSTAPD_MODULE_RADIUS,
970 "Removing pending RADIUS authentication"
971 " message for removed client");
974 prev->next = entry->next;
976 radius->msgs = entry->next;
980 radius_client_msg_free(tmp);
991 static int radius_client_dump_auth_server(char *buf, size_t buflen,
992 struct hostapd_radius_server *serv,
993 struct radius_client_data *cli)
996 struct radius_msg_list *msg;
1000 for (msg = cli->msgs; msg; msg = msg->next) {
1001 if (msg->msg_type == RADIUS_AUTH)
1006 return snprintf(buf, buflen,
1007 "radiusAuthServerIndex=%d\n"
1008 "radiusAuthServerAddress=%s\n"
1009 "radiusAuthClientServerPortNumber=%d\n"
1010 "radiusAuthClientRoundTripTime=%d\n"
1011 "radiusAuthClientAccessRequests=%u\n"
1012 "radiusAuthClientAccessRetransmissions=%u\n"
1013 "radiusAuthClientAccessAccepts=%u\n"
1014 "radiusAuthClientAccessRejects=%u\n"
1015 "radiusAuthClientAccessChallenges=%u\n"
1016 "radiusAuthClientMalformedAccessResponses=%u\n"
1017 "radiusAuthClientBadAuthenticators=%u\n"
1018 "radiusAuthClientPendingRequests=%u\n"
1019 "radiusAuthClientTimeouts=%u\n"
1020 "radiusAuthClientUnknownTypes=%u\n"
1021 "radiusAuthClientPacketsDropped=%u\n",
1023 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
1025 serv->round_trip_time,
1027 serv->retransmissions,
1028 serv->access_accepts,
1029 serv->access_rejects,
1030 serv->access_challenges,
1031 serv->malformed_responses,
1032 serv->bad_authenticators,
1035 serv->unknown_types,
1036 serv->packets_dropped);
1040 static int radius_client_dump_acct_server(char *buf, size_t buflen,
1041 struct hostapd_radius_server *serv,
1042 struct radius_client_data *cli)
1045 struct radius_msg_list *msg;
1049 for (msg = cli->msgs; msg; msg = msg->next) {
1050 if (msg->msg_type == RADIUS_ACCT ||
1051 msg->msg_type == RADIUS_ACCT_INTERIM)
1056 return snprintf(buf, buflen,
1057 "radiusAccServerIndex=%d\n"
1058 "radiusAccServerAddress=%s\n"
1059 "radiusAccClientServerPortNumber=%d\n"
1060 "radiusAccClientRoundTripTime=%d\n"
1061 "radiusAccClientRequests=%u\n"
1062 "radiusAccClientRetransmissions=%u\n"
1063 "radiusAccClientResponses=%u\n"
1064 "radiusAccClientMalformedResponses=%u\n"
1065 "radiusAccClientBadAuthenticators=%u\n"
1066 "radiusAccClientPendingRequests=%u\n"
1067 "radiusAccClientTimeouts=%u\n"
1068 "radiusAccClientUnknownTypes=%u\n"
1069 "radiusAccClientPacketsDropped=%u\n",
1071 hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
1073 serv->round_trip_time,
1075 serv->retransmissions,
1077 serv->malformed_responses,
1078 serv->bad_authenticators,
1081 serv->unknown_types,
1082 serv->packets_dropped);
1086 int radius_client_get_mib(struct radius_client_data *radius, char *buf,
1089 struct hostapd_radius_servers *conf = radius->conf;
1091 struct hostapd_radius_server *serv;
1094 if (conf->auth_servers) {
1095 for (i = 0; i < conf->num_auth_servers; i++) {
1096 serv = &conf->auth_servers[i];
1097 count += radius_client_dump_auth_server(
1098 buf + count, buflen - count, serv,
1099 serv == conf->auth_server ?
1104 if (conf->acct_servers) {
1105 for (i = 0; i < conf->num_acct_servers; i++) {
1106 serv = &conf->acct_servers[i];
1107 count += radius_client_dump_acct_server(
1108 buf + count, buflen - count, serv,
1109 serv == conf->acct_server ?