コード例 #1
0
static void* capwap_radioadmstate_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
	struct capwap_radioadmstate_element* data;

	ASSERT(handle != NULL);
	ASSERT(func != NULL);

	if (func->read_ready(handle) != 2) {
		log_printf(LOG_DEBUG, "Invalid Radio Administrative State element: underbuffer");
		return NULL;
	}

	/* Retrieve data */
	data = (struct capwap_radioadmstate_element*)capwap_alloc(sizeof(struct capwap_radioadmstate_element));
	func->read_u8(handle, &data->radioid);
	func->read_u8(handle, &data->state);

	if (!IS_VALID_RADIOID(data->radioid)) {
		capwap_radioadmstate_element_free((void*)data);
		log_printf(LOG_DEBUG, "Invalid Radio Administrative State element: invalid radioid");
		return NULL;
	} else if ((data->state != CAPWAP_RADIO_ADMIN_STATE_ENABLED) && (data->state != CAPWAP_RADIO_ADMIN_STATE_DISABLED)) {
		capwap_radioadmstate_element_free((void*)data);
		log_printf(LOG_DEBUG, "Invalid Radio Administrative State element: invalid state");
		return NULL;
	}

	return data;
}
コード例 #2
0
ファイル: ac_kmod.c プロジェクト: nm-mrt/smartcapwap
int ac_kmod_addwlan(struct capwap_sessionid_element* sessionid, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, uint8_t macmode, uint8_t tunnelmode) {
	int result;
	struct nl_msg* msg;

	ASSERT(sessionid != NULL);
	ASSERT(IS_VALID_RADIOID(radioid));
	ASSERT(IS_VALID_WLANID(wlanid));
	ASSERT(bssid != NULL);

	/* */
	msg = nlmsg_alloc();
	if (!msg) {
		return -1;
	}

	/* */
	genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_ADD_WLAN, 0);
	nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
	nla_put_u8(msg, NLSMARTCAPWAP_ATTR_RADIOID, radioid);
	nla_put_u8(msg, NLSMARTCAPWAP_ATTR_WLANID, wlanid);
	nla_put(msg, NLSMARTCAPWAP_ATTR_MACADDRESS, MACADDRESS_EUI48_LENGTH, bssid);
	nla_put_u8(msg, NLSMARTCAPWAP_ATTR_MACMODE, macmode);
	nla_put_u8(msg, NLSMARTCAPWAP_ATTR_TUNNELMODE, tunnelmode);

	/* */
	result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
	if (result) {
		log_printf(LOG_ERR, "Unable to add wlan: %d", result);
	}

	/* */
	nlmsg_free(msg);
	return result;
}
コード例 #3
0
static void capwap_80211_addwlan_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
	int length;
	struct capwap_80211_addwlan_element* element = (struct capwap_80211_addwlan_element*)data;

	ASSERT(data != NULL);
	ASSERT(IS_VALID_RADIOID(element->radioid));
	ASSERT(IS_VALID_WLANID(element->wlanid));

	func->write_u8(handle, element->radioid);
	func->write_u8(handle, element->wlanid);
	func->write_u16(handle, element->capability);
	func->write_u8(handle, element->keyindex);
	func->write_u8(handle, element->keystatus);
	func->write_u16(handle, element->keylength);
	if ((element->keylength > 0) && element->key) {
		func->write_block(handle, element->key, element->keylength);
	}
	func->write_block(handle, element->grouptsc, CAPWAP_ADD_WLAN_GROUPTSC_LENGTH);
	func->write_u8(handle, element->qos);
	func->write_u8(handle, element->authmode);
	func->write_u8(handle, element->macmode);
	func->write_u8(handle, element->tunnelmode);
	func->write_u8(handle, element->suppressssid);

	length = strlen((char*)element->ssid);
	ASSERT((length > 0) && (length <= CAPWAP_ADD_WLAN_SSID_LENGTH));

	func->write_block(handle, element->ssid, length);
}
コード例 #4
0
ファイル: ac_session.c プロジェクト: Benyjuice/smartcapwap
static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_notify_addwlan_t* notify) {
	struct capwap_header_data capwapheader;
	struct capwap_packet_txmng* txmngpacket;
	struct capwap_80211_addwlan_element addwlan;

	ASSERT(session->requestfragmentpacket->count == 0);

	/* Check if WLAN id is valid and not used */
	if (!IS_VALID_RADIOID(notify->radioid) || !IS_VALID_WLANID(notify->wlanid)) {
		return AC_NO_ERROR;
	} else if (ac_wlans_get_bssid_with_wlanid(session, notify->radioid, notify->wlanid)) {
		return AC_NO_ERROR;
	}

	/* */
	memset(&addwlan, 0, sizeof(struct capwap_80211_addwlan_element));
	addwlan.radioid = notify->radioid;
	addwlan.wlanid = notify->wlanid;
	addwlan.capability = notify->capability;
	addwlan.qos = notify->qos;
	addwlan.authmode = notify->authmode;
	addwlan.macmode = notify->macmode;
	addwlan.tunnelmode = notify->tunnelmode;
	addwlan.suppressssid = notify->suppressssid;
	addwlan.ssid = (uint8_t*)notify->ssid;

	/* Build packet */
	capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding);
	txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST, session->localseqnumber, session->mtu);

	/* Add message element */
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ADD_WLAN, &addwlan);

	/* CAPWAP_ELEMENT_80211_IE */

	/* CAPWAP_ELEMENT_VENDORPAYLOAD */				/* TODO */

	/* WLAN Configuration Request complete, get fragment packets */
	capwap_packet_txmng_get_fragment_packets(txmngpacket, session->requestfragmentpacket, session->fragmentid);
	if (session->requestfragmentpacket->count > 1) {
		session->fragmentid++;
	}

	/* Free packets manager */
	capwap_packet_txmng_free(txmngpacket);

	/* Send WLAN Configuration Request to WTP */
	if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->requestfragmentpacket)) {
		session->retransmitcount = 0;
		capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
	} else {
		capwap_logging_debug("Warning: error to send WLAN Configuration Request packet");
		ac_free_reference_last_request(session);
		ac_session_teardown(session);
	}

	return AC_NO_ERROR;
}
コード例 #5
0
static void capwap_decrypterrorreportperiod_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
	struct capwap_decrypterrorreportperiod_element* element = (struct capwap_decrypterrorreportperiod_element*)data;

	ASSERT(data != NULL);
	ASSERT(IS_VALID_RADIOID(element->radioid));

	/* */
	func->write_u8(handle, element->radioid);
	func->write_u16(handle, element->interval);
}
コード例 #6
0
static void capwap_radioadmstate_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
	struct capwap_radioadmstate_element* element = (struct capwap_radioadmstate_element*)data;

	ASSERT(data != NULL);
	ASSERT(IS_VALID_RADIOID(element->radioid));
	ASSERT((element->state == CAPWAP_RADIO_ADMIN_STATE_ENABLED) || (element->state == CAPWAP_RADIO_ADMIN_STATE_DISABLED));

	/* */
	func->write_u8(handle, element->radioid);
	func->write_u8(handle, element->state);
}
コード例 #7
0
static void* capwap_80211_antenna_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
	int i;
	uint8_t count;
	unsigned short length;
	struct capwap_80211_antenna_element* data;

	ASSERT(handle != NULL);
	ASSERT(func != NULL);

	length = func->read_ready(handle);
	if (length < 5) {
		capwap_logging_debug("Invalid IEEE 802.11 Antenna element");
		return NULL;
	}

	length -= 4;
	if (length > CAPWAP_ANTENNASELECTIONS_MAXLENGTH) {
		capwap_logging_debug("Invalid IEEE 802.11 Antenna element");
		return NULL;
	}

	/* */
	data = (struct capwap_80211_antenna_element*)capwap_alloc(sizeof(struct capwap_80211_antenna_element));
	memset(data, 0, sizeof(struct capwap_80211_antenna_element));
	data->selections = capwap_array_create(sizeof(uint8_t), 0, 1);

	/* Retrieve data */
	func->read_u8(handle, &data->radioid);
	if (!IS_VALID_RADIOID(data->radioid)) {
		capwap_80211_antenna_element_free((void*)data);
		capwap_logging_debug("Invalid IEEE 802.11 Antenna element element: invalid radio");
		return NULL;
	}

	func->read_u8(handle, &data->diversity);
	func->read_u8(handle, &data->combiner);
	func->read_u8(handle, &count);

	/* Check */
	if (count != length) {
		capwap_logging_debug("Invalid IEEE 802.11 Antenna element");
		capwap_free(data);
		return NULL;
	}

	for (i = 0; i < count; i++) {
		func->read_u8(handle, (uint8_t*)capwap_array_get_item_pointer(data->selections, i));
	}

	return data;
}
コード例 #8
0
static void* capwap_addstation_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
	unsigned short length;
	struct capwap_addstation_element* data;

	ASSERT(handle != NULL);
	ASSERT(func != NULL);

	length = func->read_ready(handle);
	if (length < 8) {
		capwap_logging_debug("Invalid Add Station element: underbuffer");
		return NULL;
	}

	length -= 2;

	/* */
	data = (struct capwap_addstation_element*)capwap_alloc(sizeof(struct capwap_addstation_element));
	memset(data, 0, sizeof(struct capwap_addstation_element));

	/* Retrieve data */
	func->read_u8(handle, &data->radioid);
	func->read_u8(handle, &data->length);

	if (!IS_VALID_RADIOID(data->radioid)) {
		capwap_addstation_element_free((void*)data);
		capwap_logging_debug("Invalid Add Station element: invalid radio");
		return NULL;
	} else if (!IS_VALID_MACADDRESS_LENGTH(data->length) || (length < data->length)) {
		capwap_addstation_element_free((void*)data);
		capwap_logging_debug("Invalid Add Station element: invalid length");
		return NULL;
	}

	data->address = (uint8_t*)capwap_alloc(data->length);
	func->read_block(handle, data->address, data->length);
	length -= data->length;

	if (length > 0) {
		if (length <= CAPWAP_ADDSTATION_VLAN_MAX_LENGTH) {
			data->vlan = (uint8_t*)capwap_alloc(length + 1);
			func->read_block(handle, data->vlan, length);
			data->vlan[length] = 0;
		} else {
			capwap_addstation_element_free((void*)data);
			capwap_logging_debug("Invalid Add Station element: invalid vlan");
			return NULL;
		}
	}

	return data;
}
コード例 #9
0
static void capwap_radiooprstate_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
	struct capwap_radiooprstate_element* element = (struct capwap_radiooprstate_element*)data;

	ASSERT(data != NULL);
	ASSERT(IS_VALID_RADIOID(element->radioid));
	ASSERT((element->state == CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED) || (element->state == CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED));
	ASSERT((element->cause == CAPWAP_RADIO_OPERATIONAL_CAUSE_NORMAL) || (element->cause == CAPWAP_RADIO_OPERATIONAL_CAUSE_RADIOFAILURE) || 
		(element->cause == CAPWAP_RADIO_OPERATIONAL_CAUSE_SOFTWAREFAILURE) || (element->cause == CAPWAP_RADIO_OPERATIONAL_CAUSE_ADMINSET));

	/* */
	func->write_u8(handle, element->radioid);
	func->write_u8(handle, element->state);
	func->write_u8(handle, element->cause);
}
コード例 #10
0
static void capwap_80211_antenna_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
	int i;
	struct capwap_80211_antenna_element* element = (struct capwap_80211_antenna_element*)data;

	ASSERT(data != NULL);
	ASSERT(IS_VALID_RADIOID(element->radioid));
	ASSERT(element->selections != NULL);

	func->write_u8(handle, element->radioid);
	func->write_u8(handle, element->diversity);
	func->write_u8(handle, element->combiner);
	func->write_u8(handle, element->selections->count);
	for (i = 0; i < element->selections->count; i++) {
		func->write_u8(handle, *(uint8_t*)capwap_array_get_item_pointer(element->selections, i));
	}
}
コード例 #11
0
ファイル: ac_session.c プロジェクト: Benyjuice/smartcapwap
static int ac_session_action_station_configuration_ieee8011_delete_station(struct ac_session_t* session, struct ac_notify_station_configuration_ieee8011_delete_station* notify) {
	struct capwap_header_data capwapheader;
	struct capwap_packet_txmng* txmngpacket;
	struct capwap_deletestation_element deletestation;

	ASSERT(session->requestfragmentpacket->count == 0);

	/* Check if RADIO id is valid */
	if (!IS_VALID_RADIOID(notify->radioid)) {
		return AC_NO_ERROR;
	}

	/* */
	memset(&deletestation, 0, sizeof(struct capwap_deletestation_element));
	deletestation.radioid = notify->radioid;
	deletestation.length = MACADDRESS_EUI48_LENGTH;
	deletestation.address = notify->address;

	/* Build packet */
	capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding);
	txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_STATION_CONFIGURATION_REQUEST, session->localseqnumber, session->mtu);

	/* Add message element */
	capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_DELETESTATION, &deletestation);
	/* CAPWAP_ELEMENT_VENDORPAYLOAD */				/* TODO */

	/* Station Configuration Request complete, get fragment packets */
	capwap_packet_txmng_get_fragment_packets(txmngpacket, session->requestfragmentpacket, session->fragmentid);
	if (session->requestfragmentpacket->count > 1) {
		session->fragmentid++;
	}

	/* Free packets manager */
	capwap_packet_txmng_free(txmngpacket);

	/* Send Station Configuration Request to WTP */
	if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->requestfragmentpacket)) {
		session->retransmitcount = 0;
		capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
	} else {
		capwap_logging_debug("Warning: error to send Station Configuration Request packet");
		ac_free_reference_last_request(session);
		ac_session_teardown(session);
	}

	return AC_NO_ERROR;
}
コード例 #12
0
ファイル: wtp_radio.c プロジェクト: nm-mrt/smartcapwap
struct wtp_radio* wtp_radio_get_phy(uint8_t radioid) {
	int i;

