$search
00001 /* 00002 * EAP peer: Method registration 00003 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #ifdef CONFIG_DYNAMIC_EAP_METHODS 00017 #include <dlfcn.h> 00018 #endif /* CONFIG_DYNAMIC_EAP_METHODS */ 00019 00020 #include "common.h" 00021 #include "eap_i.h" 00022 #include "eap_methods.h" 00023 00024 00025 static struct eap_method *eap_methods = NULL; 00026 00027 00034 const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method) 00035 { 00036 struct eap_method *m; 00037 for (m = eap_methods; m; m = m->next) { 00038 if (m->vendor == vendor && m->method == method) 00039 return m; 00040 } 00041 return NULL; 00042 } 00043 00044 00054 EapType eap_peer_get_type(const char *name, int *vendor) 00055 { 00056 struct eap_method *m; 00057 for (m = eap_methods; m; m = m->next) { 00058 if (os_strcmp(m->name, name) == 0) { 00059 *vendor = m->vendor; 00060 return m->method; 00061 } 00062 } 00063 *vendor = EAP_VENDOR_IETF; 00064 return EAP_TYPE_NONE; 00065 } 00066 00067 00077 const char * eap_get_name(int vendor, EapType type) 00078 { 00079 struct eap_method *m; 00080 for (m = eap_methods; m; m = m->next) { 00081 if (m->vendor == vendor && m->method == type) 00082 return m->name; 00083 } 00084 return NULL; 00085 } 00086 00087 00095 size_t eap_get_names(char *buf, size_t buflen) 00096 { 00097 char *pos, *end; 00098 struct eap_method *m; 00099 int ret; 00100 00101 if (buflen == 0) 00102 return 0; 00103 00104 pos = buf; 00105 end = pos + buflen; 00106 00107 for (m = eap_methods; m; m = m->next) { 00108 ret = os_snprintf(pos, end - pos, "%s%s", 00109 m == eap_methods ? "" : " ", m->name); 00110 if (ret < 0 || ret >= end - pos) 00111 break; 00112 pos += ret; 00113 } 00114 buf[buflen - 1] = '\0'; 00115 00116 return pos - buf; 00117 } 00118 00119 00130 char ** eap_get_names_as_string_array(size_t *num) 00131 { 00132 struct eap_method *m; 00133 size_t array_len = 0; 00134 char **array; 00135 int i = 0, j; 00136 00137 for (m = eap_methods; m; m = m->next) 00138 array_len++; 00139 00140 array = os_zalloc(sizeof(char *) * (array_len + 1)); 00141 if (array == NULL) 00142 return NULL; 00143 00144 for (m = eap_methods; m; m = m->next) { 00145 array[i++] = os_strdup(m->name); 00146 if (array[i - 1] == NULL) { 00147 for (j = 0; j < i; j++) 00148 os_free(array[j]); 00149 os_free(array); 00150 return NULL; 00151 } 00152 } 00153 array[i] = NULL; 00154 00155 if (num) 00156 *num = array_len; 00157 00158 return array; 00159 } 00160 00161 00167 const struct eap_method * eap_peer_get_methods(size_t *count) 00168 { 00169 int c = 0; 00170 struct eap_method *m; 00171 00172 for (m = eap_methods; m; m = m->next) 00173 c++; 00174 00175 *count = c; 00176 return eap_methods; 00177 } 00178 00179 00180 #ifdef CONFIG_DYNAMIC_EAP_METHODS 00181 00186 int eap_peer_method_load(const char *so) 00187 { 00188 void *handle; 00189 int (*dyn_init)(void); 00190 int ret; 00191 00192 handle = dlopen(so, RTLD_LAZY); 00193 if (handle == NULL) { 00194 wpa_printf(MSG_ERROR, "EAP: Failed to open dynamic EAP method " 00195 "'%s': %s", so, dlerror()); 00196 return -1; 00197 } 00198 00199 dyn_init = dlsym(handle, "eap_peer_method_dynamic_init"); 00200 if (dyn_init == NULL) { 00201 dlclose(handle); 00202 wpa_printf(MSG_ERROR, "EAP: Invalid EAP method '%s' - no " 00203 "eap_peer_method_dynamic_init()", so); 00204 return -1; 00205 } 00206 00207 ret = dyn_init(); 00208 if (ret) { 00209 dlclose(handle); 00210 wpa_printf(MSG_ERROR, "EAP: Failed to add EAP method '%s' - " 00211 "ret %d", so, ret); 00212 return ret; 00213 } 00214 00215 /* Store the handle for this shared object. It will be freed with 00216 * dlclose() when the EAP method is unregistered. */ 00217 eap_methods->dl_handle = handle; 00218 00219 wpa_printf(MSG_DEBUG, "EAP: Loaded dynamic EAP method: '%s'", so); 00220 00221 return 0; 00222 } 00223 00224 00235 int eap_peer_method_unload(struct eap_method *method) 00236 { 00237 struct eap_method *m, *prev; 00238 void *handle; 00239 00240 m = eap_methods; 00241 prev = NULL; 00242 while (m) { 00243 if (m == method) 00244 break; 00245 prev = m; 00246 m = m->next; 00247 } 00248 00249 if (m == NULL || m->dl_handle == NULL) 00250 return -1; 00251 00252 if (prev) 00253 prev->next = m->next; 00254 else 00255 eap_methods = m->next; 00256 00257 handle = m->dl_handle; 00258 00259 if (m->free) 00260 m->free(m); 00261 else 00262 eap_peer_method_free(m); 00263 00264 dlclose(handle); 00265 00266 return 0; 00267 } 00268 #endif /* CONFIG_DYNAMIC_EAP_METHODS */ 00269 00270 00283 struct eap_method * eap_peer_method_alloc(int version, int vendor, 00284 EapType method, const char *name) 00285 { 00286 struct eap_method *eap; 00287 eap = os_zalloc(sizeof(*eap)); 00288 if (eap == NULL) 00289 return NULL; 00290 eap->version = version; 00291 eap->vendor = vendor; 00292 eap->method = method; 00293 eap->name = name; 00294 return eap; 00295 } 00296 00297 00302 void eap_peer_method_free(struct eap_method *method) 00303 { 00304 os_free(method); 00305 } 00306 00307 00317 int eap_peer_method_register(struct eap_method *method) 00318 { 00319 struct eap_method *m, *last = NULL; 00320 00321 if (method == NULL || method->name == NULL || 00322 method->version != EAP_PEER_METHOD_INTERFACE_VERSION) 00323 return -1; 00324 00325 for (m = eap_methods; m; m = m->next) { 00326 if ((m->vendor == method->vendor && 00327 m->method == method->method) || 00328 os_strcmp(m->name, method->name) == 0) 00329 return -2; 00330 last = m; 00331 } 00332 00333 if (last) 00334 last->next = method; 00335 else 00336 eap_methods = method; 00337 00338 return 0; 00339 } 00340 00341 00348 void eap_peer_unregister_methods(void) 00349 { 00350 struct eap_method *m; 00351 #ifdef CONFIG_DYNAMIC_EAP_METHODS 00352 void *handle; 00353 #endif /* CONFIG_DYNAMIC_EAP_METHODS */ 00354 00355 while (eap_methods) { 00356 m = eap_methods; 00357 eap_methods = eap_methods->next; 00358 00359 #ifdef CONFIG_DYNAMIC_EAP_METHODS 00360 handle = m->dl_handle; 00361 #endif /* CONFIG_DYNAMIC_EAP_METHODS */ 00362 00363 if (m->free) 00364 m->free(m); 00365 else 00366 eap_peer_method_free(m); 00367 00368 #ifdef CONFIG_DYNAMIC_EAP_METHODS 00369 if (handle) 00370 dlclose(handle); 00371 #endif /* CONFIG_DYNAMIC_EAP_METHODS */ 00372 } 00373 }