2 * EAP peer: Method registration
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 #ifdef CONFIG_DYNAMIC_EAP_METHODS
12 #endif /* CONFIG_DYNAMIC_EAP_METHODS */
16 #include "eap_methods.h"
19 static struct eap_method
*eap_methods
= NULL
;
21 static void eap_peer_method_free(struct eap_method
*method
);
25 * eap_peer_get_eap_method - Get EAP method based on type number
26 * @vendor: EAP Vendor-Id (0 = IETF)
27 * @method: EAP type number
28 * Returns: Pointer to EAP method or %NULL if not found
30 const struct eap_method
* eap_peer_get_eap_method(int vendor
,
34 for (m
= eap_methods
; m
; m
= m
->next
) {
35 if (m
->vendor
== vendor
&& m
->method
== method
)
43 * eap_peer_get_type - Get EAP type for the given EAP method name
44 * @name: EAP method name, e.g., TLS
45 * @vendor: Buffer for returning EAP Vendor-Id
46 * Returns: EAP method type or %EAP_TYPE_NONE if not found
48 * This function maps EAP type names into EAP type numbers based on the list of
49 * EAP methods included in the build.
51 enum eap_type
eap_peer_get_type(const char *name
, int *vendor
)
54 for (m
= eap_methods
; m
; m
= m
->next
) {
55 if (os_strcmp(m
->name
, name
) == 0) {
60 *vendor
= EAP_VENDOR_IETF
;
66 * eap_get_name - Get EAP method name for the given EAP type
67 * @vendor: EAP Vendor-Id (0 = IETF)
68 * @type: EAP method type
69 * Returns: EAP method name, e.g., TLS, or %NULL if not found
71 * This function maps EAP type numbers into EAP type names based on the list of
72 * EAP methods included in the build.
74 const char * eap_get_name(int vendor
, enum eap_type type
)
77 if (vendor
== EAP_VENDOR_IETF
&& type
== EAP_TYPE_EXPANDED
)
79 for (m
= eap_methods
; m
; m
= m
->next
) {
80 if (m
->vendor
== vendor
&& m
->method
== type
)
88 * eap_get_names - Get space separated list of names for supported EAP methods
89 * @buf: Buffer for names
90 * @buflen: Buffer length
91 * Returns: Number of characters written into buf (not including nul
94 size_t eap_get_names(char *buf
, size_t buflen
)
106 for (m
= eap_methods
; m
; m
= m
->next
) {
107 ret
= os_snprintf(pos
, end
- pos
, "%s%s",
108 m
== eap_methods
? "" : " ", m
->name
);
109 if (os_snprintf_error(end
- pos
, ret
))
113 buf
[buflen
- 1] = '\0';
120 * eap_get_names_as_string_array - Get supported EAP methods as string array
121 * @num: Buffer for returning the number of items in array, not including %NULL
122 * terminator. This parameter can be %NULL if the length is not needed.
123 * Returns: A %NULL-terminated array of strings, or %NULL on error.
125 * This function returns the list of names for all supported EAP methods as an
126 * array of strings. The caller must free the returned array items and the
129 char ** eap_get_names_as_string_array(size_t *num
)
131 struct eap_method
*m
;
132 size_t array_len
= 0;
136 for (m
= eap_methods
; m
; m
= m
->next
)
139 array
= os_calloc(array_len
+ 1, sizeof(char *));
143 for (m
= eap_methods
; m
; m
= m
->next
) {
144 array
[i
++] = os_strdup(m
->name
);
145 if (array
[i
- 1] == NULL
) {
146 for (j
= 0; j
< i
; j
++)
162 * eap_peer_get_methods - Get a list of enabled EAP peer methods
163 * @count: Set to number of available methods
164 * Returns: List of enabled EAP peer methods
166 const struct eap_method
* eap_peer_get_methods(size_t *count
)
169 struct eap_method
*m
;
171 for (m
= eap_methods
; m
; m
= m
->next
)
179 #ifdef CONFIG_DYNAMIC_EAP_METHODS
181 * eap_peer_method_load - Load a dynamic EAP method library (shared object)
182 * @so: File path for the shared object file to load
183 * Returns: 0 on success, -1 on failure
185 int eap_peer_method_load(const char *so
)
188 int (*dyn_init
)(void);
191 handle
= dlopen(so
, RTLD_LAZY
);
192 if (handle
== NULL
) {
193 wpa_printf(MSG_ERROR
, "EAP: Failed to open dynamic EAP method "
194 "'%s': %s", so
, dlerror());
198 dyn_init
= dlsym(handle
, "eap_peer_method_dynamic_init");
199 if (dyn_init
== NULL
) {
201 wpa_printf(MSG_ERROR
, "EAP: Invalid EAP method '%s' - no "
202 "eap_peer_method_dynamic_init()", so
);
209 wpa_printf(MSG_ERROR
, "EAP: Failed to add EAP method '%s' - "
214 /* Store the handle for this shared object. It will be freed with
215 * dlclose() when the EAP method is unregistered. */
216 eap_methods
->dl_handle
= handle
;
218 wpa_printf(MSG_DEBUG
, "EAP: Loaded dynamic EAP method: '%s'", so
);
225 * eap_peer_method_unload - Unload a dynamic EAP method library (shared object)
226 * @method: Pointer to the dynamically loaded EAP method
227 * Returns: 0 on success, -1 on failure
229 * This function can be used to unload EAP methods that have been previously
230 * loaded with eap_peer_method_load(). Before unloading the method, all
231 * references to the method must be removed to make sure that no dereferences
232 * of freed memory will occur after unloading.
234 int eap_peer_method_unload(struct eap_method
*method
)
236 struct eap_method
*m
, *prev
;
248 if (m
== NULL
|| m
->dl_handle
== NULL
)
252 prev
->next
= m
->next
;
254 eap_methods
= m
->next
;
256 handle
= m
->dl_handle
;
261 eap_peer_method_free(m
);
267 #endif /* CONFIG_DYNAMIC_EAP_METHODS */
271 * eap_peer_method_alloc - Allocate EAP peer method structure
272 * @version: Version of the EAP peer method interface (set to
273 * EAP_PEER_METHOD_INTERFACE_VERSION)
274 * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
275 * @method: EAP type number (EAP_TYPE_*)
276 * @name: Name of the method (e.g., "TLS")
277 * Returns: Allocated EAP method structure or %NULL on failure
279 * The returned structure should be freed with eap_peer_method_free() when it
280 * is not needed anymore.
282 struct eap_method
* eap_peer_method_alloc(int version
, int vendor
,
283 enum eap_type method
,
286 struct eap_method
*eap
;
287 eap
= os_zalloc(sizeof(*eap
));
290 eap
->version
= version
;
291 eap
->vendor
= vendor
;
292 eap
->method
= method
;
299 * eap_peer_method_free - Free EAP peer method structure
300 * @method: Method structure allocated with eap_peer_method_alloc()
302 static void eap_peer_method_free(struct eap_method
*method
)
309 * eap_peer_method_register - Register an EAP peer method
310 * @method: EAP method to register from eap_peer_method_alloc()
311 * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
312 * has already been registered
314 * Each EAP peer method needs to call this function to register itself as a
315 * supported EAP method. The caller must not free the allocated method data
316 * regardless of the return value.
318 int eap_peer_method_register(struct eap_method
*method
)
320 struct eap_method
*m
, *last
= NULL
;
322 if (method
== NULL
|| method
->name
== NULL
||
323 method
->version
!= EAP_PEER_METHOD_INTERFACE_VERSION
) {
324 eap_peer_method_free(method
);
328 for (m
= eap_methods
; m
; m
= m
->next
) {
329 if ((m
->vendor
== method
->vendor
&&
330 m
->method
== method
->method
) ||
331 os_strcmp(m
->name
, method
->name
) == 0) {
332 eap_peer_method_free(method
);
341 eap_methods
= method
;
348 * eap_peer_unregister_methods - Unregister EAP peer methods
350 * This function is called at program termination to unregister all EAP peer
353 void eap_peer_unregister_methods(void)
355 struct eap_method
*m
;
356 #ifdef CONFIG_DYNAMIC_EAP_METHODS
358 #endif /* CONFIG_DYNAMIC_EAP_METHODS */
360 while (eap_methods
) {
362 eap_methods
= eap_methods
->next
;
364 #ifdef CONFIG_DYNAMIC_EAP_METHODS
365 handle
= m
->dl_handle
;
366 #endif /* CONFIG_DYNAMIC_EAP_METHODS */
371 eap_peer_method_free(m
);
373 #ifdef CONFIG_DYNAMIC_EAP_METHODS
376 #endif /* CONFIG_DYNAMIC_EAP_METHODS */