Started implementing the packet management of IEEE802.11 by AC side.

Made it clear some constants.
This commit is contained in:
vemax78
2014-04-02 22:40:04 +02:00
parent 7fd2d4357a
commit ae97e96f57
24 changed files with 609 additions and 44 deletions

View File

@ -26,11 +26,6 @@ static unsigned long ac_stations_item_gethash(const void* key, unsigned long key
return ((((unsigned long)macaddress[4] << 8) | (unsigned long)macaddress[5]) ^ ((unsigned long)macaddress[3] << 4));
}
/* */
static void ac_stations_item_free(const void* key, unsigned long keysize, void* data) {
/* TODO */
}
/* Alloc AC */
static int ac_init(void) {
g_ac.standalone = 1;
@ -79,7 +74,8 @@ static int ac_init(void) {
capwap_rwlock_init(&g_ac.sessionslock);
/* Stations */
g_ac.stations = capwap_hash_create(AC_STATIONS_HASH_SIZE, AC_STATIONS_KEY_SIZE, ac_stations_item_gethash, NULL, ac_stations_item_free);
g_ac.stations = capwap_hash_create(AC_STATIONS_HASH_SIZE, AC_STATIONS_KEY_SIZE, ac_stations_item_gethash, NULL, NULL);
capwap_rwlock_init(&g_ac.stationslock);
/* Backend */
g_ac.availablebackends = capwap_array_create(sizeof(struct ac_http_soap_server*), 0, 0);
@ -121,6 +117,7 @@ static void ac_destroy(void) {
/* Stations */
capwap_hash_free(g_ac.stations);
capwap_rwlock_destroy(&g_ac.stationslock);
/* Backend */
if (g_ac.backendacid) {

View File

@ -57,7 +57,7 @@
/* */
#define AC_STATIONS_HASH_SIZE 65536
#define AC_STATIONS_KEY_SIZE ETH_ALEN
#define AC_STATIONS_KEY_SIZE MACADDRESS_EUI48_LENGTH
/* */
struct ac_state {
@ -99,6 +99,7 @@ struct ac_t {
/* Stations */
struct capwap_hash* stations;
capwap_rwlock_t stationslock;
/* Dtls */
int enabledtls;

View File

@ -1,7 +1,9 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "capwap_array.h"
#include "ac_session.h"
#include "ac_wlans.h"
/* */
static int receive_echo_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
@ -61,13 +63,74 @@ static int receive_echo_request(struct ac_session_t* session, struct capwap_pars
return 0;
}
/* */
static void execute_ieee80211_wlan_configuration_addwlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_80211_addwlan_element* addwlan, struct capwap_parsed_packet* requestpacket) {
char buffer[18];
struct ac_wlan* wlan;
struct capwap_80211_assignbssid_element* assignbssid;
/* Get BSSID */
assignbssid = (struct capwap_80211_assignbssid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_ASSIGN_BSSID);
if (assignbssid && (assignbssid->radioid == addwlan->radioid) && (assignbssid->wlanid == addwlan->wlanid)) {
if (!ac_wlans_get_bssid(session->wlans, assignbssid->radioid, assignbssid->bssid)) {
wlan = ac_wlans_create_bssid(session->wlans, assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid);
wlan->session = session;
wlan->sessiondata = session->sessiondata;
/* Set capability */
ac_wlans_set_bssid_capability(wlan, addwlan);
/* */
capwap_logging_info("Added new wlan with radioid: %d, wlanid: %d, bssid: %s", (int)assignbssid->radioid, (int)assignbssid->wlanid, capwap_printf_macaddress(buffer, assignbssid->bssid, MACADDRESS_EUI48_LENGTH));
}
}
}
/* */
static void execute_ieee80211_wlan_configuration_updatewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_80211_updatewlan_element* updatewlan, struct capwap_parsed_packet* requestpacket) {
}
/* */
static void execute_ieee80211_wlan_configuration_deletewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_80211_deletewlan_element* deletewlan, struct capwap_parsed_packet* requestpacket) {
}
/* */
static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_80211_addwlan_element* addwlan;
struct capwap_80211_updatewlan_element* updatewlan;
struct capwap_80211_deletewlan_element* deletewlan;
struct capwap_parsed_packet requestpacket;
struct capwap_packet_rxmng* rxmngrequestpacket;
struct capwap_resultcode_element* resultcode;
/* Check the success of the Request */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
if (CAPWAP_RESULTCODE_OK(resultcode->code)) {
rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket);
if (rxmngrequestpacket) {
if (capwap_parsing_packet(rxmngrequestpacket, NULL, &requestpacket) == PARSING_COMPLETE) {
/* Detect type of IEEE802.11 WLAN Configuration Request */
addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN);
if (addwlan) {
execute_ieee80211_wlan_configuration_addwlan(session, packet, addwlan, &requestpacket);
} else {
updatewlan = (struct capwap_80211_updatewlan_element*)capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN);
if (updatewlan) {
execute_ieee80211_wlan_configuration_updatewlan(session, packet, updatewlan, &requestpacket);
} else {
deletewlan = (struct capwap_80211_deletewlan_element*)capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN);
if (deletewlan) {
execute_ieee80211_wlan_configuration_deletewlan(session, packet, deletewlan, &requestpacket);
}
}
}
}
/* */
capwap_free_parsed_packet(&requestpacket);
capwap_packet_rxmng_free(rxmngrequestpacket);
}
} else {
capwap_logging_warning("Receive IEEE802.11 WLAN Configuration Response with error: %d", (int)resultcode->code);
}

