Big update with type fix and minor new function.

Complete the IEEE802.11 Station Association with interation of AC in LocalMAC mode.
After the IEEE802.11 Authorization / Association is complete, the AC can now
authorize the WTP to accept data station packets with Station Configuration Message.
This commit is contained in:
vemax78
2014-04-14 22:33:12 +02:00
parent 2ec98ac74d
commit 3569267283
37 changed files with 969 additions and 401 deletions

View File

@ -112,7 +112,7 @@ static void ac_json_80211_wtpradioconf_createjson(struct json_object* jsonparent
json_object_object_add(jsonitem, "ShortPreamble", json_object_new_int((int)wtpradioconf->shortpreamble));
json_object_object_add(jsonitem, "NumBSSIDs", json_object_new_int((int)wtpradioconf->maxbssid));
json_object_object_add(jsonitem, "DTIMPeriod", json_object_new_int((int)wtpradioconf->dtimperiod));
json_object_object_add(jsonitem, "BSSID", json_object_new_string(capwap_printf_macaddress(buffer, (unsigned char*)wtpradioconf->bssid, MACADDRESS_EUI48_LENGTH)));
json_object_object_add(jsonitem, "BSSID", json_object_new_string(capwap_printf_macaddress(buffer, wtpradioconf->bssid, MACADDRESS_EUI48_LENGTH)));
json_object_object_add(jsonitem, "BeaconPeriod", json_object_new_int((int)wtpradioconf->beaconperiod));
json_object_object_add(jsonitem, "CountryString", json_object_new_string((char*)wtpradioconf->country));
json_object_object_add(jsonparent, "IEEE80211WTPRadioConfiguration", jsonitem);

View File

@ -10,38 +10,6 @@
#define SOAP_EVENT_STATUS_RUNNING 0
#define SOAP_EVENT_STATUS_COMPLETE 1
/* Reset notification */
struct ac_notify_reset_t {
uint32_t vendor;
uint8_t name[0];
};
/* Add WLAN notification */
struct ac_notify_addwlan_t {
uint8_t radioid;
uint8_t wlanid;
uint16_t capability;
uint8_t qos;
uint8_t authmode;
uint8_t macmode;
uint8_t tunnelmode;
uint8_t suppressssid;
char ssid[CAPWAP_ADD_WLAN_SSID_LENGTH + 1];
};
/* Station Configuration IEEE802.11 add station notification */
struct ac_notify_station_configuration_ieee8011_add_station {
uint8_t radioid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint8_t vlan[CAPWAP_ADDSTATION_VLAN_MAX_LENGTH];
uint8_t wlanid;
uint16_t associationid;
uint16_t capabilities;
uint8_t supportedratescount;
uint8_t supportedrates[CAPWAP_STATION_RATES_MAXLENGTH];
};
/* */
int ac_backend_start(void);
void ac_backend_stop(void);

View File

@ -65,24 +65,16 @@ 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[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, assignbssid->radioid, assignbssid->bssid)) {
wlan = ac_wlans_create_bssid(session, assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid);
wlan->session = session;
wlan->sessiondata = session->sessiondata;
wlan = ac_wlans_create_bssid(assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid, addwlan);
/* 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));
}
/* Assign BSSID to session */
ac_session_data_send_action(session->sessiondata, AC_SESSION_DATA_ACTION_ASSIGN_BSSID, 0, &wlan, sizeof(struct ac_wlan*));
}
}
@ -138,6 +130,64 @@ static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* s
ac_free_reference_last_request(session);
}
/* */
static void execute_ieee80211_wlan_configuration_response_addstation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_addstation_element* addstation, struct capwap_parsed_packet* requestpacket) {
struct ac_notify_add_station_status notify;
struct capwap_80211_station_element* station80211;
unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header);
struct capwap_resultcode_element* resultcode;
/* */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
/* */
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION);
if (station80211) {
memset(&notify, 0, sizeof(struct ac_notify_add_station_status));
notify.radioid = station80211->radioid;
notify.wlanid = station80211->wlanid;
memcpy(notify.address, addstation->address, MACADDRESS_EUI48_LENGTH);
notify.statuscode = resultcode->code;
ac_session_data_send_action(session->sessiondata, AC_SESSION_DATA_ACTION_ADD_STATION_STATUS, 0, (void*)&notify, sizeof(struct ac_notify_add_station_status));
}
}
}
/* */
static void execute_ieee80211_wlan_configuration_response_deletestation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_deletestation_element* deletestation, struct capwap_parsed_packet* requestpacket) {
/* TODO */
}
/* */
static void receive_ieee80211_station_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_packet_rxmng* rxmngrequestpacket;
struct capwap_parsed_packet requestpacket;
struct capwap_addstation_element* addstation;
struct capwap_deletestation_element* deletestation;
/* Parsing request message */
rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket);
if (capwap_parsing_packet(rxmngrequestpacket, NULL, &requestpacket) == PARSING_COMPLETE) {
addstation = (struct capwap_addstation_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ADDSTATION);
if (addstation) {
execute_ieee80211_wlan_configuration_response_addstation(session, packet, addstation, &requestpacket);
} else {
deletestation = (struct capwap_deletestation_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_DELETESTATION);
if (deletestation) {
execute_ieee80211_wlan_configuration_response_deletestation(session, packet, deletestation, &requestpacket);
}
}
}
/* */
capwap_free_parsed_packet(&requestpacket);
capwap_packet_rxmng_free(rxmngrequestpacket);
ac_free_reference_last_request(session);
}
/* */
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
@ -198,9 +248,7 @@ void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet*
}
case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
/* TODO */
/* */
receive_ieee80211_station_configuration_response(session, packet);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}

