From ae97e96f575d533d4b141eb920cb759c06b8b0d5 Mon Sep 17 00:00:00 2001 From: vemax78 Date: Wed, 2 Apr 2014 22:40:04 +0200 Subject: [PATCH] Started implementing the packet management of IEEE802.11 by AC side. Made it clear some constants. --- build/ac/Makefile.am | 1 + src/ac/ac.c | 9 +- src/ac/ac.h | 3 +- src/ac/ac_dfa_run.c | 65 +++++- src/ac/ac_discovery.c | 4 +- src/ac/ac_execute.c | 4 + src/ac/ac_ieee80211_data.c | 161 ++++++++++++++- src/ac/ac_session.c | 13 +- src/ac/ac_session.h | 7 +- src/ac/ac_session_data.c | 6 +- src/ac/ac_wlans.c | 191 ++++++++++++++++++ src/ac/ac_wlans.h | 58 ++++++ src/binding/ieee80211/wifi_nl80211.c | 2 +- src/common/capwap_element_80211_assignbssid.c | 4 +- src/common/capwap_element_80211_assignbssid.h | 4 +- .../capwap_element_80211_updatestationqos.c | 2 +- src/common/capwap_hash.c | 5 +- src/common/capwap_network.c | 4 +- src/common/capwap_network.h | 9 +- src/common/capwap_protocol.c | 45 ++++- src/common/capwap_protocol.h | 6 + src/common/capwap_rfc.h | 3 + src/wtp/wtp_dfa.c | 4 +- src/wtp/wtp_dfa_run.c | 43 +++- 24 files changed, 609 insertions(+), 44 deletions(-) create mode 100644 src/ac/ac_wlans.c create mode 100644 src/ac/ac_wlans.h diff --git a/build/ac/Makefile.am b/build/ac/Makefile.am index cd54ab5..5f2c810 100755 --- a/build/ac/Makefile.am +++ b/build/ac/Makefile.am @@ -52,6 +52,7 @@ ac_SOURCES = \ $(top_srcdir)/src/ac/ac_execute.c \ $(top_srcdir)/src/ac/ac_session.c \ $(top_srcdir)/src/ac/ac_session_data.c \ + $(top_srcdir)/src/ac/ac_wlans.c \ $(top_srcdir)/src/ac/ac_ieee80211_data.c \ $(top_srcdir)/src/ac/ac_discovery.c \ $(top_srcdir)/src/ac/ac_80211_json.c \ diff --git a/src/ac/ac.c b/src/ac/ac.c index 26130d5..44f7e46 100644 --- a/src/ac/ac.c +++ b/src/ac/ac.c @@ -26,11 +26,6 @@ static unsigned long ac_stations_item_gethash(const void* key, unsigned long key return ((((unsigned long)macaddress[4] << 8) | (unsigned long)macaddress[5]) ^ ((unsigned long)macaddress[3] << 4)); } -/* */ -static void ac_stations_item_free(const void* key, unsigned long keysize, void* data) { - /* TODO */ -} - /* Alloc AC */ static int ac_init(void) { g_ac.standalone = 1; @@ -79,7 +74,8 @@ static int ac_init(void) { capwap_rwlock_init(&g_ac.sessionslock); /* Stations */ - g_ac.stations = capwap_hash_create(AC_STATIONS_HASH_SIZE, AC_STATIONS_KEY_SIZE, ac_stations_item_gethash, NULL, ac_stations_item_free); + g_ac.stations = capwap_hash_create(AC_STATIONS_HASH_SIZE, AC_STATIONS_KEY_SIZE, ac_stations_item_gethash, NULL, NULL); + capwap_rwlock_init(&g_ac.stationslock); /* Backend */ g_ac.availablebackends = capwap_array_create(sizeof(struct ac_http_soap_server*), 0, 0); @@ -121,6 +117,7 @@ static void ac_destroy(void) { /* Stations */ capwap_hash_free(g_ac.stations); + capwap_rwlock_destroy(&g_ac.stationslock); /* Backend */ if (g_ac.backendacid) { diff --git a/src/ac/ac.h b/src/ac/ac.h index 6e09560..dfa9df5 100644 --- a/src/ac/ac.h +++ b/src/ac/ac.h @@ -57,7 +57,7 @@ /* */ #define AC_STATIONS_HASH_SIZE 65536 -#define AC_STATIONS_KEY_SIZE ETH_ALEN +#define AC_STATIONS_KEY_SIZE MACADDRESS_EUI48_LENGTH /* */ struct ac_state { @@ -99,6 +99,7 @@ struct ac_t { /* Stations */ struct capwap_hash* stations; + capwap_rwlock_t stationslock; /* Dtls */ int enabledtls; diff --git a/src/ac/ac_dfa_run.c b/src/ac/ac_dfa_run.c index 24b8ec8..1b8690f 100644 --- a/src/ac/ac_dfa_run.c +++ b/src/ac/ac_dfa_run.c @@ -1,7 +1,9 @@ #include "ac.h" #include "capwap_dfa.h" #include "capwap_array.h" +#include "capwap_array.h" #include "ac_session.h" +#include "ac_wlans.h" /* */ static int receive_echo_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) { @@ -61,13 +63,74 @@ static int receive_echo_request(struct ac_session_t* session, struct capwap_pars return 0; } +/* */ +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[18]; + 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->wlans, assignbssid->radioid, assignbssid->bssid)) { + wlan = ac_wlans_create_bssid(session->wlans, assignbssid->radioid, assignbssid->wlanid, assignbssid->bssid); + wlan->session = session; + wlan->sessiondata = session->sessiondata; + + /* 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)); + } + } +} + +/* */ +static void execute_ieee80211_wlan_configuration_updatewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_80211_updatewlan_element* updatewlan, struct capwap_parsed_packet* requestpacket) { +} + +/* */ +static void execute_ieee80211_wlan_configuration_deletewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_80211_deletewlan_element* deletewlan, struct capwap_parsed_packet* requestpacket) { +} + /* */ static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) { + struct capwap_80211_addwlan_element* addwlan; + struct capwap_80211_updatewlan_element* updatewlan; + struct capwap_80211_deletewlan_element* deletewlan; + struct capwap_parsed_packet requestpacket; + struct capwap_packet_rxmng* rxmngrequestpacket; struct capwap_resultcode_element* resultcode; /* Check the success of the Request */ resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE); - if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) { + if (CAPWAP_RESULTCODE_OK(resultcode->code)) { + rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket); + if (rxmngrequestpacket) { + if (capwap_parsing_packet(rxmngrequestpacket, NULL, &requestpacket) == PARSING_COMPLETE) { + /* Detect type of IEEE802.11 WLAN Configuration Request */ + addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN); + if (addwlan) { + execute_ieee80211_wlan_configuration_addwlan(session, packet, addwlan, &requestpacket); + } else { + updatewlan = (struct capwap_80211_updatewlan_element*)capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN); + if (updatewlan) { + execute_ieee80211_wlan_configuration_updatewlan(session, packet, updatewlan, &requestpacket); + } else { + deletewlan = (struct capwap_80211_deletewlan_element*)capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN); + if (deletewlan) { + execute_ieee80211_wlan_configuration_deletewlan(session, packet, deletewlan, &requestpacket); + } + } + } + } + + /* */ + capwap_free_parsed_packet(&requestpacket); + capwap_packet_rxmng_free(rxmngrequestpacket); + } + } else { capwap_logging_warning("Receive IEEE802.11 WLAN Configuration Response with error: %d", (int)resultcode->code); } diff --git a/src/ac/ac_discovery.c b/src/ac/ac_discovery.c index f74c4ac..9440a97 100644 --- a/src/ac/ac_discovery.c +++ b/src/ac/ac_discovery.c @@ -156,12 +156,12 @@ static void ac_discovery_run(void) { sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet); /* Accept only discovery request don't fragment */ - rxmngpacket = capwap_packet_rxmng_create_message(1); + rxmngpacket = capwap_packet_rxmng_create_message(CAPWAP_CONTROL_PACKET); if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, acpacket->data, sizedata) == CAPWAP_RECEIVE_COMPLETE_PACKET) { /* Validate message */ if (capwap_check_message_type(rxmngpacket) == VALID_MESSAGE_TYPE) { /* Parsing packet */ - if (!capwap_parsing_packet(rxmngpacket, NULL, &packet)) { + if (capwap_parsing_packet(rxmngpacket, NULL, &packet) == PARSING_COMPLETE) { /* Validate packet */ if (!capwap_validate_parsed_packet(&packet, NULL)) { struct capwap_packet_txmng* txmngpacket; diff --git a/src/ac/ac_execute.c b/src/ac/ac_execute.c index 99ae532..c397c19 100644 --- a/src/ac/ac_execute.c +++ b/src/ac/ac_execute.c @@ -3,6 +3,7 @@ #include "ac_session.h" #include "ac_discovery.h" #include "ac_backend.h" +#include "ac_wlans.h" #include @@ -501,6 +502,9 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres session->count = 2; capwap_event_init(&session->changereference); + /* */ + session->wlans = ac_wlans_init(); + /* */ session->timeout = capwap_timeout_init(); session->idtimercontrol = capwap_timeout_createtimer(session->timeout); diff --git a/src/ac/ac_ieee80211_data.c b/src/ac/ac_ieee80211_data.c index 397a32d..00dcdbb 100644 --- a/src/ac/ac_ieee80211_data.c +++ b/src/ac/ac_ieee80211_data.c @@ -3,8 +3,165 @@ #include "ieee80211.h" /* */ -void ac_ieee80211_data(struct ac_session_data_t* sessiondata, uint8_t* buffer, int length) { +static void ac_ieee80211_mgmt_probe_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + struct ieee80211_ie_items ieitems; + + /* Parsing Information Elements */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest)); + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { + return; + } + + /* TODO */ +} + +/* */ +static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + struct ieee80211_ie_items ieitems; + + /* Parsing Information Elements */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest)); + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { + return; + } + + /* TODO */ +} + +/* */ +static void ac_ieee80211_mgmt_association_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + struct ieee80211_ie_items ieitems; + + /* Parsing Information Elements */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest)); + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { + return; + } + + /* TODO */ +} + +/* */ +static void ac_ieee80211_mgmt_reassociation_request_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + struct ieee80211_ie_items ieitems; + + /* Parsing Information Elements */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest)); + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { + return; + } + + /* TODO */ +} + +/* */ +static void ac_ieee80211_mgmt_disassociation_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + struct ieee80211_ie_items ieitems; + + /* Parsing Information Elements */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest)); + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { + return; + } + + /* TODO */ +} + +/* */ +static void ac_ieee80211_mgmt_deauthentication_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength) { + int ielength; + struct ieee80211_ie_items ieitems; + + /* Parsing Information Elements */ + ielength = mgmtlength - (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest)); + if (ieee80211_retrieve_information_elements_position(&ieitems, &mgmt->proberequest.ie[0], ielength)) { + return; + } + + /* TODO */ +} + +/* */ +static void ac_ieee80211_mgmt_packet(struct ac_session_data_t* sessiondata, const struct ieee80211_header_mgmt* mgmt, int mgmtlength, uint16_t framecontrol_subtype) { + switch (framecontrol_subtype) { + case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_PROBE_REQUEST: { + if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->proberequest))) { + ac_ieee80211_mgmt_probe_request_packet(sessiondata, mgmt, mgmtlength); + } + + break; + } + + case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_AUTHENTICATION: { + if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->authetication))) { + ac_ieee80211_mgmt_authentication_packet(sessiondata, mgmt, mgmtlength); + } + + break; + } + + case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ASSOCIATION_REQUEST: { + if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->associationrequest))) { + ac_ieee80211_mgmt_association_request_packet(sessiondata, mgmt, mgmtlength); + } + + break; + } + + case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_REASSOCIATION_REQUEST: { + if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->reassociationrequest))) { + ac_ieee80211_mgmt_reassociation_request_packet(sessiondata, mgmt, mgmtlength); + } + + break; + } + + case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DISASSOCIATION: { + if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->disassociation))) { + ac_ieee80211_mgmt_disassociation_packet(sessiondata, mgmt, mgmtlength); + } + + break; + } + + case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_DEAUTHENTICATION: { + if (mgmtlength >= (sizeof(struct ieee80211_header) + sizeof(mgmt->deauthetication))) { + ac_ieee80211_mgmt_deauthentication_packet(sessiondata, mgmt, mgmtlength); + } + + break; + } + + case IEEE80211_FRAMECONTROL_MGMT_SUBTYPE_ACTION: { + break; + } + } +} + +/* */ +void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, const uint8_t* buffer, int length) { + const struct ieee80211_header* header; + uint16_t framecontrol; + uint16_t framecontrol_type; + uint16_t framecontrol_subtype; + ASSERT(sessiondata != NULL); ASSERT(buffer != NULL); - ASSERT(length > 0); + ASSERT(length >= sizeof(struct ieee80211_header)); + + /* Get type frame */ + header = (const struct ieee80211_header*)buffer; + framecontrol = __le16_to_cpu(header->framecontrol); + framecontrol_type = IEEE80211_FRAME_CONTROL_GET_TYPE(framecontrol); + framecontrol_subtype = IEEE80211_FRAME_CONTROL_GET_SUBTYPE(framecontrol); + + /* Parsing frame */ + if (framecontrol_type == IEEE80211_FRAMECONTROL_TYPE_MGMT) { + ac_ieee80211_mgmt_packet(sessiondata, (const struct ieee80211_header_mgmt*)buffer, length, framecontrol_subtype); + } } diff --git a/src/ac/ac_session.c b/src/ac/ac_session.c index be62b38..9330547 100644 --- a/src/ac/ac_session.c +++ b/src/ac/ac_session.c @@ -3,6 +3,7 @@ #include "capwap_dfa.h" #include "ac_session.h" #include "ac_backend.h" +#include "ac_wlans.h" #include #define AC_ERROR_TIMEOUT -1000 @@ -59,6 +60,13 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not ASSERT(session->requestfragmentpacket->count == 0); + /* 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; + } else if (ac_wlans_get_bssid_with_wlanid(session->wlans, notify->radioid, notify->wlanid)) { + return AC_ERROR_ACTION_SESSION; + } + /* */ memset(&addwlan, 0, sizeof(struct capwap_80211_addwlan_element)); addwlan.radioid = notify->radioid; @@ -397,6 +405,9 @@ 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->wlans); + /* */ capwap_event_destroy(&session->changereference); capwap_event_destroy(&session->waitpacket); @@ -497,7 +508,7 @@ static void ac_session_run(struct ac_session_t* session) { /* Defragment management */ if (!session->rxmngpacket) { - session->rxmngpacket = capwap_packet_rxmng_create_message(1); + session->rxmngpacket = capwap_packet_rxmng_create_message(CAPWAP_CONTROL_PACKET); } /* If request, defragmentation packet */ diff --git a/src/ac/ac_session.h b/src/ac/ac_session.h index 18e595c..5c30ee9 100644 --- a/src/ac/ac_session.h +++ b/src/ac/ac_session.h @@ -92,6 +92,9 @@ struct ac_session_t { long count; capwap_event_t changereference; + /* WLAN Reference */ + struct ac_wlans* wlans; + /* Soap */ struct ac_http_soap_request* soaprequest; @@ -142,8 +145,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); -/* IEEE802.11 Data Packet */ -void ac_ieee80211_data(struct ac_session_data_t* sessiondata, uint8_t* buffer, int length); +/* IEEE802.11 Packet */ +void ac_ieee80211_packet(struct ac_session_data_t* sessiondata, const uint8_t* buffer, int length); /* */ int ac_has_sessionid(struct capwap_sessionid_element* sessionid); diff --git a/src/ac/ac_session_data.c b/src/ac/ac_session_data.c index 672c8b8..57bb72b 100644 --- a/src/ac/ac_session_data.c +++ b/src/ac/ac_session_data.c @@ -344,7 +344,7 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) { /* Defragment management */ if (!sessiondata->rxmngpacket) { - sessiondata->rxmngpacket = capwap_packet_rxmng_create_message(0); + sessiondata->rxmngpacket = capwap_packet_rxmng_create_message(CAPWAP_DATA_PACKET); } /* If request, defragmentation packet */ @@ -368,8 +368,8 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) { /* Parsing body packet */ if (bodypacketlength > 0) { binding = GET_WBID_HEADER(sessiondata->rxmngpacket->header); - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - ac_ieee80211_data(sessiondata, bodypacket, bodypacketlength); + if ((binding == CAPWAP_WIRELESS_BINDING_IEEE80211) && (bodypacketlength >= sizeof(struct ieee80211_header))) { + ac_ieee80211_packet(sessiondata, bodypacket, bodypacketlength); } } } diff --git a/src/ac/ac_wlans.c b/src/ac/ac_wlans.c new file mode 100644 index 0000000..0b3fca2 --- /dev/null +++ b/src/ac/ac_wlans.c @@ -0,0 +1,191 @@ +#include "ac.h" +#include "ac_session.h" +#include "ac_wlans.h" + +/* */ +struct ac_wlans* ac_wlans_init(void) { + struct ac_wlans* wlans; + + /* */ + wlans = (struct ac_wlans*)capwap_alloc(sizeof(struct ac_wlans)); + memset(wlans, 0, sizeof(struct ac_wlans)); + + return wlans; +} + +/* */ +void ac_wlans_destroy(struct ac_wlans* wlans) { + int i; + + ASSERT(wlans != NULL); + + /* */ + for (i = 0; i < RADIOID_MAX_COUNT; i++) { + if (wlans->wlans[i]) { + while (wlans->wlans[i]->first) { + struct ac_wlan* wlan = (struct ac_wlan*)wlans->wlans[i]->first->item; + + /* Delete WLAN */ + ac_wlans_delete_bssid(wlans, i + 1, wlan->bssid); + } + + /* TODO */ + capwap_list_free(wlans->wlans[i]); + } + } + + capwap_free(wlans); +} + +/* */ +struct ac_wlan* ac_wlans_create_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid, uint8_t* bssid) { + struct ac_wlan* wlan; + struct capwap_list_item* wlanitem; + + ASSERT(wlans != NULL); + ASSERT(IS_VALID_RADIOID(radioid)); + ASSERT(IS_VALID_WLANID(wlanid)); + ASSERT(bssid != NULL); + + /* */ + wlanitem = capwap_itemlist_create(sizeof(struct ac_wlan)); + wlan = (struct ac_wlan*)wlanitem->item; + memset(wlan, 0, sizeof(struct ac_wlan)); + + /* Init WLAN */ + memcpy(wlan->bssid, bssid, MACADDRESS_EUI48_LENGTH); + wlan->wlanid = wlanid; + wlan->stations = capwap_list_create(); + + /* Create WLAN list */ + if (!wlans->wlans[radioid - 1]) { + wlans->wlans[radioid - 1] = capwap_list_create(); + } + + /* Append WLAN to list */ + capwap_itemlist_insert_after(wlans->wlans[radioid - 1], NULL, wlanitem); + + return wlan; +} + +/* */ +struct ac_wlan* ac_wlans_get_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid) { + struct capwap_list_item* search; + struct ac_wlan* wlan = NULL; + + ASSERT(wlans != NULL); + ASSERT(IS_VALID_RADIOID(radioid)); + ASSERT(bssid != NULL); + + /* */ + if (wlans->wlans[radioid - 1]) { + search = 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_wlans* wlans, uint8_t radioid, uint8_t wlanid) { + struct capwap_list_item* search; + struct ac_wlan* wlan = NULL; + + ASSERT(wlans != NULL); + ASSERT(IS_VALID_RADIOID(radioid)); + ASSERT(IS_VALID_WLANID(wlanid)); + + /* */ + if (wlans->wlans[radioid - 1]) { + search = 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_wlan* wlan) { + /* Free capability */ + if (wlan->key) { + capwap_free(wlan->key); + } + + if (wlan->ssid) { + capwap_free(wlan->ssid); + } + + /* Remove stations */ + capwap_list_free(wlan->stations); +} + +/* */ +void ac_wlans_delete_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid) { + struct capwap_list_item* search; + + ASSERT(wlans != NULL); + ASSERT(IS_VALID_RADIOID(radioid)); + ASSERT(bssid != NULL); + + /* */ + if (wlans->wlans[radioid - 1]) { + search = 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(item); + capwap_itemlist_free(capwap_itemlist_remove(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); + + wlan->capability = addwlan->capability; + + wlan->keyindex = addwlan->keyindex; + wlan->keystatus = addwlan->keystatus; + wlan->keylength = addwlan->keylength; + if (addwlan->key && (addwlan->keylength > 0)) { + wlan->key = (uint8_t*)capwap_clone(addwlan->key, wlan->keylength); + } + + memcpy(wlan->grouptsc, addwlan->grouptsc, CAPWAP_ADD_WLAN_GROUPTSC_LENGTH); + + wlan->qos = addwlan->qos; + wlan->authmode = addwlan->authmode; + wlan->macmode = addwlan->macmode; + wlan->tunnelmode = addwlan->tunnelmode; + + wlan->suppressssid = addwlan->suppressssid; + wlan->ssid = (uint8_t*)capwap_duplicate_string((const char*)addwlan->ssid); +} diff --git a/src/ac/ac_wlans.h b/src/ac/ac_wlans.h new file mode 100644 index 0000000..42e46ab --- /dev/null +++ b/src/ac/ac_wlans.h @@ -0,0 +1,58 @@ +#ifndef __AC_WLANS_HEADER__ +#define __AC_WLANS_HEADER__ + +/* AC WLAN */ +struct ac_wlan { + uint8_t bssid[MACADDRESS_EUI48_LENGTH]; + uint8_t wlanid; + + /* CAPWAP Session */ + struct ac_session_t* session; + struct ac_session_data_t* sessiondata; + + /* Capability */ + uint16_t capability; + uint8_t keyindex; + uint8_t keystatus; + uint16_t keylength; + uint8_t* key; + uint8_t grouptsc[CAPWAP_ADD_WLAN_GROUPTSC_LENGTH]; + uint8_t qos; + uint8_t authmode; + uint8_t macmode; + uint8_t tunnelmode; + uint8_t suppressssid; + uint8_t* ssid; + + /* Local cache stations */ + struct capwap_list* stations; +}; + +/* AC Station */ +struct ac_station { + uint8_t address[MACADDRESS_EUI48_LENGTH]; + + /* Reference of WLAN */ + struct ac_wlan_device* wlan; + struct capwap_list_item* itemlist; +}; + +/* */ +struct ac_wlans { + struct capwap_list* wlans[RADIOID_MAX_COUNT]; +}; + +/* */ +struct ac_wlans* ac_wlans_init(void); +void ac_wlans_destroy(struct ac_wlans* wlans); + +/* */ +struct ac_wlan* ac_wlans_create_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid, uint8_t* bssid); +struct ac_wlan* ac_wlans_get_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid); +struct ac_wlan* ac_wlans_get_bssid_with_wlanid(struct ac_wlans* wlans, uint8_t radioid, uint8_t wlanid); +void ac_wlans_delete_bssid(struct ac_wlans* wlans, uint8_t radioid, uint8_t* bssid); + +/* */ +void ac_wlans_set_bssid_capability(struct ac_wlan* wlan, struct capwap_80211_addwlan_element* addwlan); + +#endif /* __AC_WLANS_HEADER__ */ diff --git a/src/binding/ieee80211/wifi_nl80211.c b/src/binding/ieee80211/wifi_nl80211.c index a474a98..c1a8773 100644 --- a/src/binding/ieee80211/wifi_nl80211.c +++ b/src/binding/ieee80211/wifi_nl80211.c @@ -2586,7 +2586,7 @@ static int nl80211_wlan_startap(wifi_wlan_handle handle, struct wlan_startap_par /* Configuration complete */ wlanhandle->devicehandle->wlanactive++; - capwap_logging_info("Configured interface %s with '%s' SSID", wlanhandle->virtname, wlanhandle->ssid); + capwap_logging_info("Configured interface: %s, SSID: '%s'", wlanhandle->virtname, wlanhandle->ssid); return 0; } diff --git a/src/common/capwap_element_80211_assignbssid.c b/src/common/capwap_element_80211_assignbssid.c index d89256c..b5e8ebb 100644 --- a/src/common/capwap_element_80211_assignbssid.c +++ b/src/common/capwap_element_80211_assignbssid.c @@ -25,7 +25,7 @@ static void capwap_80211_assignbssid_element_create(void* data, capwap_message_e func->write_u8(handle, element->radioid); func->write_u8(handle, element->wlanid); - func->write_block(handle, element->bssid, CAPWAP_ASSIGN_BSSID_LENGTH); + func->write_block(handle, element->bssid, MACADDRESS_EUI48_LENGTH); } /* */ @@ -47,7 +47,7 @@ static void* capwap_80211_assignbssid_element_parsing(capwap_message_elements_ha /* Retrieve data */ func->read_u8(handle, &data->radioid); func->read_u8(handle, &data->wlanid); - func->read_block(handle, data->bssid, CAPWAP_ASSIGN_BSSID_LENGTH); + func->read_block(handle, data->bssid, MACADDRESS_EUI48_LENGTH); return data; } diff --git a/src/common/capwap_element_80211_assignbssid.h b/src/common/capwap_element_80211_assignbssid.h index 98bfa20..7c6a125 100644 --- a/src/common/capwap_element_80211_assignbssid.h +++ b/src/common/capwap_element_80211_assignbssid.h @@ -3,12 +3,10 @@ #define CAPWAP_ELEMENT_80211_ASSIGN_BSSID 1026 -#define CAPWAP_ASSIGN_BSSID_LENGTH 6 - struct capwap_80211_assignbssid_element { uint8_t radioid; uint8_t wlanid; - uint8_t bssid[CAPWAP_ASSIGN_BSSID_LENGTH]; + uint8_t bssid[MACADDRESS_EUI48_LENGTH]; }; extern struct capwap_message_elements_ops capwap_element_80211_assignbssid_ops; diff --git a/src/common/capwap_element_80211_updatestationqos.c b/src/common/capwap_element_80211_updatestationqos.c index 25804fc..4aebf5e 100644 --- a/src/common/capwap_element_80211_updatestationqos.c +++ b/src/common/capwap_element_80211_updatestationqos.c @@ -57,7 +57,7 @@ static void* capwap_80211_updatestationqos_element_parsing(capwap_message_elemen /* Retrieve data */ func->read_u8(handle, &data->radioid); - func->read_block(handle, data->address, CAPWAP_ASSIGN_BSSID_LENGTH); + func->read_block(handle, data->address, MACADDRESS_EUI48_LENGTH); for (i = 0; i < CAPWAP_UPDATE_STATION_QOS_SUBELEMENTS; i++) { func->read_u8(handle, &data->qos[i].priority8021p); data->qos[i].priority8021p &= CAPWAP_UPDATE_STATION_QOS_PRIORIY_MASK; diff --git a/src/common/capwap_hash.c b/src/common/capwap_hash.c index 05b76b4..635871b 100644 --- a/src/common/capwap_hash.c +++ b/src/common/capwap_hash.c @@ -59,8 +59,6 @@ static struct capwap_hash_item* capwap_hash_search_items(struct capwap_hash* has /* */ static int capwap_hash_foreach_items(struct capwap_hash* hash, struct capwap_hash_item* item, capwap_hash_item_foreach item_foreach, void* param) { - int result; - ASSERT(hash != NULL); ASSERT(item_foreach != NULL); ASSERT(item != NULL); @@ -73,8 +71,7 @@ static int capwap_hash_foreach_items(struct capwap_hash* hash, struct capwap_has } /* */ - result = item_foreach(item->key, hash->keysize, item->data, param); - if (!result) { + if (!item_foreach(item->key, hash->keysize, item->data, param)) { return 0; } diff --git a/src/common/capwap_network.c b/src/common/capwap_network.c index 616d4ce..4e85468 100644 --- a/src/common/capwap_network.c +++ b/src/common/capwap_network.c @@ -1300,7 +1300,7 @@ void capwap_interface_list(struct capwap_network* net, struct capwap_list* list) /* */ -char* capwap_printf_macaddress(char* buffer, const unsigned char* macaddress, int type) { +char* capwap_printf_macaddress(char* buffer, const uint8_t* macaddress, int type) { if (type == MACADDRESS_EUI48_LENGTH) { sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", macaddress[0], macaddress[1], macaddress[2], macaddress[3], macaddress[4], macaddress[5]); } else if (type == MACADDRESS_EUI64_LENGTH) { @@ -1313,7 +1313,7 @@ char* capwap_printf_macaddress(char* buffer, const unsigned char* macaddress, in } /* */ -int capwap_scanf_macaddress(unsigned char* macaddress, const char* buffer, int type) { +int capwap_scanf_macaddress(uint8_t* macaddress, const char* buffer, int type) { if (type == MACADDRESS_EUI48_LENGTH) { if (sscanf(buffer, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddress[0], &macaddress[1], &macaddress[2], &macaddress[3], &macaddress[4], &macaddress[5]) != 6) { return 0; diff --git a/src/common/capwap_network.h b/src/common/capwap_network.h index 69f0041..31c3fe2 100644 --- a/src/common/capwap_network.h +++ b/src/common/capwap_network.h @@ -8,11 +8,6 @@ #define CAPWAP_CONTROL_PORT 5246 #define CAPWAP_MAX_PACKET_SIZE 65535 -#define CAPWAP_MACADDRESS_NONE 0 -#define CAPWAP_MACADDRESS_EUI48 6 -#define CAPWAP_MACADDRESS_EUI64 8 -#define CAPWAP_MACADDRESS_MAX_SIZE CAPWAP_MACADDRESS_EUI64 - /* Helper */ #define CAPWAP_GET_NETWORK_PORT(address) ntohs((((address)->ss_family == AF_INET) ? ((struct sockaddr_in*)(address))->sin_port : ((struct sockaddr_in6*)(address))->sin6_port)) #define CAPWAP_SET_NETWORK_PORT(address, port) if ((address)->ss_family == AF_INET) { \ @@ -95,7 +90,7 @@ int capwap_address_from_string(const char* ip, struct sockaddr_storage* address) int capwap_get_localaddress_by_remoteaddress(struct sockaddr_storage* local, struct sockaddr_storage* remote, char* oif, int ipv6dualstack); -char* capwap_printf_macaddress(char* buffer, const unsigned char* macaddress, int type); -int capwap_scanf_macaddress(unsigned char* macaddress, const char* buffer, int type); +char* capwap_printf_macaddress(char* buffer, const uint8_t* macaddress, int type); +int capwap_scanf_macaddress(uint8_t* macaddress, const char* buffer, int type); #endif /* __CAPWAP_NETWORK_HEADER__ */ diff --git a/src/common/capwap_protocol.c b/src/common/capwap_protocol.c index b3160f3..39590f1 100644 --- a/src/common/capwap_protocol.c +++ b/src/common/capwap_protocol.c @@ -208,7 +208,7 @@ void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int rad ASSERT(data != NULL); header = (struct capwap_header*)&data->headerbuffer[0]; - if (radiotype == CAPWAP_MACADDRESS_NONE) { + if (radiotype == MACADDRESS_NONE_LENGTH) { if (IS_FLAG_M_HEADER(header)) { if (!IS_FLAG_W_HEADER(header)) { SET_HLEN_HEADER(header, sizeof(struct capwap_header) / 4); @@ -230,7 +230,7 @@ void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int rad int size = sizeof(struct capwap_header) / 4; ASSERT(macaddress != NULL); - ASSERT((radiotype == CAPWAP_MACADDRESS_EUI48) || (radiotype == CAPWAP_MACADDRESS_EUI64)); + ASSERT((radiotype == MACADDRESS_EUI48_LENGTH) || (radiotype == MACADDRESS_EUI64_LENGTH)); if (IS_FLAG_M_HEADER(header)) { radio = GET_RADIO_MAC_ADDRESS_STRUCT(header); @@ -242,7 +242,7 @@ void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int rad } /* Remove old radio mac address */ - capwap_header_set_radio_macaddress(data, CAPWAP_MACADDRESS_NONE, NULL); + capwap_header_set_radio_macaddress(data, MACADDRESS_NONE_LENGTH, NULL); } /* Radio mac address size*/ @@ -1001,6 +1001,45 @@ int capwap_packet_rxmng_add_recv_packet(struct capwap_packet_rxmng* rxmngpacket, return CAPWAP_WRONG_FRAGMENT; } +/* */ +struct capwap_packet_rxmng* capwap_packet_rxmng_create_from_requestfragmentpacket(struct capwap_list* requestfragmentpacket) { + struct capwap_packet_rxmng* rxmngpacket; + struct capwap_list_item* fragment; + int result = CAPWAP_WRONG_FRAGMENT; + + ASSERT(requestfragmentpacket != NULL); + + if (!requestfragmentpacket->count) { + return NULL; + } + + /* */ + rxmngpacket = capwap_packet_rxmng_create_message(CAPWAP_CONTROL_PACKET); + + /* */ + fragment = requestfragmentpacket->first; + while (fragment != NULL) { + struct capwap_fragment_packet_item* fragmentpacket = (struct capwap_fragment_packet_item*)fragment->item; + + /* Append fragment */ + result = capwap_packet_rxmng_add_recv_packet(rxmngpacket, fragmentpacket->buffer, fragmentpacket->offset); + if (result == CAPWAP_WRONG_FRAGMENT) { + break; + } + + /* Next fragment */ + fragment = fragment->next; + } + + /* */ + if (result != CAPWAP_RECEIVE_COMPLETE_PACKET) { + capwap_packet_rxmng_free(rxmngpacket); + rxmngpacket = NULL; + } + + return rxmngpacket; +} + /* */ void capwap_packet_rxmng_free(struct capwap_packet_rxmng* rxmngpacket) { if (rxmngpacket) { diff --git a/src/common/capwap_protocol.h b/src/common/capwap_protocol.h index 202fd29..d2be424 100644 --- a/src/common/capwap_protocol.h +++ b/src/common/capwap_protocol.h @@ -107,10 +107,16 @@ struct capwap_packet_rxmng { #define CAPWAP_REQUEST_MORE_FRAGMENT 0 #define CAPWAP_RECEIVE_COMPLETE_PACKET 1 +#define CAPWAP_CONTROL_PACKET 1 +#define CAPWAP_DATA_PACKET 0 + struct capwap_packet_rxmng* capwap_packet_rxmng_create_message(int isctrlpacket); int capwap_packet_rxmng_add_recv_packet(struct capwap_packet_rxmng* rxmngpacket, void* data, int length); void capwap_packet_rxmng_free(struct capwap_packet_rxmng* rxmngpacket); +/* Parsing a packet sent */ +struct capwap_packet_rxmng* capwap_packet_rxmng_create_from_requestfragmentpacket(struct capwap_list* requestfragmentpacket); + /* */ int capwap_is_request_type(unsigned long type); diff --git a/src/common/capwap_rfc.h b/src/common/capwap_rfc.h index 4d3dcc4..dc3e556 100644 --- a/src/common/capwap_rfc.h +++ b/src/common/capwap_rfc.h @@ -188,6 +188,9 @@ struct capwap_data_message { #define IS_SEQUENCE_SMALLER(s1, s2) (((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0) +/* */ +#define MACADDRESS_NONE_LENGTH 0 + /* */ #define MACADDRESS_EUI48_LENGTH 6 struct capwap_macaddress_eui48 { diff --git a/src/wtp/wtp_dfa.c b/src/wtp/wtp_dfa.c index 74af67e..78edeca 100644 --- a/src/wtp/wtp_dfa.c +++ b/src/wtp/wtp_dfa.c @@ -22,13 +22,13 @@ static struct capwap_packet_rxmng* wtp_get_packet_rxmng(int isctrlmsg) { if (isctrlmsg) { if (!g_wtp.rxmngctrlpacket) { - g_wtp.rxmngctrlpacket = capwap_packet_rxmng_create_message(1); + g_wtp.rxmngctrlpacket = capwap_packet_rxmng_create_message(CAPWAP_CONTROL_PACKET); } rxmngpacket = g_wtp.rxmngctrlpacket; } else { if (!g_wtp.rxmngdatapacket) { - g_wtp.rxmngdatapacket = capwap_packet_rxmng_create_message(0); + g_wtp.rxmngdatapacket = capwap_packet_rxmng_create_message(CAPWAP_DATA_PACKET); } rxmngpacket = g_wtp.rxmngdatapacket; diff --git a/src/wtp/wtp_dfa_run.c b/src/wtp/wtp_dfa_run.c index 5ed10ac..1441811 100644 --- a/src/wtp/wtp_dfa_run.c +++ b/src/wtp/wtp_dfa_run.c @@ -99,6 +99,47 @@ static void receive_reset_request(struct capwap_parsed_packet* packet) { } } +/* */ +static void receive_station_configuration_request(struct capwap_parsed_packet* packet) { + unsigned short binding; + + ASSERT(packet != NULL); + + /* */ + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + 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; + + /* TODO */ + + /* 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 */ + + /* Station Configuration response complete, get fragment packets */ + wtp_free_reference_last_response(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, g_wtp.responsefragmentpacket, g_wtp.fragmentid); + if (g_wtp.responsefragmentpacket->count > 1) { + g_wtp.fragmentid++; + } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Save remote sequence number */ + g_wtp.remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq; + capwap_get_packet_digest(packet->rxmngpacket, packet->connection, g_wtp.lastrecvpackethash); + + /* Send Station Configuration response to AC */ + if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.responsefragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { + capwap_logging_debug("Warning: error to send Station Configuration response packet"); + } + } +} + /* */ static void receive_ieee80211_wlan_configuration_request(struct capwap_parsed_packet* packet) { unsigned short binding; @@ -293,7 +334,7 @@ void wtp_dfa_state_run(struct capwap_parsed_packet* packet) { } case CAPWAP_STATION_CONFIGURATION_REQUEST: { - /* TODO */ + receive_station_configuration_request(packet); break; }