View File

@ -156,12 +156,12 @@ static void ac_discovery_run(void) {
sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet);
/* Accept only discovery request don't fragment */
rxmngpacket = capwap_packet_rxmng_create_message(1);
rxmngpacket = capwap_packet_rxmng_create_message(CAPWAP_CONTROL_PACKET);
if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, acpacket->data, sizedata) == CAPWAP_RECEIVE_COMPLETE_PACKET) {
/* Validate message */
if (capwap_check_message_type(rxmngpacket) == VALID_MESSAGE_TYPE) {
/* Parsing packet */
if (!capwap_parsing_packet(rxmngpacket, NULL, &packet)) {
if (capwap_parsing_packet(rxmngpacket, NULL, &packet) == PARSING_COMPLETE) {
/* Validate packet */
if (!capwap_validate_parsed_packet(&packet, NULL)) {
struct capwap_packet_txmng* txmngpacket;

View File

@ -3,6 +3,7 @@
#include "ac_session.h"
#include "ac_discovery.h"
#include "ac_backend.h"
#include "ac_wlans.h"
#include <signal.h>
@ -501,6 +502,9 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
session->count = 2;
capwap_event_init(&session->changereference);
/* */
session->wlans = ac_wlans_init();
/* */
session->timeout = capwap_timeout_init();
session->idtimercontrol = capwap_timeout_createtimer(session->timeout);

View File

@ -3,8 +3,165 @@
#include "ieee80211.h"
/* */
void ac_ieee80211_data(struct ac_session_data_t* sessiondata, uint8_t* buffer, int length) {
static void ac_ieee80211_mgmt_probe_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_reassociation_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_disassociation_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_deauthentication_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* TODO */
}
/* */
static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, uint16_t framecontrol_subtype) {
switch (framecontrol_subtype) {
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQUEST: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest))) {
ac_ieee80211_mgmt_probe_request_packet(sessiondata, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication))) {
ac_ieee80211_mgmt_authentication_packet(sessiondata, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest))) {
ac_ieee80211_mgmt_association_request_packet(sessiondata, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationrequest))) {
ac_ieee80211_mgmt_reassociation_request_packet(sessiondata, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->disassociation))) {
ac_ieee80211_mgmt_disassociation_packet(sessiondata, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->deauthetication))) {
ac_ieee80211_mgmt_deauthentication_packet(sessiondata, mgmt, mgmtlength);
}
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION: {
break;
}
}
}
/* */
void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, const uint8_t* buffer, int length) {
const struct ieee80211_header* header;
uint16_t framecontrol;
uint16_t framecontrol_type;
uint16_t framecontrol_subtype;
ASSERT(sessiondata != NULL);
ASSERT(buffer != NULL);
ASSERT(length > 0);
ASSERT(length >= sizeof(struct ieee80211_header));
/* Get type frame */
header = (const struct ieee80211_header*)buffer;
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
framecontrol_subtype = IEEE80211_FRAME_CONTROL_GET_SUBTYPE(framecontrol);
/* Parsing frame */
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
ac_ieee80211_mgmt_packet(sessiondata, (const struct ieee80211_header_mgmt*)buffer, length, framecontrol_subtype);
}
}

View File

