]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/radius_client.c
This commit was generated by cvs2svn to compensate for changes in r154182,
[FreeBSD/FreeBSD.git] / contrib / wpa_supplicant / radius_client.c
1 /*
2  * Host AP (software wireless LAN access point) user space daemon for
3  * Host AP kernel driver / RADIUS client / modified for eapol_test
4  * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5  *
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. See README and COPYING for
9  * more details.
10  */
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <netinet/in.h>
16 #include <string.h>
17 #include <time.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <arpa/inet.h>
21
22 #include "common.h"
23 #include "wpa.h"
24 #include "config_ssid.h"
25 #include "wpa_supplicant.h"
26 #include "wpa_supplicant_i.h"
27 #include "radius.h"
28 #include "radius_client.h"
29 #include "eloop.h"
30 #include "l2_packet.h"
31
32 #include "wpa_supplicant.h"
33 #define hostapd_logger(h, a, m, l, t...) wpa_printf(MSG_DEBUG, t)
34 #define HOSTAPD_DEBUG(l, a...) wpa_printf(MSG_DEBUG, a)
35 #define HOSTAPD_DEBUG_COND(l) 1
36
37 /* Defaults for RADIUS retransmit values (exponential backoff) */
38 #define RADIUS_CLIENT_FIRST_WAIT 1 /* seconds */
39 #define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
40 #define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
41                                       * before entry is removed from retransmit
42                                       * list */
43 #define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit
44                                       * list (oldest will be removed, if this
45                                       * limit is exceeded) */
46 #define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this
47                                       * many failed retry attempts */
48
49
50
51 static int
52 radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv,
53                      struct hostapd_radius_server *oserv,
54                      int sock, int auth);
55
56
57 static void radius_client_msg_free(struct radius_msg_list *req)
58 {
59         radius_msg_free(req->msg);
60         free(req->msg);
61         free(req);
62 }
63
64
65 int radius_client_register(struct wpa_supplicant *wpa_s, RadiusType msg_type,
66                            RadiusRxResult (*handler)(struct wpa_supplicant *wpa_s,
67                                                      struct radius_msg *msg,
68                                                      struct radius_msg *req,
69                                                      u8 *shared_secret,
70                                                      size_t shared_secret_len,
71                                                      void *data),
72                            void *data)
73 {
74         struct radius_rx_handler **handlers, *newh;
75         size_t *num;
76
77         if (msg_type == RADIUS_ACCT) {
78                 handlers = &wpa_s->radius->acct_handlers;
79                 num = &wpa_s->radius->num_acct_handlers;
80         } else {
81                 handlers = &wpa_s->radius->auth_handlers;
82                 num = &wpa_s->radius->num_auth_handlers;
83         }
84
85         newh = (struct radius_rx_handler *)
86                 realloc(*handlers,
87                         (*num + 1) * sizeof(struct radius_rx_handler));
88         if (newh == NULL)
89                 return -1;
90
91         newh[*num].handler = handler;
92         newh[*num].data = data;
93         (*num)++;
94         *handlers = newh;
95
96         return 0;
97 }
98
99
100 static int radius_client_retransmit(struct wpa_supplicant *wpa_s,
101                                     struct radius_msg_list *entry, time_t now)
102 {
103         int s;
104
105         if (entry->msg_type == RADIUS_ACCT ||
106             entry->msg_type == RADIUS_ACCT_INTERIM)
107                 s = wpa_s->radius->acct_serv_sock;
108         else
109                 s = wpa_s->radius->auth_serv_sock;
110
111         /* retransmit; remove entry if too many attempts */
112         entry->attempts++;
113         HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Resending RADIUS message (id=%d)"
114                       "\n", entry->msg->hdr->identifier);
115
116         if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
117                 perror("send[RADIUS]");
118
119         entry->next_try = now + entry->next_wait;
120         entry->next_wait *= 2;
121         if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
122                 entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
123         if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
124                 printf("Removing un-ACKed RADIUS message due to too many "
125                        "failed retransmit attempts\n");
126                 return 1;
127         }
128
129         return 0;
130 }
131
132
133 static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
134 {
135         struct wpa_supplicant *wpa_s = eloop_ctx;
136         time_t now, first;
137         struct radius_msg_list *entry, *prev, *tmp;
138         int auth_failover = 0, acct_failover = 0;
139
140         entry = wpa_s->radius->msgs;
141         if (!entry)
142                 return;
143
144         time(&now);
145         first = 0;
146
147         prev = NULL;
148         while (entry) {
149                 if (now >= entry->next_try &&
150                     radius_client_retransmit(wpa_s, entry, now)) {
151                         if (prev)
152                                 prev->next = entry->next;
153                         else
154                                 wpa_s->radius->msgs = entry->next;
155
156                         tmp = entry;
157                         entry = entry->next;
158                         radius_client_msg_free(tmp);
159                         wpa_s->radius->num_msgs--;
160                         continue;
161                 }
162
163                 if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) {
164                         if (entry->msg_type == RADIUS_ACCT ||
165                             entry->msg_type == RADIUS_ACCT_INTERIM)
166                                 acct_failover++;
167                         else
168                                 auth_failover++;
169                 }
170
171                 if (first == 0 || entry->next_try < first)
172                         first = entry->next_try;
173
174                 prev = entry;
175                 entry = entry->next;
176         }
177
178         if (wpa_s->radius->msgs) {
179                 if (first < now)
180                         first = now;
181                 eloop_register_timeout(first - now, 0,
182                                        radius_client_timer, wpa_s, NULL);
183         }
184
185         if (auth_failover && wpa_s->num_auth_servers > 1) {
186                 struct hostapd_radius_server *next, *old;
187                 old = wpa_s->auth_server;
188                 hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS,
189                                HOSTAPD_LEVEL_NOTICE,
190                                "No response from Authentication server "
191                                "%s:%d - failover",
192                                inet_ntoa(old->addr), old->port);
193
194                 next = old + 1;
195                 if (next > &(wpa_s->auth_servers
196                              [wpa_s->num_auth_servers - 1]))
197                         next = wpa_s->auth_servers;
198                 wpa_s->auth_server = next;
199                 radius_change_server(wpa_s, next, old,
200                                      wpa_s->radius->auth_serv_sock, 1);
201         }
202
203         if (acct_failover && wpa_s->num_acct_servers > 1) {
204                 struct hostapd_radius_server *next, *old;
205                 old = wpa_s->acct_server;
206                 hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS,
207                                HOSTAPD_LEVEL_NOTICE,
208                                "No response from Accounting server "
209                                "%s:%d - failover",
210                                inet_ntoa(old->addr), old->port);
211                 next = old + 1;
212                 if (next > &wpa_s->acct_servers
213                     [wpa_s->num_acct_servers - 1])
214                         next = wpa_s->acct_servers;
215                 wpa_s->acct_server = next;
216                 radius_change_server(wpa_s, next, old,
217                                      wpa_s->radius->acct_serv_sock, 0);
218         }
219 }
220
221
222 static void radius_client_list_add(struct wpa_supplicant *wpa_s, struct radius_msg *msg,
223                                    RadiusType msg_type, u8 *shared_secret,
224                                    size_t shared_secret_len, u8 *addr)
225 {
226         struct radius_msg_list *entry, *prev;
227
228         if (eloop_terminated()) {
229                 /* No point in adding entries to retransmit queue since event
230                  * loop has already been terminated. */
231                 radius_msg_free(msg);
232                 free(msg);
233                 return;
234         }
235
236         entry = malloc(sizeof(*entry));
237         if (entry == NULL) {
238                 printf("Failed to add RADIUS packet into retransmit list\n");
239                 radius_msg_free(msg);
240                 free(msg);
241                 return;
242         }
243
244         memset(entry, 0, sizeof(*entry));
245         if (addr)
246                 memcpy(entry->addr, addr, ETH_ALEN);
247         entry->msg = msg;
248         entry->msg_type = msg_type;
249         entry->shared_secret = shared_secret;
250         entry->shared_secret_len = shared_secret_len;
251         time(&entry->first_try);
252         entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
253         entry->attempts = 1;
254         entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
255
256         if (!wpa_s->radius->msgs)
257                 eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
258                                        radius_client_timer, wpa_s, NULL);
259
260         entry->next = wpa_s->radius->msgs;
261         wpa_s->radius->msgs = entry;
262
263         if (wpa_s->radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) {
264                 printf("Removing the oldest un-ACKed RADIUS packet due to "
265                        "retransmit list limits.\n");
266                 prev = NULL;
267                 while (entry->next) {
268                         prev = entry;
269                         entry = entry->next;
270                 }
271                 if (prev) {
272                         prev->next = NULL;
273                         radius_client_msg_free(entry);
274                 }
275         } else
276                 wpa_s->radius->num_msgs++;
277 }
278
279
280 static void radius_client_list_del(struct wpa_supplicant *wpa_s,
281                                    RadiusType msg_type, u8 *addr)
282 {
283         struct radius_msg_list *entry, *prev, *tmp;
284
285         if (addr == NULL)
286                 return;
287
288         entry = wpa_s->radius->msgs;
289         prev = NULL;
290         while (entry) {
291                 if (entry->msg_type == msg_type &&
292                     memcmp(entry->addr, addr, ETH_ALEN) == 0) {
293                         if (prev)
294                                 prev->next = entry->next;
295                         else
296                                 wpa_s->radius->msgs = entry->next;
297                         tmp = entry;
298                         entry = entry->next;
299                         HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
300                                       "Removing matching RADIUS message for "
301                                       MACSTR "\n", MAC2STR(addr));
302                         radius_client_msg_free(tmp);
303                         wpa_s->radius->num_msgs--;
304                         continue;
305                 }
306                 prev = entry;
307                 entry = entry->next;
308         }
309 }
310
311
312 int radius_client_send(struct wpa_supplicant *wpa_s, struct radius_msg *msg,
313                        RadiusType msg_type, u8 *addr)
314 {
315         u8 *shared_secret;
316         size_t shared_secret_len;
317         char *name;
318         int s, res;
319
320         if (msg_type == RADIUS_ACCT_INTERIM) {
321                 /* Remove any pending interim acct update for the same STA. */
322                 radius_client_list_del(wpa_s, msg_type, addr);
323         }
324
325         if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
326                 shared_secret = wpa_s->acct_server->shared_secret;
327                 shared_secret_len = wpa_s->acct_server->shared_secret_len;
328                 radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
329                 name = "accounting";
330                 s = wpa_s->radius->acct_serv_sock;
331         } else {
332                 shared_secret = wpa_s->auth_server->shared_secret;
333                 shared_secret_len = wpa_s->auth_server->shared_secret_len;
334                 radius_msg_finish(msg, shared_secret, shared_secret_len);
335                 name = "authentication";
336                 s = wpa_s->radius->auth_serv_sock;
337         }
338
339         HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
340                       "Sending RADIUS message to %s server\n", name);
341         if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
342                 radius_msg_dump(msg);
343
344         res = send(s, msg->buf, msg->buf_used, 0);
345         if (res < 0)
346                 perror("send[RADIUS]");
347
348         radius_client_list_add(wpa_s, msg, msg_type, shared_secret,
349                                shared_secret_len, addr);
350
351         return res;
352 }
353
354
355 static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
356 {
357         struct wpa_supplicant *wpa_s = (struct wpa_supplicant *) eloop_ctx;
358         RadiusType msg_type = (RadiusType) sock_ctx;
359         int len, i;
360         unsigned char buf[3000];
361         struct radius_msg *msg;
362         struct radius_rx_handler *handlers;
363         size_t num_handlers;
364         struct radius_msg_list *req, *prev_req;
365
366         len = recv(sock, buf, sizeof(buf), 0);
367         if (len < 0) {
368                 perror("recv[RADIUS]");
369                 return;
370         }
371         HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
372                       "Received %d bytes from RADIUS server\n", len);
373         if (len == sizeof(buf)) {
374                 printf("Possibly too long UDP frame for our buffer - "
375                        "dropping it\n");
376                 return;
377         }
378
379         msg = radius_msg_parse(buf, len);
380         if (msg == NULL) {
381                 printf("Parsing incoming RADIUS frame failed\n");
382                 return;
383         }
384
385         HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
386                       "Received RADIUS message\n");
387         if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
388                 radius_msg_dump(msg);
389
390         if (msg_type == RADIUS_ACCT) {
391                 handlers = wpa_s->radius->acct_handlers;
392                 num_handlers = wpa_s->radius->num_acct_handlers;
393         } else {
394                 handlers = wpa_s->radius->auth_handlers;
395                 num_handlers = wpa_s->radius->num_auth_handlers;
396         }
397
398         prev_req = NULL;
399         req = wpa_s->radius->msgs;
400         while (req) {
401                 /* TODO: also match by src addr:port of the packet when using
402                  * alternative RADIUS servers (?) */
403                 if ((req->msg_type == msg_type ||
404                      (req->msg_type == RADIUS_ACCT_INTERIM &&
405                       msg_type == RADIUS_ACCT)) &&
406                     req->msg->hdr->identifier == msg->hdr->identifier)
407                         break;
408
409                 prev_req = req;
410                 req = req->next;
411         }
412
413         if (req == NULL) {
414                 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
415                               "No matching RADIUS request found (type=%d "
416                               "id=%d) - dropping packet\n",
417                               msg_type, msg->hdr->identifier);
418                 goto fail;
419         }
420
421         /* Remove ACKed RADIUS packet from retransmit list */
422         if (prev_req)
423                 prev_req->next = req->next;
424         else
425                 wpa_s->radius->msgs = req->next;
426         wpa_s->radius->num_msgs--;
427
428         for (i = 0; i < num_handlers; i++) {
429                 RadiusRxResult res;
430                 res = handlers[i].handler(wpa_s, msg, req->msg,
431                                           req->shared_secret,
432                                           req->shared_secret_len,
433                                           handlers[i].data);
434                 switch (res) {
435                 case RADIUS_RX_PROCESSED:
436                         radius_msg_free(msg);
437                         free(msg);
438                         /* continue */
439                 case RADIUS_RX_QUEUED:
440                         radius_client_msg_free(req);
441                         return;
442                 case RADIUS_RX_UNKNOWN:
443                         /* continue with next handler */
444                         break;
445                 }
446         }
447
448         printf("No RADIUS RX handler found (type=%d code=%d id=%d) - dropping "
449                "packet\n", msg_type, msg->hdr->code, msg->hdr->identifier);
450         radius_client_msg_free(req);
451
452  fail:
453         radius_msg_free(msg);
454         free(msg);
455 }
456
457
458 u8 radius_client_get_id(struct wpa_supplicant *wpa_s)
459 {
460         struct radius_msg_list *entry, *prev, *remove;
461         u8 id = wpa_s->radius->next_radius_identifier++;
462
463         /* remove entries with matching id from retransmit list to avoid
464          * using new reply from the RADIUS server with an old request */
465         entry = wpa_s->radius->msgs;
466         prev = NULL;
467         while (entry) {
468                 if (entry->msg->hdr->identifier == id) {
469                         HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
470                                       "Removing pending RADIUS message, since "
471                                       "its id (%d) is reused\n", id);
472                         if (prev)
473                                 prev->next = entry->next;
474                         else
475                                 wpa_s->radius->msgs = entry->next;
476                         remove = entry;
477                 } else
478                         remove = NULL;
479                 prev = entry;
480                 entry = entry->next;
481
482                 if (remove)
483                         radius_client_msg_free(remove);
484         }
485
486         return id;
487 }
488
489
490 void radius_client_flush(struct wpa_supplicant *wpa_s)
491 {
492         struct radius_msg_list *entry, *prev;
493
494         if (!wpa_s->radius)
495                 return;
496
497         eloop_cancel_timeout(radius_client_timer, wpa_s, NULL);
498
499         entry = wpa_s->radius->msgs;
500         wpa_s->radius->msgs = NULL;
501         wpa_s->radius->num_msgs = 0;
502         while (entry) {
503                 prev = entry;
504                 entry = entry->next;
505                 radius_client_msg_free(prev);
506         }
507 }
508
509
510 static int
511 radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv,
512                      struct hostapd_radius_server *oserv,
513                      int sock, int auth)
514 {
515         struct sockaddr_in serv;
516
517         hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO,
518                        "%s server %s:%d",
519                        auth ? "Authentication" : "Accounting",
520                        inet_ntoa(nserv->addr), nserv->port);
521
522         if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len ||
523             memcmp(nserv->shared_secret, oserv->shared_secret,
524                    nserv->shared_secret_len) != 0) {
525                 /* Pending RADIUS packets used different shared
526                  * secret, so they would need to be modified. Could
527                  * update all message authenticators and
528                  * User-Passwords, etc. and retry with new server. For
529                  * now, just drop all pending packets. */
530                 radius_client_flush(wpa_s);
531         } else {
532                 /* Reset retry counters for the new server */
533                 struct radius_msg_list *entry;
534                 entry = wpa_s->radius->msgs;
535                 while (entry) {
536                         entry->next_try = entry->first_try +
537                                 RADIUS_CLIENT_FIRST_WAIT;
538                         entry->attempts = 0;
539                         entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
540                         entry = entry->next;
541                 }
542                 if (wpa_s->radius->msgs) {
543                         eloop_cancel_timeout(radius_client_timer, wpa_s, NULL);
544                         eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
545                                                radius_client_timer, wpa_s,
546                                                NULL);
547                 }
548         }
549
550         memset(&serv, 0, sizeof(serv));
551         serv.sin_family = AF_INET;
552         serv.sin_addr.s_addr = nserv->addr.s_addr;
553         serv.sin_port = htons(nserv->port);
554
555         if (connect(sock, (struct sockaddr *) &serv, sizeof(serv)) < 0) {
556                 perror("connect[radius]");
557                 return -1;
558         }
559
560         return 0;
561 }
562
563
564 static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
565 {
566         struct wpa_supplicant *wpa_s = eloop_ctx;
567         struct hostapd_radius_server *oserv;
568
569         if (wpa_s->radius->auth_serv_sock >= 0 && wpa_s->auth_servers &&
570             wpa_s->auth_server != wpa_s->auth_servers) {
571                 oserv = wpa_s->auth_server;
572                 wpa_s->auth_server = wpa_s->auth_servers;
573                 radius_change_server(wpa_s, wpa_s->auth_server, oserv,
574                                      wpa_s->radius->auth_serv_sock, 1);
575         }
576
577         if (wpa_s->radius->acct_serv_sock >= 0 && wpa_s->acct_servers &&
578             wpa_s->acct_server != wpa_s->acct_servers) {
579                 oserv = wpa_s->acct_server;
580                 wpa_s->acct_server = wpa_s->acct_servers;
581                 radius_change_server(wpa_s, wpa_s->acct_server, oserv,
582                                      wpa_s->radius->acct_serv_sock, 0);
583         }
584
585         if (wpa_s->radius_retry_primary_interval)
586                 eloop_register_timeout(wpa_s->
587                                        radius_retry_primary_interval, 0,
588                                        radius_retry_primary_timer, wpa_s, NULL);
589 }
590
591
592 static int radius_client_init_auth(struct wpa_supplicant *wpa_s)
593 {
594         wpa_s->radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
595         if (wpa_s->radius->auth_serv_sock < 0) {
596                 perror("socket[PF_INET,SOCK_DGRAM]");
597                 return -1;
598         }
599
600         radius_change_server(wpa_s, wpa_s->auth_server, NULL,
601                              wpa_s->radius->auth_serv_sock, 1);
602
603         if (eloop_register_read_sock(wpa_s->radius->auth_serv_sock,
604                                      radius_client_receive, wpa_s,
605                                      (void *) RADIUS_AUTH)) {
606                 printf("Could not register read socket for authentication "
607                        "server\n");
608                 return -1;
609         }
610
611         return 0;
612 }
613
614
615 static int radius_client_init_acct(struct wpa_supplicant *wpa_s)
616 {
617         wpa_s->radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0);
618         if (wpa_s->radius->acct_serv_sock < 0) {
619                 perror("socket[PF_INET,SOCK_DGRAM]");
620                 return -1;
621         }
622
623         radius_change_server(wpa_s, wpa_s->acct_server, NULL,
624                              wpa_s->radius->acct_serv_sock, 0);
625
626         if (eloop_register_read_sock(wpa_s->radius->acct_serv_sock,
627                                      radius_client_receive, wpa_s,
628                                      (void *) RADIUS_ACCT)) {
629                 printf("Could not register read socket for accounting "
630                        "server\n");
631                 return -1;
632         }
633
634         return 0;
635 }
636
637
638 int radius_client_init(struct wpa_supplicant *wpa_s)
639 {
640         wpa_s->radius = malloc(sizeof(struct radius_client_data));
641         if (wpa_s->radius == NULL)
642                 return -1;
643
644         memset(wpa_s->radius, 0, sizeof(struct radius_client_data));
645         wpa_s->radius->auth_serv_sock = wpa_s->radius->acct_serv_sock = -1;
646
647         if (wpa_s->auth_server && radius_client_init_auth(wpa_s))
648                 return -1;
649
650         if (wpa_s->acct_server && radius_client_init_acct(wpa_s))
651                 return -1;
652
653         if (wpa_s->radius_retry_primary_interval)
654                 eloop_register_timeout(wpa_s->radius_retry_primary_interval, 0,
655                                        radius_retry_primary_timer, wpa_s,
656                                        NULL);
657
658         return 0;
659 }
660
661
662 void radius_client_deinit(struct wpa_supplicant *wpa_s)
663 {
664         if (!wpa_s->radius)
665                 return;
666
667         eloop_cancel_timeout(radius_retry_primary_timer, wpa_s, NULL);
668
669         radius_client_flush(wpa_s);
670         free(wpa_s->radius->auth_handlers);
671         free(wpa_s->radius->acct_handlers);
672         free(wpa_s->radius);
673         wpa_s->radius = NULL;
674 }