Fix functions and logic.

Add new functions
Add logic into AC for create/destroy station
This commit is contained in:
vemax78
2014-04-06 17:02:31 +02:00
parent ae97e96f57
commit 539fa51e69
17 changed files with 482 additions and 166 deletions

View File

@ -21,7 +21,7 @@ static char g_configurationfile[260] = AC_DEFAULT_CONFIGURATION_FILE;
static unsigned long ac_stations_item_gethash(const void* key, unsigned long keysize, unsigned long hashsize) {
uint8_t* macaddress = (uint8_t*)key;
ASSERT(keysize == ETH_ALEN);
ASSERT(keysize == MACADDRESS_EUI48_LENGTH);
return ((((unsigned long)macaddress[4] << 8) | (unsigned long)macaddress[5]) ^ ((unsigned long)macaddress[3] << 4));
}
@ -116,6 +116,7 @@ static void ac_destroy(void) {
ac_msgqueue_free();
/* Stations */
ASSERT(g_ac.stations->count == 0);
capwap_hash_free(g_ac.stations);
capwap_rwlock_destroy(&g_ac.stationslock);

View File

@ -104,7 +104,7 @@ static int ac_json_80211_wtpradioconf_addmessageelement(struct ac_json_ieee80211
/* */
static void ac_json_80211_wtpradioconf_createjson(struct json_object* jsonparent, void* data) {
char buffer[18];
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
struct json_object* jsonitem;
struct capwap_80211_wtpradioconf_element* wtpradioconf = (struct capwap_80211_wtpradioconf_element*)data;

View File

@ -65,15 +65,15 @@ static int receive_echo_request(struct ac_session_t* session, struct capwap_pars
/* */
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];
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
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);
if (!ac_wlans_get_bssid(session, assignbssid->radioid, assignbssid->bssid)) {
wlan = ac_wlans_create_bssid(session, assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid);
wlan->session = session;
wlan->sessiondata = session->sessiondata;

View File

@ -185,9 +185,10 @@ static void ac_session_data_add_packet(struct ac_session_data_t* sessiondata, ch
}
/* Add action to session */
void ac_session_send_action(struct ac_session_t* session, long action, long param, void* data, long length) {
void ac_session_send_action(struct ac_session_t* session, long action, long param, const void* data, long length) {
struct capwap_list_item* item;
struct ac_session_action* actionsession;
struct capwap_list_item* search;
ASSERT(session != NULL);
ASSERT(length >= 0);
@ -203,17 +204,33 @@ void ac_session_send_action(struct ac_session_t* session, long action, long para
memcpy(actionsession->data, data, length);
}
/* Append to actions list */
capwap_lock_enter(&session->sessionlock);
capwap_itemlist_insert_after(session->action, NULL, item);
capwap_event_signal(&session->waitpacket);
capwap_lock_exit(&session->sessionlock);
/* Validate session before use */
capwap_rwlock_rdlock(&g_ac.sessionslock);
search = g_ac.sessions->first;
while (search != NULL) {
if (session == (struct ac_session_t*)search->item) {
/* Append to actions list */
capwap_lock_enter(&session->sessionlock);
capwap_itemlist_insert_after(session->action, NULL, item);
capwap_event_signal(&session->waitpacket);
capwap_lock_exit(&session->sessionlock);
break;
}
/* */
search = search->next;
}
capwap_rwlock_exit(&g_ac.sessionslock);
}
/* Add action to session data */
void ac_session_data_send_action(struct ac_session_data_t* sessiondata, long action, long param, void* data, long length) {
struct capwap_list_item* item;
struct ac_session_action* actionsession;
struct capwap_list_item* search;
ASSERT(sessiondata != NULL);
ASSERT(length >= 0);
@ -229,11 +246,28 @@ void ac_session_data_send_action(struct ac_session_data_t* sessiondata, long act
memcpy(actionsession->data, data, length);
}
/* Append to actions list */
capwap_lock_enter(&sessiondata->sessionlock);
capwap_itemlist_insert_after(sessiondata->action, NULL, item);
capwap_event_signal(&sessiondata->waitpacket);
capwap_lock_exit(&sessiondata->sessionlock);
/* Validate session data before use */
capwap_rwlock_rdlock(&g_ac.sessionslock);
search = g_ac.sessionsdata->first;
while (search != NULL) {
struct ac_session_data_t* sessiondata = (struct ac_session_data_t*)search->item;
if (sessiondata == (struct ac_session_data_t*)search->item) {
/* Append to actions list */
capwap_lock_enter(&sessiondata->sessionlock);
capwap_itemlist_insert_after(sessiondata->action, NULL, item);
capwap_event_signal(&sessiondata->waitpacket);
capwap_lock_exit(&sessiondata->sessionlock);
break;
}
/* */
search = search->next;
}
capwap_rwlock_exit(&g_ac.sessionslock);
}
/* Find AC sessions */
@ -406,7 +440,7 @@ char* ac_get_printable_wtpid(struct capwap_wtpboarddata_element* wtpboarddata) {
/* Get macaddress */
wtpboarddatamacaddress = capwap_wtpboarddata_get_subelement(wtpboarddata, CAPWAP_BOARD_SUBELEMENT_MACADDRESS);
if (wtpboarddatamacaddress != NULL) {
wtpid = capwap_alloc(((wtpboarddatamacaddress->length == MACADDRESS_EUI48_LENGTH) ? 18 : 24));
wtpid = capwap_alloc(((wtpboarddatamacaddress->length == MACADDRESS_EUI48_LENGTH) ? CAPWAP_MACADDRESS_EUI48_BUFFER : CAPWAP_MACADDRESS_EUI64_BUFFER));
capwap_printf_macaddress(wtpid, (unsigned char*)wtpboarddatamacaddress->data, wtpboarddatamacaddress->length);
}
@ -503,7 +537,7 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
capwap_event_init(&session->changereference);
/* */
session->wlans = ac_wlans_init();
ac_wlans_init(session);
/* */
session->timeout = capwap_timeout_init();

View File

@ -1,9 +1,9 @@
#include "ac.h"
#include "ac_session.h"
#include "ieee80211.h"
#include "ac_wlans.h"
/* */
static void ac_ieee80211_mgmt_probe_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
static void ac_ieee80211_mgmt_probe_request_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
@ -17,13 +17,59 @@ static void ac_ieee80211_mgmt_probe_request_packet(struct ac_session_data_t* ses
}
/* */
static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->authetication.ie[0], ielength)) {
return;
}
/* Create station */
station = ac_stations_create_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa);
/* */
if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
/* TODO */
} else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
/* TODO */
}
}
/* */
static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->associationrequest.ie[0], ielength)) {
return;
}
/* Get station */
station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa);
/* */
if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
/* TODO */
} else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
/* TODO */
}
}
/* */
static void ac_ieee80211_mgmt_reassociation_request_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, 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)) {
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationrequest));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->reassociationrequest.ie[0], ielength)) {
return;
}
@ -31,13 +77,13 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se
}
/* */
static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
static void ac_ieee80211_mgmt_disassociation_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, 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)) {
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->disassociation));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->disassociation.ie[0], ielength)) {
return;
}
@ -45,53 +91,30 @@ static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_
}
/* */
static void ac_ieee80211_mgmt_reassociation_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
static void ac_ieee80211_mgmt_deauthentication_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
const uint8_t* stationaddress;
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)) {
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->deauthetication));
if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->deauthetication.ie[0], ielength)) {
return;
}
/* TODO */
/* Get station address */
stationaddress = (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) ? mgmt->sa : mgmt->da);
/* Delete station */
ac_stations_delete_station(sessiondata->session, stationaddress);
}
/* */
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) {
static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, 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);
ac_ieee80211_mgmt_probe_request_packet(sessiondata, radioid, mgmt, mgmtlength);
}
break;
@ -99,7 +122,7 @@ static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, cons
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication))) {
ac_ieee80211_mgmt_authentication_packet(sessiondata, mgmt, mgmtlength);
ac_ieee80211_mgmt_authentication_packet(sessiondata, radioid, mgmt, mgmtlength);
}
break;
@ -107,7 +130,7 @@ static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, cons
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);
ac_ieee80211_mgmt_association_request_packet(sessiondata, radioid, mgmt, mgmtlength);
}
break;
@ -115,7 +138,7 @@ static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, cons
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);
ac_ieee80211_mgmt_reassociation_request_packet(sessiondata, radioid, mgmt, mgmtlength);
}
break;
@ -123,7 +146,7 @@ static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, cons
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->disassociation))) {
ac_ieee80211_mgmt_disassociation_packet(sessiondata, mgmt, mgmtlength);
ac_ieee80211_mgmt_disassociation_packet(sessiondata, radioid, mgmt, mgmtlength);
}
break;
@ -131,7 +154,7 @@ static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, cons
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION: {
if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->deauthetication))) {
ac_ieee80211_mgmt_deauthentication_packet(sessiondata, mgmt, mgmtlength);
ac_ieee80211_mgmt_deauthentication_packet(sessiondata, radioid, mgmt, mgmtlength);
}
break;
@ -144,13 +167,14 @@ static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, cons
}
/* */
void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, const uint8_t* buffer, int length) {
void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, 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(IS_VALID_RADIOID(radioid));
ASSERT(buffer != NULL);
ASSERT(length >= sizeof(struct ieee80211_header));
@ -162,6 +186,6 @@ void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, const uint8_t* b
/* Parsing frame */
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
ac_ieee80211_mgmt_packet(sessiondata, (const struct ieee80211_header_mgmt*)buffer, length, framecontrol_subtype);
ac_ieee80211_mgmt_packet(sessiondata, radioid, (const struct ieee80211_header_mgmt*)buffer, length, framecontrol_subtype);
}
}

