Improved the management of the IEEE802.11 Beacon and add the management of

IEEE802.11 Probe Response.
This commit is contained in:
vemax78 2014-01-10 13:25:28 +01:00
parent 66019df158
commit d2c01ad82a
12 changed files with 1197 additions and 430 deletions

View File

@ -82,7 +82,8 @@ ac_SOURCES = \
$(top_srcdir)/src/ac/ac_dfa_run.c \
$(top_srcdir)/src/ac/ac_dfa_reset.c \
$(top_srcdir)/src/ac/ac_dfa_teardown.c \
$(top_srcdir)/src/ac/ac_soap.c
$(top_srcdir)/src/ac/ac_soap.c \
$(top_srcdir)/src/binding/ieee80211/ieee80211.c
ac_LDADD = \
$(CONFIG_LIBS) \

View File

@ -54,6 +54,7 @@ wtp_SOURCES = \
$(top_srcdir)/src/wtp/wtp_dfa_reset.c \
$(top_srcdir)/src/wtp/wtp_dfa_imagedata.c \
$(top_srcdir)/src/wtp/wtp_radio.c \
$(top_srcdir)/src/binding/ieee80211/ieee80211.c \
$(top_srcdir)/src/binding/ieee80211/wifi_drivers.c
wtp_LDADD = \

View File

@ -275,7 +275,7 @@ static int ac_backend_parsing_addwlan_event(const char* idevent, struct json_obj
addwlan->authmode = (uint8_t)json_object_get_int(jsonauthtype);
addwlan->macmode = (uint8_t)json_object_get_int(jsonmacmode);
addwlan->tunnelmode = (uint8_t)json_object_get_int(jsontunnelmode);
addwlan->suppressssid = (uint8_t)(json_object_get_boolean(jsonhidessid) ? 0 : 1);
addwlan->suppressssid = (uint8_t)(json_object_get_boolean(jsonhidessid) ? 1 : 0);
strcpy(addwlan->ssid, ssid);
/* Notify Request to Complete Event */

View File

@ -0,0 +1,267 @@
#include "capwap.h"
#include "ieee80211.h"
/* */
static int ieee80211_ie_set_ssid(char* buffer, const char* ssid, int hidessid) {
struct ieee80211_ie_ssid* iessid = (struct ieee80211_ie_ssid*)buffer;
ASSERT(buffer != NULL);
ASSERT(ssid != NULL);
iessid->id = IEEE80211_IE_SSID;
if (hidessid) {
iessid->len = 0;
} else {
iessid->len = strlen(ssid);
if (iessid->len > IEEE80211_IE_SSID_MAX_LENGTH) {
return -1;
}
strncpy((char*)iessid->ssid, ssid, iessid->len);
}
return sizeof(struct ieee80211_ie_ssid) + iessid->len;
}
/* */
static int ieee80211_ie_set_supportedrates(char* buffer, uint8_t* supportedrates, int supportedratescount) {
int i;
int count;
struct ieee80211_ie_supported_rates* iesupportedrates = (struct ieee80211_ie_supported_rates*)buffer;
ASSERT(buffer != NULL);
ASSERT(supportedrates != NULL);
ASSERT(supportedratescount > 0);
/* IE accept max only 8 rate */
count = supportedratescount;
if (count > 8) {
count = 8;
}
/* */
iesupportedrates->id = IEEE80211_IE_SUPPORTED_RATES;
iesupportedrates->len = count;
for (i = 0; i < count; i++) {
iesupportedrates->rates[i] = supportedrates[i];
}
return sizeof(struct ieee80211_ie_supported_rates) + iesupportedrates->len;
}
/* */
static int ieee80211_ie_set_extendedsupportedrates(char* buffer, uint8_t* supportedrates, int supportedratescount) {
int i, j;
struct ieee80211_ie_extended_supported_rates* ieextendedsupportedrates = (struct ieee80211_ie_extended_supported_rates*)buffer;
ASSERT(buffer != NULL);
ASSERT(supportedrates != NULL);
/* IE accept only > 8 rate */
if (supportedratescount <= IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH) {
return 0;
}
/* */
ieextendedsupportedrates->id = IEEE80211_IE_EXTENDED_SUPPORTED_RATES;
ieextendedsupportedrates->len = supportedratescount - IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH;
for (i = IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH, j = 0; i < supportedratescount; i++, j++) {
ieextendedsupportedrates->rates[j] = supportedrates[i];
}
return sizeof(struct ieee80211_ie_extended_supported_rates) + ieextendedsupportedrates->len;
}
/* */
static int ieee80211_ie_set_dsss(char* buffer, uint8_t channel) {
struct ieee80211_ie_dsss* iedsss = (struct ieee80211_ie_dsss*)buffer;
ASSERT(buffer != NULL);
iedsss->id = IEEE80211_IE_DSSS;
iedsss->len = 1;
iedsss->channel = channel;
return sizeof(struct ieee80211_ie_dsss);
}
/* */
static int ieee80211_ie_set_erp(char* buffer, uint32_t mode) {
struct ieee80211_ie_erp* ieerp = (struct ieee80211_ie_erp*)buffer;
ASSERT(buffer != NULL);
if (!(mode & IEEE80211_RADIO_TYPE_80211G)) {
return 0;
}
ieerp->id = IEEE80211_IE_ERP;
ieerp->len = 1;
ieerp->params = 0; /* TODO */
return sizeof(struct ieee80211_ie_erp);
}
/* */
int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_params* params) {
int result;
char* pos;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
ASSERT(length == IEEE80211_MTU);
/* */
memset(buffer, 0x00, length);
header = (struct ieee80211_header_mgmt*)buffer;
params->headbeacon = buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_BEACON);
memset(header->da, 0xff, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->beacon.beaconinterval = __cpu_to_le16(params->beaconperiod);
header->beacon.capability = __cpu_to_le16(params->capability);
/* Header frame size */
params->headbeaconlength = (int)((uint8_t*)&header->beacon.ie[0] - (uint8_t*)header);
pos = buffer + params->headbeaconlength;
/* Information Element: SSID */
result = ieee80211_ie_set_ssid(pos, params->ssid, (params->ssid_hidden ? 1 : 0));
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Information Element: DSSS */
result = ieee80211_ie_set_dsss(pos, params->channel);
if (result < 0) {
return -1;
}
pos += result;
params->headbeaconlength += result;
/* Separate Information Elements into two block between IE TIM */
params->tailbeacon = pos;
params->tailbeaconlength = 0;
/* Information Element: Country */
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->erpmode);
if (result < 0) {
return -1;
}
pos += result;
params->tailbeaconlength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
params->tailbeaconlength += result;
return (params->headbeaconlength + params->tailbeaconlength);
}
/* */
int ieee80211_create_probe_response(char* buffer, int length, const struct ieee80211_header_mgmt* proberequestheader, struct ieee80211_probe_response_params* params) {
int result;
char* pos;
int responselength;
struct ieee80211_header_mgmt* header;
ASSERT(buffer != NULL);
ASSERT(length == IEEE80211_MTU);
/* */
memset(buffer, 0x00, length);
header = (struct ieee80211_header_mgmt*)buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_RESP);
if (proberequestheader) {
memcpy(header->da, proberequestheader->sa, ETH_ALEN);
} else {
memset(header->da, 0x00, ETH_ALEN);
}
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->proberesponse.beaconinterval = __cpu_to_le16(params->beaconperiod);
header->proberesponse.capability = __cpu_to_le16(params->capability);
/* Header frame size */
responselength = (int)((uint8_t*)&header->proberesponse.ie[0] - (uint8_t*)header);
pos = buffer + responselength;
/* Information Element: SSID */
result = ieee80211_ie_set_ssid(pos, params->ssid, 0);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: DSSS */
result = ieee80211_ie_set_dsss(pos, params->channel);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Country */
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->erpmode);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
return responselength;
}

View File

