multiple update
This commit is contained in:
		| @ -31,7 +31,7 @@ application: { | |||||||
|  |  | ||||||
| 	descriptor: { | 	descriptor: { | ||||||
| 		radio = ( | 		radio = ( | ||||||
| 			{ device = "wifi0"; type = "bg"; status = "enabled"; } | 			{ device = "phy0"; driver = "nl80211"; type = "bg"; status = "enabled"; } | ||||||
| 		); | 		); | ||||||
|  |  | ||||||
| 		encryption = [  | 		encryption = [  | ||||||
|  | |||||||
| @ -96,7 +96,7 @@ AC_ARG_WITH( | |||||||
| # WTP drivers wifi binding  | # WTP drivers wifi binding  | ||||||
| AC_ARG_ENABLE( | AC_ARG_ENABLE( | ||||||
| 	[wifi-drivers-nl80211], | 	[wifi-drivers-nl80211], | ||||||
| 	[AS_HELP_STRING([--wifi-drivers-nl80211], [disable WTP support for nl80211 wifi binding @<:@default=yes@:>@])], | 	[AS_HELP_STRING([--disable-wifi-drivers-nl80211], [disable WTP support for nl80211 wifi binding @<:@default=yes@:>@])], | ||||||
| 	, | 	, | ||||||
| 	[enable_wifi_drivers_nl80211="yes"] | 	[enable_wifi_drivers_nl80211="yes"] | ||||||
| ) | ) | ||||||
| @ -115,6 +115,7 @@ if test "${enable_debug}" = "yes"; then | |||||||
| 	CFLAGS="${CFLAGS} -DDEBUG -Wall -Werror -g -O0" | 	CFLAGS="${CFLAGS} -DDEBUG -Wall -Werror -g -O0" | ||||||
| else | else | ||||||
| 	CFLAGS="${CFLAGS} -O2" | 	CFLAGS="${CFLAGS} -O2" | ||||||
|  | 	AC_DEFINE([DISABLE_LOGGING_DEBUG], [1], [Disable logging debug]) | ||||||
| fi | fi | ||||||
|  |  | ||||||
| # | # | ||||||
| @ -231,7 +232,6 @@ PKG_CHECK_MODULES( | |||||||
| 		)] | 		)] | ||||||
| 	)] | 	)] | ||||||
| ) | ) | ||||||
| test "$has_libnl_ver" -gt 1 &&  |  | ||||||
|  |  | ||||||
| if test "${enable_wifi_drivers_nl80211}" = "yes"; then | if test "${enable_wifi_drivers_nl80211}" = "yes"; then | ||||||
| 	AC_CHECK_HEADERS([netlink/genl/genl.h netlink/genl/family.h netlink/genl/ctrl.h], [], [AC_MSG_ERROR(You need the netlink header)]) | 	AC_CHECK_HEADERS([netlink/genl/genl.h netlink/genl/family.h netlink/genl/ctrl.h], [], [AC_MSG_ERROR(You need the netlink header)]) | ||||||
|  | |||||||
| @ -1,11 +1,5 @@ | |||||||
| #include "wifi_drivers.h" | #include "wifi_drivers.h" | ||||||
|  | #include "capwap_array.h" | ||||||
| /* */ |  | ||||||
| struct wifi_driver_instance { |  | ||||||
| 	struct wifi_driver_ops* ops;		/* Driver functions */ |  | ||||||
|  |  | ||||||
| 	wifi_global_handle handle;			/* Global instance handle */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /* Declare enable wifi driver */ | /* Declare enable wifi driver */ | ||||||
| #ifdef ENABLE_WIFI_DRIVERS_NL80211 | #ifdef ENABLE_WIFI_DRIVERS_NL80211 | ||||||
| @ -19,30 +13,93 @@ static struct wifi_driver_instance wifi_driver[] = { | |||||||
| 	{ NULL } | 	{ NULL } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* Radio instance */ | ||||||
|  | static struct capwap_array* wifi_device = NULL; | ||||||
|  |  | ||||||
| /* */ | /* */ | ||||||
| int wifi_init_driver(void) { | int wifi_init_driver(void) { | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	for (i = 0; wifi_driver[i].ops != NULL; i++) { | 	for (i = 0; wifi_driver[i].ops != NULL; i++) { | ||||||
| 		if (!wifi_driver[i].ops->global_init) { |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		/* Initialize driver */ | 		/* Initialize driver */ | ||||||
|  | 		ASSERT(wifi_driver[i].ops->global_init != NULL); | ||||||
| 		wifi_driver[i].handle = wifi_driver[i].ops->global_init(); | 		wifi_driver[i].handle = wifi_driver[i].ops->global_init(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* Device handler */ | ||||||
|  | 	wifi_device = capwap_array_create(sizeof(struct wifi_device), 0); | ||||||
|  | 	wifi_device->zeroed = 1; | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* */ | /* */ | ||||||
| void wifi_free_driver(void) { | void wifi_free_driver(void) { | ||||||
| 	int i; | 	unsigned long i; | ||||||
|  |  | ||||||
|  | 	/* Free device */ | ||||||
|  | 	if (wifi_device) { | ||||||
|  | 		for (i = 0; i < wifi_device->count; i++) { | ||||||
|  | 			struct wifi_device* device = (struct wifi_device*)capwap_array_get_item_pointer(wifi_device, i); | ||||||
|  | 			if (device->instance->ops->device_deinit) { | ||||||
|  | 				device->instance->ops->device_deinit(device->handle); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		capwap_array_free(wifi_device); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	for (i = 0; wifi_driver[i].ops != NULL; i++) { |  | ||||||
| 	/* Free driver */ | 	/* Free driver */ | ||||||
|  | 	for (i = 0; wifi_driver[i].ops != NULL; i++) { | ||||||
| 		if (wifi_driver[i].ops->global_deinit) { | 		if (wifi_driver[i].ops->global_deinit) { | ||||||
| 			wifi_driver[i].ops->global_deinit(wifi_driver[i].handle); | 			wifi_driver[i].ops->global_deinit(wifi_driver[i].handle); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | int wifi_create_device(int radioid, char* ifname, char* driver) { | ||||||
|  | 	int i; | ||||||
|  | 	int length; | ||||||
|  | 	int result = -1; | ||||||
|  |  | ||||||
|  | 	ASSERT(radioid > 0); | ||||||
|  | 	ASSERT(ifname != NULL); | ||||||
|  | 	ASSERT(driver != NULL); | ||||||
|  |  | ||||||
|  | 	/* Check */ | ||||||
|  | 	length = strlen(ifname); | ||||||
|  | 	if ((length <= 0) || (length >= IFNAMSIZ)) { | ||||||
|  | 		capwap_logging_warning("Wifi device name error: %s", ifname); | ||||||
|  | 		return -1; | ||||||
|  | 	} else if (wifi_device->count >= radioid) { | ||||||
|  | 		capwap_logging_warning("Wifi device RadioID already used: %d", radioid); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Search driver */ | ||||||
|  | 	for (i = 0; wifi_driver[i].ops != NULL; i++) { | ||||||
|  | 		if (!strcmp(driver, wifi_driver[i].ops->name)) { | ||||||
|  | 			wifi_device_handle devicehandle; | ||||||
|  | 			struct device_init_params params = { | ||||||
|  | 				.ifname = ifname | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			/* Device init */ | ||||||
|  | 			ASSERT(wifi_driver[i].ops->device_init); | ||||||
|  | 			devicehandle = wifi_driver[i].ops->device_init(wifi_driver[i].handle, ¶ms); | ||||||
|  | 			if (devicehandle) { | ||||||
|  | 				/* Register new device */ | ||||||
|  | 				struct wifi_device* device = (struct wifi_device*)capwap_array_get_item_pointer(wifi_device, radioid); | ||||||
|  | 				device->handle = devicehandle; | ||||||
|  | 				device->instance = &wifi_driver[i]; | ||||||
|  |  | ||||||
|  | 				result = 0; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | |||||||
| @ -8,10 +8,14 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <net/if.h> | ||||||
|  |  | ||||||
| #include "capwap_debug.h" | #include "capwap_debug.h" | ||||||
| #include "capwap_logging.h" | #include "capwap_logging.h" | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | #define WIFI_DRIVER_NAME_SIZE			16 | ||||||
|  |  | ||||||
| /* */ | /* */ | ||||||
| typedef void* wifi_global_handle; | typedef void* wifi_global_handle; | ||||||
| typedef void* wifi_device_handle; | typedef void* wifi_device_handle; | ||||||
| @ -35,8 +39,23 @@ struct wifi_driver_ops { | |||||||
| 	void (*device_deinit)(wifi_device_handle handle); | 	void (*device_deinit)(wifi_device_handle handle); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | struct wifi_driver_instance { | ||||||
|  | 	struct wifi_driver_ops* ops;						/* Driver functions */ | ||||||
|  | 	wifi_global_handle handle;							/* Global instance handle */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | struct wifi_device { | ||||||
|  | 	wifi_device_handle handle;							/* Device handle */ | ||||||
|  | 	struct wifi_driver_instance* instance;				/* Driver instance */ | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* Initialize wifi driver engine */ | /* Initialize wifi driver engine */ | ||||||
| int wifi_init_driver(void); | int wifi_init_driver(void); | ||||||
| void wifi_free_driver(void); | void wifi_free_driver(void); | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | int wifi_create_device(int radioid, char* ifname, char* driver); | ||||||
|  |  | ||||||
| #endif /* __WIFI_DRIVERS_HEADER__ */ | #endif /* __WIFI_DRIVERS_HEADER__ */ | ||||||
|  | |||||||
| @ -1,14 +1,17 @@ | |||||||
| #include "wifi_drivers.h" | #include "wifi_drivers.h" | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | #include <net/if.h> | ||||||
| #include <netlink/genl/genl.h> | #include <netlink/genl/genl.h> | ||||||
| #include <netlink/genl/family.h> | #include <netlink/genl/family.h> | ||||||
| #include <netlink/genl/ctrl.h> | #include <netlink/genl/ctrl.h> | ||||||
| #include <linux/nl80211.h> | #include <linux/nl80211.h> | ||||||
|  |  | ||||||
|  | #include "capwap_list.h" | ||||||
|  | #include "wifi_nl80211.h" | ||||||
|  |  | ||||||
| /* Compatibility functions */ | /* Compatibility functions */ | ||||||
| #if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30) | #if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30) | ||||||
| #define nl_sock nl_handle |  | ||||||
| static uint32_t port_bitmap[32] = { 0 }; | static uint32_t port_bitmap[32] = { 0 }; | ||||||
|  |  | ||||||
| static struct nl_sock* nl_socket_alloc_cb(void* cb) { | static struct nl_sock* nl_socket_alloc_cb(void* cb) { | ||||||
| @ -42,21 +45,275 @@ static void nl_socket_free(struct nl_sock* handle) { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* */ | /* */ | ||||||
| wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct device_init_params* params) { | static struct nl_sock* nl_create_handle(struct nl_cb* cb) { | ||||||
|  | 	struct nl_sock* handle; | ||||||
|  |  | ||||||
|  | 	handle = nl_socket_alloc_cb(cb); | ||||||
|  | 	if (!handle) { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (genl_connect(handle)) { | ||||||
|  | 		nl_socket_free(handle); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return handle; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int nl80211_no_seq_check(struct nl_msg* msg, void* arg) { | ||||||
|  | 	return NL_OK; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int nl80211_error_handler(struct sockaddr_nl* nla, struct nlmsgerr* err, void* arg) { | ||||||
|  | 	*((int*)arg) = err->error; | ||||||
|  | 	return NL_STOP; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int nl80211_finish_handler(struct nl_msg* msg, void* arg) { | ||||||
|  | 	*((int*)arg) = 0; | ||||||
|  | 	return NL_SKIP; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int nl80211_ack_handler(struct nl_msg* msg, void* arg) { | ||||||
|  | 	*((int*)arg) = 0; | ||||||
|  | 	return NL_STOP; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int nl80211_send_and_recv(struct nl_sock* nl, struct nl_cb* nl_cb, struct nl_msg* msg, nl_valid_cb valid_cb, void* data) { | ||||||
|  | 	int result; | ||||||
|  | 	struct nl_cb* cb; | ||||||
|  |  | ||||||
|  | 	/* Clone netlink callback */ | ||||||
|  | 	cb = nl_cb_clone(nl_cb); | ||||||
|  | 	if (!cb) { | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Complete send message */ | ||||||
|  | 	result = nl_send_auto_complete(nl, msg); | ||||||
|  | 	if (result < 0) { | ||||||
|  | 		nl_cb_put(cb); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Customize message callback */ | ||||||
|  | 	nl_cb_err(cb, NL_CB_CUSTOM, nl80211_error_handler, &result); | ||||||
|  | 	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_finish_handler, &result); | ||||||
|  | 	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl80211_ack_handler, &result); | ||||||
|  |  | ||||||
|  | 	if (valid_cb) { | ||||||
|  | 		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_cb, data); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	result = 1; | ||||||
|  | 	while (result > 0) { | ||||||
|  | 		nl_recvmsgs(nl, cb); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	nl_cb_put(cb); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int nl80211_send_and_recv_msg(struct nl80211_global_handle* globalhandle, struct nl_msg* msg, nl_valid_cb valid_cb, void* data) { | ||||||
|  | 	return nl80211_send_and_recv(globalhandle->nl, globalhandle->nl_cb, msg, valid_cb, data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int cb_get_phydevice_list(struct nl_msg* msg, void* data) { | ||||||
|  | 	struct nlattr* tb_msg[NL80211_ATTR_MAX + 1]; | ||||||
|  | 	struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg)); | ||||||
|  | 	struct capwap_list* list = (struct capwap_list*)data; | ||||||
|  |  | ||||||
|  | 	nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); | ||||||
|  |  | ||||||
|  | 	if (tb_msg[NL80211_ATTR_WIPHY_NAME] && tb_msg[NL80211_ATTR_WIPHY]) { | ||||||
|  | 		struct capwap_list_item* item = capwap_itemlist_create(sizeof(struct nl80211_phydevice_item)); | ||||||
|  | 		struct nl80211_phydevice_item* phyitem = (struct nl80211_phydevice_item*)item->item; | ||||||
|  |  | ||||||
|  | 		/* Add physical device info */ | ||||||
|  | 		phyitem->index = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]); | ||||||
|  | 		strcpy(phyitem->name, nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME])); | ||||||
|  | 		capwap_itemlist_insert_after(list, NULL, item); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return NL_SKIP; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static int nl80211_get_phydevice_list(struct nl80211_global_handle* globalhandle, struct capwap_list* list) { | ||||||
|  | 	int result; | ||||||
|  | 	struct nl_msg* msg; | ||||||
|  |  | ||||||
|  | 	ASSERT(globalhandle != NULL); | ||||||
|  | 	ASSERT(list != NULL); | ||||||
|  |  | ||||||
|  | 	/* */ | ||||||
|  | 	msg = nlmsg_alloc(); | ||||||
|  | 	if (!msg) { | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Retrieve list of physical device */ | ||||||
|  | 	genlmsg_put(msg, 0, 0, globalhandle->nl80211_id, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0); | ||||||
|  |  | ||||||
|  | 	/* Retrieve all physical interface */ | ||||||
|  | 	result = nl80211_send_and_recv_msg(globalhandle, msg, cb_get_phydevice_list, list); | ||||||
|  |  | ||||||
|  | 	/* */ | ||||||
|  | 	nlmsg_free(msg); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct device_init_params* params) { | ||||||
|  | 	int result; | ||||||
|  | 	struct capwap_list* list; | ||||||
|  | 	struct capwap_list_item* item; | ||||||
|  | 	struct nl80211_device_handle* devicehandle = NULL; | ||||||
|  | 	struct nl80211_global_handle* globalhandle = (struct nl80211_global_handle*)handle; | ||||||
|  |  | ||||||
|  | 	ASSERT(params != NULL); | ||||||
|  |  | ||||||
|  | 	if (!handle) { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Retrieve physical device info */ | ||||||
|  | 	list = capwap_list_create(); | ||||||
|  | 	result = nl80211_get_phydevice_list(globalhandle, list); | ||||||
|  | 	if (!result) { | ||||||
|  | 		item = list->first; | ||||||
|  | 		while (item) { | ||||||
|  | 			struct nl80211_phydevice_item* phyitem = (struct nl80211_phydevice_item*)item->item; | ||||||
|  | 			 | ||||||
|  | 			if (!strcmp(phyitem->name, params->ifname)) { | ||||||
|  | 				/* Create device */ | ||||||
|  | 				devicehandle = (struct nl80211_device_handle*)capwap_alloc(sizeof(struct nl80211_device_handle)); | ||||||
|  | 				memset(devicehandle, 0, sizeof(struct nl80211_device_handle)); | ||||||
|  |  | ||||||
|  | 				/* */ | ||||||
|  | 				strcpy(devicehandle->phyname, phyitem->name); | ||||||
|  | 				devicehandle->phyindex = phyitem->index; | ||||||
|  |  | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			/* Next */ | ||||||
|  | 			item = item->next; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		/* Error get physical devices */ | ||||||
|  | 		capwap_logging_error("Unable retrieve physical device info, error code: %d", result); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* */ | ||||||
|  | 	capwap_list_free(list); | ||||||
|  | 	if (!devicehandle) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* */ | 	/* */ | ||||||
| void nl80211_device_deinit(wifi_device_handle handle) { | 	devicehandle->globalhandle = globalhandle; | ||||||
|  |  | ||||||
|  | 	/* Save device handle into global handle */ | ||||||
|  | 	item = capwap_itemlist_create_with_item(devicehandle, sizeof(struct nl80211_device_handle)); | ||||||
|  | 	capwap_itemlist_insert_after(globalhandle->devicelist, NULL, item); | ||||||
|  |  | ||||||
|  | 	return devicehandle; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | static void nl80211_device_deinit(wifi_device_handle handle) { | ||||||
|  | 	struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle; | ||||||
|  |  | ||||||
|  | 	if (devicehandle) { | ||||||
|  | 		struct capwap_list_item* search; | ||||||
|  |  | ||||||
|  | 		/* Remove device handle from global handle*/ | ||||||
|  | 		search = devicehandle->globalhandle->devicelist->first; | ||||||
|  | 		while (search) { | ||||||
|  | 			/* Remove item from list without destroy */ | ||||||
|  | 			if ((struct nl80211_device_handle*)search->item == devicehandle) { | ||||||
|  | 				capwap_itemlist_remove(devicehandle->globalhandle->devicelist, search); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			search = search->next; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* */ | ||||||
|  | 		capwap_free(devicehandle); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* */ | /* */ | ||||||
| static wifi_global_handle nl80211_global_init(void) { | static wifi_global_handle nl80211_global_init(void) { | ||||||
|  | 	struct nl80211_global_handle* globalhandle; | ||||||
|  |  | ||||||
|  | 	/* */ | ||||||
|  | 	globalhandle = (struct nl80211_global_handle*)capwap_alloc(sizeof(struct nl80211_global_handle)); | ||||||
|  | 	memset(globalhandle, 0, sizeof(struct nl80211_global_handle)); | ||||||
|  |  | ||||||
|  | 	/* Configure global netlink callback */ | ||||||
|  | 	globalhandle->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); | ||||||
|  | 	if (!globalhandle->nl_cb) { | ||||||
|  | 		capwap_free(globalhandle); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* Create netlink socket */ | ||||||
|  | 	globalhandle->nl = nl_create_handle(globalhandle->nl_cb); | ||||||
|  | 	if (!globalhandle->nl) { | ||||||
|  | 		nl_cb_put(globalhandle->nl_cb); | ||||||
|  | 		capwap_free(globalhandle); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Get nl80211 netlink family */ | ||||||
|  | 	globalhandle->nl80211_id = genl_ctrl_resolve(globalhandle->nl, "nl80211"); | ||||||
|  | 	if (globalhandle->nl80211_id < 0) { | ||||||
|  | 		capwap_logging_warning("Unable to found mac80211 kernel module"); | ||||||
|  | 		nl_socket_free(globalhandle->nl); | ||||||
|  | 		nl_cb_put(globalhandle->nl_cb); | ||||||
|  | 		capwap_free(globalhandle); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Configure global callback function */ | ||||||
|  | 	nl_cb_set(globalhandle->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nl80211_no_seq_check, NULL); | ||||||
|  | 	/* TODO */ | ||||||
|  |  | ||||||
|  | 	/* Device list */ | ||||||
|  | 	globalhandle->devicelist = capwap_list_create(); | ||||||
|  |  | ||||||
|  | 	return (wifi_global_handle)globalhandle; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* */ | /* */ | ||||||
| void nl80211_global_deinit(wifi_global_handle handle) { | static void nl80211_global_deinit(wifi_global_handle handle) { | ||||||
|  | 	struct nl80211_global_handle* globalhandle = (struct nl80211_global_handle*)handle; | ||||||
|  |  | ||||||
|  | 	if (globalhandle) { | ||||||
|  | 		ASSERT(globalhandle->devicelist->count == 0); | ||||||
|  |  | ||||||
|  | 		if (globalhandle->nl) { | ||||||
|  | 			nl_socket_free(globalhandle->nl); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (globalhandle->nl_cb) { | ||||||
|  | 			nl_cb_put(globalhandle->nl_cb); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		capwap_list_free(globalhandle->devicelist); | ||||||
|  | 		capwap_free(globalhandle); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Driver function */ | /* Driver function */ | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								src/binding/wifi/drivers/wifi_nl80211.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/binding/wifi/drivers/wifi_nl80211.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | #ifndef __WIFI_NL80211_HEADER__ | ||||||
|  | #define __WIFI_NL80211_HEADER__ | ||||||
|  |  | ||||||
|  | /* Compatibility functions */ | ||||||
|  | #if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30) | ||||||
|  | #define nl_sock nl_handle | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* */ | ||||||
|  | typedef int (*nl_valid_cb)(struct nl_msg* msg, void* data); | ||||||
|  |  | ||||||
|  | /* Global handle */ | ||||||
|  | struct nl80211_global_handle { | ||||||
|  | 	struct nl_sock* nl; | ||||||
|  | 	struct nl_cb* nl_cb; | ||||||
|  | 	int nl80211_id; | ||||||
|  |  | ||||||
|  | 	struct capwap_list* devicelist; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Device handle */ | ||||||
|  | struct nl80211_device_handle { | ||||||
|  | 	struct nl80211_global_handle* globalhandle; | ||||||
|  |  | ||||||
|  | 	uint32_t phyindex; | ||||||
|  | 	char phyname[IFNAMSIZ]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Physical device info */ | ||||||
|  | struct nl80211_phydevice_item { | ||||||
|  | 	uint32_t index; | ||||||
|  | 	char name[IFNAMSIZ]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif /* __WIFI_NL80211_HEADER__ */ | ||||||
| @ -80,7 +80,13 @@ void capwap_array_resize(struct capwap_array* array, unsigned long count) { | |||||||
|  |  | ||||||
| 	if (array->buffer) { | 	if (array->buffer) { | ||||||
| 		if (newbuffer != NULL) { | 		if (newbuffer != NULL) { | ||||||
| 			memcpy(newbuffer, array->buffer, array->itemsize * min(array->count, count)); | 			int newcount = min(array->count, count); | ||||||
|  | 			memcpy(newbuffer, array->buffer, array->itemsize * newcount); | ||||||
|  |  | ||||||
|  | 			/* Zeroed new items */ | ||||||
|  | 			if (array->zeroed && (count > newcount)) { | ||||||
|  | 				memset(newbuffer + array->itemsize * newcount, 0, array->itemsize * (count - newcount)); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		capwap_free(array->buffer); | 		capwap_free(array->buffer); | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ struct capwap_array { | |||||||
| 	void* buffer; | 	void* buffer; | ||||||
| 	unsigned short itemsize; | 	unsigned short itemsize; | ||||||
| 	unsigned long count; | 	unsigned long count; | ||||||
|  | 	int zeroed; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount); | struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount); | ||||||
| @ -13,9 +14,4 @@ void capwap_array_free(struct capwap_array* array); | |||||||
| void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos); | void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos); | ||||||
| void capwap_array_resize(struct capwap_array* array, unsigned long count); | void capwap_array_resize(struct capwap_array* array, unsigned long count); | ||||||
|  |  | ||||||
| /* Helper */ |  | ||||||
| #define capwap_array_getitem(x, y, z)		*((z*)capwap_array_get_item_pointer((x), (y))) |  | ||||||
| #define capwap_array_setnewitem(x, y, z)	*((z*)capwap_array_get_item_pointer((x), (x)->count)) = (y) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif /* __CAPWAP_ARRAY_HEADER__ */ | #endif /* __CAPWAP_ARRAY_HEADER__ */ | ||||||
|  | |||||||
| @ -32,6 +32,11 @@ void capwap_logging_printf(int level, const char *format, ...); | |||||||
| #define capwap_logging_error(f, args...)							capwap_logging_printf(CAPWAP_LOGGING_ERROR, f, ##args) | #define capwap_logging_error(f, args...)							capwap_logging_printf(CAPWAP_LOGGING_ERROR, f, ##args) | ||||||
| #define capwap_logging_warning(f, args...)							capwap_logging_printf(CAPWAP_LOGGING_WARNING, f, ##args) | #define capwap_logging_warning(f, args...)							capwap_logging_printf(CAPWAP_LOGGING_WARNING, f, ##args) | ||||||
| #define capwap_logging_info(f, args...)								capwap_logging_printf(CAPWAP_LOGGING_INFO, f, ##args) | #define capwap_logging_info(f, args...)								capwap_logging_printf(CAPWAP_LOGGING_INFO, f, ##args) | ||||||
|  |  | ||||||
|  | #ifdef DISABLE_LOGGING_DEBUG | ||||||
|  | #define capwap_logging_debug(f, args...) | ||||||
|  | #else | ||||||
| #define capwap_logging_debug(f, args...)							capwap_logging_printf(CAPWAP_LOGGING_DEBUG, f, ##args) | #define capwap_logging_debug(f, args...)							capwap_logging_printf(CAPWAP_LOGGING_DEBUG, f, ##args) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif /* __CAPWAP_LOGGING_HEADER__ */ | #endif /* __CAPWAP_LOGGING_HEADER__ */ | ||||||
|  | |||||||
| @ -158,6 +158,7 @@ static void wtp_print_usage(void) { | |||||||
| /* Parsing configuration */ | /* Parsing configuration */ | ||||||
| static int wtp_parsing_configuration_1_0(config_t* config) { | static int wtp_parsing_configuration_1_0(config_t* config) { | ||||||
| 	int i; | 	int i; | ||||||
|  | 	int result; | ||||||
| 	int configInt; | 	int configInt; | ||||||
| 	int configIPv4; | 	int configIPv4; | ||||||
| 	int configIPv6; | 	int configIPv6; | ||||||
| @ -246,6 +247,29 @@ static int wtp_parsing_configuration_1_0(config_t* config) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* Initialize binding */ | ||||||
|  | 	switch (g_wtp.binding) { | ||||||
|  | 		case CAPWAP_WIRELESS_BINDING_NONE: { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		case CAPWAP_WIRELESS_BINDING_IEEE80211: { | ||||||
|  | 			/* Initialize wifi binding driver */ | ||||||
|  | 			capwap_logging_info("Initializing wifi binding engine"); | ||||||
|  | 			if (wifi_init_driver()) { | ||||||
|  | 				capwap_logging_fatal("Unable initialize wifi binding engine"); | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		default: { | ||||||
|  | 			capwap_logging_fatal("Unable initialize unknown binding engine: %hu", g_wtp.binding); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* Set tunnelmode of WTP */ | 	/* Set tunnelmode of WTP */ | ||||||
| 	if (config_lookup(config, "application.tunnelmode") != NULL) { | 	if (config_lookup(config, "application.tunnelmode") != NULL) { | ||||||
| 		g_wtp.mactunnel.mode = 0; | 		g_wtp.mactunnel.mode = 0; | ||||||
| @ -364,6 +388,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) { | |||||||
| 			for (i = 0; i < count; i++) { | 			for (i = 0; i < count; i++) { | ||||||
| 				struct wtp_radio* radio; | 				struct wtp_radio* radio; | ||||||
| 				char radioname[IFNAMSIZ]; | 				char radioname[IFNAMSIZ]; | ||||||
|  | 				char drivername[WIFI_DRIVER_NAME_SIZE]; | ||||||
| 				unsigned char radiotype = 0; | 				unsigned char radiotype = 0; | ||||||
| 				int radiostatus = WTP_RADIO_ENABLED; | 				int radiostatus = WTP_RADIO_ENABLED; | ||||||
| 	 | 	 | ||||||
| @ -372,6 +397,9 @@ static int wtp_parsing_configuration_1_0(config_t* config) { | |||||||
| 					if (config_setting_lookup_string(configElement, "device", &configString) == CONFIG_TRUE) { | 					if (config_setting_lookup_string(configElement, "device", &configString) == CONFIG_TRUE) { | ||||||
| 						if (*configString && (strlen(configString) < IFNAMSIZ)) { | 						if (*configString && (strlen(configString) < IFNAMSIZ)) { | ||||||
| 							strcpy(radioname, configString); | 							strcpy(radioname, configString); | ||||||
|  | 							if (config_setting_lookup_string(configElement, "driver", &configString) == CONFIG_TRUE) { | ||||||
|  | 								if (*configString && (strlen(configString) < WIFI_DRIVER_NAME_SIZE)) { | ||||||
|  | 									strcpy(drivername, configString); | ||||||
| 									if (config_setting_lookup_string(configElement, "type", &configString) == CONFIG_TRUE) { | 									if (config_setting_lookup_string(configElement, "type", &configString) == CONFIG_TRUE) { | ||||||
| 										int length = strlen(configString); | 										int length = strlen(configString); | ||||||
| 										 | 										 | ||||||
| @ -405,6 +433,8 @@ static int wtp_parsing_configuration_1_0(config_t* config) { | |||||||
| 										} | 										} | ||||||
| 		 | 		 | ||||||
| 										if (radiotype != 0) { | 										if (radiotype != 0) { | ||||||
|  | 											int radioid; | ||||||
|  |  | ||||||
| 											if (config_setting_lookup_string(configElement, "status", &configString) == CONFIG_TRUE) { | 											if (config_setting_lookup_string(configElement, "status", &configString) == CONFIG_TRUE) { | ||||||
| 												if (!strcmp(configString, "enabled")) { | 												if (!strcmp(configString, "enabled")) { | ||||||
| 													radiostatus = WTP_RADIO_ENABLED; | 													radiostatus = WTP_RADIO_ENABLED; | ||||||
| @ -420,10 +450,20 @@ static int wtp_parsing_configuration_1_0(config_t* config) { | |||||||
| 												} | 												} | ||||||
| 											} | 											} | ||||||
|  |  | ||||||
|  | 											/* Initialize radio device */ | ||||||
|  | 											radioid = g_wtp.radios->count + 1; | ||||||
|  | 											if (radiostatus == WTP_RADIO_ENABLED) { | ||||||
|  | 												result = wifi_create_device(radioid, radioname, drivername); | ||||||
|  | 												if (result) { | ||||||
|  | 													radiostatus = WTP_RADIO_HWFAILURE; | ||||||
|  | 													capwap_logging_warning("Unable to register radio device: %s - %s", radioname, drivername); | ||||||
|  | 												} | ||||||
|  | 											} | ||||||
|  |  | ||||||
| 											/* Create new radio device */ | 											/* Create new radio device */ | ||||||
| 											radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, g_wtp.radios->count); | 											radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, g_wtp.radios->count); | ||||||
| 											strcpy(radio->device, radioname); | 											strcpy(radio->device, radioname); | ||||||
| 									radio->radioinformation.radioid = g_wtp.radios->count; | 											radio->radioinformation.radioid = radioid; | ||||||
| 											radio->radioinformation.radiotype = radiotype; | 											radio->radioinformation.radiotype = radiotype; | ||||||
| 											radio->status = radiostatus; | 											radio->status = radiostatus; | ||||||
| 										} else { | 										} else { | ||||||
| @ -434,6 +474,14 @@ static int wtp_parsing_configuration_1_0(config_t* config) { | |||||||
| 										capwap_logging_error("Invalid configuration file, element application.descriptor.radio.type not found"); | 										capwap_logging_error("Invalid configuration file, element application.descriptor.radio.type not found"); | ||||||
| 										return 0; | 										return 0; | ||||||
| 									} | 									} | ||||||
|  | 								} else { | ||||||
|  | 									capwap_logging_error("Invalid configuration file, application.descriptor.radio.driver string length exceeded"); | ||||||
|  | 									return 0; | ||||||
|  | 								} | ||||||
|  | 							} else { | ||||||
|  | 								capwap_logging_error("Invalid configuration file, element application.descriptor.radio.driver not found"); | ||||||
|  | 								return 0; | ||||||
|  | 							} | ||||||
| 						} else { | 						} else { | ||||||
| 							capwap_logging_error("Invalid configuration file, application.descriptor.radio.device string length exceeded"); | 							capwap_logging_error("Invalid configuration file, application.descriptor.radio.device string length exceeded"); | ||||||
| 							return 0; | 							return 0; | ||||||
| @ -921,26 +969,6 @@ int main(int argc, char** argv) { | |||||||
| 					result = WTP_ERROR_LOAD_CONFIGURATION; | 					result = WTP_ERROR_LOAD_CONFIGURATION; | ||||||
| 					capwap_logging_fatal("Error to load configuration"); | 					capwap_logging_fatal("Error to load configuration"); | ||||||
| 				} else if (value > 0) { | 				} else if (value > 0) { | ||||||
| 					/* Initialize binding */ |  | ||||||
| 					switch (g_wtp.binding) { |  | ||||||
| 						case CAPWAP_WIRELESS_BINDING_NONE: { |  | ||||||
| 							value = 0; |  | ||||||
| 							break; |  | ||||||
| 						} |  | ||||||
|  |  | ||||||
| 						case CAPWAP_WIRELESS_BINDING_IEEE80211: { |  | ||||||
| 							/* Initialize wifi binding driver */ |  | ||||||
| 							capwap_logging_info("Initializing wifi binding engine"); |  | ||||||
| 							value = wifi_init_driver(); |  | ||||||
| 							break; |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					/* */ |  | ||||||
| 					if (value) { |  | ||||||
| 						result = WTP_ERROR_INIT_BINDING; |  | ||||||
| 						capwap_logging_fatal("Unable initialize binding engine"); |  | ||||||
| 					} else { |  | ||||||
| 					capwap_logging_info("Startup WTP"); | 					capwap_logging_info("Startup WTP"); | ||||||
|  |  | ||||||
| 					/* Start WTP */ | 					/* Start WTP */ | ||||||
| @ -971,7 +999,6 @@ int main(int argc, char** argv) { | |||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				/* Free memory */ | 				/* Free memory */ | ||||||
| 				wtp_destroy(); | 				wtp_destroy(); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user