View File

@ -536,9 +536,6 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
session->count = 2;
capwap_event_init(&session->changereference);
/* */
ac_wlans_init(session);
/* */
session->timeout = capwap_timeout_init();
session->idtimercontrol = capwap_timeout_createtimer(session->timeout);
@ -621,6 +618,9 @@ static struct ac_session_data_t* ac_create_session_data(struct sockaddr_storage*
sessiondata->count = 2;
capwap_event_init(&sessiondata->changereference);
/* */
ac_wlans_init(sessiondata);
/* */
sessiondata->timeout = capwap_timeout_init();
sessiondata->idtimercontrol = capwap_timeout_createtimer(sessiondata->timeout);

View File

@ -26,6 +26,7 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication));
@ -33,9 +34,13 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se
return;
}
/* Create station if sent by station */
if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_create_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa);
/* */
if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && !memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_create_station(sessiondata, radioid, mgmt->bssid, mgmt->sa);
/* */
capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH);
capwap_logging_info("Receive IEEE802.11 Authentication Request from %s station", buffer);
/* */
if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
@ -43,13 +48,30 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se
} else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
/* TODO */
}
} else {
station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->da);
if (station) {
if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
/* TODO */
} else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
/* TODO */
} else if (!memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_get_station(sessiondata, radioid, mgmt->bssid, mgmt->da);
if (station && (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL)) {
uint16_t algorithm;
uint16_t transactionseqnumber;
uint16_t statuscode;
/* */
statuscode = __le16_to_cpu(mgmt->authetication.statuscode);
/* */
capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH);
capwap_logging_info("Receive IEEE802.11 Authentication Response to %s station with %d status code", buffer, (int)statuscode);
if (statuscode == IEEE80211_STATUS_SUCCESS) {
algorithm = __le16_to_cpu(mgmt->authetication.algorithm);
transactionseqnumber = __le16_to_cpu(mgmt->authetication.transactionseqnumber);
/* Check if authenticate */
if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (transactionseqnumber == 2)) {
station->flags |= AC_STATION_FLAGS_AUTHENTICATED;
} else if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY) && (transactionseqnumber == 4)) {
/* TODO */
}
}
}
}
@ -60,6 +82,7 @@ static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest));
@ -68,22 +91,34 @@ static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_
}
/* Get station */
if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa);
if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && !memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_get_station(sessiondata, 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 */
}
} else {
station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->da);
if (station) {
capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH);
capwap_logging_info("Receive IEEE802.11 Association Request from %s station", buffer);
/* Get Station Info */
station->capability = __le16_to_cpu(mgmt->associationrequest.capability);
station->listeninterval = __le16_to_cpu(mgmt->associationrequest.listeninterval);
/* Get supported rates */
if (ieitems.supported_rates && ((ieitems.supported_rates->len + (ieitems.extended_supported_rates ? ieitems.extended_supported_rates->len : 0)) <= sizeof(station->supportedrates))) {
station->supportedratescount = ieitems.supported_rates->len;
memcpy(station->supportedrates, ieitems.supported_rates->rates, ieitems.supported_rates->len);
if (ieitems.extended_supported_rates) {
station->supportedratescount += ieitems.extended_supported_rates->len;
memcpy(&station->supportedrates[ieitems.supported_rates->len], ieitems.extended_supported_rates->rates, ieitems.extended_supported_rates->len);
}
/* */
if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
/* TODO */
} else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
/* TODO */
/* Active Station */
ac_stations_authorize_station(sessiondata, station);
}
}
}
@ -94,6 +129,7 @@ static void ac_ieee80211_mgmt_association_response_packet(struct ac_session_data
int ielength;
struct ieee80211_ie_items ieitems;
struct ac_station* station;
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
/* Parsing Information Elements */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationresponse));
@ -102,13 +138,32 @@ static void ac_ieee80211_mgmt_association_response_packet(struct ac_session_data
}
/* Get station */
station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa);
if (!memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) {
station = ac_stations_get_station(sessiondata, radioid, mgmt->bssid, mgmt->da);
if (station && (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL)) {
capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH);
capwap_logging_info("Receive IEEE802.11 Association Response to %s station with %d status code", buffer, (int)mgmt->associationresponse.statuscode);
/* */
if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) {
/* TODO */
} else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) {
/* TODO */
if (mgmt->associationresponse.statuscode == IEEE80211_STATUS_SUCCESS) {
/* Get Station Info */
station->capability = __le16_to_cpu(mgmt->associationresponse.capability);
station->aid = __le16_to_cpu(mgmt->associationresponse.aid);
station->flags |= AC_STATION_FLAGS_ASSOCIATE;
/* Get supported rates */
if (ieitems.supported_rates && ((ieitems.supported_rates->len + (ieitems.extended_supported_rates ? ieitems.extended_supported_rates->len : 0)) <= sizeof(station->supportedrates))) {
station->supportedratescount = ieitems.supported_rates->len;
memcpy(station->supportedrates, ieitems.supported_rates->rates, ieitems.supported_rates->len);
if (ieitems.extended_supported_rates) {
station->supportedratescount += ieitems.extended_supported_rates->len;
memcpy(&station->supportedrates[ieitems.supported_rates->len], ieitems.extended_supported_rates->rates, ieitems.extended_supported_rates->len);
}
/* Active Station */
ac_stations_authorize_station(sessiondata, station);
}
}
}
}
}
@ -158,6 +213,7 @@ static void ac_ieee80211_mgmt_disassociation_packet(struct ac_session_data_t* se
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 ac_station* station;
struct ieee80211_ie_items ieitems;
/* Parsing Information Elements */
@ -170,7 +226,11 @@ static void ac_ieee80211_mgmt_deauthentication_packet(struct ac_session_data_t*
stationaddress = (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) ? mgmt->sa : mgmt->da);
/* Delete station */
ac_stations_delete_station(sessiondata->session, stationaddress);
station = ac_stations_get_station(sessiondata, radioid, NULL, stationaddress);
if (station) {
station->flags &= ~(AC_STATION_FLAGS_AUTHORIZED | AC_STATION_FLAGS_AUTHENTICATED | AC_STATION_FLAGS_ASSOCIATE);
ac_stations_delete_station(sessiondata, station);
}
}
/* */

