]> git.ipfire.org Git - thirdparty/strongswan.git/blobdiff - src/libcharon/plugins/eap_radius/eap_radius_plugin.c
Moved generic RADIUS protocol support to a dedicated libradius
[thirdparty/strongswan.git] / src / libcharon / plugins / eap_radius / eap_radius_plugin.c
index e544aaf3ec19cf818def86051fe015f30a7a2e4c..0caecc1ad31e9b1b716b8d7dca68a3270b1eb8fa 100644 (file)
@@ -19,8 +19,9 @@
 #include "eap_radius_accounting.h"
 #include "eap_radius_dae.h"
 #include "eap_radius_forward.h"
-#include "radius_client.h"
-#include "radius_server.h"
+
+#include <radius_client.h>
+#include <radius_server.h>
 
 #include <daemon.h>
 #include <threading/rwlock.h>
@@ -261,15 +262,43 @@ plugin_t *eap_radius_plugin_create()
 /**
  * See header
  */
-enumerator_t *eap_radius_create_server_enumerator()
+radius_client_t *eap_radius_create_client()
 {
        if (instance)
        {
+               enumerator_t *enumerator;
+               radius_server_t *server, *selected = NULL;
+               int current, best = -1;
+
                instance->lock->read_lock(instance->lock);
-               return enumerator_create_cleaner(
-                                       instance->servers->create_enumerator(instance->servers),
-                                       (void*)instance->lock->unlock, instance->lock);
+               enumerator = instance->servers->create_enumerator(instance->servers);
+               while (enumerator->enumerate(enumerator, &server))
+               {
+                       current = server->get_preference(server);
+                       if (current > best ||
+                               /* for two with equal preference, 50-50 chance */
+                               (current == best && random() % 2 == 0))
+                       {
+                               DBG2(DBG_CFG, "RADIUS server '%s' is candidate: %d",
+                                        server->get_name(server), current);
+                               best = current;
+                               DESTROY_IF(selected);
+                               selected = server->get_ref(server);
+                       }
+                       else
+                       {
+                               DBG2(DBG_CFG, "RADIUS server '%s' skipped: %d",
+                                        server->get_name(server), current);
+                       }
+               }
+               enumerator->destroy(enumerator);
+               instance->lock->unlock(instance->lock);
+
+               if (selected)
+               {
+                       return radius_client_create(selected);
+               }
        }
-       return enumerator_create_empty();
+       return NULL;
 }