From e1e4748367d01abd4bb440119e6ebcebd63563b8 Mon Sep 17 00:00:00 2001 From: vemax78 Date: Sun, 9 Feb 2014 21:55:10 +0100 Subject: [PATCH] The preparation for sending IEEE802.11 management packets to the AC by data channel. Support both Local Mac and Split Mac. --- src/binding/ieee80211/ieee80211.h | 19 +++ src/binding/ieee80211/wifi_drivers.h | 5 + src/binding/ieee80211/wifi_nl80211.c | 186 +++++++++++++++++++-------- src/binding/ieee80211/wifi_nl80211.h | 4 + src/wtp/wtp_radio.c | 29 ++++- 5 files changed, 181 insertions(+), 62 deletions(-) diff --git a/src/binding/ieee80211/ieee80211.h b/src/binding/ieee80211/ieee80211.h index 2003019..0b03923 100644 --- a/src/binding/ieee80211/ieee80211.h +++ b/src/binding/ieee80211/ieee80211.h @@ -305,10 +305,29 @@ struct ieee80211_header_mgmt { uint8_t ie[0]; } STRUCT_PACKED associationresponse; + struct { + __le16 capability; + __le16 listeninterval; + uint8_t currentap[6]; + uint8_t ie[0]; + } STRUCT_PACKED reassociationrequest; + + struct { + __le16 capability; + __le16 statuscode; + __le16 aid; + uint8_t ie[0]; + } STRUCT_PACKED reassociationresponse; + struct { __le16 reasoncode; uint8_t ie[0]; } STRUCT_PACKED deauthetication; + + struct { + __le16 reasoncode; + uint8_t ie[0]; + } STRUCT_PACKED disassociation; }; } STRUCT_PACKED; diff --git a/src/binding/ieee80211/wifi_drivers.h b/src/binding/ieee80211/wifi_drivers.h index d719195..f948eda 100644 --- a/src/binding/ieee80211/wifi_drivers.h +++ b/src/binding/ieee80211/wifi_drivers.h @@ -96,7 +96,12 @@ struct device_setconfiguration_params { }; /* */ +typedef void (*send_mgmtframe_to_ac)(void* param, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, int leavenativeframe); + struct wlan_startap_params { + send_mgmtframe_to_ac send_mgmtframe; + void* send_mgmtframe_to_ac_cbparam; + const char* ssid; uint8_t ssid_hidden; uint16_t capability; diff --git a/src/binding/ieee80211/wifi_nl80211.c b/src/binding/ieee80211/wifi_nl80211.c index 0f54f6a..f628948 100644 --- a/src/binding/ieee80211/wifi_nl80211.c +++ b/src/binding/ieee80211/wifi_nl80211.c @@ -687,6 +687,12 @@ static void nl80211_do_mgmt_probe_request_event(struct nl80211_wlan_handle* wlan if (nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) { capwap_logging_warning("Unable to send IEEE802.11 Probe Response"); + return; + } + + /* If enable Split Mac send the probe request message to AC */ + if (wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { + wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength, 1); } } @@ -703,6 +709,12 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla struct wlan_send_frame_params wlan_params; struct nl80211_station* station; + /* Information Elements packet length */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication)); + if (ielength < 0) { + return; + } + /* Ignore authentication packet from same AP */ if (!memcmp(mgmt->sa, wlanhandle->address, ETH_ALEN)) { return; @@ -714,12 +726,6 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla return; } - /* Information Elements packet length */ - ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication)); - if (ielength < 0) { - return; - } - /* Parsing Information Elements */ if (wifi_retrieve_information_elements_position(&ieitems, &mgmt->authetication.ie[0], ielength)) { return; @@ -747,29 +753,38 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla 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; + /* */ + if (wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { + /* 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(g_bufferIEEE80211, sizeof(g_bufferIEEE80211), &ieee80211_params); - if (responselength < 0) { - return; - } + responselength = ieee80211_create_authentication_response(g_bufferIEEE80211, sizeof(g_bufferIEEE80211), &ieee80211_params); + if (responselength < 0) { + return; + } - /* Send authentication response */ - memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params)); - wlan_params.packet = g_bufferIEEE80211; - wlan_params.length = responselength; - wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency; + /* Send authentication response */ + memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params)); + wlan_params.packet = g_bufferIEEE80211; + wlan_params.length = responselength; + wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency; + + if (nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) { + capwap_logging_warning("Unable to send IEEE802.11 Authentication Response"); + return; + } - 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 Authentication Response"); + + /* Notify authentication message also to AC */ + wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength, 0); + } else if ((wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) && (responsestatuscode == IEEE80211_STATUS_SUCCESS)) { + wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength, 1); } } @@ -850,6 +865,39 @@ static int nl80211_set_station_information(struct nl80211_wlan_handle* wlanhandl return IEEE80211_STATUS_SUCCESS; } +/* */ +static void nl80211_do_mgmt_disassociation_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + + /* TODO */ + + /* Information Elements packet length */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->disassociation)); + if (ielength < 0) { + return; + } + + /* TODO */ + + /* Notify disassociation message also to AC */ + wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength, ((wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) ? 0 : 1)); +} + +/* */ +static void nl80211_do_mgmt_reassociation_request_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + + /* TODO */ + + /* Information Elements packet length */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationrequest)); + if (ielength < 0) { + return; + } + + /* TODO */ +} + /* */ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { int ielength; @@ -860,6 +908,12 @@ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle struct nl80211_station* station; uint16_t resultstatuscode = IEEE80211_STATUS_SUCCESS; + /* Information Elements packet length */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest)); + if (ielength < 0) { + return; + } + /* Get station reference */ station = nl80211_station_get(wlanhandle, mgmt->sa); if (!station || !(station->flags & NL80211_STATION_FLAGS_AUTHENTICATED)) { @@ -868,52 +922,69 @@ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle return; } - /* 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; } - /* */ 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); - 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; + /* */ + if (wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { + if (resultstatuscode == IEEE80211_STATUS_SUCCESS) { + if (wifi_aid_create(wlanhandle->aidbitfield, &station->aid)) { + resultstatuscode = IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + } + } - responselength = ieee80211_create_associationresponse_response(g_bufferIEEE80211, sizeof(g_bufferIEEE80211), &ieee80211_params); - if (responselength < 0) { - return; - } + /* Create association response 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.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; - /* Send authentication response */ - memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params)); - wlan_params.packet = g_bufferIEEE80211; - wlan_params.length = responselength; - wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency; + responselength = ieee80211_create_associationresponse_response(g_bufferIEEE80211, sizeof(g_bufferIEEE80211), &ieee80211_params); + if (responselength < 0) { + return; + } + + /* Send authentication response */ + memset(&wlan_params, 0, sizeof(struct wlan_send_frame_params)); + wlan_params.packet = g_bufferIEEE80211; + wlan_params.length = responselength; + wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency; + + if (nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) { + capwap_logging_warning("Unable to send IEEE802.11 Association Response"); + return; + } - 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"); + + /* Notify association request message also to AC */ + wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength, 0); + } else if ((wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) && (resultstatuscode == IEEE80211_STATUS_SUCCESS)) { + wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength, 1); } } /* */ static void nl80211_do_mgmt_deauthentication_event(struct nl80211_wlan_handle* wlanhandle, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; struct nl80211_station* station; + /* TODO */ + + /* Information Elements packet length */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->deauthetication)); + if (ielength < 0) { + return; + } + /* Get station reference */ station = nl80211_station_get(wlanhandle, mgmt->sa); if (!station) { @@ -922,6 +993,9 @@ static void nl80211_do_mgmt_deauthentication_event(struct nl80211_wlan_handle* w /* Free station */ nl80211_station_delete(wlanhandle, mgmt->sa); + + /* Notify deauthentication message also to AC */ + wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength, ((wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) ? 0 : 1)); } /* */ @@ -955,12 +1029,12 @@ static void nl80211_do_mgmt_frame_event(struct nl80211_wlan_handle* wlanhandle, } case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST: { - /* TODO */ + nl80211_do_mgmt_reassociation_request_event(wlanhandle, mgmt, mgmtlength); break; } case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION: { - /* TODO */ + nl80211_do_mgmt_disassociation_event(wlanhandle, mgmt, mgmtlength); break; } @@ -2285,6 +2359,8 @@ static int nl80211_wlan_startap(wifi_wlan_handle handle, struct wlan_startap_par wlanhandle->authenticationtype = ((params->authmode == CAPWAP_ADD_WLAN_AUTHTYPE_WEP) ? NL80211_AUTHTYPE_SHARED_KEY : NL80211_AUTHTYPE_OPEN_SYSTEM); wlanhandle->macmode = params->macmode; wlanhandle->tunnelmode = params->tunnelmode; + wlanhandle->send_mgmtframe = params->send_mgmtframe; + wlanhandle->send_mgmtframe_to_ac_cbparam = params->send_mgmtframe_to_ac_cbparam; /* Set beacon */ if (nl80211_wlan_setbeacon(wlanhandle)) { diff --git a/src/binding/ieee80211/wifi_nl80211.h b/src/binding/ieee80211/wifi_nl80211.h index 3d035af..26aed7b 100644 --- a/src/binding/ieee80211/wifi_nl80211.h +++ b/src/binding/ieee80211/wifi_nl80211.h @@ -96,6 +96,10 @@ struct nl80211_wlan_handle { uint64_t last_cookie; + /* */ + send_mgmtframe_to_ac send_mgmtframe; + void* send_mgmtframe_to_ac_cbparam; + /* WLAN information */ char ssid[WIFI_SSID_MAX_LENGTH + 1]; uint8_t ssid_hidden; diff --git a/src/wtp/wtp_radio.c b/src/wtp/wtp_radio.c index d4fc4d7..0bec7dd 100644 --- a/src/wtp/wtp_radio.c +++ b/src/wtp/wtp_radio.c @@ -49,6 +49,17 @@ static int wtp_radio_configure_phy(struct wtp_radio* radio) { return 0; } +/* */ +static void wtp_radio_send_mgmtframe_to_ac(void* param, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, int leavenativeframe) { + //struct wtp_radio_wlan* wlan = (struct wtp_radio_wlan*)mgmt; + + ASSERT(param != NULL); + ASSERT(mgmt != NULL); + ASSERT(mgmtlength > sizeof(struct ieee80211_header_mgmt)); + + /* TODO */ +} + /* */ unsigned long wtp_radio_acl_item_gethash(const void* key, unsigned long keysize, unsigned long hashsize) { uint8_t* macaddress = (uint8_t*)key; @@ -610,8 +621,17 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa itemwlanpool = capwap_itemlist_remove_head(radio->wlanpool); wlanpool = (struct wtp_radio_wlanpool*)itemwlanpool->item; + /* Create interface used */ + itemwlan = capwap_itemlist_create(sizeof(struct wtp_radio_wlan)); + wlan = (struct wtp_radio_wlan*)itemwlan->item; + wlan->wlanid = addwlan->wlanid; + wlan->wlanhandle = wlanpool->wlanhandle; + wlan->radio = wlanpool->radio; + /* Wlan configuration */ memset(¶ms, 0, sizeof(struct wlan_startap_params)); + params.send_mgmtframe = wtp_radio_send_mgmtframe_to_ac; + params.send_mgmtframe_to_ac_cbparam = (void*)wlan; params.ssid = (const char*)addwlan->ssid; params.ssid_hidden = addwlan->suppressssid; params.capability = addwlan->capability; @@ -623,18 +643,13 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa /* Start AP */ if (wifi_wlan_startap(wlanpool->wlanhandle, ¶ms)) { + /* Set interface to pool */ + capwap_itemlist_free(itemwlan); capwap_itemlist_insert_before(radio->wlanpool, NULL, itemwlanpool); return CAPWAP_RESULTCODE_FAILURE; } /* Move interface from pool to used */ - itemwlan = capwap_itemlist_create(sizeof(struct wtp_radio_wlan)); - wlan = (struct wtp_radio_wlan*)itemwlan->item; - wlan->wlanid = addwlan->wlanid; - wlan->wlanhandle = wlanpool->wlanhandle; - wlan->radio = wlanpool->radio; - - /* */ capwap_itemlist_free(itemwlanpool); capwap_itemlist_insert_after(radio->wlan, NULL, itemwlan);