View File

@ -3,7 +3,6 @@
#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
@ -44,7 +43,7 @@ static int ac_session_action_resetwtp(struct ac_session_t* session, struct ac_no
ac_dfa_change_state(session, CAPWAP_RESET_STATE);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
} else {
capwap_logging_debug("Warning: error to send reset request packet");
capwap_logging_debug("Warning: error to send Reset Request packet");
ac_free_reference_last_request(session);
ac_session_teardown(session);
}
@ -63,8 +62,10 @@ 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;
#if 0
} else if (ac_wlans_get_bssid_with_wlanid(session, notify->radioid, notify->wlanid)) {
return AC_ERROR_ACTION_SESSION;
#endif
}
/* */
@ -104,7 +105,7 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not
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 reset request packet");
capwap_logging_debug("Warning: error to send WLAN Configuration Request packet");
ac_free_reference_last_request(session);
ac_session_teardown(session);
}
@ -114,8 +115,115 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not
/* */
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 capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
struct capwap_addstation_element addstation;
struct capwap_80211_station_element station;
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_ERROR_ACTION_SESSION;
}
/* */
memset(&addstation, 0, sizeof(struct capwap_addstation_element));
addstation.radioid = notify->radioid;
addstation.length = MACADDRESS_EUI48_LENGTH;
addstation.address = notify->address;
if (notify->vlan[0]) {
addstation.vlan = notify->vlan;
}
/* */
memset(&station, 0, sizeof(struct capwap_80211_station_element));
station.radioid = notify->radioid;
station.associationid = notify->associationid;
memcpy(station.address, notify->address, MACADDRESS_EUI48_LENGTH);
station.capabilities = notify->capabilities;
station.wlanid = notify->wlanid;
station.supportedratescount = notify->supportedratescount;
memcpy(station.supportedrates, notify->supportedrates, station.supportedratescount);
/* 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_ADDSTATION, &addstation);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_STATION, &station);
/* 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->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
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_ERROR_ACTION_SESSION;
}
/* */
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_ERROR_ACTION_SESSION;
}
/* */
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->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
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_ERROR_ACTION_SESSION;
}
@ -177,12 +285,7 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses
}
case AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION: {
break;
}
case AC_SESSION_ACTION_ROAMING_STATION: {
/* Delete station */
ac_stations_delete_station(session, (uint8_t*)action->data);
result = ac_session_action_station_configuration_ieee8011_delete_station(session, (struct ac_notify_station_configuration_ieee8011_delete_station*)action->data);
break;
}
}
@ -427,9 +530,6 @@ 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);
/* */
capwap_event_destroy(&session->changereference);
capwap_event_destroy(&session->waitpacket);