@ -3,6 +3,7 @@
#include "capwap_dfa.h"
#include "ac_session.h"
#include "ac_backend.h"
#include "ac_wlans.h"
#include <arpa/inet.h>
#define AC_ERROR_TIMEOUT -1000
@ -59,6 +60,13 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not
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_ERROR_ACTION_SESSION;
} else if (ac_wlans_get_bssid_with_wlanid(session->wlans, notify->radioid, notify->wlanid)) {
return AC_ERROR_ACTION_SESSION;
}
/* */
memset(&addwlan, 0, sizeof(struct capwap_80211_addwlan_element));
addwlan.radioid = notify->radioid;
@ -397,6 +405,9 @@ static void ac_session_destroy(struct ac_session_t* session) {
capwap_itemlist_free(capwap_itemlist_remove_head(session->packets));
}
/* Free WLANS */
ac_wlans_destroy(session->wlans);
/* */
capwap_event_destroy(&session->changereference);
capwap_event_destroy(&session->waitpacket);
@ -497,7 +508,7 @@ static void ac_session_run(struct ac_session_t* session) {
/* Defragment management */
if (!session->rxmngpacket) {
session->rxmngpacket = capwap_packet_rxmng_create_message(1);
session->rxmngpacket = capwap_packet_rxmng_create_message(CAPWAP_CONTROL_PACKET);
}
/* If request, defragmentation packet */

View File

@ -92,6 +92,9 @@ struct ac_session_t {
long count;
capwap_event_t changereference;
/* WLAN Reference */
struct ac_wlans* wlans;
/* Soap */
struct ac_http_soap_request* soaprequest;
@ -142,8 +145,8 @@ void ac_session_data_close(struct ac_session_data_t* sessiondata);
void ac_session_data_send_action(struct ac_session_data_t* sessiondata, long action, long param, void* data, long length);
void ac_session_data_release_reference(struct ac_session_data_t* sessiondata);
/* IEEE802.11 Data Packet */
void ac_ieee80211_data(struct ac_session_data_t* sessiondata, uint8_t* buffer, int length);
/* IEEE802.11 Packet */
void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, const uint8_t* buffer, int length);
/* */
int ac_has_sessionid(struct capwap_sessionid_element* sessionid);

View File

@ -344,7 +344,7 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
/* Defragment management */
if (!sessiondata->rxmngpacket) {
sessiondata->rxmngpacket = capwap_packet_rxmng_create_message(0);
sessiondata->rxmngpacket = capwap_packet_rxmng_create_message(CAPWAP_DATA_PACKET);
}
/* If request, defragmentation packet */
@ -368,8 +368,8 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
/* Parsing body packet */
if (bodypacketlength > 0) {
binding = GET_WBID_HEADER(sessiondata->rxmngpacket->header);
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
ac_ieee80211_data(sessiondata, bodypacket, bodypacketlength);
if ((binding == CAPWAP_WIRELESS_BINDING_IEEE80211) && (bodypacketlength >= sizeof(struct ieee80211_header))) {
ac_ieee80211_packet(sessiondata, bodypacket, bodypacketlength);
}
}
}

191
src/ac/ac_wlans.c Normal file
View File

