The first beacon of SmartCAPWAP
This commit is contained in:
119
src/wtp/wtp.c
119
src/wtp/wtp.c
@ -19,35 +19,6 @@ struct wtp_t g_wtp;
|
||||
|
||||
static char g_configurationfile[260] = WTP_STANDARD_CONFIGURATION_FILE;
|
||||
|
||||
/* */
|
||||
static struct wtp_radio* wtp_create_radio(void) {
|
||||
struct wtp_radio* radio;
|
||||
|
||||
/* Create disabled radio */
|
||||
radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, g_wtp.radios->count);
|
||||
radio->radioid = g_wtp.radios->count;
|
||||
radio->status = WTP_RADIO_DISABLED;
|
||||
|
||||
/* Init configuration radio */
|
||||
radio->antenna.selections = capwap_array_create(sizeof(uint8_t), 0, 1);
|
||||
|
||||
return radio;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void wtp_free_radios(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < g_wtp.radios->count; i++) {
|
||||
struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
|
||||
|
||||
capwap_array_free(radio->antenna.selections);
|
||||
}
|
||||
|
||||
/* */
|
||||
capwap_array_free(g_wtp.radios);
|
||||
}
|
||||
|
||||
/* Alloc WTP */
|
||||
static int wtp_init(void) {
|
||||
/* Init WTP with default value */
|
||||
@ -55,6 +26,7 @@ static int wtp_init(void) {
|
||||
|
||||
/* Standard running mode is standalone */
|
||||
g_wtp.standalone = 1;
|
||||
strcpy(g_wtp.wlanprefix, WTP_PREFIX_DEFAULT_NAME);
|
||||
|
||||
/* Standard name */
|
||||
g_wtp.name.name = (uint8_t*)capwap_duplicate_string(WTP_STANDARD_NAME);
|
||||
@ -108,8 +80,8 @@ static int wtp_init(void) {
|
||||
g_wtp.acdiscoveryresponse = capwap_array_create(sizeof(struct wtp_discovery_response), 0, 1);
|
||||
|
||||
/* Radios */
|
||||
g_wtp.radios = capwap_array_create(sizeof(struct wtp_radio), 0, 1);
|
||||
|
||||
wtp_radio_init();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -158,7 +130,7 @@ static void wtp_destroy(void) {
|
||||
capwap_free(g_wtp.location.value);
|
||||
|
||||
/* Free radios */
|
||||
wtp_free_radios();
|
||||
wtp_radio_free();
|
||||
}
|
||||
|
||||
/* Save AC address */
|
||||
@ -311,52 +283,6 @@ static int wtp_parsing_radio_configuration(config_setting_t* configElement, stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DSSS */
|
||||
configSection = config_setting_get_member(configElement, "dsss");
|
||||
if (configSection) {
|
||||
radio->directsequencecontrol.radioid = radio->radioid;
|
||||
radio->directsequencecontrol.currentchannel = 0;
|
||||
|
||||
if (config_setting_lookup_int(configSection, "clearchannelassessment", &configInt) == CONFIG_TRUE) {
|
||||
if ((configInt & CAPWAP_DSCONTROL_CCA_MASK) == configInt) {
|
||||
radio->directsequencecontrol.currentcca = (uint8_t)configInt;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_int(configSection, "energydetectthreshold", &configInt) == CONFIG_TRUE) {
|
||||
radio->directsequencecontrol.enerydetectthreshold = (uint32_t)configInt;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* OFDM */
|
||||
configSection = config_setting_get_member(configElement, "ofdm");
|
||||
if (configSection) {
|
||||
radio->ofdmcontrol.radioid = radio->radioid;
|
||||
radio->ofdmcontrol.currentchannel = 0;
|
||||
|
||||
if (config_setting_lookup_int(configSection, "bandsupported", &configInt) == CONFIG_TRUE) {
|
||||
if ((configInt & CAPWAP_OFDMCONTROL_BAND_MASK) == configInt) {
|
||||
radio->ofdmcontrol.bandsupport = (uint8_t)configInt;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_int(configSection, "tithreshold", &configInt) == CONFIG_TRUE) {
|
||||
radio->ofdmcontrol.tithreshold = (uint32_t)configInt;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Multi-Domain Capability */
|
||||
configSection = config_setting_get_member(configElement, "multidomaincapability");
|
||||
if (configSection) {
|
||||
@ -680,7 +606,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||
case CAPWAP_WIRELESS_BINDING_IEEE80211: {
|
||||
/* Initialize wifi binding driver */
|
||||
capwap_logging_info("Initializing wifi binding engine");
|
||||
if (wifi_init_driver()) {
|
||||
if (wifi_driver_init()) {
|
||||
capwap_logging_fatal("Unable initialize wifi binding engine");
|
||||
return 0;
|
||||
}
|
||||
@ -808,16 +734,27 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Set WLAN WTP */
|
||||
if (config_lookup_string(config, "wlan.prefix", &configString) == CONFIG_TRUE) {
|
||||
int length = strlen(configString);
|
||||
|
||||
if ((length > 0) && (length < WTP_PREFIX_NAME_MAX_LENGTH)) {
|
||||
strcpy(g_wtp.wlanprefix, configString);
|
||||
} else {
|
||||
capwap_logging_error("Invalid configuration file, wlan.prefix string length exceeded");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Radio WTP */
|
||||
configSetting = config_lookup(config, "application.radio");
|
||||
if (configSetting != NULL) {
|
||||
struct wtp_radio* radio;
|
||||
struct wifi_capability* capability;
|
||||
int count = config_setting_length(configSetting);
|
||||
|
||||
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
||||
for (i = 0; i < count; i++) {
|
||||
struct wtp_radio* radio;
|
||||
|
||||
if (!IS_VALID_RADIOID(g_wtp.radios->count + 1)) {
|
||||
capwap_logging_error("Exceeded max number of radio device");
|
||||
return 0;
|
||||
@ -829,7 +766,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||
if (config_setting_lookup_string(configElement, "device", &configString) == CONFIG_TRUE) {
|
||||
if (*configString && (strlen(configString) < IFNAMSIZ)) {
|
||||
/* Create new radio device */
|
||||
radio = wtp_create_radio();
|
||||
radio = wtp_radio_create_phy();
|
||||
strcpy(radio->device, configString);
|
||||
|
||||
if (config_setting_lookup_bool(configElement, "enabled", &configInt) == CONFIG_TRUE) {
|
||||
@ -839,14 +776,15 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
|
||||
/* Initialize radio device */
|
||||
if (config_setting_lookup_string(configElement, "driver", &configString) == CONFIG_TRUE) {
|
||||
if (*configString && (strlen(configString) < WIFI_DRIVER_NAME_SIZE)) {
|
||||
result = wifi_create_device(radio->radioid, radio->device, configString);
|
||||
result = wifi_device_connect(radio->radioid, radio->device, configString);
|
||||
if (!result) {
|
||||
radio->status = WTP_RADIO_ENABLED;
|
||||
capwap_logging_info("Register radioid %d with radio device: %s - %s", radio->radioid, radio->device, configString);
|
||||
|
||||
/* Update radio capability with device query */
|
||||
capability = wifi_get_capability_device(radio->radioid);
|
||||
capability = wifi_device_getcapability(radio->radioid);
|
||||
if (capability) {
|
||||
/* TODO */
|
||||
}
|
||||
} else {
|
||||
radio->status = WTP_RADIO_HWFAILURE;
|
||||
@ -1395,14 +1333,13 @@ int main(int argc, char** argv) {
|
||||
|
||||
capwap_logging_info("Terminate WTP");
|
||||
|
||||
/* Close radio */
|
||||
wtp_radio_close();
|
||||
|
||||
/* Free binding */
|
||||
switch (g_wtp.binding) {
|
||||
case CAPWAP_WIRELESS_BINDING_IEEE80211: {
|
||||
/* Free wifi binding driver */
|
||||
wifi_free_driver();
|
||||
capwap_logging_info("Free wifi binding engine");
|
||||
break;
|
||||
}
|
||||
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
||||
capwap_logging_info("Free wifi binding engine");
|
||||
wifi_driver_free();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,8 @@ struct wtp_t {
|
||||
int standalone;
|
||||
int running;
|
||||
|
||||
char wlanprefix[IFNAMSIZ];
|
||||
|
||||
struct wtp_state dfa;
|
||||
struct capwap_network net;
|
||||
|
||||
|
@ -31,42 +31,42 @@ void wtp_send_configure(struct timeout_control* timeout) {
|
||||
struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
|
||||
|
||||
/* Set message element */
|
||||
if ((radio->status == WTP_RADIO_ENABLED) && radio->radioinformation.radioid) {
|
||||
if ((radio->status == WTP_RADIO_ENABLED) && (radio->radioid == radio->radioinformation.radioid)) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &radio->radioinformation);
|
||||
|
||||
if (radio->radioinformation.radioid) {
|
||||
if (radio->radioid == radio->radioinformation.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ANTENNA, &radio->antenna);
|
||||
}
|
||||
|
||||
if (radio->directsequencecontrol.radioid && (radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) {
|
||||
if ((radio->radioid == radio->directsequencecontrol.radioid) && (radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL, &radio->directsequencecontrol);
|
||||
}
|
||||
|
||||
if (radio->macoperation.radioid) {
|
||||
if (radio->radioid == radio->macoperation.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MACOPERATION, &radio->macoperation);
|
||||
}
|
||||
|
||||
if (radio->multidomaincapability.radioid) {
|
||||
if (radio->radioid == radio->multidomaincapability.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY, &radio->multidomaincapability);
|
||||
}
|
||||
|
||||
if (radio->ofdmcontrol.radioid && (radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) {
|
||||
if ((radio->radioid == radio->ofdmcontrol.radioid) && (radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_OFDMCONTROL, &radio->ofdmcontrol);
|
||||
}
|
||||
|
||||
if (radio->supportedrates.radioid) {
|
||||
if (radio->radioid == radio->supportedrates.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_SUPPORTEDRATES, &radio->supportedrates);
|
||||
}
|
||||
|
||||
if (radio->txpower.radioid) {
|
||||
if (radio->radioid == radio->txpower.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWER, &radio->txpower);
|
||||
}
|
||||
|
||||
if (radio->txpowerlevel.radioid) {
|
||||
if (radio->radioid == radio->txpowerlevel.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWERLEVEL, &radio->txpowerlevel);
|
||||
}
|
||||
|
||||
if (radio->radioconfig.radioid) {
|
||||
if (radio->radioid == radio->radioconfig.radioid) {
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTP_RADIO_CONF, &radio->radioconfig);
|
||||
}
|
||||
} else {
|
||||
@ -123,15 +123,18 @@ void wtp_dfa_state_configure(struct capwap_parsed_packet* packet, struct timeout
|
||||
capwap_logging_warning("Receive Configure Status Response with error: %d", (int)resultcode->code);
|
||||
wtp_teardown_connection(timeout);
|
||||
} else {
|
||||
/* TODO: gestione richiesta */
|
||||
|
||||
/* */
|
||||
/* Timers */
|
||||
timers = (struct capwap_timers_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_TIMERS);
|
||||
g_wtp.dfa.rfcMaxDiscoveryInterval = timers->discovery;
|
||||
g_wtp.dfa.rfcEchoInterval = timers->echorequest;
|
||||
|
||||
/* Send change state event packet */
|
||||
wtp_send_datacheck(timeout);
|
||||
/* Binding values */
|
||||
if (!wtp_radio_setconfiguration(packet)) {
|
||||
wtp_send_datacheck(timeout); /* Send change state event packet */
|
||||
} else {
|
||||
capwap_logging_warning("Receive Configure Status Response with invalid elements");
|
||||
wtp_teardown_connection(timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -122,8 +122,13 @@ void wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_cont
|
||||
/* DTLS data policy */
|
||||
g_wtp.dtlsdatapolicy = acdescriptor->dtlspolicy & g_wtp.validdtlsdatapolicy;
|
||||
|
||||
/* Send configuration packet */
|
||||
wtp_send_configure(timeout);
|
||||
/* Binding values */
|
||||
if (!wtp_radio_setconfiguration(packet)) {
|
||||
wtp_send_configure(timeout); /* Send configuration packet */
|
||||
} else {
|
||||
capwap_logging_warning("Receive Join Response with invalid elements");
|
||||
wtp_teardown_connection(timeout);
|
||||
}
|
||||
} else {
|
||||
capwap_logging_warning("Receive Join Response with invalid DTLS data policy");
|
||||
wtp_teardown_connection(timeout);
|
||||
|
@ -8,7 +8,7 @@ void wtp_create_radioopsstate_element(struct capwap_packet_txmng* txmngpacket) {
|
||||
struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
|
||||
struct capwap_radiooprstate_element radiooprstate;
|
||||
|
||||
radiooprstate.radioid = (unsigned char)(i + 1);
|
||||
radiooprstate.radioid = radio->radioid;
|
||||
radiooprstate.state = ((radio->status == WTP_RADIO_ENABLED) ? CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED : CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED);
|
||||
|
||||
if (radio->status == WTP_RADIO_ENABLED) {
|
||||
@ -36,7 +36,7 @@ void wtp_create_radioadmstate_element(struct capwap_packet_txmng* txmngpacket) {
|
||||
struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
|
||||
struct capwap_radioadmstate_element radioadmstate;
|
||||
|
||||
radioadmstate.radioid = (unsigned char)(i + 1);
|
||||
radioadmstate.radioid = radio->radioid;
|
||||
radioadmstate.state = ((radio->status == WTP_RADIO_DISABLED) ? CAPWAP_RADIO_ADMIN_STATE_DISABLED : CAPWAP_RADIO_ADMIN_STATE_ENABLED);
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RADIOADMSTATE, &radioadmstate);
|
||||
}
|
||||
@ -56,7 +56,7 @@ void wtp_create_80211_wtpradioinformation_element(struct capwap_packet_txmng* tx
|
||||
memcpy(&element, &radio->radioinformation, sizeof(struct capwap_80211_wtpradioinformation_element));
|
||||
} else {
|
||||
memset(&element, 0, sizeof(struct capwap_80211_wtpradioinformation_element));
|
||||
element.radioid = (uint8_t)radio->radioid;
|
||||
element.radioid = radio->radioid;
|
||||
}
|
||||
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &element);
|
||||
|
@ -1,8 +1,436 @@
|
||||
#include "wtp.h"
|
||||
#include "wtp_radio.h"
|
||||
|
||||
/* */
|
||||
static int wtp_radio_configure_phy(struct wtp_radio* radio) {
|
||||
/* Default rate set is all supported rate */
|
||||
if (radio->radioid != radio->rateset.radioid) {
|
||||
if (radio->radioid != radio->supportedrates.radioid) {
|
||||
return -1; /* Supported rate not set */
|
||||
}
|
||||
|
||||
/* */
|
||||
radio->rateset.radioid = radio->radioid;
|
||||
radio->rateset.ratesetcount = radio->supportedrates.supportedratescount;
|
||||
memcpy(radio->rateset.rateset, radio->supportedrates.supportedrates, CAPWAP_RATESET_MAXLENGTH);
|
||||
}
|
||||
|
||||
/* Check channel radio */
|
||||
if (radio->radioid != radio->radioinformation.radioid) {
|
||||
return -1;
|
||||
} else if (radio->radioid != radio->radioconfig.radioid) {
|
||||
return -1;
|
||||
} else if ((!radio->directsequencecontrol.radioid && !radio->ofdmcontrol.radioid) || ((radio->directsequencecontrol.radioid == radio->radioid) && (radio->ofdmcontrol.radioid == radio->radioid))) {
|
||||
return -1; /* Only one from DSSS and OFDM can select */
|
||||
} else if ((radio->radioid == radio->directsequencecontrol.radioid) && !(radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) {
|
||||
return -1;
|
||||
} else if ((radio->radioid == radio->ofdmcontrol.radioid) && !(radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void wtp_radio_destroy_wlan(struct wtp_radio_wlan* wlan) {
|
||||
if (wlan->wlanid && wlan->radio) {
|
||||
if (wlan->state != WTP_RADIO_WLAN_STATE_IDLE) {
|
||||
if (wlan->state == WTP_RADIO_WLAN_STATE_AP) {
|
||||
wifi_wlan_stopap(wlan->radio->radioid, wlan->wlanid);
|
||||
}
|
||||
|
||||
/* Destroy interface */
|
||||
wifi_wlan_destroy(wlan->radio->radioid, wlan->wlanid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release item */
|
||||
memset(wlan, 0, sizeof(struct wtp_radio_wlan));
|
||||
}
|
||||
|
||||
/* */
|
||||
void wtp_radio_init(void) {
|
||||
g_wtp.radios = capwap_array_create(sizeof(struct wtp_radio), 0, 1);
|
||||
}
|
||||
|
||||
/* */
|
||||
void wtp_radio_close(void) {
|
||||
int i, j;
|
||||
|
||||
ASSERT(g_wtp.radios != NULL);
|
||||
|
||||
for (i = 0; i < g_wtp.radios->count; i++) {
|
||||
struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
|
||||
|
||||
if (radio->antenna.selections) {
|
||||
capwap_array_free(radio->antenna.selections);
|
||||
}
|
||||
|
||||
if (radio->wlan) {
|
||||
for (j = 0; j < radio->wlan->count; j++) {
|
||||
wtp_radio_destroy_wlan((struct wtp_radio_wlan*)capwap_array_get_item_pointer(radio->wlan, j));
|
||||
}
|
||||
|
||||
capwap_array_free(radio->wlan);
|
||||
}
|
||||
}
|
||||
|
||||
capwap_array_resize(g_wtp.radios, 0);
|
||||
}
|
||||
|
||||
/* */
|
||||
void wtp_radio_free(void) {
|
||||
ASSERT(g_wtp.radios != NULL);
|
||||
ASSERT(g_wtp.radios->count == 0);
|
||||
|
||||
capwap_array_free(g_wtp.radios);
|
||||
}
|
||||
|
||||
/* */
|
||||
int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
||||
int i;
|
||||
unsigned short binding;
|
||||
struct wtp_radio* radio;
|
||||
struct capwap_array* messageelements;
|
||||
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
/* */
|
||||
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
|
||||
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
||||
struct capwap_list_item* search = packet->messages->first;
|
||||
|
||||
while (search) {
|
||||
struct capwap_message_element_itemlist* messageelement = (struct capwap_message_element_itemlist*)search->item;
|
||||
|
||||
/* Parsing only IEEE 802.11 message element */
|
||||
if (IS_80211_MESSAGE_ELEMENTS(messageelement->type)) {
|
||||
switch (messageelement->type) {
|
||||
case CAPWAP_ELEMENT_80211_ANTENNA: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_antenna_element* antenna;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
antenna = *(struct capwap_80211_antenna_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(antenna->radioid);
|
||||
if (radio && (radio->radioid == antenna->radioid)) {
|
||||
capwap_element_80211_antenna_copy(&radio->antenna, antenna);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_MACOPERATION: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_macoperation_element* macoperation;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
macoperation = *(struct capwap_80211_macoperation_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(macoperation->radioid);
|
||||
if (radio && (radio->radioid == macoperation->radioid)) {
|
||||
memcpy(&radio->macoperation, macoperation, sizeof(struct capwap_80211_macoperation_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_multidomaincapability_element* multidomaincapability;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
multidomaincapability = *(struct capwap_80211_multidomaincapability_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(multidomaincapability->radioid);
|
||||
if (radio && (radio->radioid == multidomaincapability->radioid)) {
|
||||
memcpy(&radio->multidomaincapability, multidomaincapability, sizeof(struct capwap_80211_multidomaincapability_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_directsequencecontrol_element* directsequencecontrol;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
directsequencecontrol = *(struct capwap_80211_directsequencecontrol_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(directsequencecontrol->radioid);
|
||||
if (radio && (radio->radioid == directsequencecontrol->radioid)) {
|
||||
memcpy(&radio->directsequencecontrol, directsequencecontrol, sizeof(struct capwap_80211_directsequencecontrol_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_OFDMCONTROL: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_ofdmcontrol_element* ofdmcontrol;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
ofdmcontrol = *(struct capwap_80211_ofdmcontrol_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(ofdmcontrol->radioid);
|
||||
if (radio && (radio->radioid == ofdmcontrol->radioid)) {
|
||||
memcpy(&radio->ofdmcontrol, ofdmcontrol, sizeof(struct capwap_80211_ofdmcontrol_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_RATESET: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_rateset_element* rateset;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
rateset = *(struct capwap_80211_rateset_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(rateset->radioid);
|
||||
if (radio && (radio->radioid == rateset->radioid)) {
|
||||
memcpy(&radio->rateset, rateset, sizeof(struct capwap_80211_rateset_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_SUPPORTEDRATES: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_supportedrates_element* supportedrates;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
supportedrates = *(struct capwap_80211_supportedrates_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(supportedrates->radioid);
|
||||
if (radio && (radio->radioid == supportedrates->radioid)) {
|
||||
memcpy(&radio->supportedrates, supportedrates, sizeof(struct capwap_80211_supportedrates_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_TXPOWER: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_txpower_element* txpower;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
txpower = *(struct capwap_80211_txpower_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(txpower->radioid);
|
||||
if (radio && (radio->radioid == txpower->radioid)) {
|
||||
memcpy(&radio->txpower, txpower, sizeof(struct capwap_80211_txpower_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_WTP_QOS: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_wtpqos_element* qos;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
qos = *(struct capwap_80211_wtpqos_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(qos->radioid);
|
||||
if (radio && (radio->radioid == qos->radioid)) {
|
||||
memcpy(&radio->qos, qos, sizeof(struct capwap_80211_wtpqos_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_wtpradioinformation_element* radioinformation;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
radioinformation = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(radioinformation->radioid);
|
||||
if (radio && (radio->radioid == radioinformation->radioid)) {
|
||||
memcpy(&radio->radioinformation, radioinformation, sizeof(struct capwap_80211_wtpradioinformation_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ELEMENT_80211_WTP_RADIO_CONF: {
|
||||
messageelements = (struct capwap_array*)messageelement->data;
|
||||
if (messageelements && (messageelements->count > 0)) {
|
||||
struct capwap_80211_wtpradioconf_element* radioconfig;
|
||||
|
||||
for (i = 0; i < messageelements->count; i++) {
|
||||
radioconfig = *(struct capwap_80211_wtpradioconf_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(radioconfig->radioid);
|
||||
if (radio && (radio->radioid == radioconfig->radioid)) {
|
||||
memcpy(&radio->radioconfig, radioconfig, sizeof(struct capwap_80211_wtpradioconf_element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next */
|
||||
search = search->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
struct wtp_radio* wtp_radio_create_phy(void) {
|
||||
struct wtp_radio* radio;
|
||||
|
||||
/* Create disabled radio */
|
||||
radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, g_wtp.radios->count);
|
||||
radio->radioid = (uint8_t)g_wtp.radios->count;
|
||||
radio->status = WTP_RADIO_DISABLED;
|
||||
|
||||
/* Init configuration radio */
|
||||
radio->wlan = capwap_array_create(sizeof(struct wtp_radio_wlan), 0, 1);
|
||||
radio->antenna.selections = capwap_array_create(sizeof(uint8_t), 0, 1);
|
||||
return radio;
|
||||
}
|
||||
|
||||
/* */
|
||||
struct wtp_radio* wtp_radio_get_phy(uint8_t radioid) {
|
||||
int i;
|
||||
|
||||
ASSERT(IS_VALID_RADIOID(radioid));
|
||||
|
||||
for (i = 0; i < g_wtp.radios->count; i++) {
|
||||
struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i);
|
||||
if (radioid == radio->radioid) {
|
||||
return radio;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
struct wtp_radio_wlan* wtp_radio_get_wlan(struct wtp_radio* radio, uint8_t wlanid) {
|
||||
int i;
|
||||
|
||||
ASSERT(IS_VALID_WLANID(wlanid));
|
||||
|
||||
for (i = 0; i < radio->wlan->count; i++) {
|
||||
struct wtp_radio_wlan* wlan = (struct wtp_radio_wlan*)capwap_array_get_item_pointer(radio->wlan, i);
|
||||
if ((wlanid == wlan->wlanid) && (radio == wlan->radio)) {
|
||||
return wlan;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwap_80211_assignbssid_element* bssid) {
|
||||
uint32_t band;
|
||||
uint8_t channel;
|
||||
struct wtp_radio* radio;
|
||||
struct wtp_radio_wlan* wlan;
|
||||
struct capwap_80211_addwlan_element* addwlan;
|
||||
struct capwap_array* ies;
|
||||
|
||||
/* Get message elements */
|
||||
addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_ADD_WLAN);
|
||||
ies = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
|
||||
if (!addwlan) {
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Get physical radio */
|
||||
radio = wtp_radio_get_phy(addwlan->radioid);
|
||||
if (!radio) {
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Check if virtual interface is already exist */
|
||||
wlan = wtp_radio_get_wlan(radio, addwlan->wlanid);
|
||||
if (wlan) {
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Prepare physical interface for create wlan */
|
||||
if (!radio->wlan->count) {
|
||||
if (wtp_radio_configure_phy(radio)) {
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set radio channel */
|
||||
band = ((radio->radioid == radio->directsequencecontrol.radioid) ? WIFI_BAND_2GHZ : WIFI_BAND_5GHZ);
|
||||
channel = ((radio->radioid == radio->directsequencecontrol.radioid) ? radio->directsequencecontrol.currentchannel : radio->ofdmcontrol.currentchannel);
|
||||
if (wifi_device_setfrequency(addwlan->radioid, band, radio->radioinformation.radiotype, channel)) {
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Set virtual interface information */
|
||||
wlan = (struct wtp_radio_wlan*)capwap_array_get_item_pointer(radio->wlan, radio->wlan->count);
|
||||
wlan->radio = radio;
|
||||
wlan->wlanid = addwlan->wlanid;
|
||||
sprintf(wlan->wlanname, "%s%02d.%02d", g_wtp.wlanprefix, (int)addwlan->radioid, (int)addwlan->wlanid);
|
||||
if (wifi_iface_index(wlan->wlanname)) {
|
||||
memset(wlan, 0, sizeof(struct wtp_radio_wlan));
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Create virtual interface */
|
||||
if (!wifi_wlan_create(addwlan->radioid, addwlan->wlanid, wlan->wlanname, NULL)) {
|
||||
wlan->state = WTP_RADIO_WLAN_STATE_CREATED;
|
||||
} else {
|
||||
wtp_radio_destroy_wlan(wlan);
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Configure virtual interface */
|
||||
if (!wifi_wlan_setupap(addwlan, ies)) {
|
||||
wlan->state = WTP_RADIO_WLAN_STATE_READY;
|
||||
} else {
|
||||
wtp_radio_destroy_wlan(wlan);
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Start AP */
|
||||
if (!wifi_wlan_startap(addwlan->radioid, addwlan->wlanid)) {
|
||||
wlan->state = WTP_RADIO_WLAN_STATE_AP;
|
||||
} else {
|
||||
wtp_radio_destroy_wlan(wlan);
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* */
|
||||
bssid->radioid = addwlan->radioid;
|
||||
bssid->wlanid = addwlan->wlanid;
|
||||
wifi_wlan_getbssid(addwlan->radioid, addwlan->wlanid, bssid->bssid);
|
||||
|
||||
return CAPWAP_RESULTCODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,65 @@
|
||||
#ifndef __WTP_RADIO_HEADER__
|
||||
#define __WTP_RADIO_HEADER__
|
||||
|
||||
/* */
|
||||
#define WTP_RADIO_ENABLED 0
|
||||
#define WTP_RADIO_DISABLED 1
|
||||
#define WTP_RADIO_HWFAILURE 2
|
||||
#define WTP_RADIO_SWFAILURE 3
|
||||
|
||||
/* */
|
||||
#define WTP_PREFIX_NAME_MAX_LENGTH (IFNAMSIZ - 6)
|
||||
#define WTP_PREFIX_DEFAULT_NAME "ap"
|
||||
|
||||
#define WTP_RADIO_WLAN_STATE_IDLE 0
|
||||
#define WTP_RADIO_WLAN_STATE_CREATED 1
|
||||
#define WTP_RADIO_WLAN_STATE_READY 2
|
||||
#define WTP_RADIO_WLAN_STATE_AP 3
|
||||
|
||||
struct wtp_radio_wlan {
|
||||
struct wtp_radio* radio;
|
||||
|
||||
uint8_t wlanid;
|
||||
char wlanname[IFNAMSIZ];
|
||||
|
||||
int state;
|
||||
};
|
||||
|
||||
/* */
|
||||
struct wtp_radio {
|
||||
int radioid;
|
||||
uint8_t radioid;
|
||||
char device[IFNAMSIZ];
|
||||
|
||||
struct capwap_array* wlan;
|
||||
|
||||
int status;
|
||||
struct capwap_80211_antenna_element antenna;
|
||||
struct capwap_80211_directsequencecontrol_element directsequencecontrol;
|
||||
struct capwap_80211_macoperation_element macoperation;
|
||||
struct capwap_80211_multidomaincapability_element multidomaincapability;
|
||||
struct capwap_80211_ofdmcontrol_element ofdmcontrol;
|
||||
struct capwap_80211_rateset_element rateset;
|
||||
struct capwap_80211_supportedrates_element supportedrates;
|
||||
struct capwap_80211_txpower_element txpower;
|
||||
struct capwap_80211_txpowerlevel_element txpowerlevel;
|
||||
struct capwap_80211_wtpradioconf_element radioconfig;
|
||||
struct capwap_80211_wtpradioinformation_element radioinformation;
|
||||
struct capwap_80211_wtpqos_element qos;
|
||||
};
|
||||
|
||||
/* */
|
||||
void wtp_radio_init(void);
|
||||
void wtp_radio_close(void);
|
||||
void wtp_radio_free(void);
|
||||
|
||||
/* */
|
||||
struct wtp_radio* wtp_radio_create_phy(void);
|
||||
struct wtp_radio* wtp_radio_get_phy(uint8_t radioid);
|
||||
struct wtp_radio_wlan* wtp_radio_get_wlan(struct wtp_radio* radio, uint8_t wlanid);
|
||||
|
||||
/* */
|
||||
int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet);
|
||||
|
||||
/* */
|
||||
uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwap_80211_assignbssid_element* bssid);
|
||||
uint32_t wtp_radio_update_wlan(struct capwap_parsed_packet* packet);
|
||||
|
Reference in New Issue
Block a user