	/* Check */
	if (!IS_VALID_RADIOID(radioid)) {
		return NULL;
	}

	/* Retrieve radio */
	for (i = 0; i < g_wtp.radios->count; i++) {
		struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
		if (radioid == radio->radioid) {
			return radio;
		}
	}

	return NULL;
}
コード例 #13
0
static void capwap_addstation_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) {
	struct capwap_addstation_element* element = (struct capwap_addstation_element*)data;

	ASSERT(data != NULL);
	ASSERT(IS_VALID_RADIOID(element->radioid));
	ASSERT(IS_VALID_MACADDRESS_LENGTH(element->length));

	func->write_u8(handle, element->radioid);
	func->write_u8(handle, element->length);
	func->write_block(handle, element->address, element->length);
	if (element->vlan && *element->vlan) {
		unsigned short length = strlen((char*)element->vlan);

		ASSERT(length <= CAPWAP_ADDSTATION_VLAN_MAX_LENGTH);

		func->write_block(handle, element->vlan, length);
	}
}
コード例 #14
0
ファイル: ac_kmod.c プロジェクト: nm-mrt/smartcapwap
int ac_kmod_authorize_station(struct capwap_sessionid_element* sessionid, const uint8_t* macaddress, int ifindex, uint8_t radioid, uint8_t wlanid, uint16_t vlan) {
	int result;
	struct nl_msg* msg;

	ASSERT(sessionid != NULL);
	ASSERT(macaddress != NULL);
	ASSERT(ifindex >= 0);
	ASSERT(IS_VALID_RADIOID(radioid));
	ASSERT(vlan < VLAN_MAX);

	/* */
	msg = nlmsg_alloc();
	if (!msg) {
		return -1;
	}

	/* */
	genlmsg_put(msg, 0, 0, g_ac.kmodhandle.nlsmartcapwap_id, 0, 0, NLSMARTCAPWAP_CMD_AUTH_STATION, 0);
	nla_put(msg, NLSMARTCAPWAP_ATTR_SESSION_ID, sizeof(struct capwap_sessionid_element), sessionid);
	nla_put(msg, NLSMARTCAPWAP_ATTR_MACADDRESS, MACADDRESS_EUI48_LENGTH, macaddress);
	nla_put_u32(msg, NLSMARTCAPWAP_ATTR_IFPHY_INDEX, (unsigned long)ifindex);
	nla_put_u8(msg, NLSMARTCAPWAP_ATTR_RADIOID, radioid);
	nla_put_u8(msg, NLSMARTCAPWAP_ATTR_WLANID, wlanid);

	if (vlan > 0) {
		nla_put_u16(msg, NLSMARTCAPWAP_ATTR_VLAN, ifindex);
	}

	/* */
	result = ac_kmod_send_and_recv_msg(msg, NULL, NULL);
	if (result) {
		log_printf(LOG_ERR, "Unable to authorize station: %d", result);
	}

	/* */
	nlmsg_free(msg);
	return result;
}
コード例 #15
0
ファイル: ac_session.c プロジェクト: Benyjuice/smartcapwap
static int ac_session_action_station_configuration_ieee8011_add_station(struct ac_session_t* session, struct ac_notify_station_configuration_ieee8011_add_station* notify) {
	struct ac_soap_response* response;

	ASSERT(session->requestfragmentpacket->count == 0);

	/* Check if RADIO id and WLAN id is valid */
	if (!IS_VALID_RADIOID(notify->radioid) || !IS_VALID_WLANID(notify->wlanid)) {
		return AC_NO_ERROR;
	}

	/* Need authorization of Director */
	response = ac_session_action_authorizestation_request(session, notify->radioid, notify->wlanid, notify->address);
	if (response) {
		if (ac_session_action_authorizestation_response(session, response, notify)) {
			capwap_logging_info("Station is not authorized");
			/* TODO kickoff station */
		}

		ac_soapclient_free_response(response);
	}

	return AC_NO_ERROR;
}
コード例 #16
0
static void* capwap_radiooprstate_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
	struct capwap_radiooprstate_element* data;

	ASSERT(handle != NULL);
	ASSERT(func != NULL);

	if (func->read_ready(handle) != 3) {
		log_printf(LOG_DEBUG, "Invalid Radio Operational State element: underbuffer");
		return NULL;
	}

	/* Retrieve data */
	data = (struct capwap_radiooprstate_element*)capwap_alloc(sizeof(struct capwap_radiooprstate_element));
	func->read_u8(handle, &data->radioid);
	func->read_u8(handle, &data->state);
	func->read_u8(handle, &data->cause);

	if (!IS_VALID_RADIOID(data->radioid)) {
		capwap_radiooprstate_element_free((void*)data);
		log_printf(LOG_DEBUG, "Invalid Radio Operational State element: invalid radioid");
		return NULL;
	} else if ((data->state != CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED) && (data->state != CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED)) {
		capwap_radiooprstate_element_free((void*)data);
		log_printf(LOG_DEBUG, "Invalid Radio Operational State element: invalid state");
		return NULL;
	} else if ((data->cause != CAPWAP_RADIO_OPERATIONAL_CAUSE_NORMAL) && 
			(data->cause != CAPWAP_RADIO_OPERATIONAL_CAUSE_RADIOFAILURE) && 
			(data->cause != CAPWAP_RADIO_OPERATIONAL_CAUSE_SOFTWAREFAILURE) && 
			(data->cause != CAPWAP_RADIO_OPERATIONAL_CAUSE_ADMINSET)) {
		capwap_radiooprstate_element_free((void*)data);
		log_printf(LOG_DEBUG, "Invalid Radio Operational State element: invalid cause");
		return NULL;
	}

	return data;
}
コード例 #17
0
static void* capwap_decrypterrorreportperiod_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
	struct capwap_decrypterrorreportperiod_element* data;

	ASSERT(handle != NULL);
	ASSERT(func != NULL);

	if (func->read_ready(handle) != 3) {
		capwap_logging_debug("Invalid Decryption Error Report Period element: underbuffer");
		return NULL;
	}

	/* Retrieve data */
	data = (struct capwap_decrypterrorreportperiod_element*)capwap_alloc(sizeof(struct capwap_decrypterrorreportperiod_element));
	func->read_u8(handle, &data->radioid);
	func->read_u16(handle, &data->interval);

	if (!IS_VALID_RADIOID(data->radioid)) {
		capwap_decrypterrorreportperiod_element_free((void*)data);
		capwap_logging_debug("Invalid Decryption Error Report Period element: invalid radioid");
		return NULL;
	}

	return data;
}
コード例 #18
0
static void* capwap_80211_addwlan_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) {
	unsigned short length;
	struct capwap_80211_addwlan_element* data;

	ASSERT(handle != NULL);
	ASSERT(func != NULL);

	length = func->read_ready(handle);
	if (length < 20) {
		capwap_logging_debug("Invalid IEEE 802.11 Add WLAN element: underbuffer");
		return NULL;
	}

	/* */
	data = (struct capwap_80211_addwlan_element*)capwap_alloc(sizeof(struct capwap_80211_addwlan_element));
	memset(data, 0, sizeof(struct capwap_80211_addwlan_element));

	/* Retrieve data */
	func->read_u8(handle, &data->radioid);
	func->read_u8(handle, &data->wlanid);

	if (!IS_VALID_RADIOID(data->radioid)) {
		capwap_80211_addwlan_element_free((void*)data);
		capwap_logging_debug("Invalid IEEE 802.11 Add WLAN element: invalid radioid");
		return NULL;
	} else if (!IS_VALID_WLANID(data->wlanid)) {
		capwap_80211_addwlan_element_free((void*)data);
		capwap_logging_debug("Invalid IEEE 802.11 Add WLAN element: invalid wlanid");
		return NULL;
	}

	func->read_u16(handle, &data->capability);
	func->read_u8(handle, &data->keyindex);
	func->read_u8(handle, &data->keystatus);
	func->read_u16(handle, &data->keylength);

	if (data->keylength > 0) {
		data->key = (uint8_t*)capwap_alloc(data->keylength);
		func->read_block(handle, data->key, data->keylength);
	}

	func->read_block(handle, data->grouptsc, CAPWAP_ADD_WLAN_GROUPTSC_LENGTH);
	func->read_u8(handle, &data->qos);
	func->read_u8(handle, &data->authmode);
	func->read_u8(handle, &data->macmode);
	func->read_u8(handle, &data->tunnelmode);
	func->read_u8(handle, &data->suppressssid);

	length = func->read_ready(handle);
	if (!length || (length > CAPWAP_ADD_WLAN_SSID_LENGTH)) {
		capwap_80211_addwlan_element_free((void*)data);
		capwap_logging_debug("Invalid IEEE 802.11 Add WLAN element: invalid ssid");
		return NULL;
	}

	data->ssid = (uint8_t*)capwap_alloc(length + 1);
	func->read_block(handle, data->ssid, length);
	data->ssid[length] = 0;

	return data;
}