@ -10,10 +10,17 @@
#endif
/* Global values */
#define IEEE80211_MTU 2304
#define IEEE80211_MTU 2304
/* Radio type with value same of IEEE802.11 Radio Information Message Element */
#define IEEE80211_RADIO_TYPE_80211B 0x00000001
#define IEEE80211_RADIO_TYPE_80211A 0x00000002
#define IEEE80211_RADIO_TYPE_80211G 0x00000004
#define IEEE80211_RADIO_TYPE_80211N 0x00000008
/* */
#define IS_IEEE80211_FREQ_BG(x) (((x >= 2412) && (x <= 2484)) ? 1 : 0)
#define IS_IEEE80211_FREQ_A(x) (((x >= 5035) && (x <= 5825)) ? 1 : 0)
#define IS_IEEE80211_FREQ_A(x) ((((x >= 4915) && (x <= 4980)) || ((x >= 5035) && (x <= 5825))) ? 1 : 0)
/* Rate into multiple of 500Kbps */
#define IEEE80211_RATE_1M 2
@ -35,6 +42,11 @@
#define IS_IEEE80211_RATE_A(x) (((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_9M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_18M) || (x == IEEE80211_RATE_24M) || (x == IEEE80211_RATE_36M) || (x == IEEE80211_RATE_48M) || (x == IEEE80211_RATE_54M)) ? 1 : 0)
#define IS_IEEE80211_RATE_N(x) ((x == IEEE80211_RATE_80211N) ? 1 : 0)
#define IEEE80211_BASICRATE 128
#define IS_IEEE80211_BASICRATE_B(x) ((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M))
#define IS_IEEE80211_BASICRATE_G(x) ((x == IEEE80211_RATE_1M) || (x == IEEE80211_RATE_2M) || (x == IEEE80211_RATE_5_5M) || (x == IEEE80211_RATE_11M))
#define IS_IEEE80211_BASICRATE_A(x) ((x == IEEE80211_RATE_6M) || (x == IEEE80211_RATE_12M) || (x == IEEE80211_RATE_24M))
/* Frame control type */
#define IEEE80211_FRAMECONTROL_TYPE_MGMT 0
#define IEEE80211_FRAMECONTROL_TYPE_CTRL 1
@ -85,7 +97,9 @@
#define IEEE80211_FRAMECONTROL_DATA_SUBTYPE_QOSCFACK_CFPOLL 15
/* */
#define IEEE80211_FRAME_CONTROL(type, stype) __cpu_to_le16((type << 2) | (stype << 4))
#define IEEE80211_FRAME_CONTROL(type, stype) __cpu_to_le16((type << 2) | (stype << 4))
#define IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol) (((framecontrol) & 0x000c) >> 2)
#define IEEE80211_FRAME_CONTROL_GET_SUBTYPE(framecontrol) (((framecontrol) & 0x00f0) >> 4)
/* 802.11 Packet - IEEE802.11 is a little-endian protocol */
struct ieee80211_header {
@ -106,9 +120,25 @@ struct ieee80211_header_mgmt {
uint8_t bssid[ETH_ALEN];
__le16 sequencecontrol;
uint8_t timestamp[8];
__le16 beaconinterval;
__le16 capability;
union {
struct {
uint8_t timestamp[8];
__le16 beaconinterval;
__le16 capability;
uint8_t ie[0];
} STRUCT_PACKED beacon;
struct {
uint8_t ie[0];
} STRUCT_PACKED proberequest;
struct {
uint8_t timestamp[8];
__le16 beaconinterval;
__le16 capability;
uint8_t ie[0];
} STRUCT_PACKED proberesponse;
};
} STRUCT_PACKED;
/* 802.11 Generic information element */
@ -190,6 +220,8 @@ struct ieee80211_ie_extended_supported_rates {
#define EDCA_PARAMETER_RECORD_AC_VO_FIELD 3
struct ieee80211_ie_edca_parameter_set {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
@ -198,15 +230,98 @@ struct ieee80211_ie_edca_parameter_set {
#define IEEE80211_IE_QOS_CAPABILITY_LENGTH 1
struct ieee80211_ie_qos_capability {
uint8_t id;
uint8_t len;
/* TODO */
};
} STRUCT_PACKED;
/* 802.11 Power Constraint information element */
#define IEEE80211_IE_POWER_CONSTRAINT 52
#define IEEE80211_IE_POWER_CONSTRAINT_LENGTH 1
struct ieee80211_ie_power_constraint {
uint8_t id;
uint8_t len;
/* TODO */
} STRUCT_PACKED;
/* 802.11 SSID List */
#define IEEE80211_IE_SSID_LIST 84
struct ieee80211_ie_ssid_list {
uint8_t id;
uint8_t len;
uint8_t lists[0];
} STRUCT_PACKED;
/* 802.11 All information elements */
struct ieee80211_ie_items {
struct ieee80211_ie_ssid* ssid;
struct ieee80211_ie_supported_rates* supported_rates;
struct ieee80211_ie_dsss* dsss;
struct ieee80211_ie_country* country;
struct ieee80211_ie_erp* erp;
struct ieee80211_ie_extended_supported_rates* extended_supported_rates;
struct ieee80211_ie_edca_parameter_set* edca_parameter_set;
struct ieee80211_ie_qos_capability* qos_capability;
struct ieee80211_ie_power_constraint* power_constraint;
struct ieee80211_ie_ssid_list* ssid_list;
};
/* IEEE 802.11 functions */
#define IEEE80211_SUPPORTEDRATE_MAX_COUNT 16
/* Management Beacon */
struct ieee80211_beacon_params {
/* Beacon packet */
char* headbeacon;
int headbeaconlength;
char* tailbeacon;
int tailbeaconlength;
/* Header information */
uint8_t bssid[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
/* SSID */
const char* ssid;
int ssid_hidden;
/* Supported Rates */
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
/* DSSS */
uint8_t channel;
/* ERP */
uint32_t erpmode;
};
int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_params* params);
/* Management Probe Response */
struct ieee80211_probe_response_params {
/* Header information */
uint8_t bssid[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
/* SSID */
const char* ssid;
/* Supported Rates */
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
/* DSSS */
uint8_t channel;
/* ERP */
uint32_t erpmode;
};
int ieee80211_create_probe_response(char* buffer, int length, const struct ieee80211_header_mgmt* proberequestheader, struct ieee80211_probe_response_params* params);
#endif /* __CAPWAP_IEEE802_11_HEADER__ */

View File

@ -3,7 +3,6 @@
#include "capwap_element.h"
#include "wtp_radio.h"
#include "wifi_drivers.h"
#include "ieee80211.h"
/* Declare enable wifi driver */
#ifdef ENABLE_WIFI_DRIVERS_NL80211
@ -20,36 +19,6 @@ static struct wifi_driver_instance wifi_driver[] = {
/* Radio instance */
static struct capwap_array* g_wifidevice = NULL;
/* */
static void wifi_device_freecapability(struct wifi_capability* capability) {
int i;
ASSERT(capability != NULL);
/* Free memory */
if (capability->bands) {
for (i = 0; i < capability->bands->count; i++) {
struct wifi_band_capability* bandcap = (struct wifi_band_capability*)capwap_array_get_item_pointer(capability->bands, i);
if (bandcap->freq) {
capwap_array_free(bandcap->freq);
}
if (bandcap->rate) {
capwap_array_free(bandcap->rate);
}
}
capwap_array_free(capability->bands);
}
if (capability->ciphers) {
capwap_array_free(capability->ciphers);
}
capwap_free(capability);
}
/* */
int wifi_driver_init(void) {
int i;
@ -93,10 +62,6 @@ void wifi_driver_free(void) {
capwap_array_free(device->wlan);
}
if (device->capability) {
wifi_device_freecapability(device->capability);
}
if (device->handle && device->instance->ops->device_deinit) {
device->instance->ops->device_deinit(device->handle);
}
@ -291,7 +256,9 @@ int wifi_wlan_create(int radioid, int wlanid, const char* ifname, uint8_t* bssid
/* */
static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* radio) {
int i, j, w;
int radiotype;
uint32_t mode = 0;
const struct wifi_capability* capability;
ASSERT(device != NULL);
ASSERT(radio != NULL);
@ -299,11 +266,16 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
/* Free old supported rates */
device->supportedratescount = 0;
/* Retrieve cached capability */
if (!device->capability) {
if (!wifi_device_getcapability(radio->radioid)) {
return;
}
/* Retrieve capability */
capability = wifi_device_getcapability(radio->radioid);
if (!capability) {
return;
}
/* Get radio type for basic rate */
radiotype = wifi_frequency_to_radiotype(device->currentfreq.frequency);
if (radiotype < 0) {
return;
}
/* Check type of rate mode */
@ -334,20 +306,18 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
}
/* Filter band */
for (i = 0; i < device->capability->bands->count; i++) {
struct wifi_band_capability* bandcap = (struct wifi_band_capability*)capwap_array_get_item_pointer(device->capability->bands, i);
for (i = 0; i < capability->bands->count; i++) {
struct wifi_band_capability* bandcap = (struct wifi_band_capability*)capwap_array_get_item_pointer(capability->bands, i);
if (bandcap->band == device->currentfreq.band) {
if (bandcap->rate->count) {
for (j = 0; j < bandcap->rate->count; j++) {
struct wifi_rate_capability* rate = (struct wifi_rate_capability*)capwap_array_get_item_pointer(bandcap->rate, j);
for (j = 0; j < bandcap->rate->count; j++) {
struct wifi_rate_capability* rate = (struct wifi_rate_capability*)capwap_array_get_item_pointer(bandcap->rate, j);
/* Validate rate */
for (w = 0; w < radio->rateset.ratesetcount; w++) {
if (radio->rateset.rateset[w] == rate->bitrate) {
device->supportedrates[device->supportedratescount++] = rate->bitrate;
break;
}
/* Validate rate */
for (w = 0; w < radio->rateset.ratesetcount; w++) {
if (radio->rateset.rateset[w] == rate->bitrate) {
device->supportedrates[device->supportedratescount++] = rate->bitrate;
break;
}
}
}
@ -356,6 +326,23 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
}
}
/* Apply basic rate */
for (i = 0; i < device->supportedratescount; i++) {
if (radiotype == CAPWAP_RADIO_TYPE_80211A) {
if (IS_IEEE80211_BASICRATE_A(device->supportedrates[i])) {
device->supportedrates[i] |= IEEE80211_BASICRATE;
}
} else if (radiotype == CAPWAP_RADIO_TYPE_80211B) {
if (IS_IEEE80211_BASICRATE_B(device->supportedrates[i])) {
device->supportedrates[i] |= IEEE80211_BASICRATE;
}
} else if (radiotype == CAPWAP_RADIO_TYPE_80211G) {
if (IS_IEEE80211_BASICRATE_G(device->supportedrates[i])) {
device->supportedrates[i] |= IEEE80211_BASICRATE;
}
}
}
/* Add implicit 802.11n rate with only 802.11a/g rate */
if (!(mode & CAPWAP_RADIO_TYPE_80211N) && (device->currentfreq.mode & CAPWAP_RADIO_TYPE_80211N)) {
device->supportedrates[device->supportedratescount++] = IEEE80211_RATE_80211N;
@ -363,216 +350,59 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
}
/* */
static int wifi_ie_ssid(char* buffer, const char* ssid, int hidessid) {
struct ieee80211_ie_ssid* iessid = (struct ieee80211_ie_ssid*)buffer;
ASSERT(buffer != NULL);
ASSERT(ssid != NULL);
iessid->id = IEEE80211_IE_SSID;
if (!hidessid) {
iessid->len = strlen(ssid);
if (iessid->len > IEEE80211_IE_SSID_MAX_LENGTH) {
return -1;
}
strncpy((char*)iessid->ssid, ssid, iessid->len);
}
return sizeof(struct ieee80211_ie_ssid) + iessid->len;
}
/* */
static int wifi_ie_supportedrates(char* buffer, struct wifi_device* device) {
int i;
int count;
struct ieee80211_ie_supported_rates* iesupportedrates = (struct ieee80211_ie_supported_rates*)buffer;
ASSERT(buffer != NULL);
/* IE accept max only 8 rate */
count = device->supportedratescount;
if (count > 8) {
count = 8;
}
/* */
iesupportedrates->id = IEEE80211_IE_SUPPORTED_RATES;
iesupportedrates->len = count;
for (i = 0; i < count; i++) {
iesupportedrates->rates[i] = device->supportedrates[i];
}
return sizeof(struct ieee80211_ie_supported_rates) + iesupportedrates->len;
}
/* */
static int wifi_ie_extendedsupportedrates(char* buffer, struct wifi_device* device) {
int i, j;
struct ieee80211_ie_extended_supported_rates* ieextendedsupportedrates = (struct ieee80211_ie_extended_supported_rates*)buffer;
ASSERT(buffer != NULL);
/* IE accept only > 8 rate */
if (device->supportedratescount <= IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH) {
return 0;
}
/* */
ieextendedsupportedrates->id = IEEE80211_IE_EXTENDED_SUPPORTED_RATES;
ieextendedsupportedrates->len = device->supportedratescount - IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH;
for (i = IEEE80211_IE_SUPPORTED_RATES_MAX_LENGTH, j = 0; i < device->supportedratescount; i++, j++) {
ieextendedsupportedrates->rates[j] = device->supportedrates[i];
}
return sizeof(struct ieee80211_ie_extended_supported_rates) + ieextendedsupportedrates->len;
}
/* */
static int wifi_ie_dsss(char* buffer, struct wifi_device* device) {
struct ieee80211_ie_dsss* iedsss;
ASSERT(buffer != NULL);
ASSERT(device != NULL);
iedsss = (struct ieee80211_ie_dsss*)buffer;
iedsss->id = IEEE80211_IE_SSID;
iedsss->len = 1;
iedsss->channel = device->currentfreq.channel;
return sizeof(struct ieee80211_ie_dsss);
}
/* */
static int wifi_ie_erp(char* buffer, struct wifi_device* device) {
ASSERT(buffer != NULL);
ASSERT(device != NULL);
return 0;
/* TODO implements params ERP
struct ieee80211_ie_erp* ieerp = (struct ieee80211_ie_erp*)buffer;
if (device->currentfreq.mode != CAPWAP_RADIO_TYPE_80211G) {
return 0;
}
ieerp->id = IEEE80211_IE_ERP;
ieerp->len = 1;
iedsss->params = 0;
return sizeof(struct ieee80211_ie_erp);
*/
}
/* */
int wifi_wlan_setupap(struct capwap_80211_addwlan_element* addwlan, struct capwap_array* ies) {
int result;
int wifi_wlan_setupap(int radioid, int wlanid) {
struct wifi_wlan* wlan;
struct wtp_radio* radio;
char buffer[IEEE80211_MTU];
struct ieee80211_header_mgmt* header;
struct wlan_setupap_params params;
ASSERT(addwlan != NULL);
/* Get WLAN and Radio information */
wlan = wifi_wlan_getdevice(addwlan->radioid, addwlan->wlanid);
radio = wtp_radio_get_phy(addwlan->radioid);
if (!wlan || !radio || !wlan->handle || !wlan->device) {
return -1;
} else if (!wlan->device->instance->ops->wlan_setupap) {
return -1;
}
ASSERT(radioid > 0);
ASSERT(wlanid > 0);
/* */
memset(buffer, 0, sizeof(buffer));
header = (struct ieee80211_header_mgmt*)buffer;
/* */
memset(&params, 0, sizeof(struct wlan_setupap_params));
params.headbeacon = buffer;
/* Management header frame */
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_BEACON);
memset(header->da, 0xff, ETH_ALEN);
wlan->device->instance->ops->wlan_getmacaddress(wlan->handle, header->sa);
memcpy(header->bssid, header->sa, ETH_ALEN);
header->beaconinterval = __cpu_to_le16(radio->radioconfig.beaconperiod);
header->capability = __cpu_to_le16(addwlan->capability);
params.headbeaconlength += sizeof(struct ieee80211_header_mgmt);
/* Information Element: SSID */
result = wifi_ie_ssid(&params.headbeacon[params.headbeaconlength], (const char*)addwlan->ssid, (addwlan->suppressssid ? 1 : 0));
if (result < 0) {
wlan = wifi_wlan_getdevice(radioid, wlanid);
if (!wlan || !wlan->device->instance->ops->wlan_setupap) {
return -1;
}
params.headbeaconlength += result;
/* Information Element: Supported Rates */
wifi_wlan_getrates(wlan->device, radio);
result = wifi_ie_supportedrates(&params.headbeacon[params.headbeaconlength], wlan->device);
if (result < 0) {
return -1;
}
params.headbeaconlength += result;
/* Information Element: DSSS */
result = wifi_ie_dsss(&params.headbeacon[params.headbeaconlength], wlan->device);
if (result < 0) {
return -1;
}
params.headbeaconlength += result;
/* Separate Information Elements into two block between IE TIM */
params.tailbeacon = &params.headbeacon[params.headbeaconlength];
/* Information Element: Country */
/* TODO */
/* Information Element: ERP */
result = wifi_ie_erp(&params.tailbeacon[params.tailbeaconlength], wlan->device);
if (result < 0) {
return -1;
}
params.tailbeaconlength += result;
/* Information Element: Extended Supported Rates */
result = wifi_ie_extendedsupportedrates(&params.tailbeacon[params.tailbeaconlength], wlan->device);
if (result < 0) {
return -1;
}
params.tailbeaconlength += result;
/* Set configuration params */
strcpy(params.ssid, (const char*)addwlan->ssid);
params.suppressssid = addwlan->suppressssid;
params.beaconinterval = radio->radioconfig.beaconperiod;
params.dtimperiod = radio->radioconfig.dtimperiod;
params.authenticationtype = addwlan->authmode;
/* Configuration complete */
return wlan->device->instance->ops->wlan_setupap(wlan->handle, &params);
return wlan->device->instance->ops->wlan_setupap(wlan->handle);
}
/* */
int wifi_wlan_startap(int radioid, int wlanid) {
struct wifi_wlan* wlan;
struct wtp_radio* radio;
struct wtp_radio_wlan* radiowlan;
struct wlan_startap_params wlan_params;
ASSERT(radioid > 0);
ASSERT(wlanid > 0);
/* */
wlan = wifi_wlan_getdevice(radioid, wlanid);
if (!wlan->device->instance->ops->wlan_startap) {
radio = wtp_radio_get_phy(radioid);
if (!wlan || !radio || !wlan->device->instance->ops->wlan_startap) {
return -1;
}
return wlan->device->instance->ops->wlan_startap(wlan->handle);
/* */
radiowlan = wtp_radio_get_wlan(radio, wlanid);
if (!radiowlan) {
return -1;
}
/* Retrieve supported rates */
wifi_wlan_getrates(wlan->device, radiowlan->radio);
/* Start AP */
memset(&wlan_params, 0, sizeof(struct wlan_startap_params));
wlan_params.ssid = radiowlan->ssid;
wlan_params.ssid_hidden = radiowlan->ssid_hidden;
wlan_params.beaconperiod = radio->radioconfig.beaconperiod;
wlan_params.capability = radiowlan->capability;
wlan_params.dtimperiod = radio->radioconfig.dtimperiod;
memcpy(wlan_params.supportedrates, wlan->device->supportedrates, wlan->device->supportedratescount);
wlan_params.supportedratescount = wlan->device->supportedratescount;
wlan_params.authenticationtype = radiowlan->authmode;
return wlan->device->instance->ops->wlan_startap(wlan->handle, &wlan_params);
}
/* */
@ -619,7 +449,7 @@ void wifi_wlan_destroy(int radioid, int wlanid) {
}
/* */
struct wifi_capability* wifi_device_getcapability(int radioid) {
const struct wifi_capability* wifi_device_getcapability(int radioid) {
struct wifi_device* device;
ASSERT(radioid > 0);
@ -630,29 +460,18 @@ struct wifi_capability* wifi_device_getcapability(int radioid) {
/* Retrieve cached capability */
device = (struct wifi_device*)capwap_array_get_item_pointer(g_wifidevice, radioid);
if (!device->capability && device->handle && device->instance->ops->device_getcapability) {
/* Get capability from device */
device->capability = (struct wifi_capability*)capwap_alloc(sizeof(struct wifi_capability));
memset(device->capability, 0, sizeof(struct wifi_capability));
device->capability->bands = capwap_array_create(sizeof(struct wifi_band_capability), 0, 1);
device->capability->ciphers = capwap_array_create(sizeof(struct wifi_cipher_capability), 0, 1);
/* */
if (device->instance->ops->device_getcapability(device->handle, device->capability)) {
wifi_device_freecapability(device->capability);
device->capability = NULL;
}
if (!device->handle || !device->instance->ops->device_getcapability) {
return NULL;
}
return device->capability;
return device->instance->ops->device_getcapability(device->handle);
}
/* */
int wifi_device_setfrequency(int radioid, uint32_t band, uint32_t mode, uint8_t channel) {
int i, j;
int result = -1;
struct wifi_capability* capability;
const struct wifi_capability* capability;
uint32_t frequency = 0;
ASSERT(radioid > 0);
@ -768,14 +587,148 @@ int wifi_iface_hwaddr(int sock, const char* ifname, uint8_t* hwaddr) {
}
/* */
unsigned long wifi_frequency_to_channel(unsigned long freq) {
int wifi_frequency_to_radiotype(uint32_t freq) {
if ((freq >= 2412) && (freq <= 2472)) {
return CAPWAP_RADIO_TYPE_80211G;
} else if (freq == 2484) {
return CAPWAP_RADIO_TYPE_80211B;
} else if ((freq >= 4915) && (freq <= 4980)) {
return CAPWAP_RADIO_TYPE_80211A;
} else if ((freq >= 5035) && (freq <= 5825)) {
return CAPWAP_RADIO_TYPE_80211A;
}
return -1;
}
/* */
unsigned long wifi_frequency_to_channel(uint32_t freq) {
if ((freq >= 2412) && (freq <= 2472)) {
return (freq - 2407) / 5;
} else if (freq == 2484) {
return 14;
} else if ((freq >= 4915) && (freq <= 4980)) {
return (freq - 4000) / 5;
} else if ((freq >= 5035) && (freq <= 5825)) {
return freq / 5 - 1000;
return (freq - 5000) / 5;
}
return 0;
}
/* */
int wifi_is_broadcast_addr(const uint8_t* addr) {
return (((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)) ? 1 : 0);
}
/* */
int wifi_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist) {
int ssidlength;
ASSERT(ssid != NULL);
ASSERT(iessid != NULL);
/* Check SSID */
ssidlength = strlen((char*)ssid);
if ((ssidlength == iessid->len) && !memcmp(ssid, iessid->ssid, ssidlength)) {
return WIFI_VALID_SSID;
}
/* Check SSID list */
if (isssidlist) {
int length = isssidlist->len;
uint8_t* pos = isssidlist->lists;
while (length >= sizeof(struct ieee80211_ie)) {
struct ieee80211_ie_ssid* ssiditem = (struct ieee80211_ie_ssid*)pos;
/* Check buffer */
length -= sizeof(struct ieee80211_ie);
if ((ssiditem->id != IEEE80211_IE_SSID) || !ssiditem->len || (length < ssiditem->len)) {
break;
} else if ((ssidlength == ssiditem->len) && !memcmp(ssid, ssiditem->ssid, ssidlength)) {
return WIFI_VALID_SSID;
}
/* Next */
length -= ssiditem->len;
pos += sizeof(struct ieee80211_ie) + ssiditem->len;
}
}
return (!iessid->len ? WIFI_WILDCARD_SSID : WIFI_WRONG_SSID);
}
/* */
int wifi_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length) {
ASSERT(items != NULL);
ASSERT(data != NULL);
/* */
memset(items, 0, sizeof(struct ieee80211_ie_items));
/* Parsing */
while (length >= 2) {
uint8_t ie_id = data[0];
uint8_t ie_len = data[1];
/* Parsing Information Element */
switch (ie_id) {
case IEEE80211_IE_SSID: {
items->ssid = (struct ieee80211_ie_ssid*)data;
break;
}
case IEEE80211_IE_SUPPORTED_RATES: {
items->supported_rates = (struct ieee80211_ie_supported_rates*)data;
break;
}
case IEEE80211_IE_DSSS: {
items->dsss = (struct ieee80211_ie_dsss*)data;
break;
}
case IEEE80211_IE_COUNTRY: {
items->country = (struct ieee80211_ie_country*)data;
break;
}
case IEEE80211_IE_ERP: {
items->erp = (struct ieee80211_ie_erp*)data;
break;
}
case IEEE80211_IE_EXTENDED_SUPPORTED_RATES: {
items->extended_supported_rates = (struct ieee80211_ie_extended_supported_rates*)data;
break;
}
case IEEE80211_IE_EDCA_PARAMETER_SET: {
items->edca_parameter_set = (struct ieee80211_ie_edca_parameter_set*)data;
break;
}
case IEEE80211_IE_QOS_CAPABILITY: {
items->qos_capability = (struct ieee80211_ie_qos_capability*)data;
break;
}
case IEEE80211_IE_POWER_CONSTRAINT: {
items->power_constraint = (struct ieee80211_ie_power_constraint*)data;
break;
}
case IEEE80211_IE_SSID_LIST: {
items->ssid_list = (struct ieee80211_ie_ssid_list*)data;
break;
}
}
/* Next Information Element */
data += sizeof(struct ieee80211_ie) + ie_len;
length -= sizeof(struct ieee80211_ie) + ie_len;
}
return (!length ? 0 : -1);
}

View File

@ -3,6 +3,7 @@
#include <net/if_arp.h>
#include <linux/if_ether.h>
#include "ieee80211.h"
/* */
#define WIFI_DRIVER_NAME_SIZE 16
@ -13,15 +14,22 @@
#define WIFI_BAND_2GHZ 1
#define WIFI_BAND_5GHZ 2
/* */
#define WIFI_SUPPORTEDRATE_MAX_COUNT 16
/* */
#define WIFI_CAPABILITY_RADIOSUPPORTED 0x00000001
#define WIFI_CAPABILITY_RADIOTYPE 0x00000002
#define WIFI_CAPABILITY_BANDS 0x00000004
#define WIFI_CAPABILITY_CIPHERS 0x00000008
#define WIFI_CAPABILITY_ANTENNA_MASK 0x00000010
#define WIFI_CAPABILITY_MAX_SCAN_SSIDS 0x00000020
#define WIFI_CAPABILITY_MAX_SCHED_SCAN_SSIDS 0x00000040
#define WIFI_CAPABILITY_MAX_MATCH_SETS 0x00000080
#define WIFI_CAPABILITY_MAX_ACL_MACADDRESS 0x00000100
/* */
#define WIFI_CAPABILITY_FLAGS_OFFCHANNEL_TX_OK 0x00000001
#define WIFI_CAPABILITY_FLAGS_ROAM_SUPPORT 0x00000002
#define WIFI_CAPABILITY_FLAGS_SUPPORT_AP_UAPSD 0x00000004
#define WIFI_CAPABILITY_FLAGS_DEVICE_AP_SME 0x00000008
/* */
#define WIFI_CAPABILITY_AP_SUPPORTED 0x00000001
@ -71,21 +79,34 @@ struct wlan_init_params {
};
/* */
struct wlan_setupap_params {
char* headbeacon;
int headbeaconlength;
char* tailbeacon;
int tailbeaconlength;
struct wlan_startap_params {
const char* ssid;
uint8_t ssid_hidden;
char ssid[WIFI_SSID_MAX_LENGTH + 1];
uint8_t suppressssid;
uint16_t beaconinterval;
uint16_t beaconperiod;
uint16_t capability;
uint8_t dtimperiod;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
uint8_t authenticationtype;
};
/* */
struct wlan_send_frame_params {
char* packet;
int length;
uint32_t frequency;
uint32_t duration;
int offchannel_tx_ok;
int no_cck_rate;
int no_wait_ack;
uint64_t cookie;
};
/* Interface capability */
struct wifi_freq_capability {
unsigned long flags;
@ -126,6 +147,7 @@ struct wifi_capability {
wifi_device_handle device;
unsigned long flags;
unsigned long capability;
/* WIFI_CAPABILITY_RADIOSUPPORTED */
unsigned long radiosupported;
@ -142,6 +164,18 @@ struct wifi_capability {
/* WIFI_CAPABILITY_CIPHERS */
struct capwap_array* ciphers;
/* WIFI_CAPABILITY_MAX_SCAN_SSIDS */
uint8_t maxscanssids;
/* WIFI_CAPABILITY_MAX_SCHED_SCAN_SSIDS */
uint8_t maxschedscanssids;
/* WIFI_CAPABILITY_MAX_MATCH_SETS */
uint8_t maxmatchsets;
/* WIFI_CAPABILITY_MAX_ACL_MACADDRESS */
uint8_t maxaclmacaddress;
};
/* Frequency configuration */
@ -172,15 +206,15 @@ struct wifi_driver_ops {
/* Device functions */
wifi_device_handle (*device_init)(wifi_global_handle handle, struct device_init_params* params);
int (*device_getfdevent)(wifi_device_handle handle, struct pollfd* fds, struct wifi_event* events);
int (*device_getcapability)(wifi_device_handle handle, struct wifi_capability* capability);
const struct wifi_capability* (*device_getcapability)(wifi_device_handle handle);
int (*device_setfrequency)(wifi_device_handle handle, struct wifi_frequency* freq);
void (*device_deinit)(wifi_device_handle handle);
/* WLAN functions */
wifi_wlan_handle (*wlan_create)(wifi_device_handle handle, struct wlan_init_params* params);
int (*wlan_getfdevent)(wifi_wlan_handle handle, struct pollfd* fds, struct wifi_event* events);
int (*wlan_setupap)(wifi_wlan_handle handle, struct wlan_setupap_params* params);
int (*wlan_startap)(wifi_wlan_handle handle);
int (*wlan_setupap)(wifi_wlan_handle handle);
int (*wlan_startap)(wifi_wlan_handle handle, struct wlan_startap_params* params);
int (*wlan_stopap)(wifi_wlan_handle handle);
int (*wlan_getmacaddress)(wifi_wlan_handle handle, uint8_t* address);
void (*wlan_delete)(wifi_wlan_handle handle);
@ -199,15 +233,12 @@ struct wifi_device {
struct capwap_array* wlan; /* Virtual AP */
/* Cache capability */
struct wifi_capability* capability;
/* Current frequency */
struct wifi_frequency currentfreq;
/* Supported Rates */
int supportedratescount;
uint8_t supportedrates[WIFI_SUPPORTEDRATE_MAX_COUNT];
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
};
/* */
@ -225,12 +256,12 @@ int wifi_event_getfd(struct pollfd* fds, struct wifi_event* events, int count);
/* */
int wifi_device_connect(int radioid, const char* ifname, const char* driver);
struct wifi_capability* wifi_device_getcapability(int radioid);
const struct wifi_capability* wifi_device_getcapability(int radioid);
int wifi_device_setfrequency(int radioid, uint32_t band, uint32_t mode, uint8_t channel);
/* */
int wifi_wlan_create(int radioid, int wlanid, const char* ifname, uint8_t* bssid);
int wifi_wlan_setupap(struct capwap_80211_addwlan_element* addwlan, struct capwap_array* ies);
int wifi_wlan_setupap(int radioid, int wlanid);
int wifi_wlan_startap(int radioid, int wlanid);
int wifi_wlan_stopap(int radioid, int wlanid);
int wifi_wlan_getbssid(int radioid, int wlanid, uint8_t* bssid);
@ -239,7 +270,19 @@ void wifi_wlan_destroy(int radioid, int wlanid);
/* Util functions */
uint32_t wifi_iface_index(const char* ifname);
int wifi_iface_hwaddr(int sock, const char* ifname, uint8_t* hwaddr);
unsigned long wifi_frequency_to_channel(unsigned long freq);
int wifi_frequency_to_radiotype(uint32_t freq);
unsigned long wifi_frequency_to_channel(uint32_t freq);
int wifi_is_broadcast_addr(const uint8_t* addr);
/* */
#define WIFI_VALID_SSID 1
#define WIFI_WILDCARD_SSID 0
#define WIFI_WRONG_SSID -1
int wifi_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struct ieee80211_ie_ssid_list* isssidlist);
/* */
int wifi_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length);
int wifi_iface_updown(int sock, const char* ifname, int up);
#define wifi_iface_up(sock, ifname) wifi_iface_updown(sock, ifname, 1)

View File

@ -11,7 +11,6 @@
#include "wifi_drivers.h"
#include "wifi_nl80211.h"
#include "ieee80211.h"
/* Compatibility functions */
#if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30)
@ -88,29 +87,15 @@ static int nl80211_ack_handler(struct nl_msg* msg, void* arg) {
}
/* */
static int nl80211_process_bss_event(struct nl_msg* msg, void* arg) {
/* TODO */
return NL_SKIP;
}
/* */
static void nl80211_event_receive(int fd, void* param1, void* param2) {
int res;
struct nl_sock* nl = (struct nl_sock*)param1;
struct nl_cb* nl_cb = (struct nl_cb*)param2;
static int nl80211_cookie_handler(struct nl_msg* msg, void* arg) {
struct nlattr* tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg));
/* */
res = nl_recvmsgs(nl, nl_cb);
if (res) {
capwap_logging_warning("Receive nl80211 message failed: %d", res);
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
if (tb_msg[NL80211_ATTR_COOKIE]) {
*(uint64_t*)arg = nla_get_u64(tb_msg[NL80211_ATTR_COOKIE]);
}
}
/* */
static int nl80211_global_valid_handler(struct nl_msg* msg, void* arg) {
/* TODO */
capwap_logging_debug("nl80211_global_valid_handler");
/* TODO */
return NL_SKIP;
}
@ -156,6 +141,247 @@ static int nl80211_send_and_recv_msg(struct nl80211_global_handle* globalhandle,
return nl80211_send_and_recv(globalhandle->nl, globalhandle->nl_cb, msg, valid_cb, data);
}
/* */
static int nl80211_wlan_send_frame(wifi_wlan_handle handle, struct wlan_send_frame_params* params) {
int result;
uint64_t cookie;
struct nl_msg* msg;
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
/* */
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
/* */
genlmsg_put(msg, 0, 0, wlanhandle->devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_FRAME, 0);
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wlanhandle->virtindex);
if (params->frequency) {
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, params->frequency);
}
if (params->duration) {
nla_put_u32(msg, NL80211_ATTR_DURATION, params->duration);
}
if (params->offchannel_tx_ok && (wlanhandle->devicehandle->capability->capability & WIFI_CAPABILITY_FLAGS_OFFCHANNEL_TX_OK)) {
nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
}
if (params->no_cck_rate) {
nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE);
}
if (params->no_wait_ack) {
nla_put_flag(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK);
}
nla_put(msg, NL80211_ATTR_FRAME, params->length, params->packet);
/* Send frame */
cookie = 0;
result = nl80211_send_and_recv_msg(wlanhandle->devicehandle->globalhandle, msg, nl80211_cookie_handler, &cookie);
nlmsg_free(msg);
params->cookie = (result || params->no_wait_ack ? 0 : cookie);
return result;
}
/* */
static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
int ssidcheck;
char buffer[IEEE80211_MTU];
int responselength;
struct ieee80211_ie_items ieitems;
struct wlan_send_frame_params wlan_params;
struct ieee80211_probe_response_params ieee80211_params;
/* Information Elements packet length */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest));
if (ielength < 0) {
return;
}
/* Parsing Information Elements */
if (wifi_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) {
return;
}
/* Validate Probe Request Packet */
if (!ieitems.ssid || !ieitems.supported_rates) {
return;
}
/* Verify the SSID */
ssidcheck = wifi_is_valid_ssid(wlanhandle->ssid, ieitems.ssid, ieitems.ssid_list);
if (ssidcheck == WIFI_WRONG_SSID) {
return;
}
/* Create probe response */
memset(&ieee80211_params, 0, sizeof(struct ieee80211_probe_response_params));
memcpy(ieee80211_params.bssid, wlanhandle->address, ETH_ALEN);
ieee80211_params.beaconperiod = wlanhandle->beaconperiod;
ieee80211_params.capability = wlanhandle->capability;
ieee80211_params.ssid = wlanhandle->ssid;
memcpy(ieee80211_params.supportedrates, wlanhandle->supportedrates, wlanhandle->supportedratescount);
ieee80211_params.supportedratescount = wlanhandle->supportedratescount;
ieee80211_params.erpmode = 0; /* TODO */
ieee80211_params.channel = wifi_frequency_to_channel(wlanhandle->devicehandle->currentfrequency);
responselength = ieee80211_create_probe_response(buffer, IEEE80211_MTU, mgmt, &ieee80211_params);
if (responselength < 0) {
return;
}
/* Send probe response */
memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params));
wlan_params.packet = buffer;
wlan_params.length = responselength;
wlan_params.frequency = wlanhandle->devicehandle->currentfrequency;
wlan_params.no_wait_ack = ((ssidcheck == WIFI_WILDCARD_SSID) && wifi_is_broadcast_addr(mgmt->da) ? 1 : 0);
if (nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) {
capwap_logging_warning("Unable to send IEEE802.11 Probe Response");
}
}
/* */
static void nl80211_do_mgmt_frame_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, uint16_t framecontrol_subtype, int mgmtlength, uint32_t frequency) {
int broadcast;
/* Check frequency */
if (frequency && (wlanhandle->devicehandle->currentfrequency != frequency)) {
return;
}
/* Check if sent packet to correct virtual ap */
broadcast = wifi_is_broadcast_addr(mgmt->bssid);
if (!broadcast && memcmp(mgmt->bssid, wlanhandle->address, ETH_ALEN)) {
return;
}
/* */
if (framecontrol_subtype == IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQ) {
nl80211_do_mgmt_probe_request_event(wlanhandle, mgmt, mgmtlength);
} else if (!memcmp(mgmt->da, wlanhandle->address, ETH_ALEN)) {
switch (framecontrol_subtype) {
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTH: {
/* TODO */
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOC_REQ: {
/* TODO */
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOC_REQ: {
/* TODO */
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOC: {
/* TODO */
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTH: {
/* TODO */
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION: {
/* TODO */
break;
}
}
}
}
/* */
static void nl80211_do_frame_event(struct nl80211_wlan_handle* wlanhandle, struct nlattr* frame, uint32_t frequency) {
const uint8_t* framedata;
const struct ieee80211_header* header;
int framelength;
uint16_t framecontrol;
uint16_t framecontrol_type;
uint16_t framecontrol_subtype;
/* */
if (!frame) {
return;
}
/* Get frame data */
framedata = nla_data(frame);
framelength = nla_len(frame);
if (framelength < sizeof(struct ieee80211_header)) {
return;
}
/* Get type frame */
header = (const struct ieee80211_header*)framedata;
framecontrol = __le16_to_cpu(header->framecontrol);
framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol);
framecontrol_subtype = IEEE80211_FRAME_CONTROL_GET_SUBTYPE(framecontrol);
/* Parsing frame */
if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) {
nl80211_do_mgmt_frame_event(wlanhandle, (const struct ieee80211_header_mgmt*)framedata, framecontrol_subtype, framelength, frequency);
}
}
/* */
static int nl80211_process_bss_event(struct nl_msg* msg, void* arg) {
struct nlattr* tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)arg;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
switch (gnlh->cmd) {
case NL80211_CMD_FRAME: {
uint32_t frequency = 0;
if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
frequency = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
}
nl80211_do_frame_event(wlanhandle, tb_msg[NL80211_ATTR_FRAME], frequency);
break;
}
}
return NL_SKIP;
}
/* */
static void nl80211_event_receive(int fd, void* param1, void* param2) {
int res;
struct nl_sock* nl = (struct nl_sock*)param1;
struct nl_cb* nl_cb = (struct nl_cb*)param2;
/* */
res = nl_recvmsgs(nl, nl_cb);
if (res) {
capwap_logging_warning("Receive nl80211 message failed: %d", res);
}
}
/* */
static int nl80211_global_valid_handler(struct nl_msg* msg, void* arg) {
/* TODO */
capwap_logging_debug("nl80211_global_valid_handler");
/* TODO */
return NL_SKIP;
}
/* */
static unsigned long nl80211_get_cipher(uint32_t chiper) {
switch (chiper) {
@ -330,6 +556,43 @@ static int cb_get_phydevice_capability(struct nl_msg* msg, void* data) {
}
}
/* */
if (tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) {
capability->flags |= WIFI_CAPABILITY_MAX_SCAN_SSIDS;
capability->maxscanssids = nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
}
if (tb_msg[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]) {
capability->flags |= WIFI_CAPABILITY_MAX_SCHED_SCAN_SSIDS;
capability->maxschedscanssids = nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
}
if (tb_msg[NL80211_ATTR_MAX_MATCH_SETS]) {
capability->flags |= WIFI_CAPABILITY_MAX_MATCH_SETS;
capability->maxmatchsets = nla_get_u8(tb_msg[NL80211_ATTR_MAX_MATCH_SETS]);
}
if (tb_msg[NL80211_ATTR_MAC_ACL_MAX]) {
capability->flags |= WIFI_CAPABILITY_MAX_ACL_MACADDRESS;
capability->maxaclmacaddress = nla_get_u8(tb_msg[NL80211_ATTR_MAC_ACL_MAX]);
}
if (tb_msg[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
capability->capability |= WIFI_CAPABILITY_FLAGS_OFFCHANNEL_TX_OK;
}
if (tb_msg[NL80211_ATTR_ROAM_SUPPORT]) {
capability->capability |= WIFI_CAPABILITY_FLAGS_ROAM_SUPPORT;
}
if (tb_msg[NL80211_ATTR_SUPPORT_AP_UAPSD]) {
capability->capability |= WIFI_CAPABILITY_FLAGS_SUPPORT_AP_UAPSD;
}
if (tb_msg[NL80211_ATTR_DEVICE_AP_SME]) {
capability->capability |= WIFI_CAPABILITY_FLAGS_DEVICE_AP_SME;
}
/* Cipher supported */
if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) {
int count;
@ -575,6 +838,43 @@ static int nl80211_registerframe(struct nl80211_wlan_handle* wlanhandle, uint16_
return result;
}
/* */
static int nl80211_device_getcapability(struct nl80211_device_handle* devicehandle) {
int result;
struct nl_msg* msg;
ASSERT(devicehandle != NULL);
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
genlmsg_put(msg, 0, 0, devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_GET_WIPHY, 0);
nla_put_u32(msg, NL80211_ATTR_WIPHY, devicehandle->phyindex);
/* Retrieve physical device capability */
devicehandle->capability->device = (wifi_device_handle)devicehandle;
result = nl80211_send_and_recv_msg(devicehandle->globalhandle, msg, cb_get_phydevice_capability, devicehandle->capability);
if (result) {
capwap_logging_error("Unable retrieve physical device capability, error code: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
static const struct wifi_capability* nl80211_device_getcachedcapability(wifi_device_handle handle) {
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
ASSERT(handle != NULL);
ASSERT(devicehandle->capability != NULL);
return devicehandle->capability;
}
/* */
static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct device_init_params* params) {
int result;
@ -601,9 +901,19 @@ static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct
memset(devicehandle, 0, sizeof(struct nl80211_device_handle));
/* */
devicehandle->globalhandle = globalhandle;
strcpy(devicehandle->phyname, phyitem->name);
devicehandle->phyindex = phyitem->index;
/* Device capability */
devicehandle->capability = (struct wifi_capability*)capwap_alloc(sizeof(struct wifi_capability));
memset(devicehandle->capability, 0, sizeof(struct wifi_capability));
devicehandle->capability->bands = capwap_array_create(sizeof(struct wifi_band_capability), 0, 1);
devicehandle->capability->ciphers = capwap_array_create(sizeof(struct wifi_cipher_capability), 0, 1);
/* Retrieve device capability */
nl80211_device_getcapability(devicehandle);
break;
}
@ -621,9 +931,6 @@ static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct
return NULL;
}
/* */
devicehandle->globalhandle = globalhandle;
/* Remove all virtual adapter from wifi device */
nl80211_destroy_all_virtdevice(globalhandle, devicehandle->phyindex);
@ -636,41 +943,12 @@ static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct
}
/* */
int nl80211_device_getfdevent(wifi_device_handle handle, struct pollfd* fds, struct wifi_event* events) {
static int nl80211_device_getfdevent(wifi_device_handle handle, struct pollfd* fds, struct wifi_event* events) {
return 0;
}
/* */
int nl80211_device_getcapability(wifi_device_handle handle, struct wifi_capability* capability) {
int result;
struct nl_msg* msg;
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
ASSERT(handle != NULL);
ASSERT(capability != NULL);
msg = nlmsg_alloc();
if (!msg) {
return -1;
}
genlmsg_put(msg, 0, 0, devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_GET_WIPHY, 0);
nla_put_u32(msg, NL80211_ATTR_WIPHY, devicehandle->phyindex);
/* Retrieve physical device capability */
capability->device = (wifi_device_handle)devicehandle;
result = nl80211_send_and_recv_msg(devicehandle->globalhandle, msg, cb_get_phydevice_capability, capability);
if (result) {
capwap_logging_error("Unable retrieve physical device capability, error code: %d", result);
}
/* */
nlmsg_free(msg);
return result;
}
/* */
int nl80211_device_setfrequency(wifi_device_handle handle, struct wifi_frequency* freq) {
static int nl80211_device_setfrequency(wifi_device_handle handle, struct wifi_frequency* freq) {
int result;
struct nl_msg* msg;
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
@ -689,7 +967,9 @@ int nl80211_device_setfrequency(wifi_device_handle handle, struct wifi_frequency
/* Set wifi frequency */
result = nl80211_send_and_recv_msg(devicehandle->globalhandle, msg, NULL, NULL);
if (result) {
if (!result) {
devicehandle->currentfrequency = freq->frequency;
} else {
capwap_logging_error("Unable retrieve physical device capability, error code: %d", result);
}
@ -700,6 +980,7 @@ int nl80211_device_setfrequency(wifi_device_handle handle, struct wifi_frequency
/* */
static void nl80211_device_deinit(wifi_device_handle handle) {
int i;
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
if (devicehandle) {
@ -720,6 +1001,31 @@ static void nl80211_device_deinit(wifi_device_handle handle) {
search = search->next;
}
/* Free capability */
if (devicehandle->capability) {
if (devicehandle->capability->bands) {
for (i = 0; i < devicehandle->capability->bands->count; i++) {
struct wifi_band_capability* bandcap = (struct wifi_band_capability*)capwap_array_get_item_pointer(devicehandle->capability->bands, i);
if (bandcap->freq) {
capwap_array_free(bandcap->freq);
}
if (bandcap->rate) {
capwap_array_free(bandcap->rate);
}
}
capwap_array_free(devicehandle->capability->bands);
}
if (devicehandle->capability->ciphers) {
capwap_array_free(devicehandle->capability->ciphers);
}
capwap_free(devicehandle->capability);
}
/* */
capwap_free(devicehandle);
}
@ -731,14 +1037,6 @@ static void nl80211_wlan_delete(wifi_wlan_handle handle) {
ASSERT(handle != NULL);
if (wlanhandle->headbeacon) {
capwap_free(wlanhandle->headbeacon);
}
if (wlanhandle->tailbeaconlength) {
capwap_free(wlanhandle->tailbeacon);
}
if (wlanhandle->virtindex) {
nl80211_destroy_virtdevice(wlanhandle->devicehandle->globalhandle, wlanhandle->virtindex);
}
@ -820,7 +1118,7 @@ static wifi_wlan_handle nl80211_wlan_create(wifi_device_handle handle, struct wl
}
nl_cb_set(wlanhandle->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nl80211_no_seq_check, NULL);
nl_cb_set(wlanhandle->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_process_bss_event, NULL);
nl_cb_set(wlanhandle->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_process_bss_event, (void*)wlanhandle);
wlanhandle->nl = nl_create_handle(wlanhandle->nl_cb);
if (wlanhandle->nl) {
@ -854,7 +1152,7 @@ static int nl80211_wlan_getfdevent(wifi_wlan_handle handle, struct pollfd* fds,
}
/* */
static int nl80211_wlan_setupap(wifi_wlan_handle handle, struct wlan_setupap_params* params) {
static int nl80211_wlan_setupap(wifi_wlan_handle handle) {
int i;
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
static const int stypes[] = {
@ -871,34 +1169,20 @@ static int nl80211_wlan_setupap(wifi_wlan_handle handle, struct wlan_setupap_par
/* Register frames */
for (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) {
nl80211_registerframe(wlanhandle, (IEEE80211_FRAMECONTROL_TYPE_MGMT << 2) | (stypes[i] << 4), NULL, 0);
if (nl80211_registerframe(wlanhandle, (IEEE80211_FRAMECONTROL_TYPE_MGMT << 2) | (stypes[i] << 4), NULL, 0)) {
return -1;
}
}
/* Save wireless configuration */
wlanhandle->headbeaconlength = params->headbeaconlength;
if (params->headbeaconlength) {
wlanhandle->headbeacon = capwap_clone(params->headbeacon, params->headbeaconlength);
}
wlanhandle->tailbeaconlength = params->tailbeaconlength;
if (params->tailbeaconlength) {
wlanhandle->tailbeacon = capwap_clone(params->tailbeacon, params->tailbeaconlength);
}
strcpy(wlanhandle->ssid, params->ssid);
wlanhandle->suppressssid = (params->suppressssid ? NL80211_HIDDEN_SSID_ZERO_LEN : NL80211_HIDDEN_SSID_NOT_IN_USE);
wlanhandle->beaconinterval = (uint32_t)params->beaconinterval;
wlanhandle->dtimperiod = (uint32_t)params->dtimperiod;
wlanhandle->authenticationtype = ((params->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_WEP) ? NL80211_AUTHTYPE_SHARED_KEY : NL80211_AUTHTYPE_OPEN_SYSTEM);
return 0;
}
/* */
static int nl80211_wlan_startap(wifi_wlan_handle handle) {
static int nl80211_wlan_startap(wifi_wlan_handle handle, struct wlan_startap_params* params) {
int result;
struct nl_msg* msg;
char buffer[IEEE80211_MTU];
struct ieee80211_beacon_params ieee80211_params;
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
/* Enable interface */
@ -906,6 +1190,30 @@ static int nl80211_wlan_startap(wifi_wlan_handle handle) {
return -1;
}
/* Create beacon packet */
memset(&ieee80211_params, 0, sizeof(struct ieee80211_beacon_params));
memcpy(ieee80211_params.bssid, wlanhandle->address, ETH_ALEN);
ieee80211_params.beaconperiod = params->beaconperiod;
ieee80211_params.capability = params->capability;
ieee80211_params.ssid = params->ssid;
ieee80211_params.ssid_hidden = params->ssid_hidden;
memcpy(ieee80211_params.supportedrates, params->supportedrates, params->supportedratescount);
ieee80211_params.supportedratescount = params->supportedratescount;
ieee80211_params.erpmode = 0; /* TODO */
ieee80211_params.channel = wifi_frequency_to_channel(wlanhandle->devicehandle->currentfrequency);
result = ieee80211_create_beacon(buffer, IEEE80211_MTU, &ieee80211_params);
if (result < 0) {
return -1;
}
/* */
strcpy(wlanhandle->ssid, params->ssid);
wlanhandle->beaconperiod = params->beaconperiod;
wlanhandle->capability = params->capability;
memcpy(wlanhandle->supportedrates, params->supportedrates, params->supportedratescount);
wlanhandle->supportedratescount = params->supportedratescount;
/* */
msg = nlmsg_alloc();
if (!msg) {
@ -915,13 +1223,13 @@ static int nl80211_wlan_startap(wifi_wlan_handle handle) {
/* */
genlmsg_put(msg, 0, 0, wlanhandle->devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_START_AP, 0);
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wlanhandle->virtindex);
nla_put(msg, NL80211_ATTR_BEACON_HEAD, wlanhandle->headbeaconlength, wlanhandle->headbeacon);
nla_put(msg, NL80211_ATTR_BEACON_TAIL, wlanhandle->tailbeaconlength, wlanhandle->tailbeacon);
nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, wlanhandle->beaconinterval);
nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, wlanhandle->dtimperiod);
nla_put(msg, NL80211_ATTR_SSID, strlen(wlanhandle->ssid), wlanhandle->ssid);
nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, wlanhandle->suppressssid);
nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, wlanhandle->authenticationtype);
nla_put(msg, NL80211_ATTR_BEACON_HEAD, ieee80211_params.headbeaconlength, ieee80211_params.headbeacon);
nla_put(msg, NL80211_ATTR_BEACON_TAIL, ieee80211_params.tailbeaconlength, ieee80211_params.tailbeacon);
nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beaconperiod);
nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtimperiod);
nla_put(msg, NL80211_ATTR_SSID, strlen(params->ssid), params->ssid);
nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, (params->ssid_hidden ? NL80211_HIDDEN_SSID_ZERO_LEN : NL80211_HIDDEN_SSID_NOT_IN_USE));
nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, ((params->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_WEP) ? NL80211_AUTHTYPE_SHARED_KEY : NL80211_AUTHTYPE_OPEN_SYSTEM));
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
/* Start AP */
@ -960,7 +1268,7 @@ static int nl80211_wlan_stopap(wifi_wlan_handle handle) {
}
/* */
int nl80211_wlan_getmacaddress(wifi_wlan_handle handle, uint8_t* address) {
static int nl80211_wlan_getmacaddress(wifi_wlan_handle handle, uint8_t* address) {
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
ASSERT(handle != NULL);
@ -1059,7 +1367,7 @@ const struct wifi_driver_ops wifi_driver_nl80211_ops = {
.global_deinit = nl80211_global_deinit,
.device_init = nl80211_device_init,
.device_getfdevent = nl80211_device_getfdevent,
.device_getcapability = nl80211_device_getcapability,
.device_getcapability = nl80211_device_getcachedcapability,
.device_setfrequency = nl80211_device_setfrequency,
.device_deinit = nl80211_device_deinit,
.wlan_create = nl80211_wlan_create,

View File

@ -26,6 +26,10 @@ struct nl80211_device_handle {
uint32_t phyindex;
char phyname[IFNAMSIZ];
uint32_t currentfrequency;
struct wifi_capability* capability; /* Cached capability */
};
/* WLAN handle */
@ -41,19 +45,14 @@ struct nl80211_wlan_handle {
uint8_t address[ETH_ALEN];
/* Beacon / Probe response */
void* headbeacon;
int headbeaconlength;
void* tailbeacon;
int tailbeaconlength;
/* WLAN information */
char ssid[WIFI_SSID_MAX_LENGTH + 1];
uint32_t suppressssid;
uint32_t beaconinterval;
uint32_t dtimperiod;
uint16_t beaconperiod;
uint16_t capability;
uint32_t authenticationtype;
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
};
/* Physical device info */

View File

@ -750,7 +750,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
configSetting = config_lookup(config, "application.radio");
if (configSetting != NULL) {
struct wtp_radio* radio;
struct wifi_capability* capability;
const struct wifi_capability* capability;
int count = config_setting_length(configSetting);
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {

View File

@ -102,8 +102,77 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
/* */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
struct capwap_list_item* search = packet->messages->first;
struct capwap_list_item* search;
/* Set radio configuration and invalidate the old values */
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_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) {
memset(&radio->directsequencecontrol, 0, sizeof(struct capwap_80211_directsequencecontrol_element));
memset(&radio->ofdmcontrol, 0, sizeof(struct capwap_80211_ofdmcontrol_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) {
memset(&radio->directsequencecontrol, 0, sizeof(struct capwap_80211_directsequencecontrol_element));
memset(&radio->ofdmcontrol, 0, sizeof(struct capwap_80211_ofdmcontrol_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;
}
}
}
/* Next */
search = search->next;
}
/* Update new values */
search = packet->messages->first;
while (search) {
struct capwap_message_element_itemlist* messageelement = (struct capwap_message_element_itemlist*)search->item;
@ -170,7 +239,15 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
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)) {
if (!(radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) {
return -1;
}
/* Configure radio channel */
memcpy(&radio->directsequencecontrol, directsequencecontrol, sizeof(struct capwap_80211_directsequencecontrol_element));
if (wifi_device_setfrequency(radio->radioid, WIFI_BAND_2GHZ, radio->radioinformation.radiotype, radio->directsequencecontrol.currentchannel)) {
return -1;
}
}
}
}
@ -187,7 +264,15 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
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)) {
if (!(radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) {
return -1;
}
/* Configure radio channel */
memcpy(&radio->ofdmcontrol, ofdmcontrol, sizeof(struct capwap_80211_ofdmcontrol_element));
if (wifi_device_setfrequency(radio->radioid, WIFI_BAND_5GHZ, radio->radioinformation.radiotype, radio->ofdmcontrol.currentchannel)) {
return -1;
}
}
}
}
@ -263,23 +348,6 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
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)) {
@ -395,16 +463,12 @@ static void wtp_radio_update_fdevent(void) {
/* */
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;
}
@ -428,13 +492,6 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
}
}
/* 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;
@ -453,8 +510,20 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
return CAPWAP_RESULTCODE_FAILURE;
}
/* Save wlan configuration */
wlan->capability = addwlan->capability;
wlan->qos = addwlan->qos;
wlan->authmode = addwlan->authmode;
wlan->macmode = addwlan->macmode;
wlan->tunnelmode = addwlan->tunnelmode;
wlan->ssid_hidden = addwlan->suppressssid;
strcpy(wlan->ssid, (const char*)addwlan->ssid);
wifi_wlan_getbssid(addwlan->radioid, addwlan->wlanid, wlan->bssid);
/* TODO (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE) */
/* Configure virtual interface */
if (!wifi_wlan_setupap(addwlan, ies)) {
if (!wifi_wlan_setupap(addwlan->radioid, addwlan->wlanid)) {
wlan->state = WTP_RADIO_WLAN_STATE_READY;
} else {
wtp_radio_destroy_wlan(wlan);
@ -475,7 +544,7 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
/* Retrieve macaddress of new device */
bssid->radioid = addwlan->radioid;
bssid->wlanid = addwlan->wlanid;
wifi_wlan_getbssid(addwlan->radioid, addwlan->wlanid, bssid->bssid);
memcpy(bssid->bssid, wlan->bssid, ETH_ALEN);
return CAPWAP_RESULTCODE_SUCCESS;
}

View File

@ -1,6 +1,8 @@
#ifndef __WTP_RADIO_HEADER__
#define __WTP_RADIO_HEADER__
#include "ieee80211.h"
/* */
#define WTP_RADIO_ENABLED 0
#define WTP_RADIO_DISABLED 1
@ -18,11 +20,20 @@
struct wtp_radio_wlan {
struct wtp_radio* radio;
int state;
uint8_t wlanid;
char wlanname[IFNAMSIZ];
uint8_t bssid[ETH_ALEN];
int state;
/* */
uint16_t capability;
uint8_t qos;
uint8_t authmode;
uint8_t macmode;
uint8_t tunnelmode;
uint8_t ssid_hidden;
char ssid[IEEE80211_IE_SSID_MAX_LENGTH + 1];
};
/* */