Improved the management of the IEEE802.11 Beacon and add the management of
IEEE802.11 Probe Response.
This commit is contained in:
parent
66019df158
commit
d2c01ad82a
@ -82,7 +82,8 @@ ac_SOURCES = \
|
|||||||
$(top_srcdir)/src/ac/ac_dfa_run.c \
|
$(top_srcdir)/src/ac/ac_dfa_run.c \
|
||||||
$(top_srcdir)/src/ac/ac_dfa_reset.c \
|
$(top_srcdir)/src/ac/ac_dfa_reset.c \
|
||||||
$(top_srcdir)/src/ac/ac_dfa_teardown.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 = \
|
ac_LDADD = \
|
||||||
$(CONFIG_LIBS) \
|
$(CONFIG_LIBS) \
|
||||||
|
@ -54,6 +54,7 @@ wtp_SOURCES = \
|
|||||||
$(top_srcdir)/src/wtp/wtp_dfa_reset.c \
|
$(top_srcdir)/src/wtp/wtp_dfa_reset.c \
|
||||||
$(top_srcdir)/src/wtp/wtp_dfa_imagedata.c \
|
$(top_srcdir)/src/wtp/wtp_dfa_imagedata.c \
|
||||||
$(top_srcdir)/src/wtp/wtp_radio.c \
|
$(top_srcdir)/src/wtp/wtp_radio.c \
|
||||||
|
$(top_srcdir)/src/binding/ieee80211/ieee80211.c \
|
||||||
$(top_srcdir)/src/binding/ieee80211/wifi_drivers.c
|
$(top_srcdir)/src/binding/ieee80211/wifi_drivers.c
|
||||||
|
|
||||||
wtp_LDADD = \
|
wtp_LDADD = \
|
||||||
|
@ -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->authmode = (uint8_t)json_object_get_int(jsonauthtype);
|
||||||
addwlan->macmode = (uint8_t)json_object_get_int(jsonmacmode);
|
addwlan->macmode = (uint8_t)json_object_get_int(jsonmacmode);
|
||||||
addwlan->tunnelmode = (uint8_t)json_object_get_int(jsontunnelmode);
|
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);
|
strcpy(addwlan->ssid, ssid);
|
||||||
|
|
||||||
/* Notify Request to Complete Event */
|
/* Notify Request to Complete Event */
|
||||||
|
267
src/binding/ieee80211/ieee80211.c
Normal file
267
src/binding/ieee80211/ieee80211.c
Normal 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;
|
||||||
|
}
|
@ -12,8 +12,15 @@
|
|||||||
/* Global values */
|
/* 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_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 */
|
/* Rate into multiple of 500Kbps */
|
||||||
#define IEEE80211_RATE_1M 2
|
#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_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 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 */
|
/* Frame control type */
|
||||||
#define IEEE80211_FRAMECONTROL_TYPE_MGMT 0
|
#define IEEE80211_FRAMECONTROL_TYPE_MGMT 0
|
||||||
#define IEEE80211_FRAMECONTROL_TYPE_CTRL 1
|
#define IEEE80211_FRAMECONTROL_TYPE_CTRL 1
|
||||||
@ -86,6 +98,8 @@
|
|||||||
|
|
||||||
/* */
|
/* */
|
||||||
#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 */
|
/* 802.11 Packet - IEEE802.11 is a little-endian protocol */
|
||||||
struct ieee80211_header {
|
struct ieee80211_header {
|
||||||
@ -106,9 +120,25 @@ struct ieee80211_header_mgmt {
|
|||||||
uint8_t bssid[ETH_ALEN];
|
uint8_t bssid[ETH_ALEN];
|
||||||
__le16 sequencecontrol;
|
__le16 sequencecontrol;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
uint8_t timestamp[8];
|
uint8_t timestamp[8];
|
||||||
__le16 beaconinterval;
|
__le16 beaconinterval;
|
||||||
__le16 capability;
|
__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;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
/* 802.11 Generic information element */
|
/* 802.11 Generic information element */
|
||||||
@ -190,6 +220,8 @@ struct ieee80211_ie_extended_supported_rates {
|
|||||||
#define EDCA_PARAMETER_RECORD_AC_VO_FIELD 3
|
#define EDCA_PARAMETER_RECORD_AC_VO_FIELD 3
|
||||||
|
|
||||||
struct ieee80211_ie_edca_parameter_set {
|
struct ieee80211_ie_edca_parameter_set {
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t len;
|
||||||
/* TODO */
|
/* TODO */
|
||||||
} STRUCT_PACKED;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
@ -198,15 +230,98 @@ struct ieee80211_ie_edca_parameter_set {
|
|||||||
#define IEEE80211_IE_QOS_CAPABILITY_LENGTH 1
|
#define IEEE80211_IE_QOS_CAPABILITY_LENGTH 1
|
||||||
|
|
||||||
struct ieee80211_ie_qos_capability {
|
struct ieee80211_ie_qos_capability {
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t len;
|
||||||
/* TODO */
|
/* TODO */
|
||||||
};
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
/* 802.11 Power Constraint information element */
|
/* 802.11 Power Constraint information element */
|
||||||
#define IEEE80211_IE_POWER_CONSTRAINT 52
|
#define IEEE80211_IE_POWER_CONSTRAINT 52
|
||||||
#define IEEE80211_IE_POWER_CONSTRAINT_LENGTH 1
|
#define IEEE80211_IE_POWER_CONSTRAINT_LENGTH 1
|
||||||
|
|
||||||
struct ieee80211_ie_power_constraint {
|
struct ieee80211_ie_power_constraint {
|
||||||
|
uint8_t id;
|
||||||
|
uint8_t len;
|
||||||
/* TODO */
|
/* TODO */
|
||||||
} STRUCT_PACKED;
|
} 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__ */
|
#endif /* __CAPWAP_IEEE802_11_HEADER__ */
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "capwap_element.h"
|
#include "capwap_element.h"
|
||||||
#include "wtp_radio.h"
|
#include "wtp_radio.h"
|
||||||
#include "wifi_drivers.h"
|
#include "wifi_drivers.h"
|
||||||
#include "ieee80211.h"
|
|
||||||
|
|
||||||
/* Declare enable wifi driver */
|
/* Declare enable wifi driver */
|
||||||
#ifdef ENABLE_WIFI_DRIVERS_NL80211
|
#ifdef ENABLE_WIFI_DRIVERS_NL80211
|
||||||
@ -20,36 +19,6 @@ static struct wifi_driver_instance wifi_driver[] = {
|
|||||||
/* Radio instance */
|
/* Radio instance */
|
||||||
static struct capwap_array* g_wifidevice = NULL;
|
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 wifi_driver_init(void) {
|
||||||
int i;
|
int i;
|
||||||
@ -93,10 +62,6 @@ void wifi_driver_free(void) {
|
|||||||
capwap_array_free(device->wlan);
|
capwap_array_free(device->wlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->capability) {
|
|
||||||
wifi_device_freecapability(device->capability);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device->handle && device->instance->ops->device_deinit) {
|
if (device->handle && device->instance->ops->device_deinit) {
|
||||||
device->instance->ops->device_deinit(device->handle);
|
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) {
|
static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* radio) {
|
||||||
int i, j, w;
|
int i, j, w;
|
||||||
|
int radiotype;
|
||||||
uint32_t mode = 0;
|
uint32_t mode = 0;
|
||||||
|
const struct wifi_capability* capability;
|
||||||
|
|
||||||
ASSERT(device != NULL);
|
ASSERT(device != NULL);
|
||||||
ASSERT(radio != 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 */
|
/* Free old supported rates */
|
||||||
device->supportedratescount = 0;
|
device->supportedratescount = 0;
|
||||||
|
|
||||||
/* Retrieve cached capability */
|
/* Retrieve capability */
|
||||||
if (!device->capability) {
|
capability = wifi_device_getcapability(radio->radioid);
|
||||||
if (!wifi_device_getcapability(radio->radioid)) {
|
if (!capability) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get radio type for basic rate */
|
||||||
|
radiotype = wifi_frequency_to_radiotype(device->currentfreq.frequency);
|
||||||
|
if (radiotype < 0) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check type of rate mode */
|
/* Check type of rate mode */
|
||||||
@ -334,11 +306,10 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Filter band */
|
/* Filter band */
|
||||||
for (i = 0; i < device->capability->bands->count; i++) {
|
for (i = 0; i < capability->bands->count; i++) {
|
||||||
struct wifi_band_capability* bandcap = (struct wifi_band_capability*)capwap_array_get_item_pointer(device->capability->bands, 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->band == device->currentfreq.band) {
|
||||||
if (bandcap->rate->count) {
|
|
||||||
for (j = 0; j < bandcap->rate->count; 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);
|
struct wifi_rate_capability* rate = (struct wifi_rate_capability*)capwap_array_get_item_pointer(bandcap->rate, j);
|
||||||
|
|
||||||
@ -350,12 +321,28 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* Add implicit 802.11n rate with only 802.11a/g rate */
|
||||||
if (!(mode & CAPWAP_RADIO_TYPE_80211N) && (device->currentfreq.mode & CAPWAP_RADIO_TYPE_80211N)) {
|
if (!(mode & CAPWAP_RADIO_TYPE_80211N) && (device->currentfreq.mode & CAPWAP_RADIO_TYPE_80211N)) {
|
||||||
device->supportedrates[device->supportedratescount++] = IEEE80211_RATE_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) {
|
int wifi_wlan_setupap(int radioid, int wlanid) {
|
||||||
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;
|
|
||||||
struct wifi_wlan* wlan;
|
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);
|
ASSERT(radioid > 0);
|
||||||
|
ASSERT(wlanid > 0);
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
memset(buffer, 0, sizeof(buffer));
|
wlan = wifi_wlan_getdevice(radioid, wlanid);
|
||||||
header = (struct ieee80211_header_mgmt*)buffer;
|
if (!wlan || !wlan->device->instance->ops->wlan_setupap) {
|
||||||
|
|
||||||
/* */
|
|
||||||
memset(¶ms, 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(¶ms.headbeacon[params.headbeaconlength], (const char*)addwlan->ssid, (addwlan->suppressssid ? 1 : 0));
|
|
||||||
if (result < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
params.headbeaconlength += result;
|
return wlan->device->instance->ops->wlan_setupap(wlan->handle);
|
||||||
|
|
||||||
/* Information Element: Supported Rates */
|
|
||||||
wifi_wlan_getrates(wlan->device, radio);
|
|
||||||
result = wifi_ie_supportedrates(¶ms.headbeacon[params.headbeaconlength], wlan->device);
|
|
||||||
if (result < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
params.headbeaconlength += result;
|
|
||||||
|
|
||||||
/* Information Element: DSSS */
|
|
||||||
result = wifi_ie_dsss(¶ms.headbeacon[params.headbeaconlength], wlan->device);
|
|
||||||
if (result < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
params.headbeaconlength += result;
|
|
||||||
|
|
||||||
/* Separate Information Elements into two block between IE TIM */
|
|
||||||
params.tailbeacon = ¶ms.headbeacon[params.headbeaconlength];
|
|
||||||
|
|
||||||
/* Information Element: Country */
|
|
||||||
/* TODO */
|
|
||||||
|
|
||||||
/* Information Element: ERP */
|
|
||||||
result = wifi_ie_erp(¶ms.tailbeacon[params.tailbeaconlength], wlan->device);
|
|
||||||
if (result < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
params.tailbeaconlength += result;
|
|
||||||
|
|
||||||
/* Information Element: Extended Supported Rates */
|
|
||||||
result = wifi_ie_extendedsupportedrates(¶ms.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, ¶ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int wifi_wlan_startap(int radioid, int wlanid) {
|
int wifi_wlan_startap(int radioid, int wlanid) {
|
||||||
struct wifi_wlan* wlan;
|
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);
|
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 -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;
|
struct wifi_device* device;
|
||||||
|
|
||||||
ASSERT(radioid > 0);
|
ASSERT(radioid > 0);
|
||||||
@ -630,29 +460,18 @@ struct wifi_capability* wifi_device_getcapability(int radioid) {
|
|||||||
|
|
||||||
/* Retrieve cached capability */
|
/* Retrieve cached capability */
|
||||||
device = (struct wifi_device*)capwap_array_get_item_pointer(g_wifidevice, radioid);
|
device = (struct wifi_device*)capwap_array_get_item_pointer(g_wifidevice, radioid);
|
||||||
if (!device->capability && device->handle && device->instance->ops->device_getcapability) {
|
if (!device->handle || !device->instance->ops->device_getcapability) {
|
||||||
/* Get capability from device */
|
return NULL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 wifi_device_setfrequency(int radioid, uint32_t band, uint32_t mode, uint8_t channel) {
|
||||||
int i, j;
|
int i, j;
|
||||||
int result = -1;
|
int result = -1;
|
||||||
struct wifi_capability* capability;
|
const struct wifi_capability* capability;
|
||||||
uint32_t frequency = 0;
|
uint32_t frequency = 0;
|
||||||
|
|
||||||
ASSERT(radioid > 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)) {
|
if ((freq >= 2412) && (freq <= 2472)) {
|
||||||
return (freq - 2407) / 5;
|
return (freq - 2407) / 5;
|
||||||
} else if (freq == 2484) {
|
} else if (freq == 2484) {
|
||||||
return 14;
|
return 14;
|
||||||
|
} else if ((freq >= 4915) && (freq <= 4980)) {
|
||||||
|
return (freq - 4000) / 5;
|
||||||
} else if ((freq >= 5035) && (freq <= 5825)) {
|
} else if ((freq >= 5035) && (freq <= 5825)) {
|
||||||
return freq / 5 - 1000;
|
return (freq - 5000) / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
|
#include "ieee80211.h"
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
#define WIFI_DRIVER_NAME_SIZE 16
|
#define WIFI_DRIVER_NAME_SIZE 16
|
||||||
@ -13,15 +14,22 @@
|
|||||||
#define WIFI_BAND_2GHZ 1
|
#define WIFI_BAND_2GHZ 1
|
||||||
#define WIFI_BAND_5GHZ 2
|
#define WIFI_BAND_5GHZ 2
|
||||||
|
|
||||||
/* */
|
|
||||||
#define WIFI_SUPPORTEDRATE_MAX_COUNT 16
|
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
#define WIFI_CAPABILITY_RADIOSUPPORTED 0x00000001
|
#define WIFI_CAPABILITY_RADIOSUPPORTED 0x00000001
|
||||||
#define WIFI_CAPABILITY_RADIOTYPE 0x00000002
|
#define WIFI_CAPABILITY_RADIOTYPE 0x00000002
|
||||||
#define WIFI_CAPABILITY_BANDS 0x00000004
|
#define WIFI_CAPABILITY_BANDS 0x00000004
|
||||||
#define WIFI_CAPABILITY_CIPHERS 0x00000008
|
#define WIFI_CAPABILITY_CIPHERS 0x00000008
|
||||||
#define WIFI_CAPABILITY_ANTENNA_MASK 0x00000010
|
#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
|
#define WIFI_CAPABILITY_AP_SUPPORTED 0x00000001
|
||||||
@ -71,21 +79,34 @@ struct wlan_init_params {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
struct wlan_setupap_params {
|
struct wlan_startap_params {
|
||||||
char* headbeacon;
|
const char* ssid;
|
||||||
int headbeaconlength;
|
uint8_t ssid_hidden;
|
||||||
char* tailbeacon;
|
|
||||||
int tailbeaconlength;
|
|
||||||
|
|
||||||
char ssid[WIFI_SSID_MAX_LENGTH + 1];
|
uint16_t beaconperiod;
|
||||||
uint8_t suppressssid;
|
uint16_t capability;
|
||||||
|
|
||||||
uint16_t beaconinterval;
|
|
||||||
uint8_t dtimperiod;
|
uint8_t dtimperiod;
|
||||||
|
|
||||||
|
int supportedratescount;
|
||||||
|
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||||
|
|
||||||
uint8_t authenticationtype;
|
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 */
|
/* Interface capability */
|
||||||
struct wifi_freq_capability {
|
struct wifi_freq_capability {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -126,6 +147,7 @@ struct wifi_capability {
|
|||||||
wifi_device_handle device;
|
wifi_device_handle device;
|
||||||
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
unsigned long capability;
|
||||||
|
|
||||||
/* WIFI_CAPABILITY_RADIOSUPPORTED */
|
/* WIFI_CAPABILITY_RADIOSUPPORTED */
|
||||||
unsigned long radiosupported;
|
unsigned long radiosupported;
|
||||||
@ -142,6 +164,18 @@ struct wifi_capability {
|
|||||||
|
|
||||||
/* WIFI_CAPABILITY_CIPHERS */
|
/* WIFI_CAPABILITY_CIPHERS */
|
||||||
struct capwap_array* 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 */
|
/* Frequency configuration */
|
||||||
@ -172,15 +206,15 @@ struct wifi_driver_ops {
|
|||||||
/* Device functions */
|
/* Device functions */
|
||||||
wifi_device_handle (*device_init)(wifi_global_handle handle, struct device_init_params* params);
|
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_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);
|
int (*device_setfrequency)(wifi_device_handle handle, struct wifi_frequency* freq);
|
||||||
void (*device_deinit)(wifi_device_handle handle);
|
void (*device_deinit)(wifi_device_handle handle);
|
||||||
|
|
||||||
/* WLAN functions */
|
/* WLAN functions */
|
||||||
wifi_wlan_handle (*wlan_create)(wifi_device_handle handle, struct wlan_init_params* params);
|
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_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_setupap)(wifi_wlan_handle handle);
|
||||||
int (*wlan_startap)(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_stopap)(wifi_wlan_handle handle);
|
||||||
int (*wlan_getmacaddress)(wifi_wlan_handle handle, uint8_t* address);
|
int (*wlan_getmacaddress)(wifi_wlan_handle handle, uint8_t* address);
|
||||||
void (*wlan_delete)(wifi_wlan_handle handle);
|
void (*wlan_delete)(wifi_wlan_handle handle);
|
||||||
@ -199,15 +233,12 @@ struct wifi_device {
|
|||||||
|
|
||||||
struct capwap_array* wlan; /* Virtual AP */
|
struct capwap_array* wlan; /* Virtual AP */
|
||||||
|
|
||||||
/* Cache capability */
|
|
||||||
struct wifi_capability* capability;
|
|
||||||
|
|
||||||
/* Current frequency */
|
/* Current frequency */
|
||||||
struct wifi_frequency currentfreq;
|
struct wifi_frequency currentfreq;
|
||||||
|
|
||||||
/* Supported Rates */
|
/* Supported Rates */
|
||||||
int supportedratescount;
|
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);
|
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_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_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_startap(int radioid, int wlanid);
|
||||||
int wifi_wlan_stopap(int radioid, int wlanid);
|
int wifi_wlan_stopap(int radioid, int wlanid);
|
||||||
int wifi_wlan_getbssid(int radioid, int wlanid, uint8_t* bssid);
|
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 */
|
/* Util functions */
|
||||||
uint32_t wifi_iface_index(const char* ifname);
|
uint32_t wifi_iface_index(const char* ifname);
|
||||||
int wifi_iface_hwaddr(int sock, const char* ifname, uint8_t* hwaddr);
|
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);
|
int wifi_iface_updown(int sock, const char* ifname, int up);
|
||||||
#define wifi_iface_up(sock, ifname) wifi_iface_updown(sock, ifname, 1)
|
#define wifi_iface_up(sock, ifname) wifi_iface_updown(sock, ifname, 1)
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include "wifi_drivers.h"
|
#include "wifi_drivers.h"
|
||||||
#include "wifi_nl80211.h"
|
#include "wifi_nl80211.h"
|
||||||
#include "ieee80211.h"
|
|
||||||
|
|
||||||
/* Compatibility functions */
|
/* Compatibility functions */
|
||||||
#if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30)
|
#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) {
|
static int nl80211_cookie_handler(struct nl_msg* msg, void* arg) {
|
||||||
/* TODO */
|
struct nlattr* tb_msg[NL80211_ATTR_MAX + 1];
|
||||||
return NL_SKIP;
|
struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||||
}
|
|
||||||
|
|
||||||
/* */
|
|
||||||
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);
|
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
|
||||||
if (res) {
|
if (tb_msg[NL80211_ATTR_COOKIE]) {
|
||||||
capwap_logging_warning("Receive nl80211 message failed: %d", res);
|
*(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;
|
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);
|
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) {
|
static unsigned long nl80211_get_cipher(uint32_t chiper) {
|
||||||
switch (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 */
|
/* Cipher supported */
|
||||||
if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) {
|
if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) {
|
||||||
int count;
|
int count;
|
||||||
@ -575,6 +838,43 @@ static int nl80211_registerframe(struct nl80211_wlan_handle* wlanhandle, uint16_
|
|||||||
return result;
|
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) {
|
static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct device_init_params* params) {
|
||||||
int result;
|
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));
|
memset(devicehandle, 0, sizeof(struct nl80211_device_handle));
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
devicehandle->globalhandle = globalhandle;
|
||||||
strcpy(devicehandle->phyname, phyitem->name);
|
strcpy(devicehandle->phyname, phyitem->name);
|
||||||
devicehandle->phyindex = phyitem->index;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,9 +931,6 @@ static wifi_device_handle nl80211_device_init(wifi_global_handle handle, struct
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
|
||||||
devicehandle->globalhandle = globalhandle;
|
|
||||||
|
|
||||||
/* Remove all virtual adapter from wifi device */
|
/* Remove all virtual adapter from wifi device */
|
||||||
nl80211_destroy_all_virtdevice(globalhandle, devicehandle->phyindex);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
int nl80211_device_getcapability(wifi_device_handle handle, struct wifi_capability* capability) {
|
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;
|
|
||||||
|
|
||||||
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) {
|
|
||||||
int result;
|
int result;
|
||||||
struct nl_msg* msg;
|
struct nl_msg* msg;
|
||||||
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
|
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 */
|
/* Set wifi frequency */
|
||||||
result = nl80211_send_and_recv_msg(devicehandle->globalhandle, msg, NULL, NULL);
|
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);
|
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) {
|
static void nl80211_device_deinit(wifi_device_handle handle) {
|
||||||
|
int i;
|
||||||
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
|
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
|
||||||
|
|
||||||
if (devicehandle) {
|
if (devicehandle) {
|
||||||
@ -720,6 +1001,31 @@ static void nl80211_device_deinit(wifi_device_handle handle) {
|
|||||||
search = search->next;
|
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);
|
capwap_free(devicehandle);
|
||||||
}
|
}
|
||||||
@ -731,14 +1037,6 @@ static void nl80211_wlan_delete(wifi_wlan_handle handle) {
|
|||||||
|
|
||||||
ASSERT(handle != NULL);
|
ASSERT(handle != NULL);
|
||||||
|
|
||||||
if (wlanhandle->headbeacon) {
|
|
||||||
capwap_free(wlanhandle->headbeacon);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wlanhandle->tailbeaconlength) {
|
|
||||||
capwap_free(wlanhandle->tailbeacon);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wlanhandle->virtindex) {
|
if (wlanhandle->virtindex) {
|
||||||
nl80211_destroy_virtdevice(wlanhandle->devicehandle->globalhandle, 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_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);
|
wlanhandle->nl = nl_create_handle(wlanhandle->nl_cb);
|
||||||
if (wlanhandle->nl) {
|
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;
|
int i;
|
||||||
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
||||||
static const int stypes[] = {
|
static const int stypes[] = {
|
||||||
@ -871,34 +1169,20 @@ static int nl80211_wlan_setupap(wifi_wlan_handle handle, struct wlan_setupap_par
|
|||||||
|
|
||||||
/* Register frames */
|
/* Register frames */
|
||||||
for (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) {
|
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;
|
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;
|
int result;
|
||||||
struct nl_msg* msg;
|
struct nl_msg* msg;
|
||||||
|
char buffer[IEEE80211_MTU];
|
||||||
|
struct ieee80211_beacon_params ieee80211_params;
|
||||||
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
||||||
|
|
||||||
/* Enable interface */
|
/* Enable interface */
|
||||||
@ -906,6 +1190,30 @@ static int nl80211_wlan_startap(wifi_wlan_handle handle) {
|
|||||||
return -1;
|
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();
|
msg = nlmsg_alloc();
|
||||||
if (!msg) {
|
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);
|
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_u32(msg, NL80211_ATTR_IFINDEX, wlanhandle->virtindex);
|
||||||
nla_put(msg, NL80211_ATTR_BEACON_HEAD, wlanhandle->headbeaconlength, wlanhandle->headbeacon);
|
nla_put(msg, NL80211_ATTR_BEACON_HEAD, ieee80211_params.headbeaconlength, ieee80211_params.headbeacon);
|
||||||
nla_put(msg, NL80211_ATTR_BEACON_TAIL, wlanhandle->tailbeaconlength, wlanhandle->tailbeacon);
|
nla_put(msg, NL80211_ATTR_BEACON_TAIL, ieee80211_params.tailbeaconlength, ieee80211_params.tailbeacon);
|
||||||
nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, wlanhandle->beaconinterval);
|
nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beaconperiod);
|
||||||
nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, wlanhandle->dtimperiod);
|
nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtimperiod);
|
||||||
nla_put(msg, NL80211_ATTR_SSID, strlen(wlanhandle->ssid), wlanhandle->ssid);
|
nla_put(msg, NL80211_ATTR_SSID, strlen(params->ssid), params->ssid);
|
||||||
nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, wlanhandle->suppressssid);
|
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, wlanhandle->authenticationtype);
|
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);
|
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
|
||||||
|
|
||||||
/* Start AP */
|
/* 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;
|
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
||||||
|
|
||||||
ASSERT(handle != NULL);
|
ASSERT(handle != NULL);
|
||||||
@ -1059,7 +1367,7 @@ const struct wifi_driver_ops wifi_driver_nl80211_ops = {
|
|||||||
.global_deinit = nl80211_global_deinit,
|
.global_deinit = nl80211_global_deinit,
|
||||||
.device_init = nl80211_device_init,
|
.device_init = nl80211_device_init,
|
||||||
.device_getfdevent = nl80211_device_getfdevent,
|
.device_getfdevent = nl80211_device_getfdevent,
|
||||||
.device_getcapability = nl80211_device_getcapability,
|
.device_getcapability = nl80211_device_getcachedcapability,
|
||||||
.device_setfrequency = nl80211_device_setfrequency,
|
.device_setfrequency = nl80211_device_setfrequency,
|
||||||
.device_deinit = nl80211_device_deinit,
|
.device_deinit = nl80211_device_deinit,
|
||||||
.wlan_create = nl80211_wlan_create,
|
.wlan_create = nl80211_wlan_create,
|
||||||
|
@ -26,6 +26,10 @@ struct nl80211_device_handle {
|
|||||||
|
|
||||||
uint32_t phyindex;
|
uint32_t phyindex;
|
||||||
char phyname[IFNAMSIZ];
|
char phyname[IFNAMSIZ];
|
||||||
|
|
||||||
|
uint32_t currentfrequency;
|
||||||
|
|
||||||
|
struct wifi_capability* capability; /* Cached capability */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* WLAN handle */
|
/* WLAN handle */
|
||||||
@ -41,19 +45,14 @@ struct nl80211_wlan_handle {
|
|||||||
|
|
||||||
uint8_t address[ETH_ALEN];
|
uint8_t address[ETH_ALEN];
|
||||||
|
|
||||||
/* Beacon / Probe response */
|
/* WLAN information */
|
||||||
void* headbeacon;
|
|
||||||
int headbeaconlength;
|
|
||||||
void* tailbeacon;
|
|
||||||
int tailbeaconlength;
|
|
||||||
|
|
||||||
char ssid[WIFI_SSID_MAX_LENGTH + 1];
|
char ssid[WIFI_SSID_MAX_LENGTH + 1];
|
||||||
uint32_t suppressssid;
|
|
||||||
|
|
||||||
uint32_t beaconinterval;
|
uint16_t beaconperiod;
|
||||||
uint32_t dtimperiod;
|
uint16_t capability;
|
||||||
|
|
||||||
uint32_t authenticationtype;
|
int supportedratescount;
|
||||||
|
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Physical device info */
|
/* Physical device info */
|
||||||
|
@ -750,7 +750,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) {
|
|||||||
configSetting = config_lookup(config, "application.radio");
|
configSetting = config_lookup(config, "application.radio");
|
||||||
if (configSetting != NULL) {
|
if (configSetting != NULL) {
|
||||||
struct wtp_radio* radio;
|
struct wtp_radio* radio;
|
||||||
struct wifi_capability* capability;
|
const struct wifi_capability* capability;
|
||||||
int count = config_setting_length(configSetting);
|
int count = config_setting_length(configSetting);
|
||||||
|
|
||||||
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
||||||
|
@ -102,8 +102,77 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
|||||||
/* */
|
/* */
|
||||||
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
|
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
|
||||||
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
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) {
|
while (search) {
|
||||||
struct capwap_message_element_itemlist* messageelement = (struct capwap_message_element_itemlist*)search->item;
|
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);
|
directsequencecontrol = *(struct capwap_80211_directsequencecontrol_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||||
radio = wtp_radio_get_phy(directsequencecontrol->radioid);
|
radio = wtp_radio_get_phy(directsequencecontrol->radioid);
|
||||||
if (radio && (radio->radioid == 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));
|
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);
|
ofdmcontrol = *(struct capwap_80211_ofdmcontrol_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||||
radio = wtp_radio_get_phy(ofdmcontrol->radioid);
|
radio = wtp_radio_get_phy(ofdmcontrol->radioid);
|
||||||
if (radio && (radio->radioid == 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));
|
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;
|
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: {
|
case CAPWAP_ELEMENT_80211_WTP_RADIO_CONF: {
|
||||||
messageelements = (struct capwap_array*)messageelement->data;
|
messageelements = (struct capwap_array*)messageelement->data;
|
||||||
if (messageelements && (messageelements->count > 0)) {
|
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 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* radio;
|
||||||
struct wtp_radio_wlan* wlan;
|
struct wtp_radio_wlan* wlan;
|
||||||
struct capwap_80211_addwlan_element* addwlan;
|
struct capwap_80211_addwlan_element* addwlan;
|
||||||
struct capwap_array* ies;
|
|
||||||
|
|
||||||
/* Get message elements */
|
/* Get message elements */
|
||||||
addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_ADD_WLAN);
|
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) {
|
if (!addwlan) {
|
||||||
return CAPWAP_RESULTCODE_FAILURE;
|
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 */
|
/* Set virtual interface information */
|
||||||
wlan = (struct wtp_radio_wlan*)capwap_array_get_item_pointer(radio->wlan, radio->wlan->count);
|
wlan = (struct wtp_radio_wlan*)capwap_array_get_item_pointer(radio->wlan, radio->wlan->count);
|
||||||
wlan->radio = radio;
|
wlan->radio = radio;
|
||||||
@ -453,8 +510,20 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
|
|||||||
return CAPWAP_RESULTCODE_FAILURE;
|
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 */
|
/* Configure virtual interface */
|
||||||
if (!wifi_wlan_setupap(addwlan, ies)) {
|
if (!wifi_wlan_setupap(addwlan->radioid, addwlan->wlanid)) {
|
||||||
wlan->state = WTP_RADIO_WLAN_STATE_READY;
|
wlan->state = WTP_RADIO_WLAN_STATE_READY;
|
||||||
} else {
|
} else {
|
||||||
wtp_radio_destroy_wlan(wlan);
|
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 */
|
/* Retrieve macaddress of new device */
|
||||||
bssid->radioid = addwlan->radioid;
|
bssid->radioid = addwlan->radioid;
|
||||||
bssid->wlanid = addwlan->wlanid;
|
bssid->wlanid = addwlan->wlanid;
|
||||||
wifi_wlan_getbssid(addwlan->radioid, addwlan->wlanid, bssid->bssid);
|
memcpy(bssid->bssid, wlan->bssid, ETH_ALEN);
|
||||||
|
|
||||||
return CAPWAP_RESULTCODE_SUCCESS;
|
return CAPWAP_RESULTCODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef __WTP_RADIO_HEADER__
|
#ifndef __WTP_RADIO_HEADER__
|
||||||
#define __WTP_RADIO_HEADER__
|
#define __WTP_RADIO_HEADER__
|
||||||
|
|
||||||
|
#include "ieee80211.h"
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
#define WTP_RADIO_ENABLED 0
|
#define WTP_RADIO_ENABLED 0
|
||||||
#define WTP_RADIO_DISABLED 1
|
#define WTP_RADIO_DISABLED 1
|
||||||
@ -18,11 +20,20 @@
|
|||||||
|
|
||||||
struct wtp_radio_wlan {
|
struct wtp_radio_wlan {
|
||||||
struct wtp_radio* radio;
|
struct wtp_radio* radio;
|
||||||
|
int state;
|
||||||
|
|
||||||
uint8_t wlanid;
|
uint8_t wlanid;
|
||||||
char wlanname[IFNAMSIZ];
|
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];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
Loading…
Reference in New Issue
Block a user