The first beacon of SmartCAPWAP

This commit is contained in:
vemax78
2013-12-20 23:14:34 +01:00
parent 29ba25e434
commit bef31786ce
18 changed files with 6543 additions and 130 deletions

View File

@ -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();
}
}

View File

@ -79,6 +79,8 @@ struct wtp_t {
int standalone;
int running;
char wlanprefix[IFNAMSIZ];
struct wtp_state dfa;
struct capwap_network net;

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);