Add code to simple management IEEE802.11 Association Request/Response packets.

Need more code for complete the management of station association.
This commit is contained in:
vemax78 2014-01-14 19:15:58 +01:00
parent bc2a6183ce
commit 547e398924
4 changed files with 176 additions and 25 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) {
static int ieee80211_ie_set_erp(char* buffer, uint32_t mode, uint32_t erpmode) {
struct ieee80211_ie_erp* ieerp = (struct ieee80211_ie_erp*)buffer;
ASSERT(buffer != NULL);
@ -99,7 +99,7 @@ static int ieee80211_ie_set_erp(char* buffer, uint32_t mode) {
ieerp->id = IEEE80211_IE_ERP;
ieerp->len = IEEE80211_IE_ERP_LENGTH;
ieerp->params = 0; /* TODO */
ieerp->params = erpmode;
return sizeof(struct ieee80211_ie_erp);
}
@ -167,7 +167,7 @@ int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_pa
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->erpmode);
result = ieee80211_ie_set_erp(pos, params->mode, params->erpmode);
if (result < 0) {
return -1;
}
@ -250,7 +250,7 @@ int ieee80211_create_probe_response(char* buffer, int length, const struct ieee8
/* TODO */
/* Information Element: ERP */
result = ieee80211_ie_set_erp(pos, params->erpmode);
result = ieee80211_ie_set_erp(pos, params->mode, params->erpmode);
if (result < 0) {
return -1;
}
@ -301,3 +301,52 @@ int ieee80211_create_authentication_response(char* buffer, int length, const str
return responselength;
}
/* */
int ieee80211_create_associationresponse_response(char* buffer, int length, const struct ieee80211_header_mgmt* associationrequestheader, struct ieee80211_associationresponse_params* params) {
char* pos;
int result;
int responselength;
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_ASSOCIATION_RESPONSE);
header->durationid = __cpu_to_le16(0);
memcpy(header->da, associationrequestheader->sa, ETH_ALEN);
memcpy(header->sa, params->bssid, ETH_ALEN);
memcpy(header->bssid, params->bssid, ETH_ALEN);
header->sequencecontrol = __cpu_to_le16(0);
header->associationresponse.capability = __cpu_to_le16(params->capability);
header->associationresponse.statuscode = __cpu_to_le16(params->statuscode);
header->associationresponse.aid = __cpu_to_le16(params->aid);
/* Header frame size */
responselength = (int)((uint8_t*)&header->associationresponse.ie[0] - (uint8_t*)header);
pos = buffer + responselength;
/* Information Element: Supported Rates */
result = ieee80211_ie_set_supportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
/* Information Element: Extended Supported Rates */
result = ieee80211_ie_set_extendedsupportedrates(pos, params->supportedrates, params->supportedratescount);
if (result < 0) {
return -1;
}
pos += result;
responselength += result;
return responselength;
}

View File

@ -191,6 +191,9 @@
#define IEEE80211_AUTHENTICATION_ALGORITHM_FAST_BSS 2
#define IEEE80211_AUTHENTICATION_ALGORITHM_SAE 3
/* */
#define IEEE80211_AID_FIELD 0xC000
/* 802.11 Packet - IEEE802.11 is a little-endian protocol */
struct ieee80211_header {
__le16 framecontrol;
@ -235,6 +238,19 @@ struct ieee80211_header_mgmt {
__le16 statuscode;
uint8_t ie[0];
} STRUCT_PACKED authetication;
struct {
__le16 capability;
__le16 listeninterval;
uint8_t ie[0];
} STRUCT_PACKED associationrequest;
struct {
__le16 capability;
__le16 statuscode;
__le16 aid;
uint8_t ie[0];
} STRUCT_PACKED associationresponse;
};
} STRUCT_PACKED;
@ -386,29 +402,25 @@ struct ieee80211_ie_items {
/* Management Beacon */
struct ieee80211_beacon_params {
/* Beacon packet */
char* headbeacon;
int headbeaconlength;
char* tailbeacon;
int tailbeaconlength;
/* Header information */
uint8_t bssid[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
/* SSID */
const char* ssid;
int ssid_hidden;
/* Supported Rates */
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
/* DSSS */
uint8_t channel;
/* ERP */
uint32_t mode;
uint32_t erpmode;
};
@ -416,22 +428,19 @@ int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_pa
/* Management Probe Response */
struct ieee80211_probe_response_params {
/* Header information */
uint8_t bssid[ETH_ALEN];
uint16_t beaconperiod;
uint16_t capability;
/* SSID */
const char* ssid;
/* Supported Rates */
int supportedratescount;
uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT];
/* DSSS */
uint8_t channel;
/* ERP */
uint32_t mode;
uint32_t erpmode;
};
@ -439,8 +448,8 @@ int ieee80211_create_probe_response(char* buffer, int length, const struct ieee8
/* Management Authentication */
struct ieee80211_authentication_params {
/* Header information */
uint8_t bssid[ETH_ALEN];
uint16_t algorithm;
uint16_t transactionseqnumber;
uint16_t statuscode;
@ -448,4 +457,18 @@ struct ieee80211_authentication_params {
int ieee80211_create_authentication_response(char* buffer, int length, const struct ieee80211_header_mgmt* authenticationheader, struct ieee80211_authentication_params* params);
/* Management Association Response */
struct ieee80211_associationresponse_params {
uint8_t bssid[ETH_ALEN];
uint16_t capability;
uint16_t statuscode;
uint16_t aid;
int supportedratescount;
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);
#endif /* __CAPWAP_IEEE802_11_HEADER__ */

View File

@ -294,8 +294,9 @@ static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlan
ieee80211_params.ssid = wlanhandle->ssid;
memcpy(ieee80211_params.supportedrates, wlanhandle->supportedrates, wlanhandle->supportedratescount);
ieee80211_params.supportedratescount = wlanhandle->supportedratescount;
ieee80211_params.mode = wlanhandle->devicehandle->currentfrequency.mode;
ieee80211_params.erpmode = 0; /* TODO */
ieee80211_params.channel = wifi_frequency_to_channel(wlanhandle->devicehandle->currentfrequency);
ieee80211_params.channel = wlanhandle->devicehandle->currentfrequency.channel;
responselength = ieee80211_create_probe_response(buffer, IEEE80211_MTU, mgmt, &ieee80211_params);
if (responselength < 0) {
@ -306,7 +307,7 @@ static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlan
memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params));
wlan_params.packet = buffer;
wlan_params.length = responselength;
wlan_params.frequency = wlanhandle->devicehandle->currentfrequency;
wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency;
wlan_params.no_wait_ack = ((ssidcheck == WIFI_WILDCARD_SSID) && wifi_is_broadcast_addr(mgmt->da) ? 1 : 0);
if (nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) {
@ -376,7 +377,7 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla
memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params));
wlan_params.packet = buffer;
wlan_params.length = responselength;
wlan_params.frequency = wlanhandle->devicehandle->currentfrequency;
wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency;
if (!nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) {
wlanhandle->last_cookie = wlan_params.cookie;
@ -385,12 +386,62 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla
}
}
/* */
static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) {
int ielength;
int responselength;
char buffer[IEEE80211_MTU];
struct ieee80211_ie_items ieitems;
struct ieee80211_associationresponse_params ieee80211_params;
struct wlan_send_frame_params wlan_params;
/* Information Elements packet length */
ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest));
if (ielength < 0) {
return;
}
/* Parsing Information Elements */
if (wifi_retrieve_information_elements_position(&ieitems, &mgmt->associationrequest.ie[0], ielength)) {
return;
}
/* Get station reference */
/* TODO */
/* 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;
responselength = ieee80211_create_associationresponse_response(buffer, IEEE80211_MTU, mgmt, &ieee80211_params);
if (responselength < 0) {
return;
}
/* Send authentication response */
memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params));
wlan_params.packet = buffer;
wlan_params.length = responselength;
wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.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 Association Response");
}
}
/* */
static void nl80211_do_mgmt_frame_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, uint16_t framecontrol_subtype, uint32_t frequency) {
int broadcast;
/* Check frequency */
if (frequency && (wlanhandle->devicehandle->currentfrequency != frequency)) {
if (frequency && (wlanhandle->devicehandle->currentfrequency.frequency != frequency)) {
return;
}
@ -411,7 +462,7 @@ static void nl80211_do_mgmt_frame_event(struct nl80211_wlan_handle* wlanhandle,
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST: {
/* TODO */
nl80211_do_mgmt_association_request_event(wlanhandle, mgmt, mgmtlength);
break;
}
@ -493,6 +544,26 @@ 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;
/* Accept only acknowledge association response with same cookie */
if (!ack || (wlanhandle->last_cookie != cookie)) {
return;
}
/* Check packet */
if (mgmtlength < (sizeof(struct ieee80211_header) + sizeof(mgmt->associationresponse))) {
return;
}
/* */
statuscode = __le16_to_cpu(mgmt->associationresponse.statuscode);
if (statuscode == IEEE80211_STATUS_SUCCESS) {
capwap_logging_debug("Associate station");
}
}
/* */
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 */
@ -506,6 +577,11 @@ static void nl80211_do_mgmt_frame_tx_status_event(struct nl80211_wlan_handle* wl
nl80211_do_mgmt_frame_tx_status_authentication_event(wlanhandle, mgmt, mgmtlength, cookie, ack);
break;
}
case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_RESPONSE: {
nl80211_do_mgmt_frame_tx_status_association_response_event(wlanhandle, mgmt, mgmtlength, cookie, ack);
break;
}
}
/* Remove cookie */
@ -562,7 +638,7 @@ static int nl80211_execute_bss_event(struct nl80211_wlan_handle* wlanhandle, str
}
default: {
capwap_logging_debug("nl80211_execute_bss_event: %d", (int)gnlh->cmd);
capwap_logging_debug("*** nl80211_execute_bss_event: %d", (int)gnlh->cmd);
break;
}
}
@ -628,6 +704,8 @@ static int nl80211_global_valid_handler(struct nl_msg* msg, void* data) {
devicesearch = devicesearch->next;
}
} else {
capwap_logging_debug("*** Receive nl80211_global_valid_handler without interface index");
}
return NL_SKIP;
@ -1222,7 +1300,7 @@ static int nl80211_device_setfrequency(wifi_device_handle handle, struct wifi_fr
/* Set wifi frequency */
result = nl80211_send_and_recv_msg(devicehandle->globalhandle, msg, NULL, NULL);
if (!result) {
devicehandle->currentfrequency = freq->frequency;
memcpy(&devicehandle->currentfrequency, freq, sizeof(struct wifi_frequency));
} else {
capwap_logging_error("Unable retrieve physical device capability, error code: %d", result);
}
@ -1482,8 +1560,9 @@ static int nl80211_wlan_startap(wifi_wlan_handle handle, struct wlan_startap_par
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 = wifi_frequency_to_channel(wlanhandle->devicehandle->currentfrequency);
ieee80211_params.channel = wlanhandle->devicehandle->currentfrequency.channel;
result = ieee80211_create_beacon(buffer, IEEE80211_MTU, &ieee80211_params);
if (result < 0) {

View File

@ -32,7 +32,7 @@ struct nl80211_device_handle {
struct capwap_list* wlanlist;
uint32_t currentfrequency;
struct wifi_frequency currentfrequency;
struct wifi_capability* capability; /* Cached capability */
};