Initial commit

Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_diameap/diameap_plugins.c b/extensions/app_diameap/diameap_plugins.c
new file mode 100644
index 0000000..836c686
--- /dev/null
+++ b/extensions/app_diameap/diameap_plugins.c
@@ -0,0 +1,455 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTfORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************************************/
+
+#include "diameap_common.h"
+
+/********************************************/
+/*	Loading and initializing plug-ins		*/
+/********************************************/
+
+/* Add new plugin */
+int diameap_plugin_add(char * name, eap_type methodtype, u32 vendor,
+		char * filename, char * conffile)
+{
+	TRACE_ENTRY("%p %d %d %p %p", name, methodtype, vendor, filename, conffile);
+
+	/* Check the filename is valid */
+	CHECK_PARAMS(filename);
+
+	/* add new EAP method  in the list of plugins*/
+	{
+		struct plugin * plugin;
+		CHECK_MALLOC(plugin = malloc(sizeof(struct plugin)));
+		memset(plugin, 0, sizeof(struct plugin));
+		fd_list_init(&plugin->chain, plugin);
+		plugin->methodname = name;
+		plugin->methodtype = methodtype;
+		plugin->vendor = vendor;
+		plugin->pluginfile = filename;
+		plugin->conffile = conffile;
+		fd_list_insert_before(&plugins_list, &plugin->chain);
+	}
+
+	return 0;
+}
+
+/* Dump plugins list */
+void diameap_plugin_dump(void)
+{
+	struct fd_list * pl;
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		fd_log_debug("\t\t - %s plugin \t [Type: %i, Vendor: %i]  %sloaded", plugin->methodname,
+				plugin->methodtype,plugin->vendor, plugin->handler ? "" : "not ");
+	}
+}
+
+int diameap_plugin_get(u32 vendor, eap_type type, struct plugin ** getplugin)
+{
+	TRACE_ENTRY("%d %d %p",vendor,type,getplugin);
+	struct fd_list * pl;
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		if (plugin->methodtype == type && plugin->vendor == vendor)
+		{
+			*getplugin = plugin;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/* Load all method in the plugins list */
+int diameap_plugin_load(void)
+{
+
+	int ret;
+	struct fd_list * pl;
+
+	/* Loop on all plugins */
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		struct register_plugin * registerplugin;
+		int (*diameap_plugin_register)();
+
+		TRACE_DEBUG(FULL, "%sLoading EAP method plugin: %s",DIAMEAP_EXTENSION, plugin->methodname);
+
+		/* Load the method */
+		plugin->handler = dlopen(plugin->pluginfile, RTLD_LAZY | RTLD_GLOBAL);
+		if (plugin->handler == NULL)
+		{
+			TRACE_DEBUG(INFO, "%sLoading of plugin %s failed: %s",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		/* Defined register methods for this EAP method*/
+		diameap_plugin_register = (int(*)()) dlsym(plugin->handler,
+				"diameap_plugin_register");
+		if (!diameap_plugin_register)
+		{
+			TRACE_DEBUG(INFO,
+					"%s[%s plugin] Unable to register EAP method: %s.",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		if ((*diameap_plugin_register)() != 0)
+		{
+			TRACE_DEBUG(INFO,
+					"%s[%s plugin] Unable to register EAP method plugin",DIAMEAP_EXTENSION,plugin->methodname);
+		}
+
+		int (*diameap_plugin_objects)(struct register_plugin **);
+
+		diameap_plugin_objects = (int(*)(struct register_plugin **)) dlsym(
+				plugin->handler, "diameap_plugin_objects");
+		if (!diameap_plugin_objects)
+		{
+			TRACE_DEBUG(INFO,
+					"%s[%s plugin] Unable to resolve symbol of the plugin: %s",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		if ((*diameap_plugin_objects)(&registerplugin) != 0)
+		{
+
+			TRACE_DEBUG(
+					INFO,
+					"%s[%s plugin] Unable to get objects description from the plug-in: %s",DIAMEAP_EXTENSION,
+					plugin->methodname, dlerror());
+			return EINVAL;
+		}
+
+		/* eap_method_configure method */
+		if (registerplugin->configure)
+		{
+			plugin->eap_method_configure = (int(*)(char *)) dlsym(
+					plugin->handler, registerplugin->configure);
+			if (plugin->eap_method_configure == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_configure': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+			}
+		}
+		else
+		{
+			plugin->eap_method_configure = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_configure'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_init method */
+		if (registerplugin->init)
+		{
+			plugin->eap_method_init
+					= (int(*)(struct eap_state_machine *)) dlsym(
+							plugin->handler, registerplugin->init);
+			if (plugin->eap_method_init == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_init': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_init = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_init'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_initPickUp method */
+		if (registerplugin->initPickUp)
+		{
+			plugin->eap_method_initPickUp
+					= (int(*)(struct eap_state_machine *)) dlsym(
+							plugin->handler, registerplugin->initPickUp);
+		}
+		else
+		{
+			plugin->eap_method_initPickUp = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_initPickUp'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_buildReq method */
+		if (registerplugin->buildReq)
+		{
+			plugin->eap_method_buildReq = (int(*)(struct eap_state_machine *,
+					u8, struct eap_packet *)) dlsym(plugin->handler,
+					registerplugin->buildReq);
+			if (plugin->eap_method_buildReq == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_buildReq': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_buildReq = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_buildReq'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_getTimeout method */
+		if (registerplugin->getTimeout)
+		{
+			plugin->eap_method_getTimeout = (int(*)(struct eap_state_machine *,
+					int *)) dlsym(plugin->handler, registerplugin->getTimeout);
+			if (plugin->eap_method_getTimeout == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_getTimeout': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_getTimeout = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function  'eap_method_getTimeout'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_check method */
+		if (registerplugin->check)
+		{
+			plugin->eap_method_check = (boolean(*)(struct eap_state_machine *,
+					struct eap_packet*)) dlsym(plugin->handler,
+					registerplugin->check);
+			if (plugin->eap_method_check == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_check': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_check = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_check'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_process method */
+		if (registerplugin->process)
+		{
+			plugin->eap_method_process = (int(*)(struct eap_state_machine *,
+					struct eap_packet*)) dlsym(plugin->handler,
+					registerplugin->process);
+			if (plugin->eap_method_process == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_process': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_process = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_process'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_isDone method */
+		if (registerplugin->isDone)
+		{
+			plugin->eap_method_isDone
+					= (boolean(*)(struct eap_state_machine *)) dlsym(
+							plugin->handler, registerplugin->isDone);
+			if (plugin->eap_method_isDone == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_isDone': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_isDone = NULL;
+			TRACE_DEBUG(INFO,"%s[%s plugin] Unavailable function 'eap_method_isDone'",DIAMEAP_EXTENSION, plugin->methodname);
+			return EINVAL;
+		}
+
+		/* eap_method_getKey method */
+		if (registerplugin->getKey)
+		{
+			plugin->eap_method_getKey = (int(*)(struct eap_state_machine *,
+					u8**, int*,u8**, int*)) dlsym(plugin->handler, registerplugin->getKey);
+			if (plugin->eap_method_getKey == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_getKey': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_getKey = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_getKey'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_unregister method */
+		if (registerplugin->unregister)
+		{
+			plugin->eap_method_unregister = (void(*)(void)) dlsym(
+					plugin->handler, registerplugin->unregister);
+			if (plugin->eap_method_unregister == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_unregister': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_unregister = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_unregister'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		/* eap_method_datafree method */
+		if (registerplugin->datafree)
+		{
+			plugin->eap_method_free = (void(*)(void *)) dlsym(plugin->handler,
+					registerplugin->datafree);
+			if (plugin->eap_method_free == NULL)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to resolve symbol for 'eap_method_datafree': %s",DIAMEAP_EXTENSION,
+						plugin->methodname, dlerror());
+				return EINVAL;
+			}
+		}
+		else
+		{
+			plugin->eap_method_free = NULL;
+			TRACE_DEBUG(FULL+1,"%s[%s plugin] Unavailable function 'eap_method_datafree'",DIAMEAP_EXTENSION, plugin->methodname);
+		}
+
+		if (plugin->eap_method_configure != NULL)
+		{
+			/* call the configuration method */
+			ret = (*plugin->eap_method_configure)(plugin->conffile);
+			if (ret != 0)
+			{
+				TRACE_DEBUG(
+						INFO,
+						"%s[%s plugin] Unable to configure the plugin",DIAMEAP_EXTENSION,
+						plugin->methodname);
+				return ret;
+			}
+		}
+
+		TRACE_DEBUG(FULL, "%s[%s plugin] Loaded successfully.",DIAMEAP_EXTENSION,
+				plugin->methodname);
+
+		/* load next method */
+	}
+
+	return 0;
+}
+
+boolean diameap_plugin_exist(u32 vendor, eap_type type)
+{
+
+	TRACE_ENTRY("%d %d",vendor,type);
+	struct fd_list * pl;
+
+	for (pl = plugins_list.next; pl != &plugins_list; pl = pl->next)
+	{
+		struct plugin * plugin = (struct plugin *) pl;
+		if (plugin->methodtype == type && plugin->vendor == vendor)
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+int diameap_plugin_unload(void)
+{
+
+	while (!FD_IS_LIST_EMPTY(&plugins_list))
+	{
+		struct fd_list * plugin = plugins_list.next;
+		struct plugin * item = (struct plugin *) plugin;
+
+		fd_list_unlink(plugin);
+
+		if (item->eap_method_unregister != NULL)
+		{
+			(*item->eap_method_unregister)();
+		}
+
+		if (item->handler)
+		{
+			if (dlclose(item->handler) != 0)
+			{
+				TRACE_DEBUG (INFO, "%sFail to unload plugin %s : %s",DIAMEAP_EXTENSION, item->methodname, dlerror());
+			}
+		}
+
+		free(item->conffile);
+		free(item->pluginfile);
+		free(item);
+	}
+	return 0;
+}