View File

@ -63,7 +63,7 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not
/* 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)) {
} else if (ac_wlans_get_bssid_with_wlanid(session, notify->radioid, notify->wlanid)) {
return AC_ERROR_ACTION_SESSION;
}
@ -163,6 +163,12 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses
break;
}
case AC_SESSION_ACTION_ROAMING_STATION: {
/* Delete station */
ac_stations_delete_station(session, (uint8_t*)action->data);
break;
}
}
return result;
@ -406,7 +412,7 @@ static void ac_session_destroy(struct ac_session_t* session) {
}
/* Free WLANS */
ac_wlans_destroy(session->wlans);
ac_wlans_destroy(session);
/* */
capwap_event_destroy(&session->changereference);

View File

@ -25,6 +25,8 @@ struct ac_session_control {
#define AC_SESSION_ACTION_NOTIFY_EVENT 3
#define AC_SESSION_ACTION_ADDWLAN 4
#define AC_SESSION_ACTION_ROAMING_STATION 10
/* */
struct ac_session_action {
long action;
@ -134,7 +136,7 @@ struct ac_session_t {
/* Session */
void* ac_session_thread(void* param);
void ac_session_send_action(struct ac_session_t* session, long action, long param, void* data, long length);
void ac_session_send_action(struct ac_session_t* session, long action, long param, const void* data, long length);
void ac_session_teardown(struct ac_session_t* session);
void ac_session_close(struct ac_session_t* session);
void ac_session_release_reference(struct ac_session_t* session);
@ -146,7 +148,7 @@ void ac_session_data_send_action(struct ac_session_data_t* sessiondata, long act
void ac_session_data_release_reference(struct ac_session_data_t* sessiondata);
/* IEEE802.11 Packet */
void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, const uint8_t* buffer, int length);
void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* buffer, int length);
/* */
int ac_has_sessionid(struct capwap_sessionid_element* sessionid);

View File

@ -305,6 +305,7 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
int length;
struct capwap_connection connection;
char buffer[CAPWAP_MAX_PACKET_SIZE];
uint8_t radioid;
unsigned short binding;
int bodypacketlength;
uint8_t bodypacket[AC_BODY_PACKET_MAX_SIZE];
@ -367,9 +368,10 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
/* Parsing body packet */
if (bodypacketlength > 0) {
radioid = GET_RID_HEADER(sessiondata->rxmngpacket->header);
binding = GET_WBID_HEADER(sessiondata->rxmngpacket->header);
if ((binding == CAPWAP_WIRELESS_BINDING_IEEE80211) && (bodypacketlength >= sizeof(struct ieee80211_header))) {
ac_ieee80211_packet(sessiondata, bodypacket, bodypacketlength);
ac_ieee80211_packet(sessiondata, radioid, bodypacket, bodypacketlength);
}
}
}

View File

@ -3,46 +3,123 @@
#include "ac_wlans.h"
/* */
struct ac_wlans* ac_wlans_init(void) {
struct ac_wlans* wlans;
static void ac_stations_delete_station_from_global_cache(struct ac_session_t* session, uint8_t* address) {
struct ac_session_t* ownersession;
ASSERT(session != NULL);
ASSERT(address != NULL);
/* */
wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans));
memset(wlans, 0, sizeof(struct ac_wlans));
capwap_rwlock_wrlock(&g_ac.stationslock);
return wlans;
/* Can delete global reference only if match session handler */
ownersession = (struct ac_session_t*)capwap_hash_search(g_ac.stations, address);
if (ownersession == session) {
capwap_hash_delete(g_ac.stations, address);
}
capwap_rwlock_exit(&g_ac.stationslock);
}
/* */
void ac_wlans_destroy(struct ac_wlans* wlans) {
int i;
static void ac_stations_destroy_station(struct ac_session_t* session, struct ac_station* station) {
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
ASSERT(wlans != NULL);
ASSERT(session != NULL);
ASSERT(station != NULL);
/* */
capwap_logging_info("Destroy station: %s", capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH));
/* Remove reference from Global Cache Stations List */
ac_stations_delete_station_from_global_cache(session, station->address);
/* Remove reference from WLAN */
if (station->wlan) {
capwap_itemlist_remove(station->wlan->stations, station->wlanitem);
}
/* */
capwap_hash_delete(session->wlans->stations, station->address);
/* Free station reference with itemlist */
capwap_itemlist_free(station->wlanitem);
}
/* */
static unsigned long ac_wlans_item_gethash(const void* key, unsigned long keysize, unsigned long hashsize) {
uint8_t* macaddress = (uint8_t*)key;
ASSERT(keysize == MACADDRESS_EUI48_LENGTH);
return (unsigned long)(macaddress[3] ^ macaddress[4] ^ macaddress[5]);
}
/* */
static void ac_stations_reset_station(struct ac_station* station, struct ac_wlan* wlan) {
ASSERT(station != NULL);
ASSERT(wlan != NULL);
/* Remove reference from current WLAN */
if (station->wlan) {
capwap_itemlist_remove(station->wlan->stations, station->wlanitem);
}
/* Set WLAN */
station->wlan = wlan;
capwap_itemlist_insert_after(wlan->stations, NULL, station->wlanitem);
}
/* */
void ac_wlans_init(struct ac_session_t* session) {
ASSERT(session != NULL);
/* */
session->wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans));
memset(session->wlans, 0, sizeof(struct ac_wlans));
/* */
session->wlans->stations = capwap_hash_create(AC_WLANS_STATIONS_HASH_SIZE, AC_WLANS_STATIONS_KEY_SIZE, ac_wlans_item_gethash, NULL, NULL);
}
/* */
void ac_wlans_destroy(struct ac_session_t* session) {
int i;
struct capwap_list* items;
ASSERT(session != NULL);
ASSERT(session->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;
if (session->wlans->wlans[i]) {
items = session->wlans->wlans[i];
/* Delete WLAN */
ac_wlans_delete_bssid(wlans, i + 1, wlan->bssid);
/* Delete WLANS */
while (items->first) {
ac_wlans_delete_bssid(session, i + 1, ((struct ac_wlan*)items->first->item)->bssid);
}
/* TODO */
capwap_list_free(wlans->wlans[i]);
}
/* */
capwap_list_free(items);
}
}
capwap_free(wlans);
/* */
ASSERT(session->wlans->stations->count == 0);
/* */
capwap_hash_free(session->wlans->stations);
capwap_free(session->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_create_bssid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid) {
struct ac_wlan* wlan;
struct capwap_list_item* wlanitem;
ASSERT(wlans != NULL);
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
ASSERT(bssid != NULL);
@ -54,32 +131,34 @@ struct ac_wlan* ac_wlans_create_bssid(struct ac_wlans* wlans, uint8_t radioid, u
/* Init WLAN */
memcpy(wlan->bssid, bssid, MACADDRESS_EUI48_LENGTH);
wlan->radioid = radioid;
wlan->wlanid = wlanid;
wlan->stations = capwap_list_create();
/* Create WLAN list */
if (!wlans->wlans[radioid - 1]) {
wlans->wlans[radioid - 1] = capwap_list_create();
if (!session->wlans->wlans[radioid - 1]) {
session->wlans->wlans[radioid - 1] = capwap_list_create();
}
/* Append WLAN to list */
capwap_itemlist_insert_after(wlans->wlans[radioid - 1], NULL, wlanitem);
capwap_itemlist_insert_after(session->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 ac_wlan* ac_wlans_get_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(wlans != NULL);
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (wlans->wlans[radioid - 1]) {
search = wlans->wlans[radioid - 1]->first;
if (session->wlans->wlans[radioid - 1]) {
search = session->wlans->wlans[radioid - 1]->first;
while (search) {
struct ac_wlan* item = (struct ac_wlan*)search->item;
@ -97,17 +176,18 @@ struct ac_wlan* ac_wlans_get_bssid(struct ac_wlans* wlans, uint8_t radioid, uint
}
/* */
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid) {
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(wlans != NULL);
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
/* */
if (wlans->wlans[radioid - 1]) {
search = wlans->wlans[radioid - 1]->first;
if (session->wlans->wlans[radioid - 1]) {
search = session->wlans->wlans[radioid - 1]->first;
while (search) {
struct ac_wlan* item = (struct ac_wlan*)search->item;
@ -125,7 +205,7 @@ struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_wlans* wlans, uint8_t r
}
/* */
static void ac_wlans_destroy_bssid(struct ac_wlan* wlan) {
static void ac_wlans_destroy_bssid(struct ac_session_t* session, struct ac_wlan* wlan) {
/* Free capability */
if (wlan->key) {
capwap_free(wlan->key);
@ -136,26 +216,32 @@ static void ac_wlans_destroy_bssid(struct ac_wlan* wlan) {
}
/* Remove stations */
while (wlan->stations->first) {
ac_stations_destroy_station(session, (struct ac_station*)wlan->stations->first->item);
}
/* */
capwap_list_free(wlan->stations);
}
/* */
void ac_wlans_delete_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid) {
void ac_wlans_delete_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid) {
struct capwap_list_item* search;
ASSERT(wlans != NULL);
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (wlans->wlans[radioid - 1]) {
search = wlans->wlans[radioid - 1]->first;
if (session->wlans->wlans[radioid - 1]) {
search = session->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));
ac_wlans_destroy_bssid(session, item);
capwap_itemlist_free(capwap_itemlist_remove(session->wlans->wlans[radioid - 1], search));
break;
}
@ -189,3 +275,97 @@ void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_add
wlan->suppressssid = addwlan->suppressssid;
wlan->ssid = (uint8_t*)capwap_duplicate_string((const char*)addwlan->ssid);
}
/* */
struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) {
struct ac_station* station;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
ASSERT(address != NULL);
/* Get station */
station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address);
if (station && (radioid == station->wlan->radioid) && !memcmp(bssid, station->wlan->bssid, MACADDRESS_EUI48_LENGTH)) {
return station;
}
return NULL;
}
/* */
struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) {
char buffer1[CAPWAP_MACADDRESS_EUI48_BUFFER];
char buffer2[CAPWAP_MACADDRESS_EUI48_BUFFER];
struct ac_wlan* wlan;
struct ac_session_t* ownersession;
struct ac_station* station;
struct capwap_list_item* stationitem;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
ASSERT(address != NULL);
/* */
capwap_printf_macaddress(buffer1, bssid, MACADDRESS_EUI48_LENGTH);
capwap_printf_macaddress(buffer2, address, MACADDRESS_EUI48_LENGTH);
capwap_logging_info("Create station to radioid: %d, bssid: %s, station address: %s", (int)radioid, buffer1, buffer2);
/* Get session that owns the station */
capwap_rwlock_rdlock(&g_ac.stationslock);
ownersession = (struct ac_session_t*)capwap_hash_search(g_ac.stations, address);
capwap_rwlock_exit(&g_ac.stationslock);
/* If request change owner of station */
if (ownersession != session) {
/* Release station from old owner */
if (ownersession) {
ac_session_send_action(ownersession, AC_SESSION_ACTION_ROAMING_STATION, 0, (void*)address, MACADDRESS_EUI48_LENGTH);
}
/* Set station into Global Cache Stations List */
capwap_rwlock_wrlock(&g_ac.stationslock);
capwap_hash_add(g_ac.stations, address, session);
capwap_rwlock_exit(&g_ac.stationslock);
}
/* */
wlan = ac_wlans_get_bssid(session, radioid, bssid);
station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address);
if (!station) {
stationitem = capwap_itemlist_create(sizeof(struct ac_station));
station = (struct ac_station*)stationitem->item;
memset(station, 0, sizeof(struct ac_station));
/* */
memcpy(station->address, address, MACADDRESS_EUI48_LENGTH);
station->wlanitem = stationitem;
/* */
capwap_hash_add(session->wlans->stations, address, station);
}
/* Set station to WLAN */
ac_stations_reset_station(station, wlan);
return station;
}
/* */
void ac_stations_delete_station(struct ac_session_t* session, const uint8_t* address) {
struct ac_station* station;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(address != NULL);
/* Delete station */
station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address);
if (station) {
ac_stations_destroy_station(session, station);
}
}

View File

@ -1,15 +1,25 @@
#ifndef __AC_WLANS_HEADER__
#define __AC_WLANS_HEADER__
#include "ieee80211.h"
/* */
#define AC_WLANS_STATIONS_HASH_SIZE 256
#define AC_WLANS_STATIONS_KEY_SIZE MACADDRESS_EUI48_LENGTH
/* AC WLAN */
struct ac_wlan {
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
uint8_t radioid;
uint8_t wlanid;
/* CAPWAP Session */
struct ac_session_t* session;
struct ac_session_data_t* sessiondata;
/* Stations reference */
struct capwap_list* stations;
/* Capability */
uint16_t capability;
uint8_t keyindex;
@ -23,9 +33,6 @@ struct ac_wlan {
uint8_t tunnelmode;
uint8_t suppressssid;
uint8_t* ssid;
/* Local cache stations */
struct capwap_list* stations;
};
/* AC Station */
@ -33,26 +40,34 @@ struct ac_station {
uint8_t address[MACADDRESS_EUI48_LENGTH];
/* Reference of WLAN */
struct ac_wlan_device* wlan;
struct capwap_list_item* itemlist;
struct ac_wlan* wlan;
struct capwap_list_item* wlanitem;
};
/* */
struct ac_wlans {
struct capwap_list* wlans[RADIOID_MAX_COUNT];
/* Stations */
struct capwap_hash* stations;
};
/* */
struct ac_wlans* ac_wlans_init(void);
void ac_wlans_destroy(struct ac_wlans* wlans);
/* Management WLANS */
void ac_wlans_init(struct ac_session_t* session);
void ac_wlans_destroy(struct ac_session_t* session);
/* */
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);
struct ac_wlan* ac_wlans_create_bssid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid);
struct ac_wlan* ac_wlans_get_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid);
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid);
void ac_wlans_delete_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid);
/* */
void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_addwlan_element* addwlan);
/* Management Stations */
struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address);
struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address);
void ac_stations_delete_station(struct ac_session_t* session, const uint8_t* address);
#endif /* __AC_WLANS_HEADER__ */