Improved the management of authentication and association of the stations

This commit is contained in:
vemax78 2014-01-21 19:54:59 +01:00
parent 42293aad04
commit 0790fb511a
10 changed files with 975 additions and 268 deletions

View File

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

View File

@ -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__ */

View File

@ -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, &params);
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, &params);
return device->instance->ops->device_setrates(device->handle, &params);
}
/* */
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));
}

View File

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

View File

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

View File

@ -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__ */

View File

@ -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__ */

View File

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

View File

@ -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(&params, 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, &params);
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(&params, 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, &params)) {
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;
}

View File

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