Fix capwap protocol and optional wireless information header.
Complete IEEE802.11 frames tunnel WTP side. Now WTP can send data packets to the AC.
This commit is contained in:
		| @ -12,6 +12,7 @@ application: { | ||||
| 	binding = "802.11"; | ||||
|  | ||||
| 	tunnelmode: { | ||||
| 		dataframe = "usermode"; | ||||
| 		nativeframe = false; | ||||
| 		ethframe = false; | ||||
| 		localbridging = true; | ||||
|  | ||||
| @ -202,7 +202,7 @@ void capwap_header_init(struct capwap_header_data* data, unsigned short radioid, | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, char* macaddress) { | ||||
| void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, const uint8_t* macaddress) { | ||||
| 	struct capwap_header* header; | ||||
|  | ||||
| 	ASSERT(data != NULL); | ||||
| @ -288,6 +288,7 @@ void capwap_header_set_wireless_information(struct capwap_header_data* data, voi | ||||
|  | ||||
| 	/* Remove old wireless information */ | ||||
| 	if (IS_FLAG_W_HEADER(header)) { | ||||
| 		SET_FLAG_W_HEADER(header, 0); | ||||
| 		SET_HLEN_HEADER(header, size); | ||||
| 	} | ||||
|  | ||||
| @ -308,6 +309,7 @@ void capwap_header_set_wireless_information(struct capwap_header_data* data, voi | ||||
|  | ||||
| 		/* Update size */ | ||||
| 		size += lengthpadded; | ||||
| 		SET_FLAG_W_HEADER(header, 1); | ||||
| 		SET_HLEN_HEADER(header, size); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -31,7 +31,7 @@ struct capwap_header_data { | ||||
| }; | ||||
|  | ||||
| void capwap_header_init(struct capwap_header_data* data, unsigned short radioid, unsigned short binding); | ||||
| void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, char* macaddress); | ||||
| void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, const uint8_t* macaddress); | ||||
| void capwap_header_set_wireless_information(struct capwap_header_data* data, void* buffer, unsigned char length); | ||||
| void capwap_header_set_keepalive_flag(struct capwap_header_data* data, int enable); | ||||
| void capwap_header_set_nativeframe_flag(struct capwap_header_data* data, int enable); | ||||
|  | ||||
| @ -71,20 +71,27 @@ struct capwap_header { | ||||
| /* Mac Address */ | ||||
| struct capwap_mac_address { | ||||
| 	uint8_t length; | ||||
| 	int8_t address[0]; | ||||
| 	uint8_t address[0]; | ||||
| } STRUCT_PACKED; | ||||
|  | ||||
| /* Wireless Information */ | ||||
| struct capwap_wireless_information { | ||||
| 	uint8_t length; | ||||
| 	int8_t data[0]; | ||||
| 	uint8_t data[0]; | ||||
| } STRUCT_PACKED; | ||||
|  | ||||
| /* IEEE802.11 Wireless Information */ | ||||
| struct capwap_ieee80211_frame_info { | ||||
| 	uint8_t rssi; | ||||
| 	uint8_t snr; | ||||
| 	uint16_t rate; | ||||
| } STRUCT_PACKED; | ||||
|  | ||||
| /* Message element */ | ||||
| struct capwap_message_element { | ||||
| 	uint16_t type; | ||||
| 	uint16_t length; | ||||
| 	int8_t data[0]; | ||||
| 	uint8_t data[0]; | ||||
| } STRUCT_PACKED; | ||||
|  | ||||
| /* Control Message Type */ | ||||
| @ -132,7 +139,7 @@ struct capwap_control_message { | ||||
| 	uint8_t seq; | ||||
| 	uint16_t length; | ||||
| 	uint8_t flags; | ||||
| 	int8_t elements[0]; | ||||
| 	uint8_t elements[0]; | ||||
| } STRUCT_PACKED; | ||||
|  | ||||
| /* Data Message Keep-Alive*/ | ||||
| @ -140,11 +147,11 @@ struct capwap_control_message { | ||||
|  | ||||
| struct capwap_data_message { | ||||
| 	uint16_t length; | ||||
| 	int8_t elements[0]; | ||||
| 	uint8_t elements[0]; | ||||
| } STRUCT_PACKED; | ||||
|  | ||||
| /* Capwap dtls header helper */ | ||||
| #define GET_DTLS_BODY(x)					(void*)(((int8_t*)(x)) + sizeof(struct capwap_dtls_header)) | ||||
| #define GET_DTLS_BODY(x)					(void*)(((uint8_t*)(x)) + sizeof(struct capwap_dtls_header)) | ||||
|  | ||||
| /* Capwap header helper */ | ||||
| #define GET_VERSION_HEADER(x)				((x)->preamble.version) | ||||
| @ -182,9 +189,9 @@ struct capwap_data_message { | ||||
| #define GET_FRAGMENT_OFFSET_HEADER(x)		(ntohs((x)->frag_off) & FRAGMENT_OFFSET_MASK) | ||||
| #define SET_FRAGMENT_OFFSET_HEADER(x, y)	((x)->frag_off &= ~FRAGMENT_OFFSET_MASK, (x)->frag_off |= htons((uint16_t)(y) & FRAGMENT_OFFSET_MASK)) | ||||
|  | ||||
| #define GET_RADIO_MAC_ADDRESS_STRUCT(x)		((struct capwap_mac_address*)(((int8_t*)(x)) + sizeof(struct capwap_header))) | ||||
| #define GET_WIRELESS_INFORMATION_STRUCT(x)	((struct capwap_wireless_information*)(((int8_t*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0))) | ||||
| #define GET_PAYLOAD_HEADER(x)				((void*)(((int8_t*)(x)) + GET_HLEN_HEADER(x) * 4)) | ||||
| #define GET_RADIO_MAC_ADDRESS_STRUCT(x)		((struct capwap_mac_address*)(((uint8_t*)(x)) + sizeof(struct capwap_header))) | ||||
| #define GET_WIRELESS_INFORMATION_STRUCT(x)	((struct capwap_wireless_information*)(((uint8_t*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0))) | ||||
| #define GET_PAYLOAD_HEADER(x)				((void*)(((uint8_t*)(x)) + GET_HLEN_HEADER(x) * 4)) | ||||
|  | ||||
| #define IS_SEQUENCE_SMALLER(s1, s2)			(((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0) | ||||
|  | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #include <linux/rcupdate.h> | ||||
| #include <linux/err.h> | ||||
| #include <net/mac80211.h> | ||||
| #include <linux/ieee80211.h> | ||||
| #include "nlsmartcapwap.h" | ||||
| #include "netlinkapp.h" | ||||
|  | ||||
| @ -13,6 +14,7 @@ struct nlsmartcapwap_device { | ||||
| 	struct list_head list; | ||||
| 	struct ieee80211_pcktunnel pcktunnel_handler; | ||||
|  | ||||
| 	u32 usermodeid; | ||||
| 	u32 ifindex; | ||||
| 	u32 flags; | ||||
| }; | ||||
| @ -46,49 +48,56 @@ static struct genl_family nlsmartcapwap_family = { | ||||
|  | ||||
| /* */ | ||||
| static int nlsmartcapwap_handler(u32 ifindex, struct sk_buff* skb, int sig_dbm, unsigned char rate, void* data) { | ||||
| 	int result = 0; | ||||
| 	int frame8023 = 0; | ||||
| 	struct nlsmartcapwap_device* nldev = (struct nlsmartcapwap_device*)data; | ||||
| 	struct ieee80211_hdr* hdr = (struct ieee80211_hdr*)skb->data; | ||||
|  | ||||
| 	/* Check source network */ | ||||
| 	if (ifindex == nldev->ifindex) { | ||||
| 		if (nldev->flags & SMARTCAPWAP_FLAGS_SEND_USERSPACE) { | ||||
| 			void* msg; | ||||
| 			struct sk_buff* sk_msg; | ||||
| 	/* IEEE802.11 Data Packet */ | ||||
| 	if (ieee80211_is_data(hdr->frame_control)) { | ||||
| 		if ((nldev->flags & SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME) && ieee80211_is_data_present(hdr->frame_control)) { | ||||
| 			result = -1; | ||||
| 		} | ||||
|  | ||||
| 			/* Alloc message */ | ||||
| 			sk_msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | ||||
| 			if (sk_msg) { | ||||
| 				/* Set command */ | ||||
| 				msg = genlmsg_put(sk_msg, 0, 0, &nlsmartcapwap_family, 0, NLSMARTCAPWAP_CMD_FRAME); | ||||
| 				if (msg) { | ||||
| 					/* Set params */ | ||||
| 					if (nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_IFINDEX, nldev->ifindex) || | ||||
| 						nla_put(sk_msg, NLSMARTCAPWAP_ATTR_FRAME, skb->len, skb->data) || | ||||
| 						(sig_dbm && nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM, (u32)sig_dbm)) || | ||||
| 						(rate && nla_put_u8(sk_msg, NLSMARTCAPWAP_ATTR_RX_RATE, (u8)rate))) { | ||||
| 		/* Convert IEEE802.11 to IEEE802.3 */ | ||||
| 		if (nldev->flags & SMARTCAPWAP_FLAGS_TUNNEL_8023) { | ||||
| 			frame8023 = 1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 						/* Abort message */ | ||||
| 						genlmsg_cancel(sk_msg, msg); | ||||
| 						nlmsg_free(sk_msg); | ||||
| 					} else { | ||||
| 						/* Send message */ | ||||
| 						genlmsg_end(sk_msg, msg); | ||||
| 						genlmsg_unicast(&init_net, sk_msg, nlsmartcapwap_usermodeid); | ||||
| 					} | ||||
| 				} else { | ||||
| 	/* */ | ||||
| 	if (nldev->flags & SMARTCAPWAP_FLAGS_SEND_USERSPACE) { | ||||
| 		void* msg; | ||||
| 		struct sk_buff* sk_msg; | ||||
|  | ||||
| 		/* Alloc message */ | ||||
| 		sk_msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | ||||
| 		if (sk_msg) { | ||||
| 			/* Set command */ | ||||
| 			msg = genlmsg_put(sk_msg, 0, 0, &nlsmartcapwap_family, 0, NLSMARTCAPWAP_CMD_FRAME); | ||||
| 			if (msg) { | ||||
| 				/* Set params */ | ||||
| 				if (nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_IFINDEX, nldev->ifindex) || | ||||
| 					nla_put(sk_msg, NLSMARTCAPWAP_ATTR_FRAME, skb->len, skb->data) || | ||||
| 					(frame8023 && nla_put_flag(sk_msg, NLSMARTCAPWAP_ATTR_8023_FRAME)) || | ||||
| 					(sig_dbm && nla_put_u32(sk_msg, NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM, (u32)sig_dbm)) || | ||||
| 					(rate && nla_put_u8(sk_msg, NLSMARTCAPWAP_ATTR_RX_RATE, (u8)rate))) { | ||||
|  | ||||
| 					/* Abort message */ | ||||
| 					genlmsg_cancel(sk_msg, msg); | ||||
| 					nlmsg_free(sk_msg); | ||||
| 				} else { | ||||
| 					/* Send message */ | ||||
| 					genlmsg_end(sk_msg, msg); | ||||
| 					genlmsg_unicast(&init_net, sk_msg, nldev->usermodeid); | ||||
| 				} | ||||
| 			} else { | ||||
| 				nlmsg_free(sk_msg); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Check if block all IEEE802.11 Data Packet */ | ||||
| 	if ((nldev->flags & SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME) &&  | ||||
| 		((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| @ -254,6 +263,9 @@ static int nlsmartcapwap_join_mac80211_device(struct sk_buff* skb, struct genl_i | ||||
| 		nldev->pcktunnel_handler.subtype_mask[2] = nla_get_u16(info->attrs[NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK]); | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	nldev->usermodeid = genl_info_snd_portid(info); | ||||
|  | ||||
| 	/* Connect device to mac80211 */ | ||||
| 	ret = ieee80211_pcktunnel_register(ifindex, &nldev->pcktunnel_handler); | ||||
| 	if (ret) { | ||||
| @ -289,6 +301,7 @@ static const struct nla_policy nlsmartcapwap_policy[NLSMARTCAPWAP_ATTR_MAX + 1] | ||||
| 	[NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK] = { .type = NLA_U16 }, | ||||
| 	[NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK] = { .type = NLA_U16 }, | ||||
| 	[NLSMARTCAPWAP_ATTR_FRAME] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, | ||||
| 	[NLSMARTCAPWAP_ATTR_8023_FRAME] = { .type = NLA_FLAG }, | ||||
| 	[NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM] = { .type = NLA_U32 }, | ||||
| 	[NLSMARTCAPWAP_ATTR_RX_RATE] = { .type = NLA_U8 }, | ||||
| }; | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| /* */ | ||||
| #define SMARTCAPWAP_FLAGS_SEND_USERSPACE		0x00000001 | ||||
| #define SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME		0x00000002 | ||||
| #define SMARTCAPWAP_FLAGS_TUNNEL_8023			0x00000004 | ||||
|  | ||||
| /* */ | ||||
| enum nlsmartcapwap_attrs { | ||||
| @ -21,6 +22,7 @@ enum nlsmartcapwap_attrs { | ||||
| 	NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK, | ||||
|  | ||||
| 	NLSMARTCAPWAP_ATTR_FRAME, | ||||
| 	NLSMARTCAPWAP_ATTR_8023_FRAME, | ||||
| 	NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM, | ||||
| 	NLSMARTCAPWAP_ATTR_RX_RATE, | ||||
|  | ||||
|  | ||||
| @ -1,9 +1,7 @@ | ||||
| #include "capwap.h" | ||||
| #include "wtp.h" | ||||
| #include "capwap_list.h" | ||||
| #include "capwap_element.h" | ||||
| #include "capwap_network.h" | ||||
| #include "wifi_drivers.h" | ||||
| #include "wtp.h" | ||||
| #include "wtp_radio.h" | ||||
|  | ||||
| /* Declare enable wifi driver */ | ||||
| @ -316,7 +314,7 @@ static void wifi_wlan_send_mgmt_deauthentication(struct wifi_wlan* wlan, const u | ||||
| 			capwap_logging_info("Sent IEEE802.11 Deuthentication to %s station", stationaddress); | ||||
|  | ||||
| 			/* Forwards the station deauthentication also to AC */ | ||||
| 			wlan->send_frame(wlan->send_frame_to_ac_cbparam, (struct ieee80211_header_mgmt*)g_bufferIEEE80211, responselength); | ||||
| 			wifi_wlan_send_frame(wlan, (uint8_t*)g_bufferIEEE80211, responselength, 1, 0, 0, 0); | ||||
| 		} else { | ||||
| 			capwap_logging_warning("Unable to send IEEE802.11 Deuthentication to %s station", stationaddress); | ||||
| 		} | ||||
| @ -421,7 +419,7 @@ static void wifi_wlan_receive_station_mgmt_probe_request(struct wifi_wlan* wlan, | ||||
| 	if (!wlan->device->instance->ops->wlan_sendframe(wlan, g_bufferIEEE80211, responselength, wlan->device->currentfrequency.frequency, 0, 0, 0, nowaitack)) { | ||||
| 		/* If enable Split Mac send the probe request message to AC */ | ||||
| 		if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { | ||||
| 			wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length); | ||||
| 			wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate); | ||||
| 		} | ||||
| 	} else { | ||||
| 		capwap_logging_warning("Unable to send IEEE802.11 Probe Response"); | ||||
| @ -585,10 +583,10 @@ static void wifi_wlan_receive_station_mgmt_authentication(struct wifi_wlan* wlan | ||||
| 				capwap_logging_info("Sent IEEE802.11 Authentication Response to %s station with %d status code", stationaddress, (int)responsestatuscode); | ||||
|  | ||||
| 				/* Notify authentication request message also to AC */ | ||||
| 				wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length); | ||||
| 				wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate); | ||||
|  | ||||
| 				/* Forwards the authentication response message also to AC */ | ||||
| 				wlan->send_frame(wlan->send_frame_to_ac_cbparam, (struct ieee80211_header_mgmt*)g_bufferIEEE80211, responselength); | ||||
| 				wifi_wlan_send_frame(wlan, (uint8_t*)g_bufferIEEE80211, responselength, 1, 0, 0, 0); | ||||
| 			} else if (station) { | ||||
| 				capwap_logging_warning("Unable to send IEEE802.11 Authentication Response to %s station", stationaddress); | ||||
| 				wifi_station_delete(station); | ||||
| @ -598,7 +596,7 @@ static void wifi_wlan_receive_station_mgmt_authentication(struct wifi_wlan* wlan | ||||
| 			wifi_station_delete(station); | ||||
| 		} | ||||
| 	} else if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { | ||||
| 		wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length); | ||||
| 		wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -684,10 +682,10 @@ static void wifi_wlan_receive_station_mgmt_association_request(struct wifi_wlan* | ||||
| 				capwap_logging_info("Sent IEEE802.11 Association Response to %s station with %d status code", station->addrtext, (int)resultstatuscode); | ||||
|  | ||||
| 				/* Notify association request message also to AC */ | ||||
| 				wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length); | ||||
| 				wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate); | ||||
|  | ||||
| 				/* Forwards the association response message also to AC */ | ||||
| 				wlan->send_frame(wlan->send_frame_to_ac_cbparam, (struct ieee80211_header_mgmt*)g_bufferIEEE80211, responselength); | ||||
| 				wifi_wlan_send_frame(wlan, (uint8_t*)g_bufferIEEE80211, responselength, 1, 0, 0, 0); | ||||
| 			} else { | ||||
| 				capwap_logging_warning("Unable to send IEEE802.11 Association Response to %s station", station->addrtext); | ||||
| 				wifi_wlan_deauthentication_station(wlan, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID, 0); | ||||
| @ -697,7 +695,7 @@ static void wifi_wlan_receive_station_mgmt_association_request(struct wifi_wlan* | ||||
| 			wifi_wlan_deauthentication_station(wlan, station, IEEE80211_REASON_PREV_AUTH_NOT_VALID, 0); | ||||
| 		} | ||||
| 	} else if (wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { | ||||
| 		wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length); | ||||
| 		wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate); | ||||
|  | ||||
| 		/* Station information */ | ||||
| 		station->capability = __le16_to_cpu(frame->associationresponse.capability); | ||||
| @ -731,7 +729,7 @@ static void wifi_wlan_receive_station_mgmt_disassociation(struct wifi_wlan* wlan | ||||
| 	/* TODO */ | ||||
|  | ||||
| 	/* Notify disassociation message also to AC */ | ||||
| 	wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length); | ||||
| 	wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate); | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| @ -752,7 +750,7 @@ static void wifi_wlan_receive_station_mgmt_deauthentication(struct wifi_wlan* wl | ||||
| 	} | ||||
|  | ||||
| 	/* Notify deauthentication message also to AC */ | ||||
| 	wlan->send_frame(wlan->send_frame_to_ac_cbparam, frame, length); | ||||
| 	wifi_wlan_send_frame(wlan, (uint8_t*)frame, length, 1, rssi, snr, rate); | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| @ -1580,6 +1578,9 @@ void wifi_wlan_receive_station_frame(struct wifi_wlan* wlan, const struct ieee80 | ||||
| 	uint16_t framecontrol_type; | ||||
| 	uint16_t framecontrol_subtype; | ||||
|  | ||||
| 	ASSERT(wlan != NULL); | ||||
| 	ASSERT(wlan->handle != NULL); | ||||
|  | ||||
| 	/* Check frame */ | ||||
| 	if (!frame || (length < sizeof(struct ieee80211_header))) { | ||||
| 		return; | ||||
| @ -1602,6 +1603,9 @@ void wifi_wlan_receive_station_ackframe(struct wifi_wlan* wlan, const struct iee | ||||
| 	uint16_t framecontrol_type; | ||||
| 	uint16_t framecontrol_subtype; | ||||
|  | ||||
| 	ASSERT(wlan != NULL); | ||||
| 	ASSERT(wlan->handle != NULL); | ||||
|  | ||||
| 	/* Check frame */ | ||||
| 	if (!frame || (length < sizeof(struct ieee80211_header))) { | ||||
| 		return; | ||||
| @ -1625,6 +1629,9 @@ void wifi_wlan_receive_ac_frame(struct wifi_wlan* wlan, struct ieee80211_header* | ||||
| 	uint16_t framecontrol_type; | ||||
| 	uint16_t framecontrol_subtype; | ||||
|  | ||||
| 	ASSERT(wlan != NULL); | ||||
| 	ASSERT(wlan->handle != NULL); | ||||
|  | ||||
| 	/* Check frame */ | ||||
| 	if (!frame || (length < sizeof(struct ieee80211_header))) { | ||||
| 		return; | ||||
| @ -1647,6 +1654,19 @@ void wifi_wlan_receive_ac_frame(struct wifi_wlan* wlan, struct ieee80211_header* | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| int wifi_wlan_send_frame(struct wifi_wlan* wlan, const uint8_t* data, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate) { | ||||
| 	ASSERT(wlan != NULL); | ||||
| 	ASSERT(wlan->handle != NULL); | ||||
|  | ||||
| 	if (!data || (length <= 0) || !wlan->send_frame) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	return wlan->send_frame(wlan->send_frame_to_ac_cbparam, data, length, nativeframe, rssi, snr, rate, wlan->address, MACADDRESS_EUI48_LENGTH); | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| int wifi_station_authorize(struct wifi_wlan* wlan, struct station_add_params* params) { | ||||
| 	int result; | ||||
|  | ||||
| @ -87,7 +87,7 @@ struct device_setconfiguration_params { | ||||
| }; | ||||
|  | ||||
| /* */ | ||||
| typedef void (*send_frame_to_ac)(void* param, const struct ieee80211_header_mgmt* mgmt, int mgmtlength); | ||||
| typedef int (*send_frame_to_ac)(void* param, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype); | ||||
|  | ||||
| struct wlan_startap_params { | ||||
| 	send_frame_to_ac send_frame; | ||||
| @ -409,6 +409,7 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params | ||||
| void wifi_wlan_stopap(struct wifi_wlan* wlan); | ||||
| int wifi_wlan_getbssid(struct wifi_wlan* wlan, uint8_t* bssid); | ||||
| uint16_t wifi_wlan_check_capability(struct wifi_wlan* wlan, uint16_t capability); | ||||
| int wifi_wlan_send_frame(struct wifi_wlan* wlan, const uint8_t* data, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate); | ||||
| void wifi_wlan_destroy(struct wifi_wlan* wlan); | ||||
|  | ||||
| /* WLAN packet management */ | ||||
|  | ||||
| @ -1,8 +1,7 @@ | ||||
| #include "capwap.h" | ||||
| #include "wtp.h" | ||||
| #include "capwap_array.h" | ||||
| #include "capwap_list.h" | ||||
| #include "capwap_element.h" | ||||
| #include "capwap_network.h" | ||||
| #include <netlink/genl/genl.h> | ||||
| #include <netlink/genl/family.h> | ||||
| #include <netlink/genl/ctrl.h> | ||||
| @ -371,11 +370,9 @@ static int nl80211_wlan_event(struct wifi_wlan* wlan, struct genlmsghdr* gnlh, s | ||||
| 			if (tb_msg[NL80211_ATTR_FRAME]) { | ||||
| 				uint32_t frequency = (tb_msg[NL80211_ATTR_WIPHY_FREQ] ? nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]) : 0); | ||||
| 				uint8_t rssi = (tb_msg[NL80211_ATTR_RX_SIGNAL_DBM] ? (uint8_t)nla_get_u32(tb_msg[NL80211_ATTR_RX_SIGNAL_DBM]) : 0); | ||||
| 				uint8_t snr = 0; | ||||
| 				uint16_t rate = 0; | ||||
|  | ||||
| 				/* */ | ||||
| 				wifi_wlan_receive_station_frame(wlan, (struct ieee80211_header*)nla_data(tb_msg[NL80211_ATTR_FRAME]), nla_len(tb_msg[NL80211_ATTR_FRAME]), frequency, rssi, snr, rate); | ||||
| 				wifi_wlan_receive_station_frame(wlan, (struct ieee80211_header*)nla_data(tb_msg[NL80211_ATTR_FRAME]), nla_len(tb_msg[NL80211_ATTR_FRAME]), frequency, rssi, 0, 0); | ||||
| 			} | ||||
|  | ||||
| 			break; | ||||
| @ -799,15 +796,26 @@ static int nl80211_wlan_startap(struct wifi_wlan* wlan) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	if (wlan->tunnelmode != CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL) { | ||||
| 		/* Join interface to kernel module */ | ||||
| 		if ((g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_KERNELMODE) || (g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_USERMODE)) { | ||||
| 			uint32_t mode = ((g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_KERNELMODE) ? WTP_KMOD_MODE_TUNNEL_KERNELMODE : WTP_KMOD_MODE_TUNNEL_USERMODE); | ||||
| 			uint32_t flags = ((wlan->tunnelmode == CAPWAP_ADD_WLAN_TUNNELMODE_80211) ? WTP_KMOD_FLAGS_TUNNEL_NATIVE : WTP_KMOD_FLAGS_TUNNEL_8023); | ||||
|  | ||||
| 			if (!wtp_kmod_join_mac80211_device(wlan, mode, flags)) { | ||||
| 				capwap_logging_info("Joined in kernel mode the interface %d", wlan->virtindex); | ||||
| 			} | ||||
| 		} else { | ||||
| 			capwap_logging_warning("Tunneling is not supported for interface %d", wlan->virtindex); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Enable operation status */ | ||||
| 	wlan->flags |= WIFI_WLAN_OPERSTATE_RUNNING; | ||||
| 	netlink_set_link_status(wlanhandle->devicehandle->globalhandle->netlinkhandle, wlan->virtindex, -1, IF_OPER_UP); | ||||
|  | ||||
| 	/* */ | ||||
| 	if (!wtp_kmod_join_mac80211_device(wlan->virtindex)) { | ||||
| 		capwap_logging_info("Joined in kernel mode the interface %d", wlan->virtindex); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -822,6 +830,14 @@ static void nl80211_wlan_stopap(struct wifi_wlan* wlan) { | ||||
| 	/* */ | ||||
| 	wlanhandle = (struct nl80211_wlan_handle*)wlan->handle; | ||||
|  | ||||
| 	/* */ | ||||
| 	if (wlan->tunnelmode != CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL) { | ||||
| 		/* Leave interface from kernel module */ | ||||
| 		if ((g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_KERNELMODE) || (g_wtp.tunneldataframe == WTP_TUNNEL_DATA_FRAME_USERMODE)) { | ||||
| 			wtp_kmod_leave_mac80211_device(wlan); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	if (wlan->flags & WIFI_WLAN_SET_BEACON) { | ||||
| 		msg = nlmsg_alloc(); | ||||
|  | ||||
| @ -62,6 +62,7 @@ static int wtp_init(void) { | ||||
|  | ||||
| 	g_wtp.mactype.type = CAPWAP_LOCALMAC; | ||||
| 	g_wtp.mactunnel.mode = CAPWAP_WTP_LOCAL_BRIDGING; | ||||
| 	g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_KERNELMODE; | ||||
|  | ||||
| 	/* DTLS */ | ||||
| 	g_wtp.validdtlsdatapolicy = CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED; | ||||
| @ -650,6 +651,19 @@ static int wtp_parsing_configuration_1_0(config_t* config) { | ||||
| 				g_wtp.mactunnel.mode |=  CAPWAP_WTP_LOCAL_BRIDGING; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (config_lookup_string(config, "application.tunnelmode.dataframe", &configString) == CONFIG_TRUE) { | ||||
| 			if (!strcmp(configString, "none")) { | ||||
| 				g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_NONE; | ||||
| 			} else if (!strcmp(configString, "kernelmode")) { | ||||
| 				g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_KERNELMODE; | ||||
| 			} else if (!strcmp(configString, "usermode")) { | ||||
| 				g_wtp.tunneldataframe = WTP_TUNNEL_DATA_FRAME_USERMODE; | ||||
| 			} else { | ||||
| 				capwap_logging_error("Invalid configuration file, unknown application.tunnelmode.dataframe value"); | ||||
| 				return 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Set mactype of WTP */ | ||||
|  | ||||
| @ -42,6 +42,10 @@ | ||||
|  | ||||
| #define WTP_INIT_REMOTE_SEQUENCE				0xff | ||||
|  | ||||
| #define WTP_TUNNEL_DATA_FRAME_NONE				0x00000000 | ||||
| #define WTP_TUNNEL_DATA_FRAME_KERNELMODE		0x00000001 | ||||
| #define WTP_TUNNEL_DATA_FRAME_USERMODE			0x00000002 | ||||
|  | ||||
| /* */ | ||||
| struct wtp_fds { | ||||
| 	int fdstotalcount; | ||||
| @ -109,6 +113,8 @@ struct wtp_t { | ||||
| 	struct capwap_statisticstimer_element statisticstimer; | ||||
| 	struct capwap_wtprebootstat_element rebootstat; | ||||
|  | ||||
| 	int tunneldataframe; | ||||
|  | ||||
| 	struct capwap_packet_rxmng* rxmngctrlpacket; | ||||
| 	struct capwap_packet_rxmng* rxmngdatapacket; | ||||
|  | ||||
|  | ||||
| @ -69,6 +69,6 @@ void wtp_dfa_state_reset(void); | ||||
|  | ||||
| /* */ | ||||
| void wtp_ieee80211_packet(uint8_t radioid, const struct ieee80211_header* header, int length); | ||||
| void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe); | ||||
| int wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype); | ||||
|  | ||||
| #endif /* __WTP_DFA_HEADER__ */ | ||||
|  | ||||
| @ -251,22 +251,45 @@ static void send_data_keepalive_request() { | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe) { | ||||
| int wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype) { | ||||
| 	int result; | ||||
| 	struct capwap_list* txfragpacket; | ||||
| 	struct capwap_header_data capwapheader; | ||||
| 	struct capwap_packet_txmng* txmngpacket; | ||||
|  | ||||
| 	ASSERT(IS_VALID_RADIOID(radioid)); | ||||
| 	ASSERT(IS_VALID_WLANID(wlanid)); | ||||
| 	ASSERT(frame != NULL); | ||||
| 	ASSERT(length > 0); | ||||
|  | ||||
| 	/* Check for IEEE 802.3 frame */ | ||||
| 	if (!nativeframe && (!bssaddress || (bssaddresstype == MACADDRESS_NONE_LENGTH))) { | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Build packet */ | ||||
| 	capwap_header_init(&capwapheader, radioid, g_wtp.binding); | ||||
| 	capwap_header_set_nativeframe_flag(&capwapheader, (leavenativeframe ? 1: 0)); | ||||
| 	capwap_header_set_nativeframe_flag(&capwapheader, (nativeframe ? 1: 0)); | ||||
|  | ||||
| 	/* Set radio macaddress */ | ||||
| 	if (!nativeframe) { | ||||
| 		capwap_header_set_radio_macaddress(&capwapheader, bssaddresstype, bssaddress); | ||||
| 	} | ||||
|  | ||||
| 	/* Set wireless information */ | ||||
| 	if (rssi || snr || rate) { | ||||
| 		struct capwap_ieee80211_frame_info frameinfo; | ||||
|  | ||||
| 		frameinfo.rssi = rssi; | ||||
| 		frameinfo.snr = snr; | ||||
| 		frameinfo.rate = htons(rate); | ||||
| 		capwap_header_set_wireless_information(&capwapheader, &frameinfo, sizeof(struct capwap_ieee80211_frame_info)); | ||||
| 	} | ||||
|  | ||||
| 	txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, g_wtp.mtu); | ||||
|  | ||||
| 	/* */ | ||||
| 	if (leavenativeframe) { | ||||
| 		capwap_packet_txmng_add_data(txmngpacket, data, (unsigned short)length); | ||||
| 	} else { | ||||
| 		/* TODO */ | ||||
| 	} | ||||
| 	capwap_packet_txmng_add_data(txmngpacket, frame, (unsigned short)length); | ||||
|  | ||||
| 	/* Data message complete, get fragment packets into local list */ | ||||
| 	txfragpacket = capwap_list_create(); | ||||
| @ -275,13 +298,17 @@ void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data, | ||||
| 		g_wtp.fragmentid++; | ||||
| 	} | ||||
|  | ||||
| 	if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txfragpacket, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress)) { | ||||
| 	/* */ | ||||
| 	result = capwap_crypt_sendto_fragmentpacket(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txfragpacket, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress); | ||||
| 	if (!result) { | ||||
| 		capwap_logging_debug("Warning: error to send data packet"); | ||||
| 	} | ||||
|  | ||||
| 	/* Free packets manager */ | ||||
| 	capwap_list_free(txfragpacket); | ||||
| 	capwap_packet_txmng_free(txmngpacket); | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
|  | ||||
| @ -81,6 +81,33 @@ static int wtp_kmod_ack_handler(struct nl_msg* msg, void* arg) { | ||||
| 	return NL_STOP; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| static int wtp_kmod_event_handler(struct genlmsghdr* gnlh, struct nlattr** tb_msg, void* data) { | ||||
| 	switch (gnlh->cmd) { | ||||
| 		case NLSMARTCAPWAP_CMD_FRAME: { | ||||
| 			struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)data; | ||||
|  | ||||
| 			if (tb_msg[NLSMARTCAPWAP_ATTR_FRAME]) { | ||||
| 				uint32_t sig_dbm = (tb_msg[NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM] ? nla_get_u32(tb_msg[NLSMARTCAPWAP_ATTR_RX_SIGNAL_DBM]) : 0); | ||||
| 				uint16_t rate = (tb_msg[NLSMARTCAPWAP_ATTR_RX_RATE] ? ((uint16_t)nla_get_u8(tb_msg[NLSMARTCAPWAP_ATTR_RX_RATE])) * 5 : 0);		/* Convert rate 500Kbps to 100Kbps */ | ||||
| 				int nativeframe = (tb_msg[SMARTCAPWAP_FLAGS_TUNNEL_8023] ? 0 : 1); | ||||
|  | ||||
| 				/* Forwards the frame to AC */ | ||||
| 				wifi_wlan_send_frame(interface->wlan, (uint8_t*)nla_data(tb_msg[NLSMARTCAPWAP_ATTR_FRAME]), nla_len(tb_msg[NLSMARTCAPWAP_ATTR_FRAME]), nativeframe, (uint8_t)sig_dbm, 0, rate); | ||||
| 			} | ||||
|  | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		default: { | ||||
| 			capwap_logging_debug("*** wtp_kmod_event_handler: %d", (int)gnlh->cmd); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return NL_SKIP; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| static int wtp_kmod_valid_handler(struct nl_msg* msg, void* data) { | ||||
| 	struct nlattr* tb_msg[NLSMARTCAPWAP_ATTR_MAX + 1]; | ||||
| @ -88,7 +115,7 @@ static int wtp_kmod_valid_handler(struct nl_msg* msg, void* data) { | ||||
|  | ||||
| 	nla_parse(tb_msg, NLSMARTCAPWAP_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); | ||||
|  | ||||
| 	return NL_SKIP; | ||||
| 	return wtp_kmod_event_handler(gnlh, tb_msg, data); | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| @ -177,12 +204,122 @@ static void wtp_kmod_event_receive(int fd, void** params, int paramscount) { | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| int wtp_kmod_join_mac80211_device(uint32_t ifindex) { | ||||
| int wtp_kmod_join_mac80211_device(struct wifi_wlan* wlan, uint32_t mode, uint32_t flags) { | ||||
| 	int result; | ||||
| 	struct nl_sock* nl; | ||||
| 	struct nl_cb* nl_cb; | ||||
| 	struct nl_msg* msg; | ||||
| 	struct capwap_list_item* itemlist; | ||||
| 	struct wtp_kmod_iface_handle* interface; | ||||
| 	uint32_t kmodflags = 0; | ||||
| 	uint16_t subtype_mgmt = 0; | ||||
| 	uint16_t subtype_ctrl = 0; | ||||
| 	uint16_t subtype_data = 0; | ||||
|  | ||||
| 	ASSERT(wlan != NULL); | ||||
|  | ||||
| 	/* */ | ||||
| 	if (!wtp_kmod_isconnected()) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	itemlist = capwap_itemlist_create(sizeof(struct wtp_kmod_iface_handle)); | ||||
| 	interface = (struct wtp_kmod_iface_handle*)itemlist->item; | ||||
|  | ||||
| 	/* Socket management */ | ||||
| 	nl_cb = nl_cb_alloc(NL_CB_DEFAULT); | ||||
| 	if (!nl_cb) { | ||||
| 		capwap_itemlist_free(itemlist); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	nl_cb_set(nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, wtp_kmod_no_seq_check, NULL); | ||||
| 	nl_cb_set(nl_cb, NL_CB_VALID, NL_CB_CUSTOM, wtp_kmod_valid_handler, (void*)interface); | ||||
|  | ||||
| 	nl = nl_create_handle(nl_cb); | ||||
| 	if (!nl) { | ||||
| 		nl_cb_put(nl_cb); | ||||
| 		capwap_itemlist_free(itemlist); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	msg = nlmsg_alloc(); | ||||
| 	if (!msg) { | ||||
| 		nl_socket_free(nl); | ||||
| 		nl_cb_put(nl_cb); | ||||
| 		capwap_itemlist_free(itemlist); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* Set flags */ | ||||
| 	switch (mode) { | ||||
| 		case WTP_KMOD_MODE_LOCAL: { | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		case WTP_KMOD_MODE_TUNNEL_USERMODE: { | ||||
| 			kmodflags |= SMARTCAPWAP_FLAGS_SEND_USERSPACE | SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME; | ||||
| 			subtype_data = 0xffff; | ||||
|  | ||||
| 			if (flags & WTP_KMOD_FLAGS_TUNNEL_8023) { | ||||
| 				kmodflags |= SMARTCAPWAP_FLAGS_TUNNEL_8023; | ||||
| 			} | ||||
|  | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		case WTP_KMOD_MODE_TUNNEL_KERNELMODE: { | ||||
| 			kmodflags |= SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME; | ||||
| 			subtype_data = 0xffff; | ||||
|  | ||||
| 			if (flags & WTP_KMOD_FLAGS_TUNNEL_8023) { | ||||
| 				kmodflags |= SMARTCAPWAP_FLAGS_TUNNEL_8023; | ||||
| 			} | ||||
|  | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_JOIN_MAC80211_DEVICE, 0); | ||||
| 	nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFINDEX, wlan->virtindex); | ||||
| 	nla_put_u32(msg, NLSMARTCAPWAP_ATTR_FLAGS, kmodflags); | ||||
| 	nla_put_u16(msg, NLSMARTCAPWAP_ATTR_MGMT_SUBTYPE_MASK, subtype_mgmt); | ||||
| 	nla_put_u16(msg, NLSMARTCAPWAP_ATTR_CTRL_SUBTYPE_MASK, subtype_ctrl); | ||||
| 	nla_put_u16(msg, NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK, subtype_data); | ||||
|  | ||||
| 	/* */ | ||||
| 	result = wtp_kmod_send_and_recv(nl, nl_cb, msg, NULL, NULL); | ||||
| 	if (!result) { | ||||
| 		interface->nl = nl; | ||||
| 		interface->nl_fd = nl_socket_get_fd(nl); | ||||
| 		interface->nl_cb = nl_cb; | ||||
| 		interface->wlan = wlan; | ||||
|  | ||||
| 		/* */ | ||||
| 		capwap_itemlist_insert_after(g_wtp.kmodhandle.interfaces, NULL, itemlist); | ||||
| 	} else { | ||||
| 		nl_socket_free(nl); | ||||
| 		nl_cb_put(nl_cb); | ||||
| 		capwap_itemlist_free(itemlist); | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	nlmsg_free(msg); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| int wtp_kmod_leave_mac80211_device(struct wifi_wlan* wlan) { | ||||
| 	int result; | ||||
| 	struct nl_msg* msg; | ||||
|  | ||||
| 	ASSERT(wlan != NULL); | ||||
|  | ||||
| 	/* */ | ||||
| 	if (!g_wtp.kmodhandle.nlsmartcapwap_id) { | ||||
| 	if (!wtp_kmod_isconnected()) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -193,15 +330,26 @@ int wtp_kmod_join_mac80211_device(uint32_t ifindex) { | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_JOIN_MAC80211_DEVICE, 0); | ||||
| 	nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFINDEX, ifindex); | ||||
| 	nla_put_u32(msg, NLSMARTCAPWAP_ATTR_FLAGS, SMARTCAPWAP_FLAGS_SEND_USERSPACE | SMARTCAPWAP_FLAGS_BLOCK_DATA_FRAME); | ||||
| 	nla_put_u16(msg, NLSMARTCAPWAP_ATTR_DATA_SUBTYPE_MASK, 0xffff); | ||||
| 	genlmsg_put(msg, 0, 0, g_wtp.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_LEAVE_MAC80211_DEVICE, 0); | ||||
| 	nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFINDEX, wlan->virtindex); | ||||
|  | ||||
| 	/* */ | ||||
| 	result = wtp_kmod_send_and_recv_msg(msg, NULL, NULL); | ||||
| 	if (result) { | ||||
| 		capwap_logging_warning("Unable to join with interface: %d", ifindex); | ||||
| 	if (!result) { | ||||
| 		struct capwap_list_item* itemlist; | ||||
|  | ||||
| 		for (itemlist = g_wtp.kmodhandle.interfaces->first; itemlist != NULL; itemlist = itemlist->next) { | ||||
| 			struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)itemlist->item; | ||||
|  | ||||
| 			if (interface->wlan == wlan) { | ||||
| 				nl_socket_free(interface->nl); | ||||
| 				nl_cb_put(interface->nl_cb); | ||||
|  | ||||
| 				/* Free item */ | ||||
| 				capwap_itemlist_free(capwap_itemlist_remove(g_wtp.kmodhandle.interfaces, itemlist)); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| @ -216,7 +364,9 @@ int wtp_kmod_isconnected(void) { | ||||
|  | ||||
| /* */ | ||||
| int wtp_kmod_getfd(struct pollfd* fds, struct wtp_kmod_event* events, int count) { | ||||
| 	int kmodcount = (wtp_kmod_isconnected() ? 1 : 0); | ||||
| 	int i = 1; | ||||
| 	struct capwap_list_item* itemlist; | ||||
| 	int kmodcount = (wtp_kmod_isconnected() ? 1 + g_wtp.kmodhandle.interfaces->count : 0); | ||||
|  | ||||
| 	/* */ | ||||
| 	if (!fds && !events && !count) { | ||||
| @ -237,6 +387,22 @@ int wtp_kmod_getfd(struct pollfd* fds, struct wtp_kmod_event* events, int count) | ||||
| 	events[0].params[1] = (void*)g_wtp.kmodhandle.nl_cb; | ||||
| 	events[0].paramscount = 2; | ||||
|  | ||||
| 	/* */ | ||||
| 	for (itemlist = g_wtp.kmodhandle.interfaces->first; itemlist; i++, itemlist = itemlist->next) { | ||||
| 		struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)itemlist->item; | ||||
|  | ||||
| 		/* */ | ||||
| 		fds[i].fd = interface->nl_fd; | ||||
| 		fds[i].events = POLLIN | POLLERR | POLLHUP; | ||||
|  | ||||
| 		/* */ | ||||
| 		events[i].event_handler = wtp_kmod_event_receive; | ||||
| 		events[i].params[0] = (void*)interface->nl; | ||||
| 		events[i].params[1] = (void*)interface->nl_cb; | ||||
| 		events[i].paramscount = 2; | ||||
| 	} | ||||
|  | ||||
| 	ASSERT(kmodcount == i); | ||||
| 	return kmodcount; | ||||
| } | ||||
|  | ||||
| @ -279,11 +445,26 @@ int wtp_kmod_init(void) { | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	/* */ | ||||
| 	g_wtp.kmodhandle.interfaces = capwap_list_create(); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| void wtp_kmod_free(void) { | ||||
| 	if (g_wtp.kmodhandle.interfaces) { | ||||
| 		while (g_wtp.kmodhandle.interfaces->first) { | ||||
| 			struct wtp_kmod_iface_handle* interface = (struct wtp_kmod_iface_handle*)g_wtp.kmodhandle.interfaces->first->item; | ||||
|  | ||||
| 			if (wtp_kmod_leave_mac80211_device(interface->wlan)) { | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* */ | ||||
| 		capwap_list_free(g_wtp.kmodhandle.interfaces); | ||||
| 	} | ||||
|  | ||||
| 	if (g_wtp.kmodhandle.nl) { | ||||
| 		nl_socket_free(g_wtp.kmodhandle.nl); | ||||
| 	} | ||||
|  | ||||
| @ -1,17 +1,40 @@ | ||||
| #ifndef __WTP_KMOD_HEADER__ | ||||
| #define __WTP_KMOD_HEADER__ | ||||
|  | ||||
| #include "wifi_drivers.h" | ||||
|  | ||||
| /* */ | ||||
| #ifdef HAVE_LIBNL_10  | ||||
| #define nl_sock nl_handle | ||||
| #endif | ||||
|  | ||||
| /* */ | ||||
| #define WTP_KMOD_MODE_LOCAL							0x00000001 | ||||
| #define WTP_KMOD_MODE_TUNNEL_USERMODE				0x00000002 | ||||
| #define WTP_KMOD_MODE_TUNNEL_KERNELMODE				0x00000003 | ||||
|  | ||||
| /* */ | ||||
| #define WTP_KMOD_FLAGS_TUNNEL_NATIVE				0x00000000 | ||||
| #define WTP_KMOD_FLAGS_TUNNEL_8023					0x00000001 | ||||
|  | ||||
| /* */ | ||||
| struct wtp_kmod_iface_handle { | ||||
| 	struct nl_sock* nl; | ||||
| 	int nl_fd; | ||||
| 	struct nl_cb* nl_cb; | ||||
|  | ||||
| 	struct wifi_wlan* wlan; | ||||
| }; | ||||
|  | ||||
| /* */ | ||||
| struct wtp_kmod_handle { | ||||
| 	struct nl_sock* nl; | ||||
| 	int nl_fd; | ||||
| 	struct nl_cb* nl_cb; | ||||
| 	int nlsmartcapwap_id; | ||||
|  | ||||
| 	/* */ | ||||
| 	struct capwap_list* interfaces; | ||||
| }; | ||||
|  | ||||
| /* */ | ||||
| @ -31,6 +54,7 @@ int wtp_kmod_isconnected(void); | ||||
| int wtp_kmod_getfd(struct pollfd* fds, struct wtp_kmod_event* events, int count); | ||||
|  | ||||
| /* */ | ||||
| int wtp_kmod_join_mac80211_device(uint32_t ifindex); | ||||
| int wtp_kmod_join_mac80211_device(struct wifi_wlan* wlan, uint32_t mode, uint32_t flags); | ||||
| int wtp_kmod_leave_mac80211_device(struct wifi_wlan* wlan); | ||||
|  | ||||
| #endif /* __WTP_KMOD_HEADER__ */ | ||||
|  | ||||
| @ -51,15 +51,15 @@ static int wtp_radio_configure_phy(struct wtp_radio* radio) { | ||||
| } | ||||
|  | ||||
| /* */ | ||||
| static void wtp_radio_send_frame_to_ac(void* param, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { | ||||
| static int wtp_radio_send_frame_to_ac(void* param, const uint8_t* frame, int length, int nativeframe, uint8_t rssi, uint8_t snr, uint16_t rate, uint8_t* bssaddress, int bssaddresstype) { | ||||
| 	struct wtp_radio_wlan* wlan = (struct wtp_radio_wlan*)param; | ||||
|  | ||||
| 	ASSERT(param != NULL); | ||||
| 	ASSERT(mgmt != NULL); | ||||
| 	ASSERT(mgmtlength >= sizeof(struct ieee80211_header)); | ||||
| 	ASSERT(frame != NULL); | ||||
| 	ASSERT(length > 0); | ||||
|  | ||||
| 	/* Send packet */ | ||||
| 	wtp_send_data_packet(wlan->radio->radioid, wlan->wlanid, (const uint8_t*)mgmt, mgmtlength, 1); | ||||
| 	return wtp_send_data_packet(wlan->radio->radioid, wlan->wlanid, frame, length, nativeframe, rssi, snr, rate, bssaddress, bssaddresstype); | ||||
| } | ||||
|  | ||||
| /* */ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user