@ -0,0 +1,191 @@
#include "ac.h"
#include "ac_session.h"
#include "ac_wlans.h"
/* */
struct ac_wlans* ac_wlans_init(void) {
struct ac_wlans* wlans;
/* */
wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans));
memset(wlans, 0, sizeof(struct ac_wlans));
return wlans;
}
/* */
void ac_wlans_destroy(struct ac_wlans* wlans) {
int i;
ASSERT(wlans != NULL);
/* */
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
if (wlans->wlans[i]) {
while (wlans->wlans[i]->first) {
struct ac_wlan* wlan = (struct ac_wlan*)wlans->wlans[i]->first->item;
/* Delete WLAN */
ac_wlans_delete_bssid(wlans, i + 1, wlan->bssid);
}
/* TODO */
capwap_list_free(wlans->wlans[i]);
}
}
capwap_free(wlans);
}
/* */
struct ac_wlan* ac_wlans_create_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid, uint8_t* bssid) {
struct ac_wlan* wlan;
struct capwap_list_item* wlanitem;
ASSERT(wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
ASSERT(bssid != NULL);
/* */
wlanitem = capwap_itemlist_create(sizeof(struct ac_wlan));
wlan = (struct ac_wlan*)wlanitem->item;
memset(wlan, 0, sizeof(struct ac_wlan));
/* Init WLAN */
memcpy(wlan->bssid, bssid, MACADDRESS_EUI48_LENGTH);
wlan->wlanid = wlanid;
wlan->stations = capwap_list_create();
/* Create WLAN list */
if (!wlans->wlans[radioid - 1]) {
wlans->wlans[radioid - 1] = capwap_list_create();
}
/* Append WLAN to list */
capwap_itemlist_insert_after(wlans->wlans[radioid - 1], NULL, wlanitem);
return wlan;
}
/* */
struct ac_wlan* ac_wlans_get_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (wlans->wlans[radioid - 1]) {
search = wlans->wlans[radioid - 1]->first;
while (search) {
struct ac_wlan* item = (struct ac_wlan*)search->item;
if (!memcmp(bssid, item->bssid, MACADDRESS_EUI48_LENGTH)) {
wlan = item;
break;
}
/* Next */
search = search->next;
}
}
return wlan;
}
/* */
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
/* */
if (wlans->wlans[radioid - 1]) {
search = wlans->wlans[radioid - 1]->first;
while (search) {
struct ac_wlan* item = (struct ac_wlan*)search->item;
if (wlanid == item->wlanid) {
wlan = item;
break;
}
/* Next */
search = search->next;
}
}
return wlan;
}
/* */
static void ac_wlans_destroy_bssid(struct ac_wlan* wlan) {
/* Free capability */
if (wlan->key) {
capwap_free(wlan->key);
}
if (wlan->ssid) {
capwap_free(wlan->ssid);
}
/* Remove stations */
capwap_list_free(wlan->stations);
}
/* */
void ac_wlans_delete_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid) {
struct capwap_list_item* search;
ASSERT(wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (wlans->wlans[radioid - 1]) {
search = wlans->wlans[radioid - 1]->first;
while (search) {
struct ac_wlan* item = (struct ac_wlan*)search->item;
if (!memcmp(bssid, item->bssid, MACADDRESS_EUI48_LENGTH)) {
ac_wlans_destroy_bssid(item);
capwap_itemlist_free(capwap_itemlist_remove(wlans->wlans[radioid - 1], search));
break;
}
/* Next */
search = search->next;
}
}
}
/* */
void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_addwlan_element* addwlan) {
ASSERT(wlan != NULL);
ASSERT(addwlan != NULL);
wlan->capability = addwlan->capability;
wlan->keyindex = addwlan->keyindex;
wlan->keystatus = addwlan->keystatus;
wlan->keylength = addwlan->keylength;
if (addwlan->key && (addwlan->keylength > 0)) {
wlan->key = (uint8_t*)capwap_clone(addwlan->key, wlan->keylength);
}
memcpy(wlan->grouptsc, addwlan->grouptsc, CAPWAP_ADD_WLAN_GROUPTSC_LENGTH);
wlan->qos = addwlan->qos;
wlan->authmode = addwlan->authmode;
wlan->macmode = addwlan->macmode;
wlan->tunnelmode = addwlan->tunnelmode;
wlan->suppressssid = addwlan->suppressssid;
wlan->ssid = (uint8_t*)capwap_duplicate_string((const char*)addwlan->ssid);
}

58
src/ac/ac_wlans.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef __AC_WLANS_HEADER__
#define __AC_WLANS_HEADER__
/* AC WLAN */
struct ac_wlan {
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
uint8_t wlanid;
/* CAPWAP Session */
struct ac_session_t* session;
struct ac_session_data_t* sessiondata;
/* Capability */
uint16_t capability;
uint8_t keyindex;
uint8_t keystatus;
uint16_t keylength;
uint8_t* key;
uint8_t grouptsc[CAPWAP_ADD_WLAN_GROUPTSC_LENGTH];
uint8_t qos;
uint8_t authmode;
uint8_t macmode;
uint8_t tunnelmode;
uint8_t suppressssid;
uint8_t* ssid;
/* Local cache stations */
struct capwap_list* stations;
};
/* AC Station */
struct ac_station {
uint8_t address[MACADDRESS_EUI48_LENGTH];
/* Reference of WLAN */
struct ac_wlan_device* wlan;
struct capwap_list_item* itemlist;
};
/* */
struct ac_wlans {
struct capwap_list* wlans[RADIOID_MAX_COUNT];
};
/* */
struct ac_wlans* ac_wlans_init(void);
void ac_wlans_destroy(struct ac_wlans* wlans);
/* */
struct ac_wlan* ac_wlans_create_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid, uint8_t* bssid);
struct ac_wlan* ac_wlans_get_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid);
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid);
void ac_wlans_delete_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid);
/* */
void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_addwlan_element* addwlan);
#endif /* __AC_WLANS_HEADER__ */