From 3569267283b570aff3e3c4014f3c86e2e7171761 Mon Sep 17 00:00:00 2001 From: vemax78 Date: Mon, 14 Apr 2014 22:33:12 +0200 Subject: [PATCH] Big update with type fix and minor new function. Complete the IEEE802.11 Station Association with interation of AC in LocalMAC mode. After the IEEE802.11 Authorization / Association is complete, the AC can now authorize the WTP to accept data station packets with Station Configuration Message. --- src/ac/ac_80211_json_wtpradioconf.c | 2 +- src/ac/ac_backend.h | 32 -- src/ac/ac_dfa_run.c | 76 +++- src/ac/ac_execute.c | 6 +- src/ac/ac_ieee80211_data.c | 114 +++-- src/ac/ac_session.c | 124 ++++- src/ac/ac_session.h | 60 ++- src/ac/ac_session_data.c | 85 +++- src/ac/ac_wlans.c | 423 +++++++++++------- src/ac/ac_wlans.h | 47 +- src/binding/ieee80211/ieee80211.c | 26 +- src/binding/ieee80211/ieee80211.h | 16 +- src/binding/ieee80211/wifi_drivers.c | 27 ++ src/binding/ieee80211/wifi_drivers.h | 20 +- src/binding/ieee80211/wifi_nl80211.c | 158 ++++--- src/common/capwap_element.c | 11 +- src/common/capwap_element.h | 2 +- .../capwap_element_80211_miccountermeasures.c | 4 +- .../capwap_element_80211_miccountermeasures.h | 4 +- .../capwap_element_80211_rsnaerrorreport.c | 8 +- .../capwap_element_80211_rsnaerrorreport.h | 7 +- src/common/capwap_element_80211_station.c | 4 +- src/common/capwap_element_80211_station.h | 3 +- src/common/capwap_element_80211_stationkey.c | 4 +- src/common/capwap_element_80211_stationkey.h | 3 +- src/common/capwap_element_80211_stationqos.c | 4 +- src/common/capwap_element_80211_stationqos.h | 4 +- .../capwap_element_80211_updatestationqos.c | 2 +- .../capwap_element_80211_updatestationqos.h | 3 +- .../capwap_element_80211_wtpradioconf.c | 4 +- .../capwap_element_80211_wtpradioconf.h | 3 +- src/common/capwap_protocol.c | 6 +- src/common/capwap_protocol.h | 2 +- src/wtp/wtp_dfa.h | 2 +- src/wtp/wtp_dfa_run.c | 22 +- src/wtp/wtp_radio.c | 48 +- src/wtp/wtp_radio.h | 4 + 37 files changed, 969 insertions(+), 401 deletions(-) diff --git a/src/ac/ac_80211_json_wtpradioconf.c b/src/ac/ac_80211_json_wtpradioconf.c index 9a04f26..b119a0f 100644 --- a/src/ac/ac_80211_json_wtpradioconf.c +++ b/src/ac/ac_80211_json_wtpradioconf.c @@ -112,7 +112,7 @@ static void ac_json_80211_wtpradioconf_createjson(struct json_object* jsonparent json_object_object_add(jsonitem, "ShortPreamble", json_object_new_int((int)wtpradioconf->shortpreamble)); json_object_object_add(jsonitem, "NumBSSIDs", json_object_new_int((int)wtpradioconf->maxbssid)); json_object_object_add(jsonitem, "DTIMPeriod", json_object_new_int((int)wtpradioconf->dtimperiod)); - json_object_object_add(jsonitem, "BSSID", json_object_new_string(capwap_printf_macaddress(buffer, (unsigned char*)wtpradioconf->bssid, MACADDRESS_EUI48_LENGTH))); + json_object_object_add(jsonitem, "BSSID", json_object_new_string(capwap_printf_macaddress(buffer, wtpradioconf->bssid, MACADDRESS_EUI48_LENGTH))); json_object_object_add(jsonitem, "BeaconPeriod", json_object_new_int((int)wtpradioconf->beaconperiod)); json_object_object_add(jsonitem, "CountryString", json_object_new_string((char*)wtpradioconf->country)); json_object_object_add(jsonparent, "IEEE80211WTPRadioConfiguration", jsonitem); diff --git a/src/ac/ac_backend.h b/src/ac/ac_backend.h index f5027c6..9840a5f 100644 --- a/src/ac/ac_backend.h +++ b/src/ac/ac_backend.h @@ -10,38 +10,6 @@ #define SOAP_EVENT_STATUS_RUNNING 0 #define SOAP_EVENT_STATUS_COMPLETE 1 -/* Reset notification */ -struct ac_notify_reset_t { - uint32_t vendor; - uint8_t name[0]; -}; - -/* Add WLAN notification */ -struct ac_notify_addwlan_t { - uint8_t radioid; - uint8_t wlanid; - uint16_t capability; - uint8_t qos; - uint8_t authmode; - uint8_t macmode; - uint8_t tunnelmode; - uint8_t suppressssid; - char ssid[CAPWAP_ADD_WLAN_SSID_LENGTH + 1]; -}; - -/* Station Configuration IEEE802.11 add station notification */ -struct ac_notify_station_configuration_ieee8011_add_station { - uint8_t radioid; - uint8_t address[MACADDRESS_EUI48_LENGTH]; - uint8_t vlan[CAPWAP_ADDSTATION_VLAN_MAX_LENGTH]; - - uint8_t wlanid; - uint16_t associationid; - uint16_t capabilities; - uint8_t supportedratescount; - uint8_t supportedrates[CAPWAP_STATION_RATES_MAXLENGTH]; -}; - /* */ int ac_backend_start(void); void ac_backend_stop(void); diff --git a/src/ac/ac_dfa_run.c b/src/ac/ac_dfa_run.c index 7e68dcc..c6683f7 100644 --- a/src/ac/ac_dfa_run.c +++ b/src/ac/ac_dfa_run.c @@ -65,24 +65,16 @@ static int receive_echo_request(struct ac_session_t* session, struct capwap_pars /* */ static void execute_ieee80211_wlan_configuration_addwlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_80211_addwlan_element* addwlan, struct capwap_parsed_packet* requestpacket) { - char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; struct ac_wlan* wlan; struct capwap_80211_assignbssid_element* assignbssid; /* Get BSSID */ assignbssid = (struct capwap_80211_assignbssid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_ASSIGN_BSSID); if (assignbssid && (assignbssid->radioid == addwlan->radioid) && (assignbssid->wlanid == addwlan->wlanid)) { - if (!ac_wlans_get_bssid(session, assignbssid->radioid, assignbssid->bssid)) { - wlan = ac_wlans_create_bssid(session, assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid); - wlan->session = session; - wlan->sessiondata = session->sessiondata; + wlan = ac_wlans_create_bssid(assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid, addwlan); - /* Set capability */ - ac_wlans_set_bssid_capability(wlan, addwlan); - - /* */ - capwap_logging_info("Added new wlan with radioid: %d, wlanid: %d, bssid: %s", (int)assignbssid->radioid, (int)assignbssid->wlanid, capwap_printf_macaddress(buffer, assignbssid->bssid, MACADDRESS_EUI48_LENGTH)); - } + /* Assign BSSID to session */ + ac_session_data_send_action(session->sessiondata, AC_SESSION_DATA_ACTION_ASSIGN_BSSID, 0, &wlan, sizeof(struct ac_wlan*)); } } @@ -138,6 +130,64 @@ static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* s ac_free_reference_last_request(session); } +/* */ +static void execute_ieee80211_wlan_configuration_response_addstation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_addstation_element* addstation, struct capwap_parsed_packet* requestpacket) { + struct ac_notify_add_station_status notify; + struct capwap_80211_station_element* station80211; + unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header); + struct capwap_resultcode_element* resultcode; + + /* */ + resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE); + + /* */ + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION); + if (station80211) { + memset(¬ify, 0, sizeof(struct ac_notify_add_station_status)); + + notify.radioid = station80211->radioid; + notify.wlanid = station80211->wlanid; + memcpy(notify.address, addstation->address, MACADDRESS_EUI48_LENGTH); + notify.statuscode = resultcode->code; + + ac_session_data_send_action(session->sessiondata, AC_SESSION_DATA_ACTION_ADD_STATION_STATUS, 0, (void*)¬ify, sizeof(struct ac_notify_add_station_status)); + } + } +} + +/* */ +static void execute_ieee80211_wlan_configuration_response_deletestation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_deletestation_element* deletestation, struct capwap_parsed_packet* requestpacket) { + /* TODO */ +} + +/* */ +static void receive_ieee80211_station_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) { + struct capwap_packet_rxmng* rxmngrequestpacket; + struct capwap_parsed_packet requestpacket; + struct capwap_addstation_element* addstation; + struct capwap_deletestation_element* deletestation; + + /* Parsing request message */ + rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket); + if (capwap_parsing_packet(rxmngrequestpacket, NULL, &requestpacket) == PARSING_COMPLETE) { + addstation = (struct capwap_addstation_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ADDSTATION); + if (addstation) { + execute_ieee80211_wlan_configuration_response_addstation(session, packet, addstation, &requestpacket); + } else { + deletestation = (struct capwap_deletestation_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_DELETESTATION); + if (deletestation) { + execute_ieee80211_wlan_configuration_response_deletestation(session, packet, deletestation, &requestpacket); + } + } + } + + /* */ + capwap_free_parsed_packet(&requestpacket); + capwap_packet_rxmng_free(rxmngrequestpacket); + ac_free_reference_last_request(session); +} + /* */ void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) { ASSERT(session != NULL); @@ -198,9 +248,7 @@ void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* } case CAPWAP_STATION_CONFIGURATION_RESPONSE: { - /* TODO */ - - /* */ + receive_ieee80211_station_configuration_response(session, packet); capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL); break; } diff --git a/src/ac/ac_execute.c b/src/ac/ac_execute.c index 6980988..411e3d2 100644 --- a/src/ac/ac_execute.c +++ b/src/ac/ac_execute.c @@ -536,9 +536,6 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres session->count = 2; capwap_event_init(&session->changereference); - /* */ - ac_wlans_init(session); - /* */ session->timeout = capwap_timeout_init(); session->idtimercontrol = capwap_timeout_createtimer(session->timeout); @@ -621,6 +618,9 @@ static struct ac_session_data_t* ac_create_session_data(struct sockaddr_storage* sessiondata->count = 2; capwap_event_init(&sessiondata->changereference); + /* */ + ac_wlans_init(sessiondata); + /* */ sessiondata->timeout = capwap_timeout_init(); sessiondata->idtimercontrol = capwap_timeout_createtimer(sessiondata->timeout); diff --git a/src/ac/ac_ieee80211_data.c b/src/ac/ac_ieee80211_data.c index 813d802..d97a7b0 100644 --- a/src/ac/ac_ieee80211_data.c +++ b/src/ac/ac_ieee80211_data.c @@ -26,6 +26,7 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se int ielength; struct ieee80211_ie_items ieitems; struct ac_station* station; + char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; /* Parsing Information Elements */ ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication)); @@ -33,9 +34,13 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se return; } - /* Create station if sent by station */ - if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH)) { - station = ac_stations_create_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa); + /* */ + if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && !memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) { + station = ac_stations_create_station(sessiondata, radioid, mgmt->bssid, mgmt->sa); + + /* */ + capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH); + capwap_logging_info("Receive IEEE802.11 Authentication Request from %s station", buffer); /* */ if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { @@ -43,13 +48,30 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se } else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { /* TODO */ } - } else { - station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->da); - if (station) { - if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { - /* TODO */ - } else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { - /* TODO */ + } else if (!memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) { + station = ac_stations_get_station(sessiondata, radioid, mgmt->bssid, mgmt->da); + if (station && (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL)) { + uint16_t algorithm; + uint16_t transactionseqnumber; + uint16_t statuscode; + + /* */ + statuscode = __le16_to_cpu(mgmt->authetication.statuscode); + + /* */ + capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH); + capwap_logging_info("Receive IEEE802.11 Authentication Response to %s station with %d status code", buffer, (int)statuscode); + + if (statuscode == IEEE80211_STATUS_SUCCESS) { + algorithm = __le16_to_cpu(mgmt->authetication.algorithm); + transactionseqnumber = __le16_to_cpu(mgmt->authetication.transactionseqnumber); + + /* Check if authenticate */ + if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_OPEN) && (transactionseqnumber == 2)) { + station->flags |= AC_STATION_FLAGS_AUTHENTICATED; + } else if ((algorithm == IEEE80211_AUTHENTICATION_ALGORITHM_SHARED_KEY) && (transactionseqnumber == 4)) { + /* TODO */ + } } } } @@ -60,6 +82,7 @@ static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_ int ielength; struct ieee80211_ie_items ieitems; struct ac_station* station; + char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; /* Parsing Information Elements */ ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest)); @@ -68,22 +91,34 @@ static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_ } /* Get station */ - if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH)) { - station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa); + if (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && !memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) { + station = ac_stations_get_station(sessiondata, radioid, mgmt->bssid, mgmt->sa); /* */ - if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { - /* TODO */ - } else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { - /* TODO */ - } - } else { - station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->da); - if (station) { + capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH); + capwap_logging_info("Receive IEEE802.11 Association Request from %s station", buffer); + + /* Get Station Info */ + station->capability = __le16_to_cpu(mgmt->associationrequest.capability); + station->listeninterval = __le16_to_cpu(mgmt->associationrequest.listeninterval); + + /* Get supported rates */ + if (ieitems.supported_rates && ((ieitems.supported_rates->len + (ieitems.extended_supported_rates ? ieitems.extended_supported_rates->len : 0)) <= sizeof(station->supportedrates))) { + 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); + } + + /* */ if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { /* TODO */ } else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { /* TODO */ + + /* Active Station */ + ac_stations_authorize_station(sessiondata, station); } } } @@ -94,6 +129,7 @@ static void ac_ieee80211_mgmt_association_response_packet(struct ac_session_data int ielength; struct ieee80211_ie_items ieitems; struct ac_station* station; + char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; /* Parsing Information Elements */ ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->associationresponse)); @@ -102,13 +138,32 @@ static void ac_ieee80211_mgmt_association_response_packet(struct ac_session_data } /* Get station */ - station = ac_stations_get_station(sessiondata->session, radioid, mgmt->bssid, mgmt->sa); + if (!memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) && memcmp(mgmt->bssid, mgmt->da, MACADDRESS_EUI48_LENGTH)) { + station = ac_stations_get_station(sessiondata, radioid, mgmt->bssid, mgmt->da); + if (station && (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL)) { + capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH); + capwap_logging_info("Receive IEEE802.11 Association Response to %s station with %d status code", buffer, (int)mgmt->associationresponse.statuscode); - /* */ - if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { - /* TODO */ - } else if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { - /* TODO */ + if (mgmt->associationresponse.statuscode == IEEE80211_STATUS_SUCCESS) { + /* Get Station Info */ + station->capability = __le16_to_cpu(mgmt->associationresponse.capability); + station->aid = __le16_to_cpu(mgmt->associationresponse.aid); + station->flags |= AC_STATION_FLAGS_ASSOCIATE; + + /* Get supported rates */ + if (ieitems.supported_rates && ((ieitems.supported_rates->len + (ieitems.extended_supported_rates ? ieitems.extended_supported_rates->len : 0)) <= sizeof(station->supportedrates))) { + 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); + } + + /* Active Station */ + ac_stations_authorize_station(sessiondata, station); + } + } + } } } @@ -158,6 +213,7 @@ static void ac_ieee80211_mgmt_disassociation_packet(struct ac_session_data_t* se static void ac_ieee80211_mgmt_deauthentication_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { int ielength; const uint8_t* stationaddress; + struct ac_station* station; struct ieee80211_ie_items ieitems; /* Parsing Information Elements */ @@ -170,7 +226,11 @@ static void ac_ieee80211_mgmt_deauthentication_packet(struct ac_session_data_t* stationaddress = (memcmp(mgmt->bssid, mgmt->sa, MACADDRESS_EUI48_LENGTH) ? mgmt->sa : mgmt->da); /* Delete station */ - ac_stations_delete_station(sessiondata->session, stationaddress); + station = ac_stations_get_station(sessiondata, radioid, NULL, stationaddress); + if (station) { + station->flags &= ~(AC_STATION_FLAGS_AUTHORIZED | AC_STATION_FLAGS_AUTHENTICATED | AC_STATION_FLAGS_ASSOCIATE); + ac_stations_delete_station(sessiondata, station); + } } /* */ diff --git a/src/ac/ac_session.c b/src/ac/ac_session.c index d6835c2..91e5815 100644 --- a/src/ac/ac_session.c +++ b/src/ac/ac_session.c @@ -3,7 +3,6 @@ #include "capwap_dfa.h" #include "ac_session.h" #include "ac_backend.h" -#include "ac_wlans.h" #include #define AC_ERROR_TIMEOUT -1000 @@ -44,7 +43,7 @@ static int ac_session_action_resetwtp(struct ac_session_t* session, struct ac_no ac_dfa_change_state(session, CAPWAP_RESET_STATE); capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL); } else { - capwap_logging_debug("Warning: error to send reset request packet"); + capwap_logging_debug("Warning: error to send Reset Request packet"); ac_free_reference_last_request(session); ac_session_teardown(session); } @@ -63,8 +62,10 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not /* Check if WLAN id is valid and not used */ if (!IS_VALID_RADIOID(notify->radioid) || !IS_VALID_WLANID(notify->wlanid)) { return AC_ERROR_ACTION_SESSION; +#if 0 } else if (ac_wlans_get_bssid_with_wlanid(session, notify->radioid, notify->wlanid)) { return AC_ERROR_ACTION_SESSION; +#endif } /* */ @@ -104,7 +105,7 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not session->retransmitcount = 0; capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL); } else { - capwap_logging_debug("Warning: error to send reset request packet"); + capwap_logging_debug("Warning: error to send WLAN Configuration Request packet"); ac_free_reference_last_request(session); ac_session_teardown(session); } @@ -114,8 +115,115 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not /* */ static int ac_session_action_station_configuration_ieee8011_add_station(struct ac_session_t* session, struct ac_notify_station_configuration_ieee8011_add_station* notify) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + struct capwap_addstation_element addstation; + struct capwap_80211_station_element station; + ASSERT(session->requestfragmentpacket->count == 0); + /* Check if RADIO id and WLAN id is valid */ + if (!IS_VALID_RADIOID(notify->radioid) || !IS_VALID_WLANID(notify->wlanid)) { + return AC_ERROR_ACTION_SESSION; + } + + /* */ + memset(&addstation, 0, sizeof(struct capwap_addstation_element)); + addstation.radioid = notify->radioid; + addstation.length = MACADDRESS_EUI48_LENGTH; + addstation.address = notify->address; + if (notify->vlan[0]) { + addstation.vlan = notify->vlan; + } + + /* */ + memset(&station, 0, sizeof(struct capwap_80211_station_element)); + station.radioid = notify->radioid; + station.associationid = notify->associationid; + memcpy(station.address, notify->address, MACADDRESS_EUI48_LENGTH); + station.capabilities = notify->capabilities; + station.wlanid = notify->wlanid; + station.supportedratescount = notify->supportedratescount; + memcpy(station.supportedrates, notify->supportedrates, station.supportedratescount); + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_STATION_CONFIGURATION_REQUEST, session->localseqnumber++, session->mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ADDSTATION, &addstation); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_STATION, &station); + + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + + /* Station Configuration Request complete, get fragment packets */ + capwap_packet_txmng_get_fragment_packets(txmngpacket, session->requestfragmentpacket, session->fragmentid); + if (session->requestfragmentpacket->count > 1) { + session->fragmentid++; + } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Send Station Configuration Request to WTP */ + if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) { + session->retransmitcount = 0; + capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL); + } else { + capwap_logging_debug("Warning: error to send Station Configuration Request packet"); + ac_free_reference_last_request(session); + ac_session_teardown(session); + } + + return AC_ERROR_ACTION_SESSION; +} + +/* */ +static int ac_session_action_station_configuration_ieee8011_delete_station(struct ac_session_t* session, struct ac_notify_station_configuration_ieee8011_delete_station* notify) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + struct capwap_deletestation_element deletestation; + + ASSERT(session->requestfragmentpacket->count == 0); + + /* Check if RADIO id is valid */ + if (!IS_VALID_RADIOID(notify->radioid)) { + return AC_ERROR_ACTION_SESSION; + } + + /* */ + memset(&deletestation, 0, sizeof(struct capwap_deletestation_element)); + deletestation.radioid = notify->radioid; + deletestation.length = MACADDRESS_EUI48_LENGTH; + deletestation.address = notify->address; + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_STATION_CONFIGURATION_REQUEST, session->localseqnumber++, session->mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_DELETESTATION, &deletestation); + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + + /* Station Configuration Request complete, get fragment packets */ + capwap_packet_txmng_get_fragment_packets(txmngpacket, session->requestfragmentpacket, session->fragmentid); + if (session->requestfragmentpacket->count > 1) { + session->fragmentid++; + } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Send Station Configuration Request to WTP */ + if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) { + session->retransmitcount = 0; + capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL); + } else { + capwap_logging_debug("Warning: error to send Station Configuration Request packet"); + ac_free_reference_last_request(session); + ac_session_teardown(session); + } + return AC_ERROR_ACTION_SESSION; } @@ -177,12 +285,7 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses } case AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION: { - break; - } - - case AC_SESSION_ACTION_ROAMING_STATION: { - /* Delete station */ - ac_stations_delete_station(session, (uint8_t*)action->data); + result = ac_session_action_station_configuration_ieee8011_delete_station(session, (struct ac_notify_station_configuration_ieee8011_delete_station*)action->data); break; } } @@ -427,9 +530,6 @@ static void ac_session_destroy(struct ac_session_t* session) { capwap_itemlist_free(capwap_itemlist_remove_head(session->packets)); } - /* Free WLANS */ - ac_wlans_destroy(session); - /* */ capwap_event_destroy(&session->changereference); capwap_event_destroy(&session->waitpacket); diff --git a/src/ac/ac_session.h b/src/ac/ac_session.h index 12cc00f..e86ddab 100644 --- a/src/ac/ac_session.h +++ b/src/ac/ac_session.h @@ -27,7 +27,9 @@ struct ac_session_control { #define AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION 5 #define AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION 6 -#define AC_SESSION_ACTION_ROAMING_STATION 10 +#define AC_SESSION_DATA_ACTION_ROAMING_STATION 1 +#define AC_SESSION_DATA_ACTION_ASSIGN_BSSID 2 +#define AC_SESSION_DATA_ACTION_ADD_STATION_STATUS 3 /* */ struct ac_session_action { @@ -52,6 +54,52 @@ struct ac_session_notify_event_t { }; }; +/* Reset notification */ +struct ac_notify_reset_t { + uint32_t vendor; + uint8_t name[0]; +}; + +/* Add WLAN notification */ +struct ac_notify_addwlan_t { + uint8_t radioid; + uint8_t wlanid; + uint16_t capability; + uint8_t qos; + uint8_t authmode; + uint8_t macmode; + uint8_t tunnelmode; + uint8_t suppressssid; + char ssid[CAPWAP_ADD_WLAN_SSID_LENGTH + 1]; +}; + +/* Station Configuration IEEE802.11 add station notification */ +struct ac_notify_station_configuration_ieee8011_add_station { + uint8_t radioid; + uint8_t address[MACADDRESS_EUI48_LENGTH]; + uint8_t vlan[CAPWAP_ADDSTATION_VLAN_MAX_LENGTH]; + + uint8_t wlanid; + uint16_t associationid; + uint16_t capabilities; + uint8_t supportedratescount; + uint8_t supportedrates[CAPWAP_STATION_RATES_MAXLENGTH]; +}; + +/* Station Configuration IEEE802.11 delete station notification */ +struct ac_notify_station_configuration_ieee8011_delete_station { + uint8_t radioid; + uint8_t address[MACADDRESS_EUI48_LENGTH]; +}; + +/* */ +struct ac_notify_add_station_status { + uint8_t radioid; + uint8_t wlanid; + uint8_t address[MACADDRESS_EUI48_LENGTH]; + uint16_t statuscode; +}; + /* */ struct ac_session_t; struct ac_session_data_t; @@ -66,8 +114,13 @@ struct ac_session_data_t { long count; capwap_event_t changereference; + /* WLAN Reference */ + struct ac_wlans* wlans; + + /* */ int enabledtls; unsigned short mtu; + unsigned short fragmentid; struct capwap_connection connection; struct capwap_dtls dtls; @@ -96,9 +149,6 @@ struct ac_session_t { long count; capwap_event_t changereference; - /* WLAN Reference */ - struct ac_wlans* wlans; - /* Soap */ struct ac_http_soap_request* soaprequest; @@ -149,6 +199,8 @@ void ac_session_data_close(struct ac_session_data_t* sessiondata); void ac_session_data_send_action(struct ac_session_data_t* sessiondata, long action, long param, void* data, long length); void ac_session_data_release_reference(struct ac_session_data_t* sessiondata); +void ac_session_data_send_data_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe); + /* IEEE802.11 Packet */ void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* buffer, int length); diff --git a/src/ac/ac_session_data.c b/src/ac/ac_session_data.c index ee255fc..dcf12d5 100644 --- a/src/ac/ac_session_data.c +++ b/src/ac/ac_session_data.c @@ -1,6 +1,7 @@ #include "ac.h" #include "capwap_dfa.h" #include "ac_session.h" +#include "ac_wlans.h" #include "ieee80211.h" #include @@ -9,11 +10,53 @@ #define AC_BODY_PACKET_MAX_SIZE 8192 +/* */ +static int ac_session_data_action_add_station_status(struct ac_session_data_t* sessiondata, struct ac_notify_add_station_status* notify) { + struct ac_wlan* wlan; + struct ac_station* station; + + wlan = ac_wlans_get_bssid_with_wlanid(sessiondata, notify->radioid, notify->wlanid); + if (wlan) { + station = ac_stations_get_station(sessiondata, notify->radioid, wlan->bssid, notify->address); + if (station) { + if (CAPWAP_RESULTCODE_OK(notify->statuscode)) { + station->flags |= AC_STATION_FLAGS_AUTHORIZED; + } else { + ac_stations_delete_station(sessiondata, station); + } + } + } + + return AC_ERROR_ACTION_SESSION; +} + /* */ static int ac_session_data_action_execute(struct ac_session_data_t* sessiondata, struct ac_session_action* action) { int result = AC_ERROR_ACTION_SESSION; - /* TODO */ + switch (action->action) { + case AC_SESSION_DATA_ACTION_ROAMING_STATION: { + struct ac_station* station; + + /* Delete station */ + station = ac_stations_get_station(sessiondata, RADIOID_ANY, NULL, (uint8_t*)action->data); + if (station) { + ac_stations_delete_station(sessiondata, station); + } + + break; + } + + case AC_SESSION_DATA_ACTION_ASSIGN_BSSID: { + ac_wlans_assign_bssid(sessiondata, *(struct ac_wlan**)action->data); + break; + } + + case AC_SESSION_DATA_ACTION_ADD_STATION_STATUS: { + result = ac_session_data_action_add_station_status(sessiondata, (struct ac_notify_add_station_status*)action->data); + break; + } + } return result; } @@ -178,7 +221,7 @@ static int ac_session_data_keepalive(struct ac_session_data_t* sessiondata, stru /* Data keepalive complete, get fragment packets into local list */ txfragpacket = capwap_list_create(); - capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, 0); + capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, sessiondata->fragmentid); if (txfragpacket->count == 1) { /* Send Data keepalive to WTP */ if (capwap_crypt_sendto_fragmentpacket(&sessiondata->dtls, sessiondata->connection.socket.socket[sessiondata->connection.socket.type], txfragpacket, &sessiondata->connection.localaddr, &sessiondata->connection.remoteaddr)) { @@ -244,6 +287,9 @@ static void ac_session_data_destroy(struct ac_session_data_t* sessiondata) { /* Free DTLS */ capwap_crypt_freesession(&sessiondata->dtls); + /* Free WLANS */ + ac_wlans_destroy(sessiondata); + /* Free resource */ while (sessiondata->packets->count > 0) { capwap_itemlist_free(capwap_itemlist_remove_head(sessiondata->packets)); @@ -421,3 +467,38 @@ void* ac_session_data_thread(void* param) { pthread_exit(NULL); return NULL; } + +/* */ +void ac_session_data_send_data_packet(struct ac_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe) { + struct capwap_list* txfragpacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + + /* Build packet */ + capwap_header_init(&capwapheader, radioid, sessiondata->session->binding); + capwap_header_set_nativeframe_flag(&capwapheader, (leavenativeframe ? 1: 0)); + txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, sessiondata->mtu); + + /* */ + if (leavenativeframe) { + capwap_packet_txmng_add_data(txmngpacket, data, length); + } else { + /* TODO */ + } + + /* Data message complete, get fragment packets into local list */ + txfragpacket = capwap_list_create(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, sessiondata->fragmentid); + if (txfragpacket->count > 1) { + sessiondata->fragmentid++; + } + + /* */ + if (!capwap_crypt_sendto_fragmentpacket(&sessiondata->dtls, sessiondata->connection.socket.socket[sessiondata->connection.socket.type], txfragpacket, &sessiondata->connection.localaddr, &sessiondata->connection.remoteaddr)) { + capwap_logging_debug("Warning: error to send data packet"); + } + + /* Free packets manager */ + capwap_list_free(txfragpacket); + capwap_packet_txmng_free(txmngpacket); +} diff --git a/src/ac/ac_wlans.c b/src/ac/ac_wlans.c index d8bd0bb..2cf34dd 100644 --- a/src/ac/ac_wlans.c +++ b/src/ac/ac_wlans.c @@ -1,20 +1,21 @@ #include "ac.h" #include "ac_session.h" #include "ac_wlans.h" +#include "ac_backend.h" /* */ -static void ac_stations_delete_station_from_global_cache(struct ac_session_t* session, uint8_t* address) { - struct ac_session_t* ownersession; +static void ac_stations_delete_station_from_global_cache(struct ac_session_data_t* sessiondata, uint8_t* address) { + struct ac_session_data_t* ownersession; - ASSERT(session != NULL); + ASSERT(sessiondata != NULL); ASSERT(address != NULL); /* */ capwap_rwlock_wrlock(&g_ac.stationslock); /* Can delete global reference only if match session handler */ - ownersession = (struct ac_session_t*)capwap_hash_search(g_ac.stations, address); - if (ownersession == session) { + ownersession = (struct ac_session_data_t*)capwap_hash_search(g_ac.stations, address); + if (ownersession == sessiondata) { capwap_hash_delete(g_ac.stations, address); } @@ -22,17 +23,17 @@ static void ac_stations_delete_station_from_global_cache(struct ac_session_t* se } /* */ -static void ac_stations_destroy_station(struct ac_session_t* session, struct ac_station* station) { +static void ac_stations_destroy_station(struct ac_session_data_t* sessiondata, struct ac_station* station) { char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; - ASSERT(session != NULL); + ASSERT(sessiondata != NULL); ASSERT(station != NULL); /* */ capwap_logging_info("Destroy station: %s", capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH)); /* Remove reference from Global Cache Stations List */ - ac_stations_delete_station_from_global_cache(session, station->address); + ac_stations_delete_station_from_global_cache(sessiondata, station->address); /* Remove reference from WLAN */ if (station->wlan) { @@ -40,7 +41,7 @@ static void ac_stations_destroy_station(struct ac_session_t* session, struct ac_ } /* */ - capwap_hash_delete(session->wlans->stations, station->address); + capwap_hash_delete(sessiondata->wlans->stations, station->address); /* Free station reference with itemlist */ capwap_itemlist_free(station->wlanitem); @@ -65,39 +66,42 @@ static void ac_stations_reset_station(struct ac_station* station, struct ac_wlan capwap_itemlist_remove(station->wlan->stations, station->wlanitem); } + /* */ + station->flags = 0; + /* Set WLAN */ station->wlan = wlan; capwap_itemlist_insert_after(wlan->stations, NULL, station->wlanitem); } /* */ -void ac_wlans_init(struct ac_session_t* session) { - ASSERT(session != NULL); +void ac_wlans_init(struct ac_session_data_t* sessiondata) { + ASSERT(sessiondata != NULL); /* */ - session->wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans)); - memset(session->wlans, 0, sizeof(struct ac_wlans)); + sessiondata->wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans)); + memset(sessiondata->wlans, 0, sizeof(struct ac_wlans)); /* */ - session->wlans->stations = capwap_hash_create(AC_WLANS_STATIONS_HASH_SIZE, AC_WLANS_STATIONS_KEY_SIZE, ac_wlans_item_gethash, NULL, NULL); + sessiondata->wlans->stations = capwap_hash_create(AC_WLANS_STATIONS_HASH_SIZE, AC_WLANS_STATIONS_KEY_SIZE, ac_wlans_item_gethash, NULL, NULL); } /* */ -void ac_wlans_destroy(struct ac_session_t* session) { +void ac_wlans_destroy(struct ac_session_data_t* sessiondata) { int i; struct capwap_list* items; - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); /* */ for (i = 0; i < RADIOID_MAX_COUNT; i++) { - if (session->wlans->wlans[i]) { - items = session->wlans->wlans[i]; + if (sessiondata->wlans->wlans[i]) { + items = sessiondata->wlans->wlans[i]; /* Delete WLANS */ while (items->first) { - ac_wlans_delete_bssid(session, i + 1, ((struct ac_wlan*)items->first->item)->bssid); + ac_wlans_delete_bssid(sessiondata, i + 1, ((struct ac_wlan*)items->first->item)->bssid); } /* */ @@ -106,20 +110,50 @@ void ac_wlans_destroy(struct ac_session_t* session) { } /* */ - ASSERT(session->wlans->stations->count == 0); + ASSERT(sessiondata->wlans->stations->count == 0); /* */ - capwap_hash_free(session->wlans->stations); - capwap_free(session->wlans); + capwap_hash_free(sessiondata->wlans->stations); + capwap_free(sessiondata->wlans); } /* */ -struct ac_wlan* ac_wlans_create_bssid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid) { +int ac_wlans_assign_bssid(struct ac_session_data_t* sessiondata, struct ac_wlan* wlan) { + char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; + + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); + ASSERT(wlan != NULL); + ASSERT(IS_VALID_RADIOID(wlan->radioid)); + ASSERT(IS_VALID_WLANID(wlan->wlanid)); + + /* */ + if (ac_wlans_get_bssid(sessiondata, wlan->radioid, wlan->bssid)) { + return 0; + } + + /* */ + wlan->session = sessiondata->session; + wlan->sessiondata = sessiondata; + + /* Create WLAN list */ + if (!sessiondata->wlans->wlans[wlan->radioid - 1]) { + sessiondata->wlans->wlans[wlan->radioid - 1] = capwap_list_create(); + } + + /* Append WLAN to list */ + capwap_itemlist_insert_after(sessiondata->wlans->wlans[wlan->radioid - 1], NULL, wlan->wlanitem); + + /* */ + capwap_logging_info("Added new wlan with radioid: %d, wlanid: %d, bssid: %s", (int)wlan->radioid, (int)wlan->wlanid, capwap_printf_macaddress(buffer, wlan->bssid, MACADDRESS_EUI48_LENGTH)); + return 1; +} + +/* */ +struct ac_wlan* ac_wlans_create_bssid(uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, struct capwap_80211_addwlan_element* addwlan) { struct ac_wlan* wlan; struct capwap_list_item* wlanitem; - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); ASSERT(IS_VALID_RADIOID(radioid)); ASSERT(IS_VALID_WLANID(wlanid)); ASSERT(bssid != NULL); @@ -130,132 +164,13 @@ struct ac_wlan* ac_wlans_create_bssid(struct ac_session_t* session, uint8_t radi memset(wlan, 0, sizeof(struct ac_wlan)); /* Init WLAN */ + wlan->wlanitem = wlanitem; memcpy(wlan->bssid, bssid, MACADDRESS_EUI48_LENGTH); wlan->radioid = radioid; wlan->wlanid = wlanid; wlan->stations = capwap_list_create(); - /* Create WLAN list */ - if (!session->wlans->wlans[radioid - 1]) { - session->wlans->wlans[radioid - 1] = capwap_list_create(); - } - - /* Append WLAN to list */ - capwap_itemlist_insert_after(session->wlans->wlans[radioid - 1], NULL, wlanitem); - - return wlan; -} - -/* */ -struct ac_wlan* ac_wlans_get_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid) { - struct capwap_list_item* search; - struct ac_wlan* wlan = NULL; - - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); - ASSERT(IS_VALID_RADIOID(radioid)); - ASSERT(bssid != NULL); - - /* */ - if (session->wlans->wlans[radioid - 1]) { - search = session->wlans->wlans[radioid - 1]->first; - while (search) { - struct ac_wlan* item = (struct ac_wlan*)search->item; - - if (!memcmp(bssid, item->bssid, MACADDRESS_EUI48_LENGTH)) { - wlan = item; - break; - } - - /* Next */ - search = search->next; - } - } - - return wlan; -} - -/* */ -struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid) { - struct capwap_list_item* search; - struct ac_wlan* wlan = NULL; - - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); - ASSERT(IS_VALID_RADIOID(radioid)); - ASSERT(IS_VALID_WLANID(wlanid)); - - /* */ - if (session->wlans->wlans[radioid - 1]) { - search = session->wlans->wlans[radioid - 1]->first; - while (search) { - struct ac_wlan* item = (struct ac_wlan*)search->item; - - if (wlanid == item->wlanid) { - wlan = item; - break; - } - - /* Next */ - search = search->next; - } - } - - return wlan; -} - -/* */ -static void ac_wlans_destroy_bssid(struct ac_session_t* session, struct ac_wlan* wlan) { - /* Free capability */ - if (wlan->key) { - capwap_free(wlan->key); - } - - if (wlan->ssid) { - capwap_free(wlan->ssid); - } - - /* Remove stations */ - while (wlan->stations->first) { - ac_stations_destroy_station(session, (struct ac_station*)wlan->stations->first->item); - } - - /* */ - capwap_list_free(wlan->stations); -} - -/* */ -void ac_wlans_delete_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid) { - struct capwap_list_item* search; - - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); - ASSERT(IS_VALID_RADIOID(radioid)); - ASSERT(bssid != NULL); - - /* */ - if (session->wlans->wlans[radioid - 1]) { - search = session->wlans->wlans[radioid - 1]->first; - while (search) { - struct ac_wlan* item = (struct ac_wlan*)search->item; - - if (!memcmp(bssid, item->bssid, MACADDRESS_EUI48_LENGTH)) { - ac_wlans_destroy_bssid(session, item); - capwap_itemlist_free(capwap_itemlist_remove(session->wlans->wlans[radioid - 1], search)); - break; - } - - /* Next */ - search = search->next; - } - } -} - -/* */ -void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_addwlan_element* addwlan) { - ASSERT(wlan != NULL); - ASSERT(addwlan != NULL); - + /* Set capability */ wlan->capability = addwlan->capability; wlan->keyindex = addwlan->keyindex; @@ -274,21 +189,126 @@ void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_add wlan->suppressssid = addwlan->suppressssid; wlan->ssid = (uint8_t*)capwap_duplicate_string((const char*)addwlan->ssid); + + return wlan; } /* */ -struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) { - struct ac_station* station; +struct ac_wlan* ac_wlans_get_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid) { + struct capwap_list_item* search; + struct ac_wlan* wlan = NULL; - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); ASSERT(IS_VALID_RADIOID(radioid)); ASSERT(bssid != NULL); + + /* */ + if (sessiondata->wlans->wlans[radioid - 1]) { + search = sessiondata->wlans->wlans[radioid - 1]->first; + while (search) { + struct ac_wlan* item = (struct ac_wlan*)search->item; + + if (!memcmp(bssid, item->bssid, MACADDRESS_EUI48_LENGTH)) { + wlan = item; + break; + } + + /* Next */ + search = search->next; + } + } + + return wlan; +} + +/* */ +struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid) { + struct capwap_list_item* search; + struct ac_wlan* wlan = NULL; + + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); + ASSERT(IS_VALID_RADIOID(radioid)); + ASSERT(IS_VALID_WLANID(wlanid)); + + /* */ + if (sessiondata->wlans->wlans[radioid - 1]) { + search = sessiondata->wlans->wlans[radioid - 1]->first; + while (search) { + struct ac_wlan* item = (struct ac_wlan*)search->item; + + if (wlanid == item->wlanid) { + wlan = item; + break; + } + + /* Next */ + search = search->next; + } + } + + return wlan; +} + +/* */ +static void ac_wlans_destroy_bssid(struct ac_session_data_t* sessiondata, struct ac_wlan* wlan) { + /* Free capability */ + if (wlan->key) { + capwap_free(wlan->key); + } + + if (wlan->ssid) { + capwap_free(wlan->ssid); + } + + /* Remove stations */ + while (wlan->stations->first) { + ac_stations_destroy_station(sessiondata, (struct ac_station*)wlan->stations->first->item); + } + + /* */ + capwap_list_free(wlan->stations); +} + +/* */ +void ac_wlans_delete_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid) { + struct capwap_list_item* search; + + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); + ASSERT(IS_VALID_RADIOID(radioid)); + ASSERT(bssid != NULL); + + /* */ + if (sessiondata->wlans->wlans[radioid - 1]) { + search = sessiondata->wlans->wlans[radioid - 1]->first; + while (search) { + struct ac_wlan* item = (struct ac_wlan*)search->item; + + if (!memcmp(bssid, item->bssid, MACADDRESS_EUI48_LENGTH)) { + ac_wlans_destroy_bssid(sessiondata, item); + capwap_itemlist_free(capwap_itemlist_remove(sessiondata->wlans->wlans[radioid - 1], search)); + break; + } + + /* Next */ + search = search->next; + } + } +} + +/* */ +struct ac_station* ac_stations_get_station(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) { + struct ac_station* station; + + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); ASSERT(address != NULL); /* Get station */ - station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address); - if (station && (radioid == station->wlan->radioid) && !memcmp(bssid, station->wlan->bssid, MACADDRESS_EUI48_LENGTH)) { + station = (struct ac_station*)capwap_hash_search(sessiondata->wlans->stations, address); + if (station && ((radioid == RADIOID_ANY) || (radioid == station->wlan->radioid)) && (!bssid || !memcmp(bssid, station->wlan->bssid, MACADDRESS_EUI48_LENGTH))) { return station; } @@ -296,16 +316,16 @@ struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t } /* */ -struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) { +struct ac_station* ac_stations_create_station(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid, const uint8_t* address) { char buffer1[CAPWAP_MACADDRESS_EUI48_BUFFER]; char buffer2[CAPWAP_MACADDRESS_EUI48_BUFFER]; struct ac_wlan* wlan; - struct ac_session_t* ownersession; + struct ac_session_data_t* ownersession; struct ac_station* station; struct capwap_list_item* stationitem; - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); ASSERT(IS_VALID_RADIOID(radioid)); ASSERT(bssid != NULL); ASSERT(address != NULL); @@ -317,25 +337,25 @@ struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint /* Get session that owns the station */ capwap_rwlock_rdlock(&g_ac.stationslock); - ownersession = (struct ac_session_t*)capwap_hash_search(g_ac.stations, address); + ownersession = (struct ac_session_data_t*)capwap_hash_search(g_ac.stations, address); capwap_rwlock_exit(&g_ac.stationslock); /* If request change owner of station */ - if (ownersession != session) { + if (ownersession != sessiondata) { /* Release station from old owner */ if (ownersession) { - ac_session_send_action(ownersession, AC_SESSION_ACTION_ROAMING_STATION, 0, (void*)address, MACADDRESS_EUI48_LENGTH); + ac_session_data_send_action(ownersession, AC_SESSION_DATA_ACTION_ROAMING_STATION, 0, (void*)address, MACADDRESS_EUI48_LENGTH); } /* Set station into Global Cache Stations List */ capwap_rwlock_wrlock(&g_ac.stationslock); - capwap_hash_add(g_ac.stations, address, session); + capwap_hash_add(g_ac.stations, address, sessiondata); capwap_rwlock_exit(&g_ac.stationslock); } /* */ - wlan = ac_wlans_get_bssid(session, radioid, bssid); - station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address); + wlan = ac_wlans_get_bssid(sessiondata, radioid, bssid); + station = ac_stations_get_station(sessiondata, RADIOID_ANY, NULL, address); if (!station) { stationitem = capwap_itemlist_create(sizeof(struct ac_station)); station = (struct ac_station*)stationitem->item; @@ -346,7 +366,7 @@ struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint station->wlanitem = stationitem; /* */ - capwap_hash_add(session->wlans->stations, address, station); + capwap_hash_add(sessiondata->wlans->stations, address, station); } /* Set station to WLAN */ @@ -356,16 +376,73 @@ struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint } /* */ -void ac_stations_delete_station(struct ac_session_t* session, const uint8_t* address) { - struct ac_station* station; +void ac_stations_delete_station(struct ac_session_data_t* sessiondata, struct ac_station* station) { + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); + ASSERT(station != NULL); - ASSERT(session != NULL); - ASSERT(session->wlans != NULL); - ASSERT(address != NULL); + /* Deauthorize station */ + ac_stations_deauthorize_station(sessiondata, station); - /* Delete station */ - station = (struct ac_station*)capwap_hash_search(session->wlans->stations, address); - if (station) { - ac_stations_destroy_station(session, station); + /* Destroy station reference */ + ac_stations_destroy_station(sessiondata, station); +} + +/* */ +void ac_stations_authorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station) { + struct ac_notify_station_configuration_ieee8011_add_station notify; + + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); + ASSERT(station != NULL); + + /* Active Station only if Authenticated, Associated and not Authrizated */ + if ((station->flags & AC_STATION_FLAGS_AUTHENTICATED) && (station->flags & AC_STATION_FLAGS_ASSOCIATE) && !(station->flags & AC_STATION_FLAGS_AUTHORIZED)) { + memset(¬ify, 0, sizeof(struct ac_notify_station_configuration_ieee8011_add_station)); + notify.radioid = station->wlan->radioid; + memcpy(notify.address, station->address, MACADDRESS_EUI48_LENGTH); + notify.wlanid = station->wlan->wlanid; + notify.associationid = station->aid; + notify.capabilities = station->capability; + notify.supportedratescount = station->supportedratescount; + memcpy(notify.supportedrates, station->supportedrates, station->supportedratescount); + + ac_session_send_action(sessiondata->session, AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION, 0, ¬ify, sizeof(struct ac_notify_station_configuration_ieee8011_add_station)); + } +} + +/* */ +void ac_stations_deauthorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station) { + int responselength; + uint8_t buffer[IEEE80211_MTU]; + struct ieee80211_deauthentication_params ieee80211_params; + struct ac_notify_station_configuration_ieee8011_delete_station notify; + + ASSERT(sessiondata != NULL); + ASSERT(sessiondata->wlans != NULL); + ASSERT(station != NULL); + + /* Delete Station only if Authrizated */ + if (station->flags & AC_STATION_FLAGS_AUTHORIZED) { + memset(¬ify, 0, sizeof(struct ac_notify_station_configuration_ieee8011_delete_station)); + notify.radioid = station->wlan->radioid; + memcpy(notify.address, station->address, MACADDRESS_EUI48_LENGTH); + + /* Request recall ac_stations_deauthorize_station for deauthentication the station */ + station->flags &= ~AC_STATION_FLAGS_AUTHORIZED; + ac_session_send_action(sessiondata->session, AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION, 0, ¬ify, sizeof(struct ac_notify_station_configuration_ieee8011_delete_station)); + } else if (station->flags & AC_STATION_FLAGS_AUTHENTICATED) { + /* Create deauthentication packet */ + memset(&ieee80211_params, 0, sizeof(struct ieee80211_deauthentication_params)); + memcpy(ieee80211_params.bssid, station->wlan->bssid, MACADDRESS_EUI48_LENGTH); + memcpy(ieee80211_params.station, station->address, MACADDRESS_EUI48_LENGTH); + ieee80211_params.reasoncode = IEEE80211_REASON_PREV_AUTH_NOT_VALID; + + /* */ + responselength = ieee80211_create_deauthentication(buffer, IEEE80211_MTU, &ieee80211_params); + if (responselength > 0) { + station->flags &= ~(AC_STATION_FLAGS_AUTHENTICATED | AC_STATION_FLAGS_ASSOCIATE); + ac_session_data_send_data_packet(sessiondata, station->wlan->radioid, station->wlan->wlanid, buffer, responselength, 1); + } } } diff --git a/src/ac/ac_wlans.h b/src/ac/ac_wlans.h index b8d8523..16c333c 100644 --- a/src/ac/ac_wlans.h +++ b/src/ac/ac_wlans.h @@ -3,12 +3,17 @@ #include "ieee80211.h" +/* */ +#define RADIOID_ANY 0 + /* */ #define AC_WLANS_STATIONS_HASH_SIZE 256 #define AC_WLANS_STATIONS_KEY_SIZE MACADDRESS_EUI48_LENGTH /* AC WLAN */ struct ac_wlan { + struct capwap_list_item* wlanitem; + uint8_t bssid[MACADDRESS_EUI48_LENGTH]; uint8_t radioid; uint8_t wlanid; @@ -35,13 +40,31 @@ struct ac_wlan { uint8_t* ssid; }; +/* */ +#define AC_STATION_FLAGS_AUTHENTICATED 0x00000001 +#define AC_STATION_FLAGS_ASSOCIATE 0x00000002 +#define AC_STATION_FLAGS_AUTHORIZED 0x00000004 + /* AC Station */ struct ac_station { uint8_t address[MACADDRESS_EUI48_LENGTH]; + unsigned long flags; /* Reference of WLAN */ struct ac_wlan* wlan; struct capwap_list_item* wlanitem; + + /* */ + uint16_t capability; + uint16_t listeninterval; + uint16_t aid; + + /* */ + int supportedratescount; + uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT]; + + /* Authentication */ + uint16_t authalgorithm; }; /* */ @@ -53,21 +76,21 @@ struct ac_wlans { }; /* Management WLANS */ -void ac_wlans_init(struct ac_session_t* session); -void ac_wlans_destroy(struct ac_session_t* session); +void ac_wlans_init(struct ac_session_data_t* sessiondata); +void ac_wlans_destroy(struct ac_session_data_t* sessiondata); /* */ -struct ac_wlan* ac_wlans_create_bssid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid, const uint8_t* bssid); -struct ac_wlan* ac_wlans_get_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid); -struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_t* session, uint8_t radioid, uint8_t wlanid); -void ac_wlans_delete_bssid(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid); - -/* */ -void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_addwlan_element* addwlan); +struct ac_wlan* ac_wlans_create_bssid(uint8_t radioid, uint8_t wlanid, const uint8_t* bssid, struct capwap_80211_addwlan_element* addwlan); +int ac_wlans_assign_bssid(struct ac_session_data_t* sessiondata, struct ac_wlan* wlan); +struct ac_wlan* ac_wlans_get_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid); +struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_session_data_t* sessiondata, uint8_t radioid, uint8_t wlanid); +void ac_wlans_delete_bssid(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid); /* Management Stations */ -struct ac_station* ac_stations_create_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address); -struct ac_station* ac_stations_get_station(struct ac_session_t* session, uint8_t radioid, const uint8_t* bssid, const uint8_t* address); -void ac_stations_delete_station(struct ac_session_t* session, const uint8_t* address); +struct ac_station* ac_stations_create_station(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid, const uint8_t* address); +struct ac_station* ac_stations_get_station(struct ac_session_data_t* sessiondata, uint8_t radioid, const uint8_t* bssid, const uint8_t* address); +void ac_stations_delete_station(struct ac_session_data_t* sessiondata, struct ac_station* station); +void ac_stations_authorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station); +void ac_stations_deauthorize_station(struct ac_session_data_t* sessiondata, struct ac_station* station); #endif /* __AC_WLANS_HEADER__ */ diff --git a/src/binding/ieee80211/ieee80211.c b/src/binding/ieee80211/ieee80211.c index 519518f..4a885b7 100644 --- a/src/binding/ieee80211/ieee80211.c +++ b/src/binding/ieee80211/ieee80211.c @@ -2,7 +2,7 @@ #include "ieee80211.h" /* */ -static int ieee80211_ie_set_ssid(char* buffer, const char* ssid, int hidessid) { +static int ieee80211_ie_set_ssid(uint8_t* buffer, const char* ssid, int hidessid) { struct ieee80211_ie_ssid* iessid = (struct ieee80211_ie_ssid*)buffer; ASSERT(buffer != NULL); @@ -24,7 +24,7 @@ static int ieee80211_ie_set_ssid(char* buffer, const char* ssid, int hidessid) { } /* */ -static int ieee80211_ie_set_supportedrates(char* buffer, uint8_t* supportedrates, int supportedratescount) { +static int ieee80211_ie_set_supportedrates(uint8_t* buffer, uint8_t* supportedrates, int supportedratescount) { int i; int count; struct ieee80211_ie_supported_rates* iesupportedrates = (struct ieee80211_ie_supported_rates*)buffer; @@ -51,7 +51,7 @@ static int ieee80211_ie_set_supportedrates(char* buffer, uint8_t* supportedrates } /* */ -static int ieee80211_ie_set_extendedsupportedrates(char* buffer, uint8_t* supportedrates, int supportedratescount) { +static int ieee80211_ie_set_extendedsupportedrates(uint8_t* buffer, uint8_t* supportedrates, int supportedratescount) { int i, j; struct ieee80211_ie_extended_supported_rates* ieextendedsupportedrates = (struct ieee80211_ie_extended_supported_rates*)buffer; @@ -75,7 +75,7 @@ static int ieee80211_ie_set_extendedsupportedrates(char* buffer, uint8_t* suppor } /* */ -static int ieee80211_ie_set_dsss(char* buffer, uint8_t channel) { +static int ieee80211_ie_set_dsss(uint8_t* buffer, uint8_t channel) { struct ieee80211_ie_dsss* iedsss = (struct ieee80211_ie_dsss*)buffer; ASSERT(buffer != NULL); @@ -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, uint8_t erpinfo) { +static int ieee80211_ie_set_erp(uint8_t* buffer, uint32_t mode, uint8_t erpinfo) { struct ieee80211_ie_erp* ieerp = (struct ieee80211_ie_erp*)buffer; ASSERT(buffer != NULL); @@ -349,9 +349,9 @@ uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnone /* */ -int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_params* params) { +int ieee80211_create_beacon(uint8_t* buffer, int length, struct ieee80211_beacon_params* params) { int result; - char* pos; + uint8_t* pos; struct ieee80211_header_mgmt* header; ASSERT(buffer != NULL); @@ -458,9 +458,9 @@ int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_pa } /* */ -int ieee80211_create_probe_response(char* buffer, int length, struct ieee80211_probe_response_params* params) { +int ieee80211_create_probe_response(uint8_t* buffer, int length, struct ieee80211_probe_response_params* params) { int result; - char* pos; + uint8_t* pos; int responselength; struct ieee80211_header_mgmt* header; @@ -536,7 +536,7 @@ int ieee80211_create_probe_response(char* buffer, int length, struct ieee80211_p } /* */ -int ieee80211_create_authentication_response(char* buffer, int length, struct ieee80211_authentication_params* params) { +int ieee80211_create_authentication_response(uint8_t* buffer, int length, struct ieee80211_authentication_params* params) { int responselength; struct ieee80211_header_mgmt* header; @@ -565,8 +565,8 @@ int ieee80211_create_authentication_response(char* buffer, int length, struct ie } /* */ -int ieee80211_create_associationresponse_response(char* buffer, int length, struct ieee80211_associationresponse_params* params) { - char* pos; +int ieee80211_create_associationresponse_response(uint8_t* buffer, int length, struct ieee80211_associationresponse_params* params) { + uint8_t* pos; int result; int responselength; struct ieee80211_header_mgmt* header; @@ -613,7 +613,7 @@ int ieee80211_create_associationresponse_response(char* buffer, int length, stru } /* */ -int ieee80211_create_deauthentication(char* buffer, int length, struct ieee80211_deauthentication_params* params) { +int ieee80211_create_deauthentication(uint8_t* buffer, int length, struct ieee80211_deauthentication_params* params) { struct ieee80211_header_mgmt* header; ASSERT(buffer != NULL); diff --git a/src/binding/ieee80211/ieee80211.h b/src/binding/ieee80211/ieee80211.h index e41f3c5..a91f47e 100644 --- a/src/binding/ieee80211/ieee80211.h +++ b/src/binding/ieee80211/ieee80211.h @@ -483,9 +483,9 @@ uint8_t ieee80211_get_erpinfo(uint32_t mode, int olbc, unsigned long stationnone struct ieee80211_beacon_params { unsigned long flags; - char* headbeacon; + uint8_t* headbeacon; int headbeaconlength; - char* tailbeacon; + uint8_t* tailbeacon; int tailbeaconlength; uint8_t bssid[ETH_ALEN]; @@ -504,11 +504,11 @@ struct ieee80211_beacon_params { uint32_t mode; uint8_t erpinfo; - char* proberesponseoffload; + uint8_t* proberesponseoffload; int proberesponseoffloadlength; }; -int ieee80211_create_beacon(char* buffer, int length, struct ieee80211_beacon_params* params); +int ieee80211_create_beacon(uint8_t* buffer, int length, struct ieee80211_beacon_params* params); /* Management Probe Response */ struct ieee80211_probe_response_params { @@ -529,7 +529,7 @@ struct ieee80211_probe_response_params { uint8_t erpinfo; }; -int ieee80211_create_probe_response(char* buffer, int length, struct ieee80211_probe_response_params* params); +int ieee80211_create_probe_response(uint8_t* buffer, int length, struct ieee80211_probe_response_params* params); /* Management Authentication */ struct ieee80211_authentication_params { @@ -541,7 +541,7 @@ struct ieee80211_authentication_params { uint16_t statuscode; }; -int ieee80211_create_authentication_response(char* buffer, int length, struct ieee80211_authentication_params* params); +int ieee80211_create_authentication_response(uint8_t* buffer, int length, struct ieee80211_authentication_params* params); /* Management Association Response */ struct ieee80211_associationresponse_params { @@ -556,7 +556,7 @@ struct ieee80211_associationresponse_params { uint8_t supportedrates[IEEE80211_SUPPORTEDRATE_MAX_COUNT]; }; -int ieee80211_create_associationresponse_response(char* buffer, int length, struct ieee80211_associationresponse_params* params); +int ieee80211_create_associationresponse_response(uint8_t* buffer, int length, struct ieee80211_associationresponse_params* params); /* Management Deauthentication */ struct ieee80211_deauthentication_params { @@ -566,7 +566,7 @@ struct ieee80211_deauthentication_params { uint16_t reasoncode; }; -int ieee80211_create_deauthentication(char* buffer, int length, struct ieee80211_deauthentication_params* params); +int ieee80211_create_deauthentication(uint8_t* buffer, int length, struct ieee80211_deauthentication_params* params); /* Utils */ int ieee80211_retrieve_information_elements_position(struct ieee80211_ie_items* items, const uint8_t* data, int length); diff --git a/src/binding/ieee80211/wifi_drivers.c b/src/binding/ieee80211/wifi_drivers.c index 59d63e2..625815d 100644 --- a/src/binding/ieee80211/wifi_drivers.c +++ b/src/binding/ieee80211/wifi_drivers.c @@ -481,6 +481,33 @@ void wifi_wlan_destroy(struct wifi_wlan* wlan) { } } +/* */ +int wifi_station_add(struct wifi_wlan* wlan, struct station_add_params* params) { + ASSERT(wlan != NULL); + ASSERT(wlan->device != NULL); + ASSERT(params != NULL); + + /* Check */ + if (!wlan->device->instance->ops->station_add) { + return -1; + } + + return wlan->device->instance->ops->station_add(wlan->handle, params); +} + +/* */ +int wifi_station_delete(struct wifi_device* device, struct station_delete_params* params) { + ASSERT(device != NULL); + ASSERT(params != NULL); + + /* Check */ + if (!device->instance->ops->station_delete) { + return -1; + } + + return device->instance->ops->station_delete(device->handle, params); +} + /* */ uint32_t wifi_iface_index(const char* ifname) { if (!ifname || !*ifname) { diff --git a/src/binding/ieee80211/wifi_drivers.h b/src/binding/ieee80211/wifi_drivers.h index 470eb3a..7c46c8c 100644 --- a/src/binding/ieee80211/wifi_drivers.h +++ b/src/binding/ieee80211/wifi_drivers.h @@ -116,7 +116,7 @@ struct wlan_startap_params { /* */ struct wlan_send_frame_params { - char* packet; + uint8_t* packet; int length; uint32_t frequency; @@ -128,6 +128,16 @@ struct wlan_send_frame_params { uint64_t cookie; }; +/* */ +struct station_add_params { + uint8_t* address; +}; + +/* */ +struct station_delete_params { + uint8_t* address; +}; + /* Interface capability */ struct wifi_freq_capability { unsigned long flags; @@ -241,6 +251,10 @@ struct wifi_driver_ops { void (*wlan_stopap)(wifi_wlan_handle handle); int (*wlan_getmacaddress)(wifi_wlan_handle handle, uint8_t* address); void (*wlan_delete)(wifi_wlan_handle handle); + + /* Stations functions */ + int (*station_add)(wifi_wlan_handle handle, struct station_add_params* params); + int (*station_delete)(wifi_device_handle handle, struct station_delete_params* params); }; /* */ @@ -287,6 +301,10 @@ void wifi_wlan_stopap(struct wifi_wlan* wlan); int wifi_wlan_getbssid(struct wifi_wlan* wlan, uint8_t* bssid); void wifi_wlan_destroy(struct wifi_wlan* wlan); +/* */ +int wifi_station_add(struct wifi_wlan* wlan, struct station_add_params* params); +int wifi_station_delete(struct wifi_device* device, struct station_delete_params* params); + /* Util functions */ uint32_t wifi_iface_index(const char* ifname); int wifi_iface_hwaddr(int sock, const char* ifname, uint8_t* hwaddr); diff --git a/src/binding/ieee80211/wifi_nl80211.c b/src/binding/ieee80211/wifi_nl80211.c index ddbe5ae..b71fc03 100644 --- a/src/binding/ieee80211/wifi_nl80211.c +++ b/src/binding/ieee80211/wifi_nl80211.c @@ -15,7 +15,7 @@ #include "wifi_nl80211.h" /* */ -static char g_bufferIEEE80211[IEEE80211_MTU]; +static uint8_t g_bufferIEEE80211[IEEE80211_MTU]; /* */ static void nl80211_station_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param); @@ -539,12 +539,10 @@ static int nl80211_wlan_new_station(struct nl80211_wlan_handle* wlanhandle, stru if (result == -EEXIST) { result = 0; } else { - capwap_logging_error("Unable create station, error code: %d", result); + capwap_logging_error("Unable add station into wireless driver, error code: %d", result); } } - capwap_logging_info("Create station, error code: %d", result); - /* */ nlmsg_free(msg); return result; @@ -614,6 +612,11 @@ static void nl80211_station_clean(struct nl80211_station* station) { ASSERT(station != NULL); if (station->wlanhandle) { + /* Delete station into wireless driver */ + if (station->flags & NL80211_STATION_FLAGS_AUTHORIZED) { + nl80211_wlan_delete_station(station->wlanhandle, station->address); + } + if (station->aid) { ieee80211_aid_free(station->wlanhandle->aidbitfield, station->aid); station->aid = 0; @@ -889,13 +892,11 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla int ielength; struct ieee80211_ie_items ieitems; int responselength; - uint16_t algorithm; - uint16_t transactionseqnumber; - uint16_t responsestatuscode; struct ieee80211_authentication_params ieee80211_params; struct wlan_send_frame_params wlan_params; struct nl80211_station* station; char stationaddress[CAPWAP_MACADDRESS_EUI48_BUFFER]; + uint16_t responsestatuscode; /* Information Elements packet length */ ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication)); @@ -911,7 +912,7 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla } /* */ - capwap_printf_macaddress(stationaddress, (unsigned char*)mgmt->sa, MACADDRESS_EUI48_LENGTH); + capwap_printf_macaddress(stationaddress, mgmt->sa, MACADDRESS_EUI48_LENGTH); /* Get ACL Station */ acl = wtp_radio_acl_station(mgmt->sa); @@ -932,27 +933,34 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla /* Create station reference */ station = nl80211_station_create(wlanhandle, mgmt->sa); if (station) { - 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)) { - 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 */ - } + /* A station is removed if the association does not complete within a given period of time */ + station->timeoutaction = NL80211_STATION_TIMEOUT_ACTION_DEAUTHENTICATE; + station->idtimeout = capwap_timeout_set(station->globalhandle->timeout, station->idtimeout, NL80211_STATION_TIMEOUT_ASSOCIATION_COMPLETE, nl80211_station_timeout, station, wlanhandle); + responsestatuscode = IEEE80211_STATUS_SUCCESS; } else { responsestatuscode = IEEE80211_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; } /* */ - if (wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { + if ((responsestatuscode != IEEE80211_STATUS_SUCCESS) || (wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL)) { + uint16_t algorithm = __le16_to_cpu(mgmt->authetication.algorithm); + uint16_t transactionseqnumber = __le16_to_cpu(mgmt->authetication.transactionseqnumber); + + /* Check authentication algorithm */ + if (responsestatuscode == IEEE80211_STATUS_SUCCESS) { + 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 */ + } + } + /* Create authentication packet */ memset(&ieee80211_params, 0, sizeof(struct ieee80211_authentication_params)); memcpy(ieee80211_params.bssid, wlanhandle->address, ETH_ALEN); @@ -970,33 +978,25 @@ static void nl80211_do_mgmt_authentication_event(struct nl80211_wlan_handle* wla wlan_params.frequency = wlanhandle->devicehandle->currentfrequency.frequency; if (!nl80211_wlan_send_frame((wifi_wlan_handle)wlanhandle, &wlan_params)) { - capwap_logging_info("Sent IEEE802.11 Authentication Response to %s station with %d response status code", stationaddress, (int)responsestatuscode); + capwap_logging_info("Sent IEEE802.11 Authentication Response to %s station with %d status code", stationaddress, (int)responsestatuscode); wlanhandle->last_cookie = wlan_params.cookie; - /* A station is removed if the association does not complete within a given period of time */ - station->timeoutaction = NL80211_STATION_TIMEOUT_ACTION_DEAUTHENTICATE; - station->idtimeout = capwap_timeout_set(station->globalhandle->timeout, station->idtimeout, NL80211_STATION_TIMEOUT_ASSOCIATION_COMPLETE, nl80211_station_timeout, station, wlanhandle); - /* Notify authentication request message also to AC */ wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength); /* Forwards the authentication response message also to AC */ wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, (struct ieee80211_header_mgmt*)g_bufferIEEE80211, responselength); - } else { + } else if (station) { capwap_logging_warning("Unable to send IEEE802.11 Authentication Response to %s station", stationaddress); nl80211_station_delete(station); } - } else { + } else if (station) { capwap_logging_warning("Unable to create IEEE802.11 Authentication Response to %s station", stationaddress); nl80211_station_delete(station); } - } else if ((wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) && (responsestatuscode == IEEE80211_STATUS_SUCCESS)) { + } else if (wlanhandle->macmode == CAPWAP_ADD_WLAN_MACMODE_SPLIT) { wlanhandle->send_mgmtframe(wlanhandle->send_mgmtframe_to_ac_cbparam, mgmt, mgmtlength); - - /* A station is removed if the association does not complete within a given period of time */ - station->timeoutaction = NL80211_STATION_TIMEOUT_ACTION_DEAUTHENTICATE; - station->idtimeout = capwap_timeout_set(station->globalhandle->timeout, station->idtimeout, NL80211_STATION_TIMEOUT_ASSOCIATION_COMPLETE, nl80211_station_timeout, station, wlanhandle); } } @@ -1129,7 +1129,7 @@ static void nl80211_do_mgmt_association_request_event(struct nl80211_wlan_handle } /* */ - capwap_printf_macaddress(stationaddress, (unsigned char*)mgmt->sa, MACADDRESS_EUI48_LENGTH); + capwap_printf_macaddress(stationaddress, mgmt->sa, MACADDRESS_EUI48_LENGTH); /* Get station reference */ station = nl80211_station_get(wlanhandle->devicehandle->globalhandle, wlanhandle, mgmt->sa); @@ -1207,12 +1207,11 @@ static void nl80211_do_mgmt_deauthentication_event(struct nl80211_wlan_handle* w return; } - /* */ - nl80211_wlan_delete_station(wlanhandle, mgmt->sa); - /* Delete station */ station = nl80211_station_get(wlanhandle->devicehandle->globalhandle, wlanhandle, mgmt->sa); - if (station) { + if (!station) { + nl80211_wlan_delete_station(wlanhandle, mgmt->sa); /* Delete station into wireless driver */ + } else { nl80211_station_delete(station); } @@ -1360,12 +1359,6 @@ static void nl80211_do_mgmt_frame_tx_status_association_response_event(struct nl statuscode = __le16_to_cpu(mgmt->associationresponse.statuscode); if (statuscode == IEEE80211_STATUS_SUCCESS) { station->flags |= NL80211_STATION_FLAGS_ASSOCIATE; - - /* TODO: remove when CAPWAP Add Station is ready */ - capwap_timeout_deletetimer(station->globalhandle->timeout, station->idtimeout); - station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET; - station->flags |= NL80211_STATION_FLAGS_AUTHORIZED; - nl80211_wlan_new_station(wlanhandle, station); } } @@ -2669,15 +2662,14 @@ static void nl80211_wlan_deauthentication_station(struct nl80211_wlan_handle* wl ASSERT(wlanhandle != NULL); ASSERT(stationaddress != NULL); - /* Blocks the station */ - nl80211_wlan_delete_station(wlanhandle, stationaddress); - /* Send deauthentication message */ nl80211_wlan_send_deauthentication(wlanhandle, stationaddress, reasoncode); /* Clean station */ station = nl80211_station_get(wlanhandle->devicehandle->globalhandle, wlanhandle, stationaddress); - if (station) { + if (!station) { + nl80211_wlan_delete_station(wlanhandle, stationaddress); /* Delete station into wireless driver */ + } else { if (reusestation) { nl80211_station_clean(station); } else { @@ -2686,6 +2678,66 @@ static void nl80211_wlan_deauthentication_station(struct nl80211_wlan_handle* wl } } +/* */ +int nl80211_station_authorize(wifi_wlan_handle handle, struct station_add_params* params) { + struct nl80211_station* station; + char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; + struct nl80211_wlan_handle* wlanhandle = (struct nl80211_wlan_handle*)handle; + + ASSERT(handle != NULL); + ASSERT(params != NULL); + + /* Get station */ + station = nl80211_station_get(wlanhandle->devicehandle->globalhandle, wlanhandle, params->address); + if (!station) { + return -1; + } else if (!(station->flags & NL80211_STATION_FLAGS_AUTHENTICATED) || !(station->flags & NL80211_STATION_FLAGS_ASSOCIATE)) { + return -1; + } else if (station->flags & NL80211_STATION_FLAGS_AUTHORIZED) { + return 0; + } + + /* */ + capwap_logging_info("Authorize station: %s", capwap_printf_macaddress(buffer, params->address, MACADDRESS_EUI48_LENGTH)); + + /* */ + capwap_timeout_deletetimer(station->globalhandle->timeout, station->idtimeout); + station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET; + + /* Station authorized */ + station->flags |= NL80211_STATION_FLAGS_AUTHORIZED; + nl80211_wlan_new_station(wlanhandle, station); + + return 0; +} + +/* */ +int nl80211_station_deauthorize(wifi_device_handle handle, struct station_delete_params* params) { + struct nl80211_station* station; + char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; + struct nl80211_device_handle* devicehandle = (struct nl80211_device_handle*)handle; + + ASSERT(handle != NULL); + ASSERT(params != NULL); + + /* Get station */ + station = nl80211_station_get(devicehandle->globalhandle, NULL, params->address); + if (!station || !station->wlanhandle) { + return -1; + } else if (!(station->flags & NL80211_STATION_FLAGS_AUTHORIZED)) { + return 0; + } + + /* */ + capwap_logging_info("Deauthorize station: %s", capwap_printf_macaddress(buffer, params->address, MACADDRESS_EUI48_LENGTH)); + + /* Station deauthorized */ + station->flags |= NL80211_STATION_FLAGS_AUTHORIZED; + nl80211_wlan_delete_station(station->wlanhandle, station->address); + + return 0; +} + /* */ static void nl80211_global_deinit(wifi_global_handle handle) { struct nl80211_global_handle* globalhandle = (struct nl80211_global_handle*)handle; @@ -2875,5 +2927,7 @@ const struct wifi_driver_ops wifi_driver_nl80211_ops = { .wlan_startap = nl80211_wlan_startap, .wlan_stopap = nl80211_wlan_stopap, .wlan_getmacaddress = nl80211_wlan_getmacaddress, - .wlan_delete = nl80211_wlan_delete + .wlan_delete = nl80211_wlan_delete, + .station_add = nl80211_station_authorize, + .station_delete = nl80211_station_deauthorize }; diff --git a/src/common/capwap_element.c b/src/common/capwap_element.c index cc28265..e4f8146 100644 --- a/src/common/capwap_element.c +++ b/src/common/capwap_element.c @@ -662,7 +662,16 @@ int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct ca } case CAPWAP_STATION_CONFIGURATION_REQUEST: { - /* TODO */ + if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDSTATION)) { + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_STATION)) { + return 0; + } + } else { + return 0; + } + } + break; } diff --git a/src/common/capwap_element.h b/src/common/capwap_element.h index da19466..781120c 100644 --- a/src/common/capwap_element.h +++ b/src/common/capwap_element.h @@ -11,7 +11,7 @@ struct capwap_write_message_elements_ops { int (*write_u8)(capwap_message_elements_handle handle, uint8_t data); int (*write_u16)(capwap_message_elements_handle handle, uint16_t data); int (*write_u32)(capwap_message_elements_handle handle, uint32_t data); - int (*write_block)(capwap_message_elements_handle handle, uint8_t* data, unsigned short length); + int (*write_block)(capwap_message_elements_handle handle, const uint8_t* data, unsigned short length); }; struct capwap_read_message_elements_ops { diff --git a/src/common/capwap_element_80211_miccountermeasures.c b/src/common/capwap_element_80211_miccountermeasures.c index f2b7fc9..e0d9ad5 100644 --- a/src/common/capwap_element_80211_miccountermeasures.c +++ b/src/common/capwap_element_80211_miccountermeasures.c @@ -25,7 +25,7 @@ static void capwap_80211_miccountermeasures_element_create(void* data, capwap_me func->write_u8(handle, element->radioid); func->write_u8(handle, element->wlanid); - func->write_block(handle, element->address, CAPWAP_MIC_COUNTERMEASURES_MACADDRESS_LENGTH); + func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH); } /* */ @@ -47,7 +47,7 @@ static void* capwap_80211_miccountermeasures_element_parsing(capwap_message_elem /* Retrieve data */ func->read_u8(handle, &data->radioid); func->read_u8(handle, &data->wlanid); - func->read_block(handle, data->address, CAPWAP_MIC_COUNTERMEASURES_MACADDRESS_LENGTH); + func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH); return data; } diff --git a/src/common/capwap_element_80211_miccountermeasures.h b/src/common/capwap_element_80211_miccountermeasures.h index 7fbe3d2..d3cb06f 100644 --- a/src/common/capwap_element_80211_miccountermeasures.h +++ b/src/common/capwap_element_80211_miccountermeasures.h @@ -3,12 +3,10 @@ #define CAPWAP_ELEMENT_80211_MIC_COUNTERMEASURES 1031 -#define CAPWAP_MIC_COUNTERMEASURES_MACADDRESS_LENGTH 6 - struct capwap_80211_miccountermeasures_element { uint8_t radioid; uint8_t wlanid; - uint8_t address[CAPWAP_MIC_COUNTERMEASURES_MACADDRESS_LENGTH]; + uint8_t address[MACADDRESS_EUI48_LENGTH]; }; extern struct capwap_message_elements_ops capwap_element_80211_miccountermeasures_ops; diff --git a/src/common/capwap_element_80211_rsnaerrorreport.c b/src/common/capwap_element_80211_rsnaerrorreport.c index 649e59e..28fb860 100644 --- a/src/common/capwap_element_80211_rsnaerrorreport.c +++ b/src/common/capwap_element_80211_rsnaerrorreport.c @@ -40,8 +40,8 @@ static void capwap_80211_rsnaerrorreport_element_create(void* data, capwap_messa ASSERT(data != NULL); - func->write_block(handle, element->client, CAPWAP_RSNA_ERROR_REPORT_CLIENT_LENGTH); - func->write_block(handle, element->bssid, CAPWAP_RSNA_ERROR_REPORT_BSSID_LENGTH); + func->write_block(handle, element->client, MACADDRESS_EUI48_LENGTH); + func->write_block(handle, element->bssid, MACADDRESS_EUI48_LENGTH); func->write_u8(handle, element->radioid); func->write_u8(handle, element->wlanid); func->write_u16(handle, 0); @@ -70,8 +70,8 @@ static void* capwap_80211_rsnaerrorreport_element_parsing(capwap_message_element memset(data, 0, sizeof(struct capwap_80211_rsnaerrorreport_element)); /* Retrieve data */ - func->read_block(handle, data->client, CAPWAP_RSNA_ERROR_REPORT_CLIENT_LENGTH); - func->read_block(handle, data->bssid, CAPWAP_RSNA_ERROR_REPORT_BSSID_LENGTH); + func->read_block(handle, data->client, MACADDRESS_EUI48_LENGTH); + func->read_block(handle, data->bssid, MACADDRESS_EUI48_LENGTH); func->read_u8(handle, &data->radioid); func->read_u8(handle, &data->wlanid); func->read_u16(handle, NULL); diff --git a/src/common/capwap_element_80211_rsnaerrorreport.h b/src/common/capwap_element_80211_rsnaerrorreport.h index d2b1e3c..e16d6a6 100644 --- a/src/common/capwap_element_80211_rsnaerrorreport.h +++ b/src/common/capwap_element_80211_rsnaerrorreport.h @@ -3,12 +3,9 @@ #define CAPWAP_ELEMENT_80211_RSNA_ERROR_REPORT 1035 -#define CAPWAP_RSNA_ERROR_REPORT_CLIENT_LENGTH 6 -#define CAPWAP_RSNA_ERROR_REPORT_BSSID_LENGTH 6 - struct capwap_80211_rsnaerrorreport_element { - uint8_t client[CAPWAP_RSNA_ERROR_REPORT_CLIENT_LENGTH]; - uint8_t bssid[CAPWAP_RSNA_ERROR_REPORT_BSSID_LENGTH]; + uint8_t client[MACADDRESS_EUI48_LENGTH]; + uint8_t bssid[MACADDRESS_EUI48_LENGTH]; uint8_t radioid; uint8_t wlanid; uint32_t tkipicverrors; diff --git a/src/common/capwap_element_80211_station.c b/src/common/capwap_element_80211_station.c index 3f2fab4..5c60f38 100644 --- a/src/common/capwap_element_80211_station.c +++ b/src/common/capwap_element_80211_station.c @@ -30,7 +30,7 @@ static void capwap_80211_station_element_create(void* data, capwap_message_eleme func->write_u8(handle, element->radioid); func->write_u16(handle, element->associationid); func->write_u8(handle, element->flags); - func->write_block(handle, element->address, CAPWAP_STATION_ADDRESS_LENGTH); + func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH); func->write_u16(handle, element->capabilities); func->write_u8(handle, element->wlanid); func->write_block(handle, element->supportedrates, element->supportedratescount); @@ -64,7 +64,7 @@ static void* capwap_80211_station_element_parsing(capwap_message_elements_handle func->read_u8(handle, &data->radioid); func->read_u16(handle, &data->associationid); func->read_u8(handle, &data->flags); - func->read_block(handle, data->address, CAPWAP_STATION_ADDRESS_LENGTH); + func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH); func->read_u16(handle, &data->capabilities); func->read_u8(handle, &data->wlanid); data->supportedratescount = length; diff --git a/src/common/capwap_element_80211_station.h b/src/common/capwap_element_80211_station.h index 6eb84e3..fad0466 100644 --- a/src/common/capwap_element_80211_station.h +++ b/src/common/capwap_element_80211_station.h @@ -3,14 +3,13 @@ #define CAPWAP_ELEMENT_80211_STATION 1036 -#define CAPWAP_STATION_ADDRESS_LENGTH 6 #define CAPWAP_STATION_RATES_MAXLENGTH 128 struct capwap_80211_station_element { uint8_t radioid; uint16_t associationid; uint8_t flags; - uint8_t address[CAPWAP_STATION_ADDRESS_LENGTH]; + uint8_t address[MACADDRESS_EUI48_LENGTH]; uint16_t capabilities; uint8_t wlanid; uint8_t supportedratescount; diff --git a/src/common/capwap_element_80211_stationkey.c b/src/common/capwap_element_80211_stationkey.c index d8b7766..66309e1 100644 --- a/src/common/capwap_element_80211_stationkey.c +++ b/src/common/capwap_element_80211_stationkey.c @@ -31,7 +31,7 @@ static void capwap_80211_stationkey_element_create(void* data, capwap_message_el ASSERT(data != NULL); - func->write_block(handle, element->address, CAPWAP_STATION_SESSION_KEY_ADDRESS_LENGTH); + func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH); func->write_u16(handle, element->flags); func->write_block(handle, element->pairwisetsc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH); func->write_block(handle, element->pairwisersc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH); @@ -59,7 +59,7 @@ static void* capwap_80211_stationkey_element_parsing(capwap_message_elements_han memset(data, 0, sizeof(struct capwap_80211_stationkey_element)); /* Retrieve data */ - func->read_block(handle, data->address, CAPWAP_STATION_SESSION_KEY_ADDRESS_LENGTH); + func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH); func->read_u16(handle, &data->flags); func->read_block(handle, data->pairwisetsc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH); func->read_block(handle, data->pairwisersc, CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH); diff --git a/src/common/capwap_element_80211_stationkey.h b/src/common/capwap_element_80211_stationkey.h index c5ed7da..54fd6e1 100644 --- a/src/common/capwap_element_80211_stationkey.h +++ b/src/common/capwap_element_80211_stationkey.h @@ -3,7 +3,6 @@ #define CAPWAP_ELEMENT_80211_STATION_SESSION_KEY_PROFILE 1038 -#define CAPWAP_STATION_SESSION_KEY_ADDRESS_LENGTH 6 #define CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH 6 #define CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH 6 @@ -11,7 +10,7 @@ #define CAPWAP_STATION_SESSION_KEY_AC_ENCRYPT 0x4000 struct capwap_80211_stationkey_element { - uint8_t address[CAPWAP_STATION_SESSION_KEY_ADDRESS_LENGTH]; + uint8_t address[MACADDRESS_EUI48_LENGTH]; uint16_t flags; uint8_t pairwisetsc[CAPWAP_STATION_SESSION_KEY_PAIRWISE_TSC_LENGTH]; uint8_t pairwisersc[CAPWAP_STATION_SESSION_KEY_PAIRWISE_RSC_LENGTH]; diff --git a/src/common/capwap_element_80211_stationqos.c b/src/common/capwap_element_80211_stationqos.c index a0624fa..72e0031 100644 --- a/src/common/capwap_element_80211_stationqos.c +++ b/src/common/capwap_element_80211_stationqos.c @@ -23,7 +23,7 @@ static void capwap_80211_stationqos_element_create(void* data, capwap_message_el ASSERT(data != NULL); - func->write_block(handle, element->address, CAPWAP_STATION_QOS_ADDRESS_LENGTH); + func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH); func->write_u8(handle, 0); func->write_u8(handle, element->priority); } @@ -45,7 +45,7 @@ static void* capwap_80211_stationqos_element_parsing(capwap_message_elements_han memset(data, 0, sizeof(struct capwap_80211_stationqos_element)); /* Retrieve data */ - func->read_block(handle, data->address, CAPWAP_STATION_QOS_ADDRESS_LENGTH); + func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH); func->read_u8(handle, NULL); func->read_u8(handle, &data->priority); diff --git a/src/common/capwap_element_80211_stationqos.h b/src/common/capwap_element_80211_stationqos.h index a171717..2f462e7 100644 --- a/src/common/capwap_element_80211_stationqos.h +++ b/src/common/capwap_element_80211_stationqos.h @@ -3,10 +3,8 @@ #define CAPWAP_ELEMENT_80211_STATION_QOS_PROFILE 1037 -#define CAPWAP_STATION_QOS_ADDRESS_LENGTH 6 - struct capwap_80211_stationqos_element { - uint8_t address[CAPWAP_STATION_QOS_ADDRESS_LENGTH]; + uint8_t address[MACADDRESS_EUI48_LENGTH]; uint8_t priority; }; diff --git a/src/common/capwap_element_80211_updatestationqos.c b/src/common/capwap_element_80211_updatestationqos.c index 4aebf5e..43dce70 100644 --- a/src/common/capwap_element_80211_updatestationqos.c +++ b/src/common/capwap_element_80211_updatestationqos.c @@ -31,7 +31,7 @@ static void capwap_80211_updatestationqos_element_create(void* data, capwap_mess ASSERT(data != NULL); func->write_u8(handle, element->radioid); - func->write_block(handle, element->address, CAPWAP_UPDATE_STATION_QOS_ADDRESS_LENGTH); + func->write_block(handle, element->address, MACADDRESS_EUI48_LENGTH); for (i = 0; i < CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS; i++) { func->write_u8(handle, element->qos[i].priority8021p & CAPWAP_UPDATE_STATION_QOS_PRIORIY_MASK); func->write_u8(handle, element->qos[i].dscp & CAPWAP_UPDATE_STATION_QOS_DSCP_MASK); diff --git a/src/common/capwap_element_80211_updatestationqos.h b/src/common/capwap_element_80211_updatestationqos.h index bd7bd01..c2393a6 100644 --- a/src/common/capwap_element_80211_updatestationqos.h +++ b/src/common/capwap_element_80211_updatestationqos.h @@ -3,7 +3,6 @@ #define CAPWAP_ELEMENT_80211_UPDATE_STATION_QOS 1043 -#define CAPWAP_UPDATE_STATION_QOS_ADDRESS_LENGTH 6 #define CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS 4 #define CAPWAP_UPDATE_STATION_QOS_PRIORIY_MASK 0x07 @@ -16,7 +15,7 @@ struct capwap_80211_updatestationqos_subelement { struct capwap_80211_updatestationqos_element { uint8_t radioid; - uint8_t address[CAPWAP_UPDATE_STATION_QOS_ADDRESS_LENGTH]; + uint8_t address[MACADDRESS_EUI48_LENGTH]; struct capwap_80211_updatestationqos_subelement qos[CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS]; }; diff --git a/src/common/capwap_element_80211_wtpradioconf.c b/src/common/capwap_element_80211_wtpradioconf.c index c8765b4..f608603 100644 --- a/src/common/capwap_element_80211_wtpradioconf.c +++ b/src/common/capwap_element_80211_wtpradioconf.c @@ -31,7 +31,7 @@ static void capwap_80211_wtpradioconf_element_create(void* data, capwap_message_ func->write_u8(handle, element->shortpreamble); func->write_u8(handle, element->maxbssid); func->write_u8(handle, element->dtimperiod); - func->write_block(handle, element->bssid, CAPWAP_WTP_RADIO_CONF_BSSID_LENGTH); + func->write_block(handle, element->bssid, MACADDRESS_EUI48_LENGTH); func->write_u16(handle, element->beaconperiod); func->write_block(handle, element->country, CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH); } @@ -57,7 +57,7 @@ static void* capwap_80211_wtpradioconf_element_parsing(capwap_message_elements_h func->read_u8(handle, &data->shortpreamble); func->read_u8(handle, &data->maxbssid); func->read_u8(handle, &data->dtimperiod); - func->read_block(handle, data->bssid, CAPWAP_WTP_RADIO_CONF_BSSID_LENGTH); + func->read_block(handle, data->bssid, MACADDRESS_EUI48_LENGTH); func->read_u16(handle, &data->beaconperiod); func->read_block(handle, data->country, CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH); diff --git a/src/common/capwap_element_80211_wtpradioconf.h b/src/common/capwap_element_80211_wtpradioconf.h index 3589102..4f7ce5d 100644 --- a/src/common/capwap_element_80211_wtpradioconf.h +++ b/src/common/capwap_element_80211_wtpradioconf.h @@ -3,7 +3,6 @@ #define CAPWAP_ELEMENT_80211_WTP_RADIO_CONF 1046 -#define CAPWAP_WTP_RADIO_CONF_BSSID_LENGTH 6 #define CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH 4 #define CAPWAP_WTP_RADIO_CONF_SHORTPREAMBLE_DISABLE 0 @@ -14,7 +13,7 @@ struct capwap_80211_wtpradioconf_element { uint8_t shortpreamble; uint8_t maxbssid; uint8_t dtimperiod; - uint8_t bssid[CAPWAP_WTP_RADIO_CONF_BSSID_LENGTH]; + uint8_t bssid[MACADDRESS_EUI48_LENGTH]; uint16_t beaconperiod; uint8_t country[CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH]; }; diff --git a/src/common/capwap_protocol.c b/src/common/capwap_protocol.c index 39590f1..092fb01 100644 --- a/src/common/capwap_protocol.c +++ b/src/common/capwap_protocol.c @@ -352,7 +352,7 @@ static struct capwap_list_item* capwap_packet_txmng_create_fragment_item(struct } /* */ -static int capwap_fragment_write_block_from_pos(struct capwap_packet_txmng* txmngpacket, uint8_t* data, unsigned short length, struct write_block_from_pos* writepos) { +static int capwap_fragment_write_block_from_pos(struct capwap_packet_txmng* txmngpacket, const uint8_t* data, unsigned short length, struct write_block_from_pos* writepos) { unsigned short packetpos; struct capwap_list_item* item; struct capwap_fragment_packet_item* fragmentpacket; @@ -430,7 +430,7 @@ static int capwap_fragment_write_block_from_pos(struct capwap_packet_txmng* txmn } /* */ -static int capwap_fragment_write_block(capwap_message_elements_handle handle, uint8_t* data, unsigned short length) { +static int capwap_fragment_write_block(capwap_message_elements_handle handle, const uint8_t* data, unsigned short length) { struct capwap_packet_txmng* txmngpacket; struct write_block_from_pos writepos; @@ -611,7 +611,7 @@ struct capwap_packet_txmng* capwap_packet_txmng_create_data_message(struct capwa } /* */ -void capwap_packet_txmng_add_data(struct capwap_packet_txmng* txmngpacket, uint8_t* data, unsigned short length) { +void capwap_packet_txmng_add_data(struct capwap_packet_txmng* txmngpacket, const uint8_t* data, unsigned short length) { ASSERT(txmngpacket != NULL); ASSERT(txmngpacket->isctrlpacket == 0); diff --git a/src/common/capwap_protocol.h b/src/common/capwap_protocol.h index d2be424..f34a033 100644 --- a/src/common/capwap_protocol.h +++ b/src/common/capwap_protocol.h @@ -65,7 +65,7 @@ struct capwap_packet_txmng { /* */ struct capwap_packet_txmng* capwap_packet_txmng_create_ctrl_message(struct capwap_header_data* data, unsigned long type, unsigned char seq, unsigned short mtu); struct capwap_packet_txmng* capwap_packet_txmng_create_data_message(struct capwap_header_data* data, unsigned short mtu); -void capwap_packet_txmng_add_data(struct capwap_packet_txmng* txmngpacket, uint8_t* data, unsigned short length); +void capwap_packet_txmng_add_data(struct capwap_packet_txmng* txmngpacket, const uint8_t* data, unsigned short length); void capwap_packet_txmng_add_message_element(struct capwap_packet_txmng* txmngpacket, unsigned short type, void* data); void capwap_packet_txmng_get_fragment_packets(struct capwap_packet_txmng* txmngpacket, struct capwap_list* fragmentlist, unsigned short fragmentid); void capwap_packet_txmng_free(struct capwap_packet_txmng* txmngpacket); diff --git a/src/wtp/wtp_dfa.h b/src/wtp/wtp_dfa.h index d40c212..1a09012 100644 --- a/src/wtp/wtp_dfa.h +++ b/src/wtp/wtp_dfa.h @@ -65,6 +65,6 @@ void wtp_dfa_state_run_keepalivedead_timeout(struct capwap_timeout* timeout, uns void wtp_dfa_state_reset(void); /* */ -void wtp_send_data_wireless_packet(uint8_t radioid, uint8_t wlanid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, int leavenativeframe); +void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe); #endif /* __WTP_DFA_HEADER__ */ diff --git a/src/wtp/wtp_dfa_run.c b/src/wtp/wtp_dfa_run.c index 1441811..2983146 100644 --- a/src/wtp/wtp_dfa_run.c +++ b/src/wtp/wtp_dfa_run.c @@ -110,14 +110,22 @@ static void receive_station_configuration_request(struct capwap_parsed_packet* p if ((binding == g_wtp.binding) && IS_SEQUENCE_SMALLER(g_wtp.remoteseqnumber, packet->rxmngpacket->ctrlmsg.seq)) { struct capwap_header_data capwapheader; struct capwap_packet_txmng* txmngpacket; + struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE }; - /* TODO */ + /* Parsing request message */ + if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDSTATION)) { + resultcode.code = wtp_radio_add_station(packet); + } else if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETESTATION)) { + resultcode.code = wtp_radio_delete_station(packet); + } /* Build packet */ capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_STATION_CONFIGURATION_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, g_wtp.mtu); - /* TODO */ + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ /* Station Configuration response complete, get fragment packets */ wtp_free_reference_last_response(); @@ -238,7 +246,7 @@ static void send_data_keepalive_request() { } /* */ -void wtp_send_data_wireless_packet(uint8_t radioid, uint8_t wlanid, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, int leavenativeframe) { +void wtp_send_data_packet(uint8_t radioid, uint8_t wlanid, const uint8_t* data, int length, int leavenativeframe) { struct capwap_list* txfragpacket; struct capwap_header_data capwapheader; struct capwap_packet_txmng* txmngpacket; @@ -250,14 +258,18 @@ void wtp_send_data_wireless_packet(uint8_t radioid, uint8_t wlanid, const struct /* */ if (leavenativeframe) { - capwap_packet_txmng_add_data(txmngpacket, (uint8_t*)mgmt, (unsigned short)mgmtlength); + capwap_packet_txmng_add_data(txmngpacket, data, (unsigned short)length); } else { /* TODO */ } /* Data message complete, get fragment packets into local list */ txfragpacket = capwap_list_create(); - capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, 0); + capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, g_wtp.fragmentid); + if (txfragpacket->count > 1) { + g_wtp.fragmentid++; + } + if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txfragpacket, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress)) { capwap_logging_debug("Warning: error to send data packet"); } diff --git a/src/wtp/wtp_radio.c b/src/wtp/wtp_radio.c index 31f1940..bf87aec 100644 --- a/src/wtp/wtp_radio.c +++ b/src/wtp/wtp_radio.c @@ -59,7 +59,7 @@ static void wtp_radio_send_mgmtframe_to_ac(void* param, const struct ieee80211_h ASSERT(mgmtlength >= sizeof(struct ieee80211_header)); /* Send packet */ - wtp_send_data_wireless_packet(wlan->radio->radioid, wlan->wlanid, mgmt, mgmtlength, 1); + wtp_send_data_packet(wlan->radio->radioid, wlan->wlanid, (const uint8_t*)mgmt, mgmtlength, 1); } /* */ @@ -589,6 +589,8 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa struct wlan_startap_params params; struct capwap_80211_addwlan_element* addwlan; + ASSERT(packet != NULL); + /* Get message elements */ addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_ADD_WLAN); if (!addwlan) { @@ -678,6 +680,50 @@ uint32_t wtp_radio_delete_wlan(struct capwap_parsed_packet* packet) { return CAPWAP_RESULTCODE_SUCCESS; } +/* */ +uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet) { + struct capwap_addstation_element* addstation; + struct capwap_80211_station_element* station80211; + struct wtp_radio* radio; + struct wtp_radio_wlan* wlan; + struct station_add_params stationparams; + + /* Get message elements */ + addstation = (struct capwap_addstation_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ADDSTATION); + station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION); + if (!station80211 || (addstation->radioid != station80211->radioid)) { + return CAPWAP_RESULTCODE_FAILURE; + } + + /* Get physical radio */ + radio = wtp_radio_get_phy(addstation->radioid); + if (!radio) { + return CAPWAP_RESULTCODE_FAILURE; + } + + /* Get virtual interface */ + wlan = wtp_radio_get_wlan(radio, station80211->wlanid); + if (!wlan) { + return CAPWAP_RESULTCODE_FAILURE; + } + + /* Authorize station */ + memset(&stationparams, 0, sizeof(struct station_add_params)); + stationparams.address = station80211->address; + + if (wifi_station_add(wlan->wlanhandle, &stationparams)) { + return CAPWAP_RESULTCODE_FAILURE; + } + + return CAPWAP_RESULTCODE_SUCCESS; +} + +/* */ +uint32_t wtp_radio_delete_station(struct capwap_parsed_packet* packet) { + /* TODO */ + return CAPWAP_RESULTCODE_SUCCESS; +} + /* */ int wtp_radio_acl_station(const uint8_t* macaddress) { ASSERT(macaddress != NULL); diff --git a/src/wtp/wtp_radio.h b/src/wtp/wtp_radio.h index 2e07f48..9b4ff27 100644 --- a/src/wtp/wtp_radio.h +++ b/src/wtp/wtp_radio.h @@ -76,6 +76,10 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet, struct capwa uint32_t wtp_radio_update_wlan(struct capwap_parsed_packet* packet); uint32_t wtp_radio_delete_wlan(struct capwap_parsed_packet* packet); +/* */ +uint32_t wtp_radio_add_station(struct capwap_parsed_packet* packet); +uint32_t wtp_radio_delete_station(struct capwap_parsed_packet* packet); + /* Station ACL */ int wtp_radio_acl_station(const uint8_t* macaddress); void wtp_radio_acl_addstation(const uint8_t* macaddress);