View File

@ -27,7 +27,9 @@ struct ac_session_control {
#define AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION 5
#define AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION 6
#define AC_SESSION_ACTION_ROAMING_STATION 10
#define AC_SESSION_DATA_ACTION_ROAMING_STATION 1
#define AC_SESSION_DATA_ACTION_ASSIGN_BSSID 2
#define AC_SESSION_DATA_ACTION_ADD_STATION_STATUS 3
/* */
struct ac_session_action {
@ -52,6 +54,52 @@ struct ac_session_notify_event_t {
};
};
/* Reset notification */
struct ac_notify_reset_t {
uint32_t vendor;
uint8_t name[0];
};
/* Add WLAN notification */
struct ac_notify_addwlan_t {
uint8_t radioid;
uint8_t wlanid;
uint16_t capability;
uint8_t qos;
uint8_t authmode;
uint8_t macmode;
uint8_t tunnelmode;
uint8_t suppressssid;
char ssid[CAPWAP_ADD_WLAN_SSID_LENGTH + 1];
};
/* Station Configuration IEEE802.11 add station notification */
struct ac_notify_station_configuration_ieee8011_add_station {
uint8_t radioid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint8_t vlan[CAPWAP_ADDSTATION_VLAN_MAX_LENGTH];
uint8_t wlanid;
uint16_t associationid;
uint16_t capabilities;
uint8_t supportedratescount;
uint8_t supportedrates[CAPWAP_STATION_RATES_MAXLENGTH];
};
/* Station Configuration IEEE802.11 delete station notification */
struct ac_notify_station_configuration_ieee8011_delete_station {
uint8_t radioid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
};
/* */
struct ac_notify_add_station_status {
uint8_t radioid;
uint8_t wlanid;
uint8_t address[MACADDRESS_EUI48_LENGTH];
uint16_t statuscode;
};
/* */
struct ac_session_t;
struct ac_session_data_t;
@ -66,8 +114,13 @@ struct ac_session_data_t {
long count;
capwap_event_t changereference;
/* WLAN Reference */
struct ac_wlans* wlans;
/* */
int enabledtls;
unsigned short mtu;
unsigned short fragmentid;
struct capwap_connection connection;
struct capwap_dtls dtls;
@ -96,9 +149,6 @@ struct ac_session_t {
long count;
capwap_event_t changereference;
/* WLAN Reference */
struct ac_wlans* wlans;
/* Soap */
struct ac_http_soap_request* soaprequest;
@ -149,6 +199,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);
void ac_session_data_send_data_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe);
/* IEEE802.11 Packet */
void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* buffer, int length);

View File

