diff --git a/src/ac/ac_dfa_run.c b/src/ac/ac_dfa_run.c index c6683f7..55220b3 100644 --- a/src/ac/ac_dfa_run.c +++ b/src/ac/ac_dfa_run.c @@ -64,10 +64,14 @@ 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) { +static void execute_ieee80211_wlan_configuration_addwlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) { struct ac_wlan* wlan; + struct capwap_80211_addwlan_element* addwlan; struct capwap_80211_assignbssid_element* assignbssid; + /* */ + addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN); + /* 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)) { @@ -79,18 +83,23 @@ static void execute_ieee80211_wlan_configuration_addwlan(struct ac_session_t* se } /* */ -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_updatewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) { + //struct capwap_80211_updatewlan_element* updatewlan; + + /* */ + //updatewlan = (struct capwap_80211_updatewlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN); } /* */ -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 execute_ieee80211_wlan_configuration_deletewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) { + //struct capwap_80211_deletewlan_element* deletewlan; + + /* */ + //deletewlan = (struct capwap_80211_deletewlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN); } /* */ 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; @@ -102,19 +111,12 @@ static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* s 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); - } - } + if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN)) { + execute_ieee80211_wlan_configuration_addwlan(session, packet, &requestpacket); + } else if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN)) { + execute_ieee80211_wlan_configuration_updatewlan(session, packet, &requestpacket); + } else if (capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN)) { + execute_ieee80211_wlan_configuration_deletewlan(session, packet, &requestpacket); } } @@ -131,7 +133,8 @@ static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* s } /* */ -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) { +static void execute_ieee80211_station_configuration_response_addstation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) { + struct capwap_addstation_element* addstation; struct ac_notify_add_station_status notify; struct capwap_80211_station_element* station80211; unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header); @@ -139,10 +142,11 @@ static void execute_ieee80211_wlan_configuration_response_addstation(struct ac_s /* */ resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE); + addstation = (struct capwap_addstation_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_ADDSTATION); /* */ if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_STATION); + station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_STATION); if (station80211) { memset(¬ify, 0, sizeof(struct ac_notify_add_station_status)); @@ -157,28 +161,25 @@ static void execute_ieee80211_wlan_configuration_response_addstation(struct ac_s } /* */ -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) { +static void execute_ieee80211_station_configuration_response_deletestation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) { + //struct capwap_deletestation_element* deletestation; + /* TODO */ + //deletestation = (struct capwap_deletestation_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_DELETESTATION); } /* */ 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); - } + if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_ADDSTATION)) { + execute_ieee80211_station_configuration_response_addstation(session, packet, &requestpacket); + } else if (capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_DELETESTATION)) { + execute_ieee80211_station_configuration_response_deletestation(session, packet, &requestpacket); } } diff --git a/src/ac/ac_ieee80211_data.c b/src/ac/ac_ieee80211_data.c index d97a7b0..e2ac032 100644 --- a/src/ac/ac_ieee80211_data.c +++ b/src/ac/ac_ieee80211_data.c @@ -42,6 +42,10 @@ static void ac_ieee80211_mgmt_authentication_packet(struct ac_session_data_t* se capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH); capwap_logging_info("Receive IEEE802.11 Authentication Request from %s station", buffer); + /* A station is removed if the association does not complete within a given period of time */ + station->timeoutaction = AC_STATION_TIMEOUT_ACTION_DEAUTHENTICATE; + station->idtimeout = capwap_timeout_set(sessiondata->timeout, station->idtimeout, AC_STATION_TIMEOUT_ASSOCIATION_COMPLETE, ac_stations_timeout, station, sessiondata); + /* */ if (station->wlan->macmode == CAPWAP_ADD_WLAN_MACMODE_LOCAL) { /* TODO */ diff --git a/src/ac/ac_session_data.c b/src/ac/ac_session_data.c index dcf12d5..53ce3e2 100644 --- a/src/ac/ac_session_data.c +++ b/src/ac/ac_session_data.c @@ -14,13 +14,20 @@ 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; + char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; 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)) { + /* */ + capwap_logging_info("Authorized station: %s", capwap_printf_macaddress(buffer, station->address, MACADDRESS_EUI48_LENGTH)); + + /* */ station->flags |= AC_STATION_FLAGS_AUTHORIZED; + capwap_timeout_deletetimer(sessiondata->timeout, station->idtimeout); + station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET; } else { ac_stations_delete_station(sessiondata, station); } @@ -378,11 +385,9 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) { /* Get packet */ length = ac_network_read(sessiondata, buffer, sizeof(buffer)); if (length < 0) { - if ((length == AC_ERROR_ACTION_SESSION) || (length == CAPWAP_ERROR_AGAIN)) { - continue; /* Nothing */ + if ((length == CAPWAP_ERROR_SHUTDOWN) || (length == CAPWAP_ERROR_CLOSE)) { + break; /* Close Session Data */ } - - break; /* Close Session Data */ } else if (length > 0) { /* Check generic capwap packet */ check = capwap_sanity_check(0, CAPWAP_UNDEF_STATE, buffer, length, 0, 0); diff --git a/src/ac/ac_wlans.c b/src/ac/ac_wlans.c index 2cf34dd..6caeba5 100644 --- a/src/ac/ac_wlans.c +++ b/src/ac/ac_wlans.c @@ -22,6 +22,32 @@ static void ac_stations_delete_station_from_global_cache(struct ac_session_data_ capwap_rwlock_exit(&g_ac.stationslock); } +/* */ +static void ac_stations_reset_station(struct ac_session_data_t* sessiondata, struct ac_station* station, struct ac_wlan* wlan) { + ASSERT(sessiondata != NULL); + ASSERT(station != NULL); + + /* Remove reference from current WLAN */ + if (station->wlan) { + capwap_itemlist_remove(station->wlan->stations, station->wlanitem); + } + + /* Remove timers */ + if (station->idtimeout != CAPWAP_TIMEOUT_INDEX_NO_SET) { + capwap_timeout_deletetimer(sessiondata->timeout, station->idtimeout); + station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET; + } + + /* */ + station->flags = 0; + + /* Set WLAN */ + station->wlan = wlan; + if (station->wlan) { + capwap_itemlist_insert_after(wlan->stations, NULL, station->wlanitem); + } +} + /* */ static void ac_stations_destroy_station(struct ac_session_data_t* sessiondata, struct ac_station* station) { char buffer[CAPWAP_MACADDRESS_EUI48_BUFFER]; @@ -36,9 +62,7 @@ static void ac_stations_destroy_station(struct ac_session_data_t* sessiondata, s ac_stations_delete_station_from_global_cache(sessiondata, station->address); /* Remove reference from WLAN */ - if (station->wlan) { - capwap_itemlist_remove(station->wlan->stations, station->wlanitem); - } + ac_stations_reset_station(sessiondata, station, NULL); /* */ capwap_hash_delete(sessiondata->wlans->stations, station->address); @@ -56,24 +80,6 @@ static unsigned long ac_wlans_item_gethash(const void* key, unsigned long keysiz return (unsigned long)(macaddress[3] ^ macaddress[4] ^ macaddress[5]); } -/* */ -static void ac_stations_reset_station(struct ac_station* station, struct ac_wlan* wlan) { - ASSERT(station != NULL); - ASSERT(wlan != NULL); - - /* Remove reference from current WLAN */ - if (station->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_data_t* sessiondata) { ASSERT(sessiondata != NULL); @@ -308,7 +314,7 @@ struct ac_station* ac_stations_get_station(struct ac_session_data_t* sessiondata /* Get station */ 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))) { + if (station && (station->flags & AC_STATION_FLAGS_ENABLED) && ((radioid == RADIOID_ANY) || (radioid == station->wlan->radioid)) && (!bssid || !memcmp(bssid, station->wlan->bssid, MACADDRESS_EUI48_LENGTH))) { return station; } @@ -355,13 +361,14 @@ struct ac_station* ac_stations_create_station(struct ac_session_data_t* sessiond /* */ wlan = ac_wlans_get_bssid(sessiondata, radioid, bssid); - station = ac_stations_get_station(sessiondata, RADIOID_ANY, NULL, address); + station = (struct ac_station*)capwap_hash_search(sessiondata->wlans->stations, address); if (!station) { stationitem = capwap_itemlist_create(sizeof(struct ac_station)); station = (struct ac_station*)stationitem->item; memset(station, 0, sizeof(struct ac_station)); /* */ + station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET; memcpy(station->address, address, MACADDRESS_EUI48_LENGTH); station->wlanitem = stationitem; @@ -370,7 +377,8 @@ struct ac_station* ac_stations_create_station(struct ac_session_data_t* sessiond } /* Set station to WLAN */ - ac_stations_reset_station(station, wlan); + ac_stations_reset_station(sessiondata, station, wlan); + station->flags |= AC_STATION_FLAGS_ENABLED; return station; } @@ -422,16 +430,19 @@ void ac_stations_deauthorize_station(struct ac_session_data_t* sessiondata, stru ASSERT(sessiondata->wlans != NULL); ASSERT(station != NULL); - /* Delete Station only if Authrizated */ + /* Deauthorize station */ 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) { + } + + /* Deauthenticate station */ + 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); @@ -446,3 +457,24 @@ void ac_stations_deauthorize_station(struct ac_session_data_t* sessiondata, stru } } } + +/* */ +void ac_stations_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) { + char stationaddress[CAPWAP_MACADDRESS_EUI48_BUFFER]; + struct ac_station* station = (struct ac_station*)context; + + ASSERT(station != NULL); + + /* */ + capwap_printf_macaddress(stationaddress, station->address, MACADDRESS_EUI48_LENGTH); + + if (station->idtimeout == index) { + switch (station->timeoutaction) { + case AC_STATION_TIMEOUT_ACTION_DEAUTHENTICATE: { + capwap_logging_warning("The %s station has not completed the association in time", stationaddress); + ac_stations_delete_station((struct ac_session_data_t*)param, station); + break; + } + } + } +} diff --git a/src/ac/ac_wlans.h b/src/ac/ac_wlans.h index 16c333c..145993f 100644 --- a/src/ac/ac_wlans.h +++ b/src/ac/ac_wlans.h @@ -41,9 +41,16 @@ struct ac_wlan { }; /* */ -#define AC_STATION_FLAGS_AUTHENTICATED 0x00000001 -#define AC_STATION_FLAGS_ASSOCIATE 0x00000002 -#define AC_STATION_FLAGS_AUTHORIZED 0x00000004 +#define AC_STATION_TIMEOUT_ASSOCIATION_COMPLETE 30000 + +/* */ +#define AC_STATION_TIMEOUT_ACTION_DEAUTHENTICATE 0x00000001 + +/* */ +#define AC_STATION_FLAGS_ENABLED 0x00000001 +#define AC_STATION_FLAGS_AUTHENTICATED 0x00000002 +#define AC_STATION_FLAGS_ASSOCIATE 0x00000004 +#define AC_STATION_FLAGS_AUTHORIZED 0x00000008 /* AC Station */ struct ac_station { @@ -54,6 +61,10 @@ struct ac_station { struct ac_wlan* wlan; struct capwap_list_item* wlanitem; + /* Timers */ + int timeoutaction; + unsigned long idtimeout; + /* */ uint16_t capability; uint16_t listeninterval; @@ -93,4 +104,7 @@ void ac_stations_delete_station(struct ac_session_data_t* sessiondata, struct ac 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); +/* */ +void ac_stations_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param); + #endif /* __AC_WLANS_HEADER__ */ diff --git a/src/wtp/binding/ieee80211/wifi_nl80211.c b/src/wtp/binding/ieee80211/wifi_nl80211.c index b71fc03..d9eabe6 100644 --- a/src/wtp/binding/ieee80211/wifi_nl80211.c +++ b/src/wtp/binding/ieee80211/wifi_nl80211.c @@ -2698,7 +2698,7 @@ int nl80211_station_authorize(wifi_wlan_handle handle, struct station_add_params } /* */ - capwap_logging_info("Authorize station: %s", capwap_printf_macaddress(buffer, params->address, MACADDRESS_EUI48_LENGTH)); + capwap_logging_info("Authorized station: %s", capwap_printf_macaddress(buffer, params->address, MACADDRESS_EUI48_LENGTH)); /* */ capwap_timeout_deletetimer(station->globalhandle->timeout, station->idtimeout);