Improved the management of authentication and association of the stations
This commit is contained in:
parent
42293aad04
commit
0790fb511a
@ -88,7 +88,7 @@ static int ieee80211_ie_set_dsss(char* buffer, uint8_t channel) {
|
||||
}
|
||||
|
||||
/* */
|
||||
static int ieee80211_ie_set_erp(char* buffer, uint32_t mode, uint32_t erpmode) {
|
||||
static int ieee80211_ie_set_erp(char* buffer, uint32_t mode, uint8_t erpinfo) {
|
||||
struct ieee80211_ie_erp* ieerp = (struct ieee80211_ie_erp*)buffer;
|
||||
|
||||
ASSERT(buffer != NULL);
|
||||
@ -99,11 +99,34 @@ static int ieee80211_ie_set_erp(char* buffer, uint32_t mode, uint32_t erpmode) {
|
||||
|
||||
ieerp->id = IEEE80211_IE_ERP;
|
||||
ieerp->len = IEEE80211_IE_ERP_LENGTH;
|
||||
ieerp->params = erpmode;
|
||||
ieerp->params = erpinfo;
|
||||
|
||||
return sizeof(struct ieee80211_ie_erp);
|
||||
}
|
||||
|
||||
/* */
|
||||
uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnonerpcount, unsigned long stationnoshortpreamblecount, int shortpreamble) {
|
||||
uint8_t result = 0;
|
||||
|
||||
/* Erp mode is valid only in IEEE 802.11 g*/
|
||||
if (mode & IEEE80211_RADIO_TYPE_80211G) {
|
||||
if (olbc) {
|
||||
result |= IEEE80211_ERP_INFO_USE_PROTECTION;
|
||||
}
|
||||
|
||||
if (stationnonerpcount > 0) {
|
||||
result |= (IEEE80211_ERP_INFO_NON_ERP_PRESENT | IEEE80211_ERP_INFO_USE_PROTECTION);
|
||||
}
|
||||
|
||||
if (!shortpreamble || (stationnoshortpreamblecount > 0)) {
|
||||
result |= IEEE80211_ERP_INFO_BARKER_PREAMBLE_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* */
|
||||
int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_params* params) {
|
||||
int result;
|
||||
@ -167,7 +190,7 @@ int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_pa
|
||||
/* TODO */
|
||||
|
||||
/* Information Element: ERP */
|
||||
result = ieee80211_ie_set_erp(pos, params->mode, params->erpmode);
|
||||
result = ieee80211_ie_set_erp(pos, params->mode, params->erpinfo);
|
||||
if (result < 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -188,7 +211,7 @@ int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_pa
|
||||
}
|
||||
|
||||
/* */
|
||||
int ieee80211_create_probe_response(char* buffer, int length, const struct ieee80211_header_mgmt* proberequestheader, struct ieee80211_probe_response_params* params) {
|
||||
int ieee80211_create_probe_response(char* buffer, int length, struct ieee80211_probe_response_params* params) {
|
||||
int result;
|
||||
char* pos;
|
||||
int responselength;
|
||||
@ -203,11 +226,7 @@ int ieee80211_create_probe_response(char* buffer, int length, const struct ieee8
|
||||
/* Management header frame */
|
||||
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_RESPONSE);
|
||||
header->durationid = __cpu_to_le16(0);
|
||||
if (proberequestheader) {
|
||||
memcpy(header->da, proberequestheader->sa, ETH_ALEN);
|
||||
} else {
|
||||
memset(header->da, 0, ETH_ALEN);
|
||||
}
|
||||
memcpy(header->da, params->station, ETH_ALEN);
|
||||
memcpy(header->sa, params->bssid, ETH_ALEN);
|
||||
memcpy(header->bssid, params->bssid, ETH_ALEN);
|
||||
header->sequencecontrol = __cpu_to_le16(0);
|
||||
@ -250,7 +269,7 @@ int ieee80211_create_probe_response(char* buffer, int length, const struct ieee8
|
||||
/* TODO */
|
||||
|
||||
/* Information Element: ERP */
|
||||
result = ieee80211_ie_set_erp(pos, params->mode, params->erpmode);
|
||||
result = ieee80211_ie_set_erp(pos, params->mode, params->erpinfo);
|
||||
if (result < 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -271,7 +290,7 @@ int ieee80211_create_probe_response(char* buffer, int length, const struct ieee8
|
||||
}
|
||||
|
||||
/* */
|
||||
int ieee80211_create_authentication_response(char* buffer, int length, const struct ieee80211_header_mgmt* authenticationheader, struct ieee80211_authentication_params* params) {
|
||||
int ieee80211_create_authentication_response(char* buffer, int length, struct ieee80211_authentication_params* params) {
|
||||
char* pos;
|
||||
int responselength;
|
||||
struct ieee80211_header_mgmt* header;
|
||||
@ -285,7 +304,7 @@ int ieee80211_create_authentication_response(char* buffer, int length, const str
|
||||
/* Management header frame */
|
||||
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION);
|
||||
header->durationid = __cpu_to_le16(0);
|
||||
memcpy(header->da, authenticationheader->sa, ETH_ALEN);
|
||||
memcpy(header->da, params->station, ETH_ALEN);
|
||||
memcpy(header->sa, params->bssid, ETH_ALEN);
|
||||
memcpy(header->bssid, params->bssid, ETH_ALEN);
|
||||
header->sequencecontrol = __cpu_to_le16(0);
|
||||
@ -303,7 +322,7 @@ int ieee80211_create_authentication_response(char* buffer, int length, const str
|
||||
}
|
||||
|
||||
/* */
|
||||
int ieee80211_create_associationresponse_response(char* buffer, int length, const struct ieee80211_header_mgmt* associationrequestheader, struct ieee80211_associationresponse_params* params) {
|
||||
int ieee80211_create_associationresponse_response(char* buffer, int length, struct ieee80211_associationresponse_params* params) {
|
||||
char* pos;
|
||||
int result;
|
||||
int responselength;
|
||||
@ -318,7 +337,7 @@ int ieee80211_create_associationresponse_response(char* buffer, int length, cons
|
||||
/* Management header frame */
|
||||
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_RESPONSE);
|
||||
header->durationid = __cpu_to_le16(0);
|
||||
memcpy(header->da, associationrequestheader->sa, ETH_ALEN);
|
||||
memcpy(header->da, params->station, ETH_ALEN);
|
||||
memcpy(header->sa, params->bssid, ETH_ALEN);
|
||||
memcpy(header->bssid, params->bssid, ETH_ALEN);
|
||||
header->sequencecontrol = __cpu_to_le16(0);
|
||||
@ -349,4 +368,26 @@ int ieee80211_create_associationresponse_response(char* buffer, int length, cons
|
||||
responselength += result;
|
||||
|
||||
return responselength;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
int ieee80211_create_deauthentication(char* buffer, int length, struct ieee80211_deauthentication_params* params) {
|
||||
struct ieee80211_header_mgmt* header;
|
||||
|
||||
ASSERT(buffer != NULL);
|
||||
ASSERT(length == IEEE80211_MTU);
|
||||
|
||||
/* */
|
||||
header = (struct ieee80211_header_mgmt*)buffer;
|
||||
|
||||
/* Management header frame */
|
||||
header->framecontrol = IEEE80211_FRAME_CONTROL(IEEE80211_FRAMECONTROL_TYPE_MGMT, IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION);
|
||||
header->durationid = __cpu_to_le16(0);
|
||||
memcpy(header->da, params->station, ETH_ALEN);
|
||||
memcpy(header->sa, params->bssid, ETH_ALEN);
|
||||
memcpy(header->bssid, params->bssid, ETH_ALEN);
|
||||
header->sequencecontrol = __cpu_to_le16(0);
|
||||
header->deauthetication.reasoncode = __cpu_to_le16(params->reasoncode);
|
||||
|
||||
return (int)((uint8_t*)&header->deauthetication.ie[0] - (uint8_t*)header);
|
||||
}
|
||||
|
@ -10,7 +10,8 @@
|
||||
#endif
|
||||
|
||||
/* Global values */
|
||||
#define IEEE80211_MTU 2304
|
||||
#define IEEE80211_MTU 2304
|
||||
#define IEEE80211_SUPPORTEDRATE_MAX_COUNT 16
|
||||
|
||||
/* Radio type with value same of IEEE802.11 Radio Information Message Element */
|
||||
#define IEEE80211_RADIO_TYPE_80211B 0x00000001
|
||||
@ -185,6 +186,34 @@
|
||||
#define IEEE80211_STATUS_MAF_LIMIT_EXCEEDED 101
|
||||
#define IEEE80211_STATUS_MCCA_TRACK_LIMIT_EXCEEDED 102
|
||||
|
||||
/* IEEE802.11 Reason code */
|
||||
#define IEEE80211_REASON_UNSPECIFIED 1
|
||||
#define IEEE80211_REASON_PREV_AUTH_NOT_VALID 2
|
||||
#define IEEE80211_REASON_DEAUTH_LEAVING 3
|
||||
#define IEEE80211_REASON_DISASSOC_DUE_TO_INACTIVITY 4
|
||||
#define IEEE80211_REASON_DISASSOC_AP_BUSY 5
|
||||
#define IEEE80211_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
|
||||
#define IEEE80211_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7
|
||||
#define IEEE80211_REASON_DISASSOC_STA_HAS_LEFT 8
|
||||
#define IEEE80211_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9
|
||||
#define IEEE80211_REASON_PWR_CAPABILITY_NOT_VALID 10
|
||||
#define IEEE80211_REASON_SUPPORTED_CHANNEL_NOT_VALID 11
|
||||
#define IEEE80211_REASON_INVALID_IE 13
|
||||
#define IEEE80211_REASON_MICHAEL_MIC_FAILURE 14
|
||||
#define IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT 15
|
||||
#define IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
|
||||
#define IEEE80211_REASON_IE_IN_4WAY_DIFFERS 17
|
||||
#define IEEE80211_REASON_GROUP_CIPHER_NOT_VALID 18
|
||||
#define IEEE80211_REASON_PAIRWISE_CIPHER_NOT_VALID 19
|
||||
#define IEEE80211_REASON_AKMP_NOT_VALID 20
|
||||
#define IEEE80211_REASON_UNSUPPORTED_RSN_IE_VERSION 21
|
||||
#define IEEE80211_REASON_INVALID_RSN_IE_CAPAB 22
|
||||
#define IEEE80211_REASON_IEEE_802_1X_AUTH_FAILED 23
|
||||
#define IEEE80211_REASON_CIPHER_SUITE_REJECTED 24
|
||||
#define IEEE80211_REASON_TDLS_TEARDOWN_UNREACHABLE 25
|
||||
#define IEEE80211_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
|
||||
#define IEEE80211_REASON_DISASSOC_LOW_ACK 34
|
||||
|
||||
/* IEEE802.11 Authentication Algorithm */
|
||||
#define IEEE80211_AUTHENTICATION_ALGORITHM_OPEN 0
|
||||
#define IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY 1
|
||||
@ -193,6 +222,29 @@
|
||||
|
||||
/* */
|
||||
#define IEEE80211_AID_FIELD 0xC000
|
||||
#define IEEE80211_AID_MAX_VALUE 2007
|
||||
|
||||
/* */
|
||||
#define IEEE80211_ERP_INFO_NON_ERP_PRESENT 0x01
|
||||
#define IEEE80211_ERP_INFO_USE_PROTECTION 0x02
|
||||
#define IEEE80211_ERP_INFO_BARKER_PREAMBLE_MODE 0x04
|
||||
|
||||
/* */
|
||||
#define IEEE80211_CAPABILITY_ESS 0x0001
|
||||
#define IEEE80211_CAPABILITY_IBSS 0x0002
|
||||
#define IEEE80211_CAPABILITY_CFPOLLABLE 0x0004
|
||||
#define IEEE80211_CAPABILITY_CFPOLLREQUEST 0x0008
|
||||
#define IEEE80211_CAPABILITY_PRIVACY 0x0010
|
||||
#define IEEE80211_CAPABILITY_SHORTPREAMBLE 0x0020
|
||||
#define IEEE80211_CAPABILITY_PBCC 0x0040
|
||||
#define IEEE80211_CAPABILITY_CHANNELAGILITY 0x0080
|
||||
#define IEEE80211_CAPABILITY_SPECTRUMMAN 0x0100
|
||||
#define IEEE80211_CAPABILITY_QOS 0x0200
|
||||
#define IEEE80211_CAPABILITY_SHORTSLOTTIME 0x0400
|
||||
#define IEEE80211_CAPABILITY_APSD 0x0800
|
||||
#define IEEE80211_CAPABILITY_DSSS_OFDM 0x2000
|
||||
#define IEEE80211_CAPABILITY_DELAYEDACK 0x4000
|
||||
#define IEEE80211_CAPABILITY_IMMEDIATEACK 0x8000
|
||||
|
||||
/* 802.11 Packet - IEEE802.11 is a little-endian protocol */
|
||||
struct ieee80211_header {
|
||||
@ -251,6 +303,11 @@ struct ieee80211_header_mgmt {
|
||||
__le16 aid;
|
||||
uint8_t ie[0];
|
||||
} STRUCT_PACKED associationresponse;
|
||||
|
||||
struct {
|
||||
__le16 reasoncode;
|
||||
uint8_t ie[0];
|
||||
} STRUCT_PACKED deauthetication;
|
||||
};
|
||||
} STRUCT_PACKED;
|
||||
|
||||
@ -398,7 +455,7 @@ struct ieee80211_ie_items {
|
||||
};
|
||||
|
||||
/* IEEE 802.11 functions */
|
||||
#define IEEE80211_SUPPORTEDRATE_MAX_COUNT 16
|
||||
uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnonerpcount, unsigned long stationnoshortpreamblecount, int shortpreamble);
|
||||
|
||||
/* Management Beacon */
|
||||
struct ieee80211_beacon_params {
|
||||
@ -421,7 +478,7 @@ struct ieee80211_beacon_params {
|
||||
uint8_t channel;
|
||||
|
||||
uint32_t mode;
|
||||
uint32_t erpmode;
|
||||
uint8_t erpinfo;
|
||||
};
|
||||
|
||||
int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_params* params);
|
||||
@ -429,6 +486,7 @@ int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_pa
|
||||
/* Management Probe Response */
|
||||
struct ieee80211_probe_response_params {
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
uint8_t station[ETH_ALEN];
|
||||
|
||||
uint16_t beaconperiod;
|
||||
uint16_t capability;
|
||||
@ -441,25 +499,27 @@ struct ieee80211_probe_response_params {
|
||||
uint8_t channel;
|
||||
|
||||
uint32_t mode;
|
||||
uint32_t erpmode;
|
||||
uint8_t erpinfo;
|
||||
};
|
||||
|
||||
int ieee80211_create_probe_response(char* buffer, int length, const struct ieee80211_header_mgmt* proberequestheader, struct ieee80211_probe_response_params* params);
|
||||
int ieee80211_create_probe_response(char* buffer, int length, struct ieee80211_probe_response_params* params);
|
||||
|
||||
/* Management Authentication */
|
||||
struct ieee80211_authentication_params {
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
uint8_t station[ETH_ALEN];
|
||||
|
||||
uint16_t algorithm;
|
||||
uint16_t transactionseqnumber;
|
||||
uint16_t statuscode;
|
||||
};
|
||||
|
||||
int ieee80211_create_authentication_response(char* buffer, int length, const struct ieee80211_header_mgmt* authenticationheader, struct ieee80211_authentication_params* params);
|
||||
int ieee80211_create_authentication_response(char* buffer, int length, struct ieee80211_authentication_params* params);
|
||||
|
||||
/* Management Association Response */
|
||||
struct ieee80211_associationresponse_params {
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
uint8_t station[ETH_ALEN];
|
||||
|
||||
uint16_t capability;
|
||||
uint16_t statuscode;
|
||||
@ -469,6 +529,16 @@ struct ieee80211_associationresponse_params {
|
||||
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
};
|
||||
|
||||
int ieee80211_create_associationresponse_response(char* buffer, int length, const struct ieee80211_header_mgmt* associationrequestheader, struct ieee80211_associationresponse_params* params);
|
||||
int ieee80211_create_associationresponse_response(char* buffer, int length, struct ieee80211_associationresponse_params* params);
|
||||
|
||||
/* Management Deauthentication */
|
||||
struct ieee80211_deauthentication_params {
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
uint8_t station[ETH_ALEN];
|
||||
|
||||
uint16_t reasoncode;
|
||||
};
|
||||
|
||||
int ieee80211_create_deauthentication(char* buffer, int length, struct ieee80211_deauthentication_params* params);
|
||||
|
||||
#endif /* __CAPWAP_IEEE802_11_HEADER__ */
|
||||
|
@ -170,6 +170,25 @@ int wifi_device_connect(int radioid, const char* ifname, const char* driver) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
static struct wifi_device* wifi_device_getdevice(int radioid) {
|
||||
struct wifi_device* device;
|
||||
|
||||
ASSERT(radioid > 0);
|
||||
|
||||
if (g_wifidevice->count < radioid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get radio connection */
|
||||
device = (struct wifi_device*)capwap_array_get_item_pointer(g_wifidevice, radioid);
|
||||
if (!device->handle) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
/* */
|
||||
static struct wifi_wlan* wifi_wlan_getdevice(int radioid, int wlanid) {
|
||||
struct wifi_device* device;
|
||||
@ -183,7 +202,7 @@ static struct wifi_wlan* wifi_wlan_getdevice(int radioid, int wlanid) {
|
||||
|
||||
/* Get radio connection */
|
||||
device = (struct wifi_device*)capwap_array_get_item_pointer(g_wifidevice, radioid);
|
||||
if (device->wlan->count < wlanid) {
|
||||
if (!device->handle || (device->wlan->count < wlanid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -202,10 +221,7 @@ int wifi_wlan_create(int radioid, int wlanid, const char* ifname, uint8_t* bssid
|
||||
struct wifi_device* device;
|
||||
struct wifi_wlan* wlan;
|
||||
wifi_wlan_handle wlanhandle;
|
||||
struct wlan_init_params params = {
|
||||
.ifname = ifname,
|
||||
.type = WLAN_INTERFACE_AP
|
||||
};
|
||||
struct wlan_init_params params;
|
||||
|
||||
ASSERT(radioid > 0);
|
||||
ASSERT(wlanid > 0);
|
||||
@ -239,6 +255,8 @@ int wifi_wlan_create(int radioid, int wlanid, const char* ifname, uint8_t* bssid
|
||||
}
|
||||
|
||||
/* Create interface */
|
||||
params.ifname = ifname;
|
||||
params.type = WLAN_INTERFACE_AP;
|
||||
wlanhandle = device->instance->ops->wlan_create(device->handle, ¶ms);
|
||||
if (!wlanhandle) {
|
||||
capwap_logging_warning("Unable to create virtual interface: %s", ifname);
|
||||
@ -254,7 +272,7 @@ 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, struct device_setrates_params* device_params) {
|
||||
int i, j, w;
|
||||
int radiotype;
|
||||
uint32_t mode = 0;
|
||||
@ -262,9 +280,10 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
|
||||
|
||||
ASSERT(device != NULL);
|
||||
ASSERT(radio != NULL);
|
||||
ASSERT(radio->rateset.ratesetcount > 0);
|
||||
|
||||
/* Free old supported rates */
|
||||
device->supportedratescount = 0;
|
||||
/* */
|
||||
memset(device_params, 0, sizeof(struct device_setrates_params));
|
||||
|
||||
/* Retrieve capability */
|
||||
capability = wifi_device_getcapability(radio->radioid);
|
||||
@ -299,10 +318,10 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
|
||||
|
||||
/* Add implicit 802.11b rate with only 802.11g rate */
|
||||
if ((device->currentfreq.band == WIFI_BAND_2GHZ) && !(mode & CAPWAP_RADIO_TYPE_80211B) && (device->currentfreq.mode & CAPWAP_RADIO_TYPE_80211B)) {
|
||||
device->supportedrates[device->supportedratescount++] = IEEE80211_RATE_1M;
|
||||
device->supportedrates[device->supportedratescount++] = IEEE80211_RATE_2M;
|
||||
device->supportedrates[device->supportedratescount++] = IEEE80211_RATE_5_5M;
|
||||
device->supportedrates[device->supportedratescount++] = IEEE80211_RATE_11M;
|
||||
device_params->supportedrates[device_params->supportedratescount++] = IEEE80211_RATE_1M;
|
||||
device_params->supportedrates[device_params->supportedratescount++] = IEEE80211_RATE_2M;
|
||||
device_params->supportedrates[device_params->supportedratescount++] = IEEE80211_RATE_5_5M;
|
||||
device_params->supportedrates[device_params->supportedratescount++] = IEEE80211_RATE_11M;
|
||||
}
|
||||
|
||||
/* Filter band */
|
||||
@ -316,7 +335,7 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
|
||||
/* Validate rate */
|
||||
for (w = 0; w < radio->rateset.ratesetcount; w++) {
|
||||
if (radio->rateset.rateset[w] == rate->bitrate) {
|
||||
device->supportedrates[device->supportedratescount++] = rate->bitrate;
|
||||
device_params->supportedrates[device_params->supportedratescount++] = rate->bitrate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -327,49 +346,34 @@ static void wifi_wlan_getrates(struct wifi_device* device, struct wtp_radio* rad
|
||||
}
|
||||
|
||||
/* Apply basic rate */
|
||||
for (i = 0; i < device->supportedratescount; i++) {
|
||||
for (i = 0; i < device_params->supportedratescount; i++) {
|
||||
if (radiotype == CAPWAP_RADIO_TYPE_80211A) {
|
||||
if (IS_IEEE80211_BASICRATE_A(device->supportedrates[i])) {
|
||||
device->supportedrates[i] |= IEEE80211_BASICRATE;
|
||||
if (IS_IEEE80211_BASICRATE_A(device_params->supportedrates[i])) {
|
||||
device_params->basicrates[device_params->basicratescount++] = device_params->supportedrates[i];
|
||||
device_params->supportedrates[i] |= IEEE80211_BASICRATE;
|
||||
}
|
||||
} else if (radiotype == CAPWAP_RADIO_TYPE_80211B) {
|
||||
if (IS_IEEE80211_BASICRATE_B(device->supportedrates[i])) {
|
||||
device->supportedrates[i] |= IEEE80211_BASICRATE;
|
||||
if (IS_IEEE80211_BASICRATE_B(device_params->supportedrates[i])) {
|
||||
device_params->basicrates[device_params->basicratescount++] = device_params->supportedrates[i];
|
||||
device_params->supportedrates[i] |= IEEE80211_BASICRATE;
|
||||
}
|
||||
} else if (radiotype == CAPWAP_RADIO_TYPE_80211G) {
|
||||
if (IS_IEEE80211_BASICRATE_G(device->supportedrates[i])) {
|
||||
device->supportedrates[i] |= IEEE80211_BASICRATE;
|
||||
if (IS_IEEE80211_BASICRATE_G(device_params->supportedrates[i])) {
|
||||
device_params->basicrates[device_params->basicratescount++] = device_params->supportedrates[i];
|
||||
device_params->supportedrates[i] |= IEEE80211_BASICRATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add implicit 802.11n rate with only 802.11a/g rate */
|
||||
if (!(mode & CAPWAP_RADIO_TYPE_80211N) && (device->currentfreq.mode & CAPWAP_RADIO_TYPE_80211N)) {
|
||||
device->supportedrates[device->supportedratescount++] = IEEE80211_RATE_80211N;
|
||||
device_params->supportedrates[device_params->supportedratescount++] = IEEE80211_RATE_80211N;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_wlan_setupap(int radioid, int wlanid) {
|
||||
int wifi_wlan_startap(int radioid, int wlanid, struct wifi_wlan_startap_params* params) {
|
||||
struct wifi_wlan* wlan;
|
||||
|
||||
ASSERT(radioid > 0);
|
||||
ASSERT(wlanid > 0);
|
||||
|
||||
/* */
|
||||
wlan = wifi_wlan_getdevice(radioid, wlanid);
|
||||
if (!wlan || !wlan->device->instance->ops->wlan_setupap) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return wlan->device->instance->ops->wlan_setupap(wlan->handle);
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_wlan_startap(int radioid, int wlanid) {
|
||||
struct wifi_wlan* wlan;
|
||||
struct wtp_radio* radio;
|
||||
struct wtp_radio_wlan* radiowlan;
|
||||
struct wlan_startap_params wlan_params;
|
||||
|
||||
ASSERT(radioid > 0);
|
||||
@ -377,30 +381,16 @@ int wifi_wlan_startap(int radioid, int wlanid) {
|
||||
|
||||
/* */
|
||||
wlan = wifi_wlan_getdevice(radioid, wlanid);
|
||||
radio = wtp_radio_get_phy(radioid);
|
||||
if (!wlan || !radio || !wlan->device->instance->ops->wlan_startap) {
|
||||
if (!wlan || !wlan->device->instance->ops->wlan_startap) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
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;
|
||||
wlan_params.ssid = params->ssid;
|
||||
wlan_params.ssid_hidden = params->ssid_hidden;
|
||||
wlan_params.capability = params->capability;
|
||||
wlan_params.authenticationtype = params->authmode;
|
||||
|
||||
return wlan->device->instance->ops->wlan_startap(wlan->handle, &wlan_params);
|
||||
}
|
||||
@ -467,6 +457,20 @@ const struct wifi_capability* wifi_device_getcapability(int radioid) {
|
||||
return device->instance->ops->device_getcapability(device->handle);
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_device_setconfiguration(int radioid, struct device_setconfiguration_params* params) {
|
||||
struct wifi_device* device;
|
||||
|
||||
/* Get radio device */
|
||||
device = wifi_device_getdevice(radioid);
|
||||
if (!device || !device->handle || !device->instance->ops->device_setconfiguration) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set rates */
|
||||
return device->instance->ops->device_setconfiguration(device->handle, params);
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_device_setfrequency(int radioid, uint32_t band, uint32_t mode, uint8_t channel) {
|
||||
int i, j;
|
||||
@ -529,6 +533,24 @@ int wifi_device_setfrequency(int radioid, uint32_t band, uint32_t mode, uint8_t
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_device_updaterates(int radioid) {
|
||||
struct wtp_radio* radio;
|
||||
struct wifi_device* device;
|
||||
struct device_setrates_params params;
|
||||
|
||||
/* Get radio device */
|
||||
device = wifi_device_getdevice(radioid);
|
||||
radio = wtp_radio_get_phy(radioid);
|
||||
if (!device || !radio || !device->handle || !device->instance->ops->device_setrates) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set rates */
|
||||
wifi_wlan_getrates(device, radio, ¶ms);
|
||||
return device->instance->ops->device_setrates(device->handle, ¶ms);
|
||||
}
|
||||
|
||||
/* */
|
||||
uint32_t wifi_iface_index(const char* ifname) {
|
||||
if (!ifname || !*ifname) {
|
||||
@ -626,7 +648,10 @@ int wifi_is_valid_ssid(const char* ssid, struct ieee80211_ie_ssid* iessid, struc
|
||||
int ssidlength;
|
||||
|
||||
ASSERT(ssid != NULL);
|
||||
ASSERT(iessid != NULL);
|
||||
|
||||
if (!iessid) {
|
||||
return WIFI_WRONG_SSID;
|
||||
}
|
||||
|
||||
/* Check SSID */
|
||||
ssidlength = strlen((char*)ssid);
|
||||
@ -777,3 +802,44 @@ int wifi_retrieve_information_elements_position(struct ieee80211_ie_items* items
|
||||
|
||||
return (!length ? 0 : -1);
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_aid_create(uint32_t* aidbitfield, uint16_t* aid) {
|
||||
int i, j;
|
||||
|
||||
ASSERT(aidbitfield != NULL);
|
||||
ASSERT(aid != NULL);
|
||||
|
||||
/* Search free aid bitfield */
|
||||
for (i = 0; i < WIFI_AID_BITFIELD_SIZE; i++) {
|
||||
if (aidbitfield[i] != 0xffffffff) {
|
||||
uint32_t bitfield = aidbitfield[i];
|
||||
|
||||
/* Search free bit */
|
||||
for (j = 0; j < 32; j++) {
|
||||
if (!(bitfield & (1 << j))) {
|
||||
*aid = i * 32 + j + 1;
|
||||
if (*aid <= IEEE80211_AID_MAX_VALUE) {
|
||||
aidbitfield[i] |= (1 << j);
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*aid = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
void wifi_aid_free(uint32_t* aidbitfield, uint16_t aid) {
|
||||
ASSERT(aidbitfield != NULL);
|
||||
ASSERT((aid > 0) && (aid <= IEEE80211_AID_MAX_VALUE));
|
||||
|
||||
aidbitfield[(aid - 1) / 32] &= ~(1 << ((aid - 1) % 32));
|
||||
}
|
||||
|
@ -62,6 +62,9 @@
|
||||
|
||||
#define WLAN_INTERFACE_AP 1
|
||||
|
||||
/* IEEE802.11 Aid management */
|
||||
#define WIFI_AID_BITFIELD_SIZE 63
|
||||
|
||||
/* */
|
||||
typedef void* wifi_global_handle;
|
||||
typedef void* wifi_device_handle;
|
||||
@ -72,6 +75,25 @@ struct device_init_params {
|
||||
const char* ifname;
|
||||
};
|
||||
|
||||
/* */
|
||||
struct device_setrates_params {
|
||||
int supportedratescount;
|
||||
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
int basicratescount;
|
||||
uint8_t basicrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
};
|
||||
|
||||
/* */
|
||||
#define WIFI_COUNTRY_LENGTH 4
|
||||
struct device_setconfiguration_params {
|
||||
int shortpreamble;
|
||||
uint8_t maxbssid;
|
||||
uint8_t dtimperiod;
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
uint16_t beaconperiod;
|
||||
uint8_t country[WIFI_COUNTRY_LENGTH];
|
||||
};
|
||||
|
||||
/* */
|
||||
struct wlan_init_params {
|
||||
const char* ifname;
|
||||
@ -83,12 +105,7 @@ struct wlan_startap_params {
|
||||
const char* ssid;
|
||||
uint8_t ssid_hidden;
|
||||
|
||||
uint16_t beaconperiod;
|
||||
uint16_t capability;
|
||||
uint8_t dtimperiod;
|
||||
|
||||
int supportedratescount;
|
||||
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
|
||||
uint8_t authenticationtype;
|
||||
};
|
||||
@ -207,13 +224,14 @@ struct wifi_driver_ops {
|
||||
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);
|
||||
const struct wifi_capability* (*device_getcapability)(wifi_device_handle handle);
|
||||
int (*device_setconfiguration)(wifi_device_handle handle, struct device_setconfiguration_params* params);
|
||||
int (*device_setfrequency)(wifi_device_handle handle, struct wifi_frequency* freq);
|
||||
int (*device_setrates)(wifi_device_handle handle, struct device_setrates_params* params);
|
||||
void (*device_deinit)(wifi_device_handle handle);
|
||||
|
||||
/* WLAN functions */
|
||||
wifi_wlan_handle (*wlan_create)(wifi_device_handle handle, struct wlan_init_params* params);
|
||||
int (*wlan_getfdevent)(wifi_wlan_handle handle, struct pollfd* fds, struct wifi_event* events);
|
||||
int (*wlan_setupap)(wifi_wlan_handle handle);
|
||||
int (*wlan_startap)(wifi_wlan_handle handle, struct wlan_startap_params* params);
|
||||
int (*wlan_stopap)(wifi_wlan_handle handle);
|
||||
int (*wlan_getmacaddress)(wifi_wlan_handle handle, uint8_t* address);
|
||||
@ -235,10 +253,6 @@ struct wifi_device {
|
||||
|
||||
/* Current frequency */
|
||||
struct wifi_frequency currentfreq;
|
||||
|
||||
/* Supported Rates */
|
||||
int supportedratescount;
|
||||
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
};
|
||||
|
||||
/* */
|
||||
@ -247,6 +261,17 @@ struct wifi_wlan {
|
||||
struct wifi_device* device;
|
||||
};
|
||||
|
||||
/* */
|
||||
struct wifi_wlan_startap_params {
|
||||
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];
|
||||
};
|
||||
|
||||
/* Initialize wifi driver engine */
|
||||
int wifi_driver_init(void);
|
||||
void wifi_driver_free(void);
|
||||
@ -257,12 +282,13 @@ 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);
|
||||
const struct wifi_capability* wifi_device_getcapability(int radioid);
|
||||
int wifi_device_setconfiguration(int radioid, struct device_setconfiguration_params* params);
|
||||
int wifi_device_setfrequency(int radioid, uint32_t band, uint32_t mode, uint8_t channel);
|
||||
int wifi_device_updaterates(int radioid);
|
||||
|
||||
/* */
|
||||
int wifi_wlan_create(int radioid, int wlanid, const char* ifname, uint8_t* bssid);
|
||||
int wifi_wlan_setupap(int radioid, int wlanid);
|
||||
int wifi_wlan_startap(int radioid, int wlanid);
|
||||
int wifi_wlan_startap(int radioid, int wlanid, struct wifi_wlan_startap_params* params);
|
||||
int wifi_wlan_stopap(int radioid, int wlanid);
|
||||
int wifi_wlan_getbssid(int radioid, int wlanid, uint8_t* bssid);
|
||||
void wifi_wlan_destroy(int radioid, int wlanid);
|
||||
@ -281,6 +307,10 @@ int wifi_is_broadcast_addr(const uint8_t* addr);
|
||||
#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_aid_create(uint32_t* aidbitfield, uint16_t* aid);
|
||||
void wifi_aid_free(uint32_t* aidbitfield, uint16_t aid);
|
||||
|
||||
/* */
|
||||
int wifi_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length);
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "capwap_array.h"
|
||||
#include "capwap_list.h"
|
||||
#include "capwap_element.h"
|
||||
#include "wtp_radio.h"
|
||||
#include <netlink/genl/genl.h>
|
||||
#include <netlink/genl/family.h>
|
||||
#include <netlink/genl/ctrl.h>
|
||||
@ -254,6 +255,267 @@ static int nl80211_wlan_send_frame(wifi_wlan_handle handle, struct wlan_send_fra
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
static uint16_t nl80211_wlan_check_capability(struct nl80211_wlan_handle* wlanhandle, uint16_t capability) {
|
||||
uint16_t result = capability;
|
||||
|
||||
/* Force ESS capability */
|
||||
result |= IEEE80211_CAPABILITY_ESS;
|
||||
|
||||
/* Check short preamble capability */
|
||||
if (wlanhandle->devicehandle->shortpreamble && !wlanhandle->devicehandle->stationsnoshortpreamblecount) {
|
||||
result |= IEEE80211_CAPABILITY_SHORTPREAMBLE;
|
||||
} else {
|
||||
result &= ~IEEE80211_CAPABILITY_SHORTPREAMBLE;
|
||||
}
|
||||
|
||||
/* Check privacy capability */
|
||||
/* TODO */
|
||||
|
||||
/* Check short slot time capability */
|
||||
if ((wlanhandle->devicehandle->currentfrequency.mode & IEEE80211_RADIO_TYPE_80211G) && !wlanhandle->devicehandle->stationsnoshortslottimecount) {
|
||||
result |= IEEE80211_CAPABILITY_SHORTSLOTTIME;
|
||||
} else {
|
||||
result &= ~IEEE80211_CAPABILITY_SHORTSLOTTIME;
|
||||
}
|
||||
|
||||
return capability;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_wlan_setbss(struct nl80211_wlan_handle* wlanhandle, int cts, int preamble, int slot, int htopmode, int apisolate) {
|
||||
int result;
|
||||
struct nl_msg* msg;
|
||||
|
||||
/* */
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
genlmsg_put(msg, 0, 0, wlanhandle->devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_SET_BSS, 0);
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wlanhandle->virtindex);
|
||||
|
||||
if (cts >= 0) {
|
||||
nla_put_u8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);
|
||||
}
|
||||
|
||||
if (preamble >= 0) {
|
||||
nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);
|
||||
}
|
||||
|
||||
if (slot >= 0) {
|
||||
nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
|
||||
}
|
||||
|
||||
if (htopmode >= 0) {
|
||||
nla_put_u16(msg, NL80211_ATTR_BSS_HT_OPMODE, htopmode);
|
||||
}
|
||||
|
||||
if (apisolate >= 0) {
|
||||
nla_put_u8(msg, NL80211_ATTR_AP_ISOLATE, apisolate);
|
||||
}
|
||||
|
||||
if (wlanhandle->devicehandle->basicratescount > 0) {
|
||||
nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, wlanhandle->devicehandle->basicratescount, wlanhandle->devicehandle->basicrates);
|
||||
}
|
||||
|
||||
/* */
|
||||
result = nl80211_send_and_recv_msg(wlanhandle->devicehandle->globalhandle, msg, NULL, NULL);
|
||||
nlmsg_free(msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_wlan_setbeacon(struct nl80211_wlan_handle* wlanhandle) {
|
||||
int result;
|
||||
struct nl_msg* msg;
|
||||
char buffer[IEEE80211_MTU];
|
||||
struct ieee80211_beacon_params ieee80211_params;
|
||||
|
||||
/* Create beacon packet */
|
||||
memset(&ieee80211_params, 0, sizeof(struct ieee80211_beacon_params));
|
||||
memcpy(ieee80211_params.bssid, wlanhandle->address, ETH_ALEN);
|
||||
ieee80211_params.beaconperiod = wlanhandle->devicehandle->beaconperiod;
|
||||
ieee80211_params.capability = nl80211_wlan_check_capability(wlanhandle, wlanhandle->capability);
|
||||
ieee80211_params.ssid = wlanhandle->ssid;
|
||||
ieee80211_params.ssid_hidden = wlanhandle->ssid_hidden;
|
||||
memcpy(ieee80211_params.supportedrates, wlanhandle->devicehandle->supportedrates, wlanhandle->devicehandle->supportedratescount);
|
||||
ieee80211_params.supportedratescount = wlanhandle->devicehandle->supportedratescount;
|
||||
ieee80211_params.mode = wlanhandle->devicehandle->currentfrequency.mode;
|
||||
ieee80211_params.erpinfo = ieee80211_get_erpinfo(wlanhandle->devicehandle->currentfrequency.mode, wlanhandle->devicehandle->olbc, wlanhandle->devicehandle->stationsnonerpcount, wlanhandle->devicehandle->stationsnoshortpreamblecount, wlanhandle->devicehandle->shortpreamble);
|
||||
ieee80211_params.channel = wlanhandle->devicehandle->currentfrequency.channel;
|
||||
|
||||
result = ieee80211_create_beacon(buffer, IEEE80211_MTU, &ieee80211_params);
|
||||
if (result < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
genlmsg_put(msg, 0, 0, wlanhandle->devicehandle->globalhandle->nl80211_id, 0, 0, ((wlanhandle->flags & NL80211_WLAN_SET_BEACON) ? NL80211_CMD_SET_BEACON : NL80211_CMD_START_AP), 0);
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wlanhandle->virtindex);
|
||||
nla_put(msg, NL80211_ATTR_BEACON_HEAD, ieee80211_params.headbeaconlength, ieee80211_params.headbeacon);
|
||||
nla_put(msg, NL80211_ATTR_BEACON_TAIL, ieee80211_params.tailbeaconlength, ieee80211_params.tailbeacon);
|
||||
nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, wlanhandle->devicehandle->beaconperiod);
|
||||
nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, wlanhandle->devicehandle->dtimperiod);
|
||||
nla_put(msg, NL80211_ATTR_SSID, strlen(wlanhandle->ssid), wlanhandle->ssid);
|
||||
nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, (wlanhandle->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_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
|
||||
|
||||
/* Start AP */
|
||||
result = nl80211_send_and_recv_msg(wlanhandle->devicehandle->globalhandle, msg, NULL, NULL);
|
||||
nlmsg_free(msg);
|
||||
|
||||
/* Configure AP */
|
||||
if (!result) {
|
||||
int cts = ((ieee80211_params.erpinfo & IEEE80211_ERP_INFO_USE_PROTECTION) ? 1 : 0);
|
||||
int preamble = ((!wlanhandle->devicehandle->stationsnoshortpreamblecount && wlanhandle->devicehandle->shortpreamble) ? 1 : 0);
|
||||
int slot = ((wlanhandle->devicehandle->currentfrequency.mode & IEEE80211_RADIO_TYPE_80211G) ? (wlanhandle->devicehandle->stationsnoshortslottimecount ? 0 : 1) : -1);
|
||||
int htopmode = -1; /* TODO: 802.11n */
|
||||
int apisolate = -1; /* TODO: AP Isolation */
|
||||
|
||||
result = nl80211_wlan_setbss(wlanhandle, cts, preamble, slot, htopmode, apisolate);
|
||||
if (!result) {
|
||||
wlanhandle->flags |= NL80211_WLAN_SET_BEACON;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_device_updatebeacons(struct nl80211_device_handle* devicehandle) {
|
||||
struct capwap_list_item* wlansearch;
|
||||
|
||||
ASSERT(devicehandle != NULL);
|
||||
|
||||
/* Update all wlan beacon */
|
||||
wlansearch = devicehandle->wlanlist->first;
|
||||
while (wlansearch) {
|
||||
nl80211_wlan_setbeacon((struct nl80211_wlan_handle*)wlansearch->item);
|
||||
wlansearch = wlansearch->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_station_delete(struct nl80211_wlan_handle* wlanhandle, const uint8_t* macaddress) {
|
||||
int updatebeacons = 0;
|
||||
struct nl80211_station* station;
|
||||
|
||||
ASSERT(macaddress != NULL);
|
||||
|
||||
station = (struct nl80211_station*)capwap_hash_search(wlanhandle->stations, macaddress);
|
||||
if (station) {
|
||||
if (station->aid) {
|
||||
wifi_aid_free(wlanhandle->aidbitfield, station->aid);
|
||||
}
|
||||
|
||||
if (station->flags & NL80211_STATION_FLAGS_NON_ERP) {
|
||||
wlanhandle->devicehandle->stationsnonerpcount--;
|
||||
if (!wlanhandle->devicehandle->stationsnonerpcount) {
|
||||
updatebeacons = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (station->flags & NL80211_STATION_FLAGS_NO_SHORT_SLOT_TIME) {
|
||||
wlanhandle->devicehandle->stationsnoshortslottimecount--;
|
||||
if (!wlanhandle->devicehandle->stationsnoshortslottimecount && (wlanhandle->devicehandle->currentfrequency.mode & IEEE80211_RADIO_TYPE_80211G)) {
|
||||
updatebeacons = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (station->flags & NL80211_STATION_FLAGS_NO_SHORT_PREAMBLE) {
|
||||
wlanhandle->devicehandle->stationsnoshortpreamblecount--;
|
||||
if (!wlanhandle->devicehandle->stationsnoshortpreamblecount && (wlanhandle->devicehandle->currentfrequency.mode & IEEE80211_RADIO_TYPE_80211G)) {
|
||||
updatebeacons = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free station into hash callback */
|
||||
wlanhandle->stationscount--;
|
||||
capwap_hash_delete(wlanhandle->stations, macaddress);
|
||||
|
||||
/* Update beacons */
|
||||
if (updatebeacons) {
|
||||
nl80211_device_updatebeacons(wlanhandle->devicehandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static struct nl80211_station* nl80211_station_create(struct nl80211_wlan_handle* wlanhandle, const uint8_t* macaddress) {
|
||||
struct nl80211_station* station;
|
||||
|
||||
ASSERT(macaddress != NULL);
|
||||
|
||||
/* If exist free old station */
|
||||
nl80211_station_delete(wlanhandle, macaddress);
|
||||
|
||||
/* Checks if it has reached the maximum number of stations */
|
||||
/* TODO */
|
||||
|
||||
/* Disconnect from another WLAN */
|
||||
/* TODO */
|
||||
|
||||
/* Create new station */
|
||||
station = (struct nl80211_station*)capwap_alloc(sizeof(struct nl80211_station));
|
||||
memset(station, 0, sizeof(struct nl80211_station));
|
||||
|
||||
/* TODO */
|
||||
|
||||
/* */
|
||||
wlanhandle->stationscount++;
|
||||
capwap_hash_add(wlanhandle->stations, macaddress, station);
|
||||
return station;
|
||||
}
|
||||
|
||||
/* */
|
||||
static struct nl80211_station* nl80211_station_get(struct nl80211_wlan_handle* wlanhandle, const uint8_t* macaddress) {
|
||||
ASSERT(macaddress != NULL);
|
||||
|
||||
return (struct nl80211_station*)capwap_hash_search(wlanhandle->stations, macaddress);
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_wlan_send_deauthentication(struct nl80211_wlan_handle* wlanhandle, const uint8_t* stationaddress, uint16_t reasoncode) {
|
||||
int responselength;
|
||||
char buffer[IEEE80211_MTU];
|
||||
struct ieee80211_deauthentication_params ieee80211_params;
|
||||
struct wlan_send_frame_params wlan_params;
|
||||
|
||||
/* Create deauthentication packet */
|
||||
memset(&ieee80211_params, 0, sizeof(struct ieee80211_deauthentication_params));
|
||||
memcpy(ieee80211_params.bssid, wlanhandle->address, ETH_ALEN);
|
||||
memcpy(ieee80211_params.station, stationaddress, ETH_ALEN);
|
||||
ieee80211_params.reasoncode = reasoncode;
|
||||
|
||||
responselength = ieee80211_create_deauthentication(buffer, IEEE80211_MTU, &ieee80211_params);
|
||||
if (responselength < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send deauthentication */
|
||||
memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params));
|
||||
wlan_params.packet = buffer;
|
||||
wlan_params.length = responselength;
|
||||
wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency;
|
||||
|
||||
if (!nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) {
|
||||
wlanhandle->last_cookie = wlan_params.cookie;
|
||||
} else {
|
||||
capwap_logging_warning("Unable to send IEEE802.11 Deuthentication");
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
|
||||
int ielength;
|
||||
@ -289,16 +551,17 @@ static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlan
|
||||
/* 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;
|
||||
memcpy(ieee80211_params.station, mgmt->sa, ETH_ALEN);
|
||||
ieee80211_params.beaconperiod = wlanhandle->devicehandle->beaconperiod;
|
||||
ieee80211_params.capability = nl80211_wlan_check_capability(wlanhandle, wlanhandle->capability);
|
||||
ieee80211_params.ssid = wlanhandle->ssid;
|
||||
memcpy(ieee80211_params.supportedrates, wlanhandle->supportedrates, wlanhandle->supportedratescount);
|
||||
ieee80211_params.supportedratescount = wlanhandle->supportedratescount;
|
||||
memcpy(ieee80211_params.supportedrates, wlanhandle->devicehandle->supportedrates, wlanhandle->devicehandle->supportedratescount);
|
||||
ieee80211_params.supportedratescount = wlanhandle->devicehandle->supportedratescount;
|
||||
ieee80211_params.mode = wlanhandle->devicehandle->currentfrequency.mode;
|
||||
ieee80211_params.erpmode = 0; /* TODO */
|
||||
ieee80211_params.erpinfo = ieee80211_get_erpinfo(wlanhandle->devicehandle->currentfrequency.mode, wlanhandle->devicehandle->olbc, wlanhandle->devicehandle->stationsnonerpcount, wlanhandle->devicehandle->stationsnoshortpreamblecount, wlanhandle->devicehandle->shortpreamble);
|
||||
ieee80211_params.channel = wlanhandle->devicehandle->currentfrequency.channel;
|
||||
|
||||
responselength = ieee80211_create_probe_response(buffer, IEEE80211_MTU, mgmt, &ieee80211_params);
|
||||
responselength = ieee80211_create_probe_response(buffer, IEEE80211_MTU, &ieee80211_params);
|
||||
if (responselength < 0) {
|
||||
return;
|
||||
}
|
||||
@ -327,6 +590,7 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla
|
||||
char buffer[IEEE80211_MTU];
|
||||
struct ieee80211_authentication_params ieee80211_params;
|
||||
struct wlan_send_frame_params wlan_params;
|
||||
struct nl80211_station* station;
|
||||
|
||||
/* Ignore authentication packet from same AP */
|
||||
if (!memcmp(mgmt->sa, wlanhandle->address, ETH_ALEN)) {
|
||||
@ -351,28 +615,36 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla
|
||||
}
|
||||
|
||||
/* Create station reference */
|
||||
/* TODO */
|
||||
station = nl80211_station_create(wlanhandle, mgmt->sa);
|
||||
if (station) {
|
||||
algorithm = __le16_to_cpu(mgmt->authetication.algorithm);
|
||||
transactionseqnumber = __le16_to_cpu(mgmt->authetication.transactionseqnumber);
|
||||
|
||||
/* */
|
||||
algorithm = __le16_to_cpu(mgmt->authetication.algorithm);
|
||||
transactionseqnumber = __le16_to_cpu(mgmt->authetication.transactionseqnumber);
|
||||
|
||||
/* Check authentication algorithm */
|
||||
responsestatuscode = IEEE80211_STATUS_NOT_SUPPORTED_AUTHENTICATION_ALGORITHM;
|
||||
if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (wlanhandle->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_OPEN)) {
|
||||
responsestatuscode = ((transactionseqnumber == 1) ? IEEE80211_STATUS_SUCCESS : IEEE80211_STATUS_UNKNOWN_AUTHENTICATION_TRANSACTION);
|
||||
} else if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (wlanhandle->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_WEP)) {
|
||||
/* TODO */
|
||||
/* Check authentication algorithm */
|
||||
responsestatuscode = IEEE80211_STATUS_NOT_SUPPORTED_AUTHENTICATION_ALGORITHM;
|
||||
if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (wlanhandle->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_OPEN)) {
|
||||
if (transactionseqnumber == 1) {
|
||||
responsestatuscode = IEEE80211_STATUS_SUCCESS;
|
||||
station->authalgorithm = IEEE80211_AUTHENTICATION_ALGORITHM_OPEN;
|
||||
} else {
|
||||
responsestatuscode = IEEE80211_STATUS_UNKNOWN_AUTHENTICATION_TRANSACTION;
|
||||
}
|
||||
} else if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY) && (wlanhandle->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_WEP)) {
|
||||
/* TODO */
|
||||
}
|
||||
} else {
|
||||
responsestatuscode = IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
|
||||
}
|
||||
|
||||
/* Create authentication packet */
|
||||
memset(&ieee80211_params, 0, sizeof(struct ieee80211_authentication_params));
|
||||
memcpy(ieee80211_params.bssid, wlanhandle->address, ETH_ALEN);
|
||||
memcpy(ieee80211_params.station, mgmt->sa, ETH_ALEN);
|
||||
ieee80211_params.algorithm = algorithm;
|
||||
ieee80211_params.transactionseqnumber = transactionseqnumber + 1;
|
||||
ieee80211_params.statuscode = responsestatuscode;
|
||||
|
||||
responselength = ieee80211_create_authentication_response(buffer, IEEE80211_MTU, mgmt, &ieee80211_params);
|
||||
responselength = ieee80211_create_authentication_response(buffer, IEEE80211_MTU, &ieee80211_params);
|
||||
if (responselength < 0) {
|
||||
return;
|
||||
}
|
||||
@ -390,6 +662,83 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_set_station_information(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, struct ieee80211_ie_items* ieitems, struct nl80211_station* station) {
|
||||
int updatebeacons = 0;
|
||||
|
||||
/* Verify SSID */
|
||||
if (wifi_is_valid_ssid(wlanhandle->ssid, ieitems->ssid, NULL) != WIFI_VALID_SSID) {
|
||||
return IEEE80211_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
/* */
|
||||
station->capability = __le16_to_cpu(mgmt->associationrequest.capability);
|
||||
station->listeninterval = __le16_to_cpu(mgmt->associationrequest.listeninterval);
|
||||
if (wifi_aid_create(wlanhandle->aidbitfield, &station->aid)) {
|
||||
return IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
|
||||
}
|
||||
|
||||
/* Get supported rates */
|
||||
if (!ieitems->supported_rates) {
|
||||
return IEEE80211_STATUS_UNSPECIFIED_FAILURE;
|
||||
} else if ((ieitems->supported_rates->len + (ieitems->extended_supported_rates ? ieitems->extended_supported_rates->len : 0)) > sizeof(station->supportedrates)) {
|
||||
return IEEE80211_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
station->supportedratescount = ieitems->supported_rates->len;
|
||||
memcpy(station->supportedrates, ieitems->supported_rates->rates, ieitems->supported_rates->len);
|
||||
if (ieitems->extended_supported_rates) {
|
||||
station->supportedratescount += ieitems->extended_supported_rates->len;
|
||||
memcpy(&station->supportedrates[ieitems->supported_rates->len], ieitems->extended_supported_rates->rates, ieitems->extended_supported_rates->len);
|
||||
}
|
||||
|
||||
/* Check NON ERP */
|
||||
if (wlanhandle->devicehandle->currentfrequency.mode & IEEE80211_RADIO_TYPE_80211G) {
|
||||
int i;
|
||||
int stationnonerp = 1;
|
||||
|
||||
for (i = 0; i < station->supportedratescount; i++) {
|
||||
if (IS_IEEE80211_RATE_G(station->supportedrates[i])) {
|
||||
stationnonerp = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stationnonerp) {
|
||||
station->flags |= NL80211_STATION_FLAGS_NON_ERP;
|
||||
wlanhandle->devicehandle->stationsnonerpcount++;
|
||||
if (wlanhandle->devicehandle->stationsnonerpcount == 1) {
|
||||
updatebeacons = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check short slot capability */
|
||||
if (!(station->capability & IEEE80211_CAPABILITY_SHORTSLOTTIME)) {
|
||||
station->flags |= NL80211_STATION_FLAGS_NO_SHORT_SLOT_TIME;
|
||||
wlanhandle->devicehandle->stationsnoshortslottimecount++;
|
||||
if ((wlanhandle->devicehandle->stationsnoshortslottimecount == 1) && (wlanhandle->devicehandle->currentfrequency.mode & IEEE80211_RADIO_TYPE_80211G)) {
|
||||
updatebeacons = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check short preamble capability */
|
||||
if (!(station->capability & IEEE80211_CAPABILITY_SHORTPREAMBLE)) {
|
||||
station->flags |= NL80211_STATION_FLAGS_NO_SHORT_PREAMBLE;
|
||||
wlanhandle->devicehandle->stationsnoshortpreamblecount++;
|
||||
if ((wlanhandle->devicehandle->stationsnoshortpreamblecount == 1) && (wlanhandle->devicehandle->currentfrequency.mode & IEEE80211_RADIO_TYPE_80211G)) {
|
||||
updatebeacons = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update beacon */
|
||||
if (updatebeacons) {
|
||||
nl80211_device_updatebeacons(wlanhandle->devicehandle);
|
||||
}
|
||||
|
||||
return IEEE80211_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
|
||||
int ielength;
|
||||
@ -398,6 +747,16 @@ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle
|
||||
struct ieee80211_ie_items ieitems;
|
||||
struct ieee80211_associationresponse_params ieee80211_params;
|
||||
struct wlan_send_frame_params wlan_params;
|
||||
struct nl80211_station* station;
|
||||
uint16_t resultstatuscode = IEEE80211_STATUS_SUCCESS;
|
||||
|
||||
/* Get station reference */
|
||||
station = nl80211_station_get(wlanhandle, mgmt->sa);
|
||||
if (!station || !(station->flags & NL80211_STATION_FLAGS_AUTHENTICATED)) {
|
||||
/* Invalid station, send deauthentication message */
|
||||
nl80211_wlan_send_deauthentication(wlanhandle, mgmt->sa, IEEE80211_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Information Elements packet length */
|
||||
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest));
|
||||
@ -410,19 +769,20 @@ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get station reference */
|
||||
/* TODO */
|
||||
/* */
|
||||
resultstatuscode = nl80211_set_station_information(wlanhandle, mgmt, &ieitems, station);
|
||||
|
||||
/* Create association response packet */
|
||||
memset(&ieee80211_params, 0, sizeof(struct ieee80211_authentication_params));
|
||||
memcpy(ieee80211_params.bssid, wlanhandle->address, ETH_ALEN);
|
||||
ieee80211_params.capability = wlanhandle->capability;
|
||||
ieee80211_params.statuscode = IEEE80211_STATUS_SUCCESS;
|
||||
ieee80211_params.aid = IEEE80211_AID_FIELD | 1;
|
||||
memcpy(ieee80211_params.supportedrates, wlanhandle->supportedrates, wlanhandle->supportedratescount);
|
||||
ieee80211_params.supportedratescount = wlanhandle->supportedratescount;
|
||||
memcpy(ieee80211_params.station, mgmt->sa, ETH_ALEN);
|
||||
ieee80211_params.capability = nl80211_wlan_check_capability(wlanhandle, wlanhandle->capability);
|
||||
ieee80211_params.statuscode = resultstatuscode;
|
||||
ieee80211_params.aid = IEEE80211_AID_FIELD | station->aid;
|
||||
memcpy(ieee80211_params.supportedrates, wlanhandle->devicehandle->supportedrates, wlanhandle->devicehandle->supportedratescount);
|
||||
ieee80211_params.supportedratescount = wlanhandle->devicehandle->supportedratescount;
|
||||
|
||||
responselength = ieee80211_create_associationresponse_response(buffer, IEEE80211_MTU, mgmt, &ieee80211_params);
|
||||
responselength = ieee80211_create_associationresponse_response(buffer, IEEE80211_MTU, &ieee80211_params);
|
||||
if (responselength < 0) {
|
||||
return;
|
||||
}
|
||||
@ -522,6 +882,7 @@ static void nl80211_do_mgmt_frame_tx_status_authentication_event(struct nl80211_
|
||||
uint16_t algorithm;
|
||||
uint16_t transactionseqnumber;
|
||||
uint16_t statuscode;
|
||||
struct nl80211_station* station;
|
||||
|
||||
/* Accept only acknowledge authentication response with same cookie */
|
||||
if (!ack || (wlanhandle->last_cookie != cookie)) {
|
||||
@ -533,6 +894,12 @@ static void nl80211_do_mgmt_frame_tx_status_authentication_event(struct nl80211_
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get station information */
|
||||
station = nl80211_station_get(wlanhandle, mgmt->da);
|
||||
if (!station) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* */
|
||||
statuscode = __le16_to_cpu(mgmt->authetication.statuscode);
|
||||
if (statuscode == IEEE80211_STATUS_SUCCESS) {
|
||||
@ -541,7 +908,7 @@ static void nl80211_do_mgmt_frame_tx_status_authentication_event(struct nl80211_
|
||||
|
||||
/* Check if authenticate */
|
||||
if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (transactionseqnumber == 2)) {
|
||||
capwap_logging_debug("Authenticate station");
|
||||
station->flags |= NL80211_STATION_FLAGS_AUTHENTICATED;
|
||||
} else if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY) && (transactionseqnumber == 4)) {
|
||||
/* TODO */
|
||||
}
|
||||
@ -551,6 +918,7 @@ static void nl80211_do_mgmt_frame_tx_status_authentication_event(struct nl80211_
|
||||
/* */
|
||||
static void nl80211_do_mgmt_frame_tx_status_association_response_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, uint64_t cookie, int ack) {
|
||||
uint16_t statuscode;
|
||||
struct nl80211_station* station;
|
||||
|
||||
/* Accept only acknowledge association response with same cookie */
|
||||
if (!ack || (wlanhandle->last_cookie != cookie)) {
|
||||
@ -562,12 +930,19 @@ static void nl80211_do_mgmt_frame_tx_status_association_response_event(struct nl
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get station information */
|
||||
station = nl80211_station_get(wlanhandle, mgmt->da);
|
||||
if (!station) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* */
|
||||
statuscode = __le16_to_cpu(mgmt->associationresponse.statuscode);
|
||||
if (statuscode == IEEE80211_STATUS_SUCCESS) {
|
||||
capwap_logging_debug("Associate station");
|
||||
station->flags |= NL80211_STATION_FLAGS_ASSOCIATE;
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_do_mgmt_frame_tx_status_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, uint16_t framecontrol_subtype, uint64_t cookie, int ack) {
|
||||
/* Ignore packet if not sent to AP */
|
||||
@ -586,6 +961,11 @@ static void nl80211_do_mgmt_frame_tx_status_event(struct nl80211_wlan_handle* wl
|
||||
nl80211_do_mgmt_frame_tx_status_association_response_event(wlanhandle, mgmt, mgmtlength, cookie, ack);
|
||||
break;
|
||||
}
|
||||
|
||||
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION: {
|
||||
/* TODO */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove cookie */
|
||||
@ -674,6 +1054,24 @@ static void nl80211_event_receive(int fd, void* param1, void* param2) {
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
static unsigned long nl80211_hash_station_gethash(const void* key, unsigned long keysize, unsigned long hashsize) {
|
||||
uint8_t* macaddress = (uint8_t*)key;
|
||||
|
||||
ASSERT(keysize == ETH_ALEN);
|
||||
|
||||
return ((macaddress[3] ^ macaddress[4] ^ macaddress[5]) >> 2);
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_hash_station_free(const void* key, unsigned long keysize, void* data) {
|
||||
struct nl80211_station* station = (struct nl80211_station*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(station);
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_global_valid_handler(struct nl_msg* msg, void* data) {
|
||||
uint32_t ifindex;
|
||||
@ -1283,6 +1681,22 @@ static int nl80211_device_getfdevent(wifi_device_handle handle, struct pollfd* f
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_device_setconfiguration(wifi_device_handle handle, struct device_setconfiguration_params* params) {
|
||||
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
/* */
|
||||
devicehandle->beaconperiod = params->beaconperiod;
|
||||
devicehandle->dtimperiod = params->dtimperiod;
|
||||
devicehandle->shortpreamble = (params->shortpreamble ? 1 : 0);
|
||||
|
||||
/* Update beacons */
|
||||
nl80211_device_updatebeacons(devicehandle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_device_setfrequency(wifi_device_handle handle, struct wifi_frequency* freq) {
|
||||
int result;
|
||||
@ -1314,6 +1728,31 @@ static int nl80211_device_setfrequency(wifi_device_handle handle, struct wifi_fr
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_device_setrates(wifi_device_handle handle, struct device_setrates_params* params) {
|
||||
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
ASSERT(params != NULL);
|
||||
|
||||
/* */
|
||||
if (!params->supportedratescount || (params->supportedratescount > IEEE80211_SUPPORTEDRATE_MAX_COUNT)) {
|
||||
return -1;
|
||||
} else if (!params->basicratescount || (params->basicratescount > IEEE80211_SUPPORTEDRATE_MAX_COUNT)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set new rates */
|
||||
memcpy(devicehandle->supportedrates, params->supportedrates, params->supportedratescount);
|
||||
devicehandle->supportedratescount = params->supportedratescount;
|
||||
memcpy(devicehandle->basicrates, params->basicrates, params->basicratescount);
|
||||
devicehandle->basicratescount = params->basicratescount;
|
||||
|
||||
/* Update beacons */
|
||||
nl80211_device_updatebeacons(devicehandle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void nl80211_wlan_delete(wifi_wlan_handle handle) {
|
||||
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
||||
@ -1347,6 +1786,10 @@ static void nl80211_wlan_delete(wifi_wlan_handle handle) {
|
||||
nl_cb_put(wlanhandle->nl_cb);
|
||||
}
|
||||
|
||||
if (wlanhandle->stations) {
|
||||
capwap_hash_free(wlanhandle->stations);
|
||||
}
|
||||
|
||||
capwap_free(wlanhandle);
|
||||
}
|
||||
}
|
||||
@ -1413,12 +1856,22 @@ static void nl80211_device_deinit(wifi_device_handle handle) {
|
||||
|
||||
/* */
|
||||
static wifi_wlan_handle nl80211_wlan_create(wifi_device_handle handle, struct wlan_init_params* params) {
|
||||
int i;
|
||||
int result;
|
||||
uint32_t ifindex;
|
||||
struct nl_msg* msg;
|
||||
struct capwap_list_item* item;
|
||||
struct nl80211_wlan_handle* wlanhandle = NULL;
|
||||
struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle;
|
||||
static const int stypes[] = {
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQUEST,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION
|
||||
};
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
ASSERT(params != NULL);
|
||||
@ -1493,6 +1946,17 @@ static wifi_wlan_handle nl80211_wlan_create(wifi_device_handle handle, struct wl
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Register frames */
|
||||
for (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) {
|
||||
if (nl80211_registerframe(wlanhandle, (IEEE80211_FRAMECONTROL_TYPE_MGMT << 2) | (stypes[i] << 4), NULL, 0)) {
|
||||
nl80211_wlan_delete((wifi_wlan_handle)wlanhandle);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stations */
|
||||
wlanhandle->stations = capwap_hash_create(WIFI_NL80211_STATIONS_HASH_SIZE, WIFI_NL80211_STATIONS_KEY_SIZE, nl80211_hash_station_gethash, NULL, nl80211_hash_station_free);
|
||||
|
||||
return wlanhandle;
|
||||
}
|
||||
|
||||
@ -1516,38 +1980,8 @@ static int nl80211_wlan_getfdevent(wifi_wlan_handle handle, struct pollfd* fds,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_wlan_setupap(wifi_wlan_handle handle) {
|
||||
int i;
|
||||
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
||||
static const int stypes[] = {
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQUEST,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION,
|
||||
IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION
|
||||
};
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
|
||||
/* Register frames */
|
||||
for (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) {
|
||||
if (nl80211_registerframe(wlanhandle, (IEEE80211_FRAMECONTROL_TYPE_MGMT << 2) | (stypes[i] << 4), NULL, 0)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* */
|
||||
static int nl80211_wlan_startap(wifi_wlan_handle handle, struct wlan_startap_params* params) {
|
||||
int result;
|
||||
struct nl_msg* msg;
|
||||
char buffer[IEEE80211_MTU];
|
||||
struct ieee80211_beacon_params ieee80211_params;
|
||||
struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle;
|
||||
|
||||
/* Enable interface */
|
||||
@ -1555,55 +1989,14 @@ static int nl80211_wlan_startap(wifi_wlan_handle handle, struct wlan_startap_par
|
||||
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.mode = wlanhandle->devicehandle->currentfrequency.mode;
|
||||
ieee80211_params.erpmode = 0; /* TODO */
|
||||
ieee80211_params.channel = wlanhandle->devicehandle->currentfrequency.channel;
|
||||
|
||||
result = ieee80211_create_beacon(buffer, IEEE80211_MTU, &ieee80211_params);
|
||||
if (result < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
/* Save configuration */
|
||||
strcpy(wlanhandle->ssid, params->ssid);
|
||||
wlanhandle->beaconperiod = params->beaconperiod;
|
||||
wlanhandle->ssid_hidden = params->ssid_hidden;
|
||||
wlanhandle->capability = params->capability;
|
||||
memcpy(wlanhandle->supportedrates, params->supportedrates, params->supportedratescount);
|
||||
wlanhandle->supportedratescount = params->supportedratescount;
|
||||
wlanhandle->authenticationtype = params->authenticationtype;
|
||||
wlanhandle->authenticationtype = ((params->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_WEP) ? NL80211_AUTHTYPE_SHARED_KEY : NL80211_AUTHTYPE_OPEN_SYSTEM);
|
||||
|
||||
/* */
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* */
|
||||
genlmsg_put(msg, 0, 0, wlanhandle->devicehandle->globalhandle->nl80211_id, 0, 0, NL80211_CMD_START_AP, 0);
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wlanhandle->virtindex);
|
||||
nla_put(msg, NL80211_ATTR_BEACON_HEAD, ieee80211_params.headbeaconlength, ieee80211_params.headbeacon);
|
||||
nla_put(msg, NL80211_ATTR_BEACON_TAIL, ieee80211_params.tailbeaconlength, ieee80211_params.tailbeacon);
|
||||
nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beaconperiod);
|
||||
nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtimperiod);
|
||||
nla_put(msg, NL80211_ATTR_SSID, strlen(params->ssid), params->ssid);
|
||||
nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, (params->ssid_hidden ? NL80211_HIDDEN_SSID_ZERO_LEN : NL80211_HIDDEN_SSID_NOT_IN_USE));
|
||||
nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, ((params->authenticationtype == CAPWAP_ADD_WLAN_AUTHTYPE_WEP) ? NL80211_AUTHTYPE_SHARED_KEY : NL80211_AUTHTYPE_OPEN_SYSTEM));
|
||||
nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
|
||||
|
||||
/* Start AP */
|
||||
result = nl80211_send_and_recv_msg(wlanhandle->devicehandle->globalhandle, msg, NULL, NULL);
|
||||
nlmsg_free(msg);
|
||||
|
||||
return result;
|
||||
/* Set beacon */
|
||||
return nl80211_wlan_setbeacon(wlanhandle);
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -1792,11 +2185,12 @@ const struct wifi_driver_ops wifi_driver_nl80211_ops = {
|
||||
.device_init = nl80211_device_init,
|
||||
.device_getfdevent = nl80211_device_getfdevent,
|
||||
.device_getcapability = nl80211_device_getcachedcapability,
|
||||
.device_setconfiguration = nl80211_device_setconfiguration,
|
||||
.device_setfrequency = nl80211_device_setfrequency,
|
||||
.device_setrates = nl80211_device_setrates,
|
||||
.device_deinit = nl80211_device_deinit,
|
||||
.wlan_create = nl80211_wlan_create,
|
||||
.wlan_getfdevent = nl80211_wlan_getfdevent,
|
||||
.wlan_setupap = nl80211_wlan_setupap,
|
||||
.wlan_startap = nl80211_wlan_startap,
|
||||
.wlan_stopap = nl80211_wlan_stopap,
|
||||
.wlan_getmacaddress = nl80211_wlan_getmacaddress,
|
||||
|
@ -1,11 +1,17 @@
|
||||
#ifndef __WIFI_NL80211_HEADER__
|
||||
#define __WIFI_NL80211_HEADER__
|
||||
|
||||
#include "capwap_hash.h"
|
||||
|
||||
/* Compatibility functions */
|
||||
#if !defined(HAVE_LIBNL20) && !defined(HAVE_LIBNL30)
|
||||
#define nl_sock nl_handle
|
||||
#endif
|
||||
|
||||
/* */
|
||||
#define WIFI_NL80211_STATIONS_HASH_SIZE 64
|
||||
#define WIFI_NL80211_STATIONS_KEY_SIZE ETH_ALEN
|
||||
|
||||
/* */
|
||||
typedef int (*nl_valid_cb)(struct nl_msg* msg, void* data);
|
||||
|
||||
@ -32,12 +38,33 @@ struct nl80211_device_handle {
|
||||
|
||||
struct capwap_list* wlanlist;
|
||||
|
||||
/* */
|
||||
uint16_t beaconperiod;
|
||||
uint8_t dtimperiod;
|
||||
int shortpreamble;
|
||||
|
||||
/* */
|
||||
struct wifi_frequency currentfrequency;
|
||||
|
||||
struct wifi_capability* capability; /* Cached capability */
|
||||
/* Cached capability */
|
||||
struct wifi_capability* capability;
|
||||
|
||||
/* Rates */
|
||||
unsigned long supportedratescount;
|
||||
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
unsigned long basicratescount;
|
||||
uint8_t basicrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
|
||||
/* ERP Information */
|
||||
int olbc;
|
||||
unsigned long stationsnonerpcount;
|
||||
unsigned long stationsnoshortslottimecount;
|
||||
unsigned long stationsnoshortpreamblecount;
|
||||
};
|
||||
|
||||
/* WLAN handle */
|
||||
#define NL80211_WLAN_SET_BEACON 0x00000001
|
||||
|
||||
struct nl80211_wlan_handle {
|
||||
struct nl80211_device_handle* devicehandle;
|
||||
|
||||
@ -45,6 +72,8 @@ struct nl80211_wlan_handle {
|
||||
int nl_fd;
|
||||
struct nl_cb* nl_cb;
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
uint32_t virtindex;
|
||||
char virtname[IFNAMSIZ];
|
||||
|
||||
@ -54,14 +83,17 @@ struct nl80211_wlan_handle {
|
||||
|
||||
/* WLAN information */
|
||||
char ssid[WIFI_SSID_MAX_LENGTH + 1];
|
||||
|
||||
uint16_t beaconperiod;
|
||||
uint8_t ssid_hidden;
|
||||
uint16_t capability;
|
||||
|
||||
int supportedratescount;
|
||||
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
|
||||
/* Authentication */
|
||||
uint8_t authenticationtype;
|
||||
|
||||
/* Station information */
|
||||
unsigned long stationscount;
|
||||
struct capwap_hash* stations;
|
||||
|
||||
uint32_t aidbitfield[WIFI_AID_BITFIELD_SIZE];
|
||||
};
|
||||
|
||||
/* Physical device info */
|
||||
@ -77,4 +109,28 @@ struct nl80211_virtdevice_item {
|
||||
char virtname[IFNAMSIZ];
|
||||
};
|
||||
|
||||
/* Station */
|
||||
#define NL80211_STATION_FLAGS_AUTHENTICATED 0x00000001
|
||||
#define NL80211_STATION_FLAGS_ASSOCIATE 0x00000002
|
||||
#define NL80211_STATION_FLAGS_NON_ERP 0x00000004
|
||||
#define NL80211_STATION_FLAGS_NO_SHORT_SLOT_TIME 0x00000008
|
||||
#define NL80211_STATION_FLAGS_NO_SHORT_PREAMBLE 0x00000010
|
||||
|
||||
/* */
|
||||
struct nl80211_station {
|
||||
unsigned long flags;
|
||||
|
||||
/* */
|
||||
uint16_t capability;
|
||||
uint16_t listeninterval;
|
||||
uint16_t aid;
|
||||
|
||||
/* */
|
||||
int supportedratescount;
|
||||
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
|
||||
|
||||
/* Authentication */
|
||||
uint16_t authalgorithm;
|
||||
};
|
||||
|
||||
#endif /* __WIFI_NL80211_HEADER__ */
|
||||
|
@ -122,15 +122,4 @@ int capwap_check_message_type(struct capwap_packet_rxmng* rxmngpacket);
|
||||
void capwap_get_packet_digest(struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, unsigned char packetdigest[16]);
|
||||
int capwap_recv_retrasmitted_request(struct capwap_dtls* dtls, struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, unsigned char packetdigest[16], struct capwap_list* txfragmentpacket);
|
||||
|
||||
/* TODO utile ?
|
||||
#define CAPWAP_VALID_PACKET 0x00000000
|
||||
#define CAPWAP_MISSING_MANDATORY_MSG_ELEMENT 0x00000001
|
||||
#define CAPWAP_UNRECOGNIZED_MSG_ELEMENT 0x00000002
|
||||
|
||||
struct unrecognized_info {
|
||||
unsigned short element;
|
||||
unsigned char reason;
|
||||
};
|
||||
*/
|
||||
|
||||
#endif /* __CAPWAP_PROTOCOL_HEADER__ */
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "capwap_array.h"
|
||||
#include "capwap_dfa.h"
|
||||
#include "capwap_dtls.h"
|
||||
#include "wtp_radio.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@ -221,6 +222,9 @@ int wtp_dfa_running(void) {
|
||||
g_wtp.fdstotalcount = g_wtp.fdsnetworkcount;
|
||||
ASSERT(g_wtp.fdstotalcount > 0);
|
||||
|
||||
/* Update Event File Descriptor */
|
||||
wtp_radio_update_fdevent();
|
||||
|
||||
/* Handler signal */
|
||||
g_wtp.running = 1;
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
@ -2,6 +2,17 @@
|
||||
#include "capwap_hash.h"
|
||||
#include "wtp_radio.h"
|
||||
|
||||
/* */
|
||||
#define WTP_UPDATE_FREQUENCY_DSSS 1
|
||||
#define WTP_UPDATE_FREQUENCY_OFDM 2
|
||||
#define WTP_UPDATE_RATES 3
|
||||
#define WTP_UPDATE_CONFIGURATION 4
|
||||
|
||||
struct wtp_update_configuration_item {
|
||||
int type;
|
||||
struct wtp_radio* radio;
|
||||
};
|
||||
|
||||
/* */
|
||||
static int wtp_radio_configure_phy(struct wtp_radio* radio) {
|
||||
/* Default rate set is all supported rate */
|
||||
@ -14,6 +25,11 @@ static int wtp_radio_configure_phy(struct wtp_radio* radio) {
|
||||
radio->rateset.radioid = radio->radioid;
|
||||
radio->rateset.ratesetcount = radio->supportedrates.supportedratescount;
|
||||
memcpy(radio->rateset.rateset, radio->supportedrates.supportedrates, CAPWAP_RATESET_MAXLENGTH);
|
||||
|
||||
/* Update rates */
|
||||
if (wifi_device_updaterates(radio->radioid)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check channel radio */
|
||||
@ -107,12 +123,18 @@ void wtp_radio_free(void) {
|
||||
/* */
|
||||
int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
||||
int i;
|
||||
int result = 0;
|
||||
unsigned short binding;
|
||||
struct wtp_radio* radio;
|
||||
struct capwap_array* messageelements;
|
||||
struct capwap_array* updateitems;
|
||||
struct wtp_update_configuration_item* item;
|
||||
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
/* */
|
||||
updateitems = capwap_array_create(sizeof(struct wtp_update_configuration_item), 0, 1);
|
||||
|
||||
/* */
|
||||
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
|
||||
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
|
||||
@ -253,14 +275,13 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
||||
directsequencecontrol = *(struct capwap_80211_directsequencecontrol_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(directsequencecontrol->radioid);
|
||||
if (radio && (radio->radioid == directsequencecontrol->radioid)) {
|
||||
if (!(radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) {
|
||||
return -1;
|
||||
}
|
||||
if (radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G)) {
|
||||
memcpy(&radio->directsequencecontrol, directsequencecontrol, sizeof(struct capwap_80211_directsequencecontrol_element));
|
||||
|
||||
/* Configure radio channel */
|
||||
memcpy(&radio->directsequencecontrol, directsequencecontrol, sizeof(struct capwap_80211_directsequencecontrol_element));
|
||||
if (wifi_device_setfrequency(radio->radioid, WIFI_BAND_2GHZ, radio->radioinformation.radiotype, radio->directsequencecontrol.currentchannel)) {
|
||||
return -1;
|
||||
/* Pending change radio channel */
|
||||
item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, updateitems->count);
|
||||
item->type = WTP_UPDATE_FREQUENCY_DSSS;
|
||||
item->radio = radio;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,14 +299,13 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
||||
ofdmcontrol = *(struct capwap_80211_ofdmcontrol_element**)capwap_array_get_item_pointer(messageelements, i);
|
||||
radio = wtp_radio_get_phy(ofdmcontrol->radioid);
|
||||
if (radio && (radio->radioid == ofdmcontrol->radioid)) {
|
||||
if (!(radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) {
|
||||
return -1;
|
||||
}
|
||||
if (radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A) {
|
||||
memcpy(&radio->ofdmcontrol, ofdmcontrol, sizeof(struct capwap_80211_ofdmcontrol_element));
|
||||
|
||||
/* Configure radio channel */
|
||||
memcpy(&radio->ofdmcontrol, ofdmcontrol, sizeof(struct capwap_80211_ofdmcontrol_element));
|
||||
if (wifi_device_setfrequency(radio->radioid, WIFI_BAND_5GHZ, radio->radioinformation.radiotype, radio->ofdmcontrol.currentchannel)) {
|
||||
return -1;
|
||||
/* Pending change radio channel */
|
||||
item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, updateitems->count);
|
||||
item->type = WTP_UPDATE_FREQUENCY_OFDM;
|
||||
item->radio = radio;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -304,6 +324,11 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
||||
radio = wtp_radio_get_phy(rateset->radioid);
|
||||
if (radio && (radio->radioid == rateset->radioid)) {
|
||||
memcpy(&radio->rateset, rateset, sizeof(struct capwap_80211_rateset_element));
|
||||
|
||||
/* Pending change radio rates */
|
||||
item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, updateitems->count);
|
||||
item->type = WTP_UPDATE_RATES;
|
||||
item->radio = radio;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -372,6 +397,11 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
||||
radio = wtp_radio_get_phy(radioconfig->radioid);
|
||||
if (radio && (radio->radioid == radioconfig->radioid)) {
|
||||
memcpy(&radio->radioconfig, radioconfig, sizeof(struct capwap_80211_wtpradioconf_element));
|
||||
|
||||
/* Pending change radio configuration */
|
||||
item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, updateitems->count);
|
||||
item->type = WTP_UPDATE_CONFIGURATION;
|
||||
item->radio = radio;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -386,7 +416,52 @@ int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* Update radio frequency */
|
||||
for (i = 0; (i < updateitems->count) && !result; i++) {
|
||||
struct wtp_update_configuration_item* item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, i);
|
||||
|
||||
switch (item->type) {
|
||||
case WTP_UPDATE_FREQUENCY_DSSS: {
|
||||
result = wifi_device_setfrequency(item->radio->radioid, WIFI_BAND_2GHZ, item->radio->radioinformation.radiotype, item->radio->directsequencecontrol.currentchannel);
|
||||
break;
|
||||
}
|
||||
|
||||
case WTP_UPDATE_FREQUENCY_OFDM: {
|
||||
result = wifi_device_setfrequency(item->radio->radioid, WIFI_BAND_5GHZ, item->radio->radioinformation.radiotype, item->radio->ofdmcontrol.currentchannel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update radio configuration */
|
||||
for (i = 0; (i < updateitems->count) && !result; i++) {
|
||||
struct wtp_update_configuration_item* item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, i);
|
||||
|
||||
switch (item->type) {
|
||||
case WTP_UPDATE_RATES: {
|
||||
result = wifi_device_updaterates(radio->radioid);
|
||||
break;
|
||||
}
|
||||
|
||||
case WTP_UPDATE_CONFIGURATION: {
|
||||
struct device_setconfiguration_params params;
|
||||
|
||||
memset(¶ms, 0, sizeof(struct device_setconfiguration_params));
|
||||
params.shortpreamble = ((item->radio->radioconfig.shortpreamble == CAPWAP_WTP_RADIO_CONF_SHORTPREAMBLE_ENABLE) ? 1 : 0);
|
||||
params.maxbssid = item->radio->radioconfig.maxbssid;
|
||||
params.dtimperiod = item->radio->radioconfig.dtimperiod;
|
||||
memcpy(params.bssid, item->radio->radioconfig.bssid, ETH_ALEN);
|
||||
params.beaconperiod = item->radio->radioconfig.beaconperiod;
|
||||
memcpy(params.country, item->radio->radioconfig.country, WIFI_COUNTRY_LENGTH);
|
||||
result = wifi_device_setconfiguration(item->radio->radioid, ¶ms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
capwap_array_free(updateitems);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -437,7 +512,7 @@ struct wtp_radio_wlan* wtp_radio_get_wlan(struct wtp_radio* radio, uint8_t wlani
|
||||
}
|
||||
|
||||
/* */
|
||||
static void wtp_radio_update_fdevent(void) {
|
||||
void wtp_radio_update_fdevent(void) {
|
||||
int count;
|
||||
|
||||
/* Retrieve number of File Descriptor Event */
|
||||
@ -477,8 +552,10 @@ static void wtp_radio_update_fdevent(void) {
|
||||
|
||||
/* */
|
||||
uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwap_80211_assignbssid_element* bssid) {
|
||||
char wlanname[IFNAMSIZ];
|
||||
struct wtp_radio* radio;
|
||||
struct wtp_radio_wlan* wlan;
|
||||
struct wifi_wlan_startap_params params;
|
||||
struct capwap_80211_addwlan_element* addwlan;
|
||||
|
||||
/* Get message elements */
|
||||
@ -510,42 +587,34 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
|
||||
wlan = (struct wtp_radio_wlan*)capwap_array_get_item_pointer(radio->wlan, radio->wlan->count);
|
||||
wlan->radio = radio;
|
||||
wlan->wlanid = addwlan->wlanid;
|
||||
sprintf(wlan->wlanname, "%s%02d.%02d", g_wtp.wlanprefix, (int)addwlan->radioid, (int)addwlan->wlanid);
|
||||
if (wifi_iface_index(wlan->wlanname)) {
|
||||
sprintf(wlanname, "%s%02d.%02d", g_wtp.wlanprefix, (int)addwlan->radioid, (int)addwlan->wlanid);
|
||||
if (wifi_iface_index(wlanname)) {
|
||||
memset(wlan, 0, sizeof(struct wtp_radio_wlan));
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Create virtual interface */
|
||||
if (!wifi_wlan_create(addwlan->radioid, addwlan->wlanid, wlan->wlanname, NULL)) {
|
||||
if (!wifi_wlan_create(addwlan->radioid, addwlan->wlanid, wlanname, NULL)) {
|
||||
wlan->state = WTP_RADIO_WLAN_STATE_CREATED;
|
||||
} else {
|
||||
wtp_radio_destroy_wlan(wlan);
|
||||
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);
|
||||
/* Wlan configuration */
|
||||
memset(¶ms, 0, sizeof(struct wifi_wlan_startap_params));
|
||||
params.capability = addwlan->capability;
|
||||
params.qos = addwlan->qos;
|
||||
params.authmode = addwlan->authmode;
|
||||
params.macmode = addwlan->macmode;
|
||||
params.tunnelmode = addwlan->tunnelmode;
|
||||
params.ssid_hidden = addwlan->suppressssid;
|
||||
strcpy(params.ssid, (const char*)addwlan->ssid);
|
||||
|
||||
/* TODO (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE) */
|
||||
|
||||
/* Configure virtual interface */
|
||||
if (!wifi_wlan_setupap(addwlan->radioid, addwlan->wlanid)) {
|
||||
wlan->state = WTP_RADIO_WLAN_STATE_READY;
|
||||
} else {
|
||||
wtp_radio_destroy_wlan(wlan);
|
||||
return CAPWAP_RESULTCODE_FAILURE;
|
||||
}
|
||||
|
||||
/* Start AP */
|
||||
if (!wifi_wlan_startap(addwlan->radioid, addwlan->wlanid)) {
|
||||
if (!wifi_wlan_startap(addwlan->radioid, addwlan->wlanid, ¶ms)) {
|
||||
wlan->state = WTP_RADIO_WLAN_STATE_AP;
|
||||
} else {
|
||||
wtp_radio_destroy_wlan(wlan);
|
||||
@ -558,7 +627,7 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa
|
||||
/* Retrieve macaddress of new device */
|
||||
bssid->radioid = addwlan->radioid;
|
||||
bssid->wlanid = addwlan->wlanid;
|
||||
memcpy(bssid->bssid, wlan->bssid, ETH_ALEN);
|
||||
wifi_wlan_getbssid(addwlan->radioid, addwlan->wlanid, bssid->bssid);
|
||||
|
||||
return CAPWAP_RESULTCODE_SUCCESS;
|
||||
}
|
||||
|
@ -22,25 +22,12 @@
|
||||
|
||||
#define WTP_RADIO_WLAN_STATE_IDLE 0
|
||||
#define WTP_RADIO_WLAN_STATE_CREATED 1
|
||||
#define WTP_RADIO_WLAN_STATE_READY 2
|
||||
#define WTP_RADIO_WLAN_STATE_AP 3
|
||||
#define WTP_RADIO_WLAN_STATE_AP 2
|
||||
|
||||
struct wtp_radio_wlan {
|
||||
struct wtp_radio* radio;
|
||||
int state;
|
||||
|
||||
uint8_t wlanid;
|
||||
char wlanname[IFNAMSIZ];
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
|
||||
/* */
|
||||
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];
|
||||
};
|
||||
|
||||
/* */
|
||||
@ -77,6 +64,7 @@ struct wtp_radio_wlan* wtp_radio_get_wlan(struct wtp_radio* radio, uint8_t wlani
|
||||
|
||||
/* */
|
||||
int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet);
|
||||
void wtp_radio_update_fdevent(void);
|
||||
|
||||
/* */
|
||||
uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwap_80211_assignbssid_element* bssid);
|
||||
|
Loading…
Reference in New Issue
Block a user