@ -1,6 +1,7 @@
#include "ac.h"
#include "capwap_dfa.h"
#include "ac_session.h"
#include "ac_wlans.h"
#include "ieee80211.h"
#include <arpa/inet.h>
@ -9,11 +10,53 @@
#define AC_BODY_PACKET_MAX_SIZE 8192
/* */
static int ac_session_data_action_add_station_status(struct ac_session_data_t* sessiondata, struct ac_notify_add_station_status* notify) {
struct ac_wlan* wlan;
struct ac_station* station;
wlan = ac_wlans_get_bssid_with_wlanid(sessiondata, notify->radioid, notify->wlanid);
if (wlan) {
station = ac_stations_get_station(sessiondata, notify->radioid, wlan->bssid, notify->address);
if (station) {
if (CAPWAP_RESULTCODE_OK(notify->statuscode)) {
station->flags |= AC_STATION_FLAGS_AUTHORIZED;
} else {
ac_stations_delete_station(sessiondata, station);
}
}
}
return AC_ERROR_ACTION_SESSION;
}
/* */
static int ac_session_data_action_execute(struct ac_session_data_t* sessiondata, struct ac_session_action* action) {
int result = AC_ERROR_ACTION_SESSION;
/* TODO */
switch (action->action) {
case AC_SESSION_DATA_ACTION_ROAMING_STATION: {
struct ac_station* station;
/* Delete station */
station = ac_stations_get_station(sessiondata, RADIOID_ANY, NULL, (uint8_t*)action->data);
if (station) {
ac_stations_delete_station(sessiondata, station);
}
break;
}
case AC_SESSION_DATA_ACTION_ASSIGN_BSSID: {
ac_wlans_assign_bssid(sessiondata, *(struct ac_wlan**)action->data);
break;
}
case AC_SESSION_DATA_ACTION_ADD_STATION_STATUS: {
result = ac_session_data_action_add_station_status(sessiondata, (struct ac_notify_add_station_status*)action->data);
break;
}
}
return result;
}
@ -178,7 +221,7 @@ static int ac_session_data_keepalive(struct ac_session_data_t* sessiondata, stru
/* Data keepalive complete, get fragment packets into local list */
txfragpacket = capwap_list_create();
capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, 0);
capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, sessiondata->fragmentid);
if (txfragpacket->count == 1) {
/* Send Data keepalive to WTP */
if (capwap_crypt_sendto_fragmentpacket(&sessiondata->dtls, sessiondata->connection.socket.socket[sessiondata->connection.socket.type], txfragpacket, &sessiondata->connection.localaddr, &sessiondata->connection.remoteaddr)) {
@ -244,6 +287,9 @@ static void ac_session_data_destroy(struct ac_session_data_t* sessiondata) {
/* Free DTLS */
capwap_crypt_freesession(&sessiondata->dtls);
/* Free WLANS */
ac_wlans_destroy(sessiondata);
/* Free resource */
while (sessiondata->packets->count > 0) {
capwap_itemlist_free(capwap_itemlist_remove_head(sessiondata->packets));
@ -421,3 +467,38 @@ void* ac_session_data_thread(void* param) {
pthread_exit(NULL);
return NULL;
}
/* */
void ac_session_data_send_data_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe) {
struct capwap_list* txfragpacket;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
/* Build packet */
capwap_header_init(&capwapheader, radioid, sessiondata->session->binding);
capwap_header_set_nativeframe_flag(&capwapheader, (leavenativeframe ? 1: 0));
txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, sessiondata->mtu);
/* */
if (leavenativeframe) {
capwap_packet_txmng_add_data(txmngpacket, data, length);
} else {
/* TODO */
}
/* Data message complete, get fragment packets into local list */
txfragpacket = capwap_list_create();
capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, sessiondata->fragmentid);
if (txfragpacket->count > 1) {
sessiondata->fragmentid++;
}
/* */
if (!capwap_crypt_sendto_fragmentpacket(&sessiondata->dtls, sessiondata->connection.socket.socket[sessiondata->connection.socket.type], txfragpacket, &sessiondata->connection.localaddr, &sessiondata->connection.remoteaddr)) {
capwap_logging_debug("Warning: error to send data packet");
}
/* Free packets manager */
capwap_list_free(txfragpacket);
capwap_packet_txmng_free(txmngpacket);
}

View File

@ -1,20 +1,21 @@
#include "ac.h"
#include "ac_session.h"
#include "ac_wlans.h"
#include "ac_backend.h"
/* */
static void ac_stations_delete_station_from_global_cache(struct ac_session_t* session, uint8_t* address) {
struct ac_session_t* ownersession;
static void ac_stations_delete_station_from_global_cache(struct ac_session_data_t* sessiondata, uint8_t* address) {
struct ac_session_data_t* ownersession;
ASSERT(session != NULL);
ASSERT(sessiondata != NULL);
ASSERT(address != NULL);
/* */
capwap_rwlock_wrlock(&g_ac.stationslock);
/* Can delete global reference only if match session handler */
ownersession = (struct ac_session_t*)capwap_hash_search(g_ac.stations, address);
if (ownersession == session) {
ownersession = (struct ac_session_data_t*)capwap_hash_search(g_ac.stations, address);
if (ownersession == sessiondata) {
capwap_hash_delete(g_ac.stations, address);
}
@ -22,17 +23,17 @@ static void ac_stations_delete_station_from_global_cache(struct ac_session_t* se
}
/* */
static void ac_stations_destroy_station(struct ac_session_t* session, struct ac_station* station) {
static void ac_stations_destroy_station(struct ac_session_data_t* sessiondata, struct ac_station* station) {
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
ASSERT(session != NULL);
ASSERT(sessiondata != 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);
ac_stations_delete_station_from_global_cache(sessiondata, station->address);
/* Remove reference from WLAN */
if (station->wlan) {
@ -40,7 +41,7 @@ static void ac_stations_destroy_station(struct ac_session_t* session, struct ac_
}
/* */
capwap_hash_delete(session->wlans->stations, station->address);
capwap_hash_delete(sessiondata->wlans->stations, station->address);
/* Free station reference with itemlist */
capwap_itemlist_free(station->wlanitem);
@ -65,39 +66,42 @@ static void ac_stations_reset_station(struct ac_station* station, struct ac_wlan
capwap_itemlist_remove(station->wlan->stations, station->wlanitem);
}
/* */
station->flags = 0;
/* 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);
void ac_wlans_init(struct ac_session_data_t* sessiondata) {
ASSERT(sessiondata != NULL);
/* */
session->wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans));
memset(session->wlans, 0, sizeof(struct ac_wlans));
sessiondata->wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans));
memset(sessiondata->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);
sessiondata->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) {
void ac_wlans_destroy(struct ac_session_data_t* sessiondata) {
int i;
struct capwap_list* items;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
/* */
for (i = 0; i < RADIOID_MAX_COUNT; i++) {
if (session->wlans->wlans[i]) {
items = session->wlans->wlans[i];
if (sessiondata->wlans->wlans[i]) {
items = sessiondata->wlans->wlans[i];
/* Delete WLANS */
while (items->first) {
ac_wlans_delete_bssid(session, i + 1, ((struct ac_wlan*)items->first->item)->bssid);
ac_wlans_delete_bssid(sessiondata, i + 1, ((struct ac_wlan*)items->first->item)->bssid);
}
/* */
@ -106,20 +110,50 @@ void ac_wlans_destroy(struct ac_session_t* session) {
}
/* */
ASSERT(session->wlans->stations->count == 0);
ASSERT(sessiondata->wlans->stations->count == 0);
/* */
capwap_hash_free(session->wlans->stations);
capwap_free(session->wlans);
capwap_hash_free(sessiondata->wlans->stations);
capwap_free(sessiondata->wlans);
}
/* */
struct ac_wlan* ac_wlans_create_bssid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid) {
int ac_wlans_assign_bssid(struct ac_session_data_t* sessiondata, struct ac_wlan* wlan) {
char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER];
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(wlan != NULL);
ASSERT(IS_VALID_RADIOID(wlan->radioid));
ASSERT(IS_VALID_WLANID(wlan->wlanid));
/* */
if (ac_wlans_get_bssid(sessiondata, wlan->radioid, wlan->bssid)) {
return 0;
}
/* */
wlan->session = sessiondata->session;
wlan->sessiondata = sessiondata;
/* Create WLAN list */
if (!sessiondata->wlans->wlans[wlan->radioid - 1]) {
sessiondata->wlans->wlans[wlan->radioid - 1] = capwap_list_create();
}
/* Append WLAN to list */
capwap_itemlist_insert_after(sessiondata->wlans->wlans[wlan->radioid - 1], NULL, wlan->wlanitem);
/* */
capwap_logging_info("Added new wlan with radioid: %d, wlanid: %d, bssid: %s", (int)wlan->radioid, (int)wlan->wlanid, capwap_printf_macaddress(buffer, wlan->bssid, MACADDRESS_EUI48_LENGTH));
return 1;
}
/* */
struct ac_wlan* ac_wlans_create_bssid(uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, struct capwap_80211_addwlan_element* addwlan) {
struct ac_wlan* wlan;
struct capwap_list_item* wlanitem;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
ASSERT(bssid != NULL);
@ -130,132 +164,13 @@ struct ac_wlan* ac_wlans_create_bssid(struct ac_session_t* session, uint8_t radi
memset(wlan, 0, sizeof(struct ac_wlan));
/* Init WLAN */
wlan->wlanitem = wlanitem;
memcpy(wlan->bssid, bssid, MACADDRESS_EUI48_LENGTH);
wlan->radioid = radioid;
wlan->wlanid = wlanid;
wlan->stations = capwap_list_create();
/* Create WLAN list */
if (!session->wlans->wlans[radioid - 1]) {
session->wlans->wlans[radioid - 1] = capwap_list_create();
}
/* Append WLAN to list */
capwap_itemlist_insert_after(session->wlans->wlans[radioid - 1], NULL, wlanitem);
return wlan;
}
/* */
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(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
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)) {
wlan = item;
break;
}
/* Next */
search = search->next;
}
}
return wlan;
}
/* */
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(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
/* */
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 (wlanid == item->wlanid) {
wlan = item;
break;
}
/* Next */
search = search->next;
}
}
return 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);
}
if (wlan->ssid) {
capwap_free(wlan->ssid);
}
/* 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_session_t* session, uint8_t radioid, const uint8_t* bssid) {
struct capwap_list_item* search;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
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(session, item);
capwap_itemlist_free(capwap_itemlist_remove(session->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);
/* Set capability */
wlan->capability = addwlan->capability;
wlan->keyindex = addwlan->keyindex;
@ -274,21 +189,126 @@ 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);
return wlan;
}
/* */
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;
struct ac_wlan* ac_wlans_get_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (sessiondata->wlans->wlans[radioid - 1]) {
search = sessiondata->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_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid) {
struct capwap_list_item* search;
struct ac_wlan* wlan = NULL;
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(IS_VALID_WLANID(wlanid));
/* */
if (sessiondata->wlans->wlans[radioid - 1]) {
search = sessiondata->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_session_data_t* sessiondata, struct ac_wlan* wlan) {
/* Free capability */
if (wlan->key) {
capwap_free(wlan->key);
}
if (wlan->ssid) {
capwap_free(wlan->ssid);
}
/* Remove stations */
while (wlan->stations->first) {
ac_stations_destroy_station(sessiondata, (struct ac_station*)wlan->stations->first->item);
}
/* */
capwap_list_free(wlan->stations);
}
/* */
void ac_wlans_delete_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid) {
struct capwap_list_item* search;
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
/* */
if (sessiondata->wlans->wlans[radioid - 1]) {
search = sessiondata->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(sessiondata, item);
capwap_itemlist_free(capwap_itemlist_remove(sessiondata->wlans->wlans[radioid - 1], search));
break;
}
/* Next */
search = search->next;
}
}
}
/* */
struct ac_station* ac_stations_get_station(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) {
struct ac_station* station;
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != 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)) {
station = (struct ac_station*)capwap_hash_search(sessiondata->wlans->stations, address);
if (station && ((radioid == RADIOID_ANY) || (radioid == station->wlan->radioid)) && (!bssid || !memcmp(bssid, station->wlan->bssid, MACADDRESS_EUI48_LENGTH))) {
return station;
}
@ -296,16 +316,16 @@ struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t
}
/* */
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_create_station(struct ac_session_data_t* sessiondata, 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_session_data_t* ownersession;
struct ac_station* station;
struct capwap_list_item* stationitem;
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(IS_VALID_RADIOID(radioid));
ASSERT(bssid != NULL);
ASSERT(address != NULL);
@ -317,25 +337,25 @@ struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint
/* Get session that owns the station */
capwap_rwlock_rdlock(&g_ac.stationslock);
ownersession = (struct ac_session_t*)capwap_hash_search(g_ac.stations, address);
ownersession = (struct ac_session_data_t*)capwap_hash_search(g_ac.stations, address);
capwap_rwlock_exit(&g_ac.stationslock);
/* If request change owner of station */
if (ownersession != session) {
if (ownersession != sessiondata) {
/* Release station from old owner */
if (ownersession) {
ac_session_send_action(ownersession, AC_SESSION_ACTION_ROAMING_STATION, 0, (void*)address, MACADDRESS_EUI48_LENGTH);
ac_session_data_send_action(ownersession, AC_SESSION_DATA_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_hash_add(g_ac.stations, address, sessiondata);
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);
wlan = ac_wlans_get_bssid(sessiondata, radioid, bssid);
station = ac_stations_get_station(sessiondata, RADIOID_ANY, NULL, address);
if (!station) {
stationitem = capwap_itemlist_create(sizeof(struct ac_station));
station = (struct ac_station*)stationitem->item;
@ -346,7 +366,7 @@ struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint
station->wlanitem = stationitem;
/* */
capwap_hash_add(session->wlans->stations, address, station);
capwap_hash_add(sessiondata->wlans->stations, address, station);
}
/* Set station to WLAN */
@ -356,16 +376,73 @@ struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint
}
/* */
void ac_stations_delete_station(struct ac_session_t* session, const uint8_t* address) {
struct ac_station* station;
void ac_stations_delete_station(struct ac_session_data_t* sessiondata, struct ac_station* station) {
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(station != NULL);
ASSERT(session != NULL);
ASSERT(session->wlans != NULL);
ASSERT(address != NULL);
/* Deauthorize station */
ac_stations_deauthorize_station(sessiondata, station);
/* Delete station */
station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address);
if (station) {
ac_stations_destroy_station(session, station);
/* Destroy station reference */
ac_stations_destroy_station(sessiondata, station);
}
/* */
void ac_stations_authorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station) {
struct ac_notify_station_configuration_ieee8011_add_station notify;
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(station != NULL);
/* Active Station only if Authenticated, Associated and not Authrizated */
if ((station->flags & AC_STATION_FLAGS_AUTHENTICATED) && (station->flags & AC_STATION_FLAGS_ASSOCIATE) && !(station->flags & AC_STATION_FLAGS_AUTHORIZED)) {
memset(&notify, 0, sizeof(struct ac_notify_station_configuration_ieee8011_add_station));
notify.radioid = station->wlan->radioid;
memcpy(notify.address, station->address, MACADDRESS_EUI48_LENGTH);
notify.wlanid = station->wlan->wlanid;
notify.associationid = station->aid;
notify.capabilities = station->capability;
notify.supportedratescount = station->supportedratescount;
memcpy(notify.supportedrates, station->supportedrates, station->supportedratescount);
ac_session_send_action(sessiondata->session, AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION, 0, &notify, sizeof(struct ac_notify_station_configuration_ieee8011_add_station));
}
}
/* */
void ac_stations_deauthorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station) {
int responselength;
uint8_t buffer[IEEE80211_MTU];
struct ieee80211_deauthentication_params ieee80211_params;
struct ac_notify_station_configuration_ieee8011_delete_station notify;
ASSERT(sessiondata != NULL);
ASSERT(sessiondata->wlans != NULL);
ASSERT(station != NULL);
/* Delete Station only if Authrizated */
if (station->flags & AC_STATION_FLAGS_AUTHORIZED) {
memset(&notify, 0, sizeof(struct ac_notify_station_configuration_ieee8011_delete_station));
notify.radioid = station->wlan->radioid;
memcpy(notify.address, station->address, MACADDRESS_EUI48_LENGTH);
/* Request recall ac_stations_deauthorize_station for deauthentication the station */
station->flags &= ~AC_STATION_FLAGS_AUTHORIZED;
ac_session_send_action(sessiondata->session, AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION, 0, &notify, sizeof(struct ac_notify_station_configuration_ieee8011_delete_station));
} else if (station->flags & AC_STATION_FLAGS_AUTHENTICATED) {
/* Create deauthentication packet */
memset(&ieee80211_params, 0, sizeof(struct ieee80211_deauthentication_params));
memcpy(ieee80211_params.bssid, station->wlan->bssid, MACADDRESS_EUI48_LENGTH);
memcpy(ieee80211_params.station, station->address, MACADDRESS_EUI48_LENGTH);
ieee80211_params.reasoncode = IEEE80211_REASON_PREV_AUTH_NOT_VALID;
/* */
responselength = ieee80211_create_deauthentication(buffer, IEEE80211_MTU, &ieee80211_params);
if (responselength > 0) {
station->flags &= ~(AC_STATION_FLAGS_AUTHENTICATED | AC_STATION_FLAGS_ASSOCIATE);
ac_session_data_send_data_packet(sessiondata, station->wlan->radioid, station->wlan->wlanid, buffer, responselength, 1);
}
}
}

View File

@ -3,12 +3,17 @@
#include "ieee80211.h"
/* */
#define RADIOID_ANY 0
/* */
#define AC_WLANS_STATIONS_HASH_SIZE 256
#define AC_WLANS_STATIONS_KEY_SIZE MACADDRESS_EUI48_LENGTH
/* AC WLAN */
struct ac_wlan {
struct capwap_list_item* wlanitem;
uint8_t bssid[MACADDRESS_EUI48_LENGTH];
uint8_t radioid;
uint8_t wlanid;
@ -35,13 +40,31 @@ struct ac_wlan {
uint8_t* ssid;
};
/* */
#define AC_STATION_FLAGS_AUTHENTICATED 0x00000001
#define AC_STATION_FLAGS_ASSOCIATE 0x00000002
#define AC_STATION_FLAGS_AUTHORIZED 0x00000004
/* AC Station */
struct ac_station {
uint8_t address[MACADDRESS_EUI48_LENGTH];
unsigned long flags;
/* Reference of WLAN */
struct ac_wlan* wlan;
struct capwap_list_item* wlanitem;
/* */
uint16_t capability;
uint16_t listeninterval;
uint16_t aid;
/* */
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
/* Authentication */
uint16_t authalgorithm;
};
/* */
@ -53,21 +76,21 @@ struct ac_wlans {
};
/* Management WLANS */
void ac_wlans_init(struct ac_session_t* session);
void ac_wlans_destroy(struct ac_session_t* session);
void ac_wlans_init(struct ac_session_data_t* sessiondata);
void ac_wlans_destroy(struct ac_session_data_t* sessiondata);
/* */
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);
struct ac_wlan* ac_wlans_create_bssid(uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, struct capwap_80211_addwlan_element* addwlan);
int ac_wlans_assign_bssid(struct ac_session_data_t* sessiondata, struct ac_wlan* wlan);
struct ac_wlan* ac_wlans_get_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid);
struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid);
void ac_wlans_delete_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid);
/* 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);
struct ac_station* ac_stations_create_station(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid, const uint8_t* address);
struct ac_station* ac_stations_get_station(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid, const uint8_t* address);
void ac_stations_delete_station(struct ac_session_data_t* sessiondata, struct ac_station* station);
void ac_stations_authorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station);
void ac_stations_deauthorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station);
#endif /* __AC_WLANS_HEADER__ */