diff --git a/src/ac/ac_dfa_reset.c b/src/ac/ac_dfa_reset.c index 2dcc064..2745a7b 100644 --- a/src/ac/ac_dfa_reset.c +++ b/src/ac/ac_dfa_reset.c @@ -21,17 +21,19 @@ void ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packe capwap_logging_warning("Receive Reset Response with error: %d", (int)resultcode->code); } + /* */ + ac_free_reference_last_request(session); ac_session_teardown(session); } } else { - /* No Configuration status response received */ + /* No Reset Response received */ session->dfa.rfcRetransmitCount++; if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) { /* Timeout reset state */ ac_free_reference_last_request(session); ac_session_teardown(session); } else { - /* Retransmit configuration request */ + /* Retransmit Reset Request */ if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) { capwap_logging_debug("Warning: error to resend reset request packet"); } diff --git a/src/ac/ac_dfa_run.c b/src/ac/ac_dfa_run.c index 648405f..7503ffb 100644 --- a/src/ac/ac_dfa_run.c +++ b/src/ac/ac_dfa_run.c @@ -61,6 +61,20 @@ static int receive_echo_request(struct ac_session_t* session, struct capwap_pars return 0; } +/* */ +static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) { + 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)) { + capwap_logging_warning("Receive IEEE802.11 WLAN Configuration Response with error: %d", (int)resultcode->code); + } + + /* */ + ac_free_reference_last_request(session); +} + /* */ void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) { ASSERT(session != NULL); @@ -70,6 +84,8 @@ void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* switch (packet->rxmngpacket->ctrlmsg.type) { case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: { /* TODO */ + + /* */ capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); break; } @@ -92,6 +108,8 @@ void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: { /* TODO */ + + /* */ capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); break; } @@ -110,63 +128,44 @@ void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* case CAPWAP_DATA_TRANSFER_RESPONSE: { /* TODO */ + + /* */ capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); break; } case CAPWAP_STATION_CONFIGURATION_RESPONSE: { /* TODO */ + + /* */ capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); break; } case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: { - /* TODO */ + receive_ieee80211_wlan_configuration_response(session, packet); capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); break; } } } + } else if ((session->requestfragmentpacket->count > 0)) { + /* No response received */ + session->dfa.rfcRetransmitCount++; + if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) { + /* Timeout */ + ac_free_reference_last_request(session); + ac_session_teardown(session); + } else { + /* Retransmit request */ + if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) { + capwap_logging_debug("Warning: error to resend request packet"); + } + + /* Update timeout */ + capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + } } else { ac_session_teardown(session); } } - -/* */ -void ac_session_reset(struct ac_session_t* session, struct capwap_imageidentifier_element* startupimage) { - struct capwap_header_data capwapheader; - struct capwap_packet_txmng* txmngpacket; - - ASSERT(session != NULL); - ASSERT(startupimage != NULL); - - /* Build packet */ - capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding); - txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_RESET_REQUEST, session->localseqnumber++, session->mtu); - - /* Add message element */ - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_IMAGEIDENTIFIER, startupimage); - /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ - - /* Reset request complete, get fragment packets */ - ac_free_reference_last_request(session); - 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 Configure response 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->dfa.rfcRetransmitCount = 0; - capwap_killall_timeout(&session->timeout); - capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - ac_dfa_change_state(session, CAPWAP_RESET_STATE); - } else { - capwap_logging_debug("Warning: error to send reset request packet"); - ac_free_reference_last_request(session); - ac_session_teardown(session); - } -} diff --git a/src/ac/ac_session.c b/src/ac/ac_session.c index fa486a1..defddba 100644 --- a/src/ac/ac_session.c +++ b/src/ac/ac_session.c @@ -8,6 +8,104 @@ #define AC_ERROR_TIMEOUT -1000 #define AC_ERROR_ACTION_SESSION -1001 +/* */ +static int ac_session_action_resetwtp(struct ac_session_t* session, struct ac_notify_reset_t* reset) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + struct capwap_imageidentifier_element imageidentifier; + + ASSERT(session->requestfragmentpacket->count == 0); + + /* */ + imageidentifier.vendor = reset->vendor; + imageidentifier.name = reset->name; + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_RESET_REQUEST, session->localseqnumber++, session->mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_IMAGEIDENTIFIER, &imageidentifier); + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + + /* Reset 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 Reset 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->dfa.rfcRetransmitCount = 0; + capwap_killall_timeout(&session->timeout); + capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + ac_dfa_change_state(session, CAPWAP_RESET_STATE); + } else { + capwap_logging_debug("Warning: error to send reset request packet"); + ac_free_reference_last_request(session); + ac_session_teardown(session); + } + + return AC_ERROR_ACTION_SESSION; +} + +/* */ +static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_notify_addwlan_t* notify) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + struct capwap_80211_addwlan_element addwlan; + + ASSERT(session->requestfragmentpacket->count == 0); + + /* */ + memset(&addwlan, 0, sizeof(struct capwap_80211_addwlan_element)); + addwlan.radioid = notify->radioid; + addwlan.wlanid = notify->wlanid; + addwlan.capability = notify->capability; + addwlan.qos = notify->qos; + addwlan.authmode = notify->authmode; + addwlan.macmode = notify->macmode; + addwlan.tunnelmode = notify->tunnelmode; + addwlan.suppressssid = notify->suppressssid; + addwlan.ssid = (uint8_t*)notify->ssid; + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST, session->localseqnumber++, session->mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ADD_WLAN, &addwlan); + + /* CAPWAP_ELEMENT_80211_IE */ + + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + + /* WLAN 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 WLAN 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->dfa.rfcRetransmitCount = 0; + capwap_killall_timeout(&session->timeout); + capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + } else { + capwap_logging_debug("Warning: error to send reset request packet"); + ac_free_reference_last_request(session); + ac_session_teardown(session); + } + + return AC_ERROR_ACTION_SESSION; +} + /* */ static int ac_session_action_execute(struct ac_session_t* session, struct ac_session_action* action) { int result = AC_ERROR_ACTION_SESSION; @@ -19,14 +117,12 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses } case AC_SESSION_ACTION_RESET_WTP: { - struct capwap_imageidentifier_element imageidentifier; - struct ac_notify_reset_t* reset = (struct ac_notify_reset_t*)action->data; - - /* Send reset command */ - imageidentifier.vendor = reset->vendor; - imageidentifier.name = reset->name; - ac_session_reset(session, &imageidentifier); + result = ac_session_action_resetwtp(session, (struct ac_notify_reset_t*)action->data); + break; + } + case AC_SESSION_ACTION_ADDWLAN: { + result = ac_session_action_addwlan(session, (struct ac_notify_addwlan_t*)action->data); break; } @@ -51,15 +147,6 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses break; } - case AC_SESSION_ACTION_ADDWLAN: { - struct ac_notify_addwlan_t* addwlan = (struct ac_notify_addwlan_t*)action->data; - - /* TODO */ - addwlan = NULL; - - break; - } - case AC_SESSION_ACTION_NOTIFY_EVENT: { struct capwap_list_item* item; @@ -91,7 +178,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt if (!session->running) { capwap_lock_exit(&session->sessionlock); return CAPWAP_ERROR_CLOSE; - } else if (!session->waitresponse && (session->action->count > 0)) { + } else if (!session->requestfragmentpacket->count && (session->action->count > 0)) { struct capwap_list_item* itemaction; itemaction = capwap_itemlist_remove_head(session->action); @@ -451,9 +538,11 @@ static void ac_session_run(struct ac_session_t* session) { } else if (!hasrequest && (notify->action == NOTIFY_ACTION_RECEIVE_RESPONSE_CONTROLMESSAGE)) { char buffer[4]; struct ac_soap_response* response; + struct capwap_resultcode_element* resultcode; - /* TODO: check result code of control message */ - response = ac_soap_updatebackendevent(session, notify->idevent, capwap_itoa(SOAP_EVENT_STATUS_COMPLETE, buffer)); + /* Check the success of the Request */ + resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(&packet, CAPWAP_ELEMENT_RESULTCODE); + response = ac_soap_updatebackendevent(session, notify->idevent, capwap_itoa(((!resultcode || CAPWAP_RESULTCODE_OK(resultcode->code)) ? SOAP_EVENT_STATUS_COMPLETE : SOAP_EVENT_STATUS_GENERIC_ERROR), buffer)); if (response) { ac_soapclient_free_response(response); } diff --git a/src/ac/ac_session.h b/src/ac/ac_session.h index a13f99d..6847f8c 100644 --- a/src/ac/ac_session.h +++ b/src/ac/ac_session.h @@ -96,7 +96,6 @@ struct ac_session_t { char* wtpid; unsigned long state; struct ac_state dfa; - int waitresponse; unsigned short binding; struct ac_session_data_t* sessiondata; @@ -127,7 +126,6 @@ struct ac_session_t { /* Session */ void* ac_session_thread(void* param); void ac_session_send_action(struct ac_session_t* session, long action, long param, void* data, long length); -void ac_session_reset(struct ac_session_t* session, struct capwap_imageidentifier_element* startupimage); void ac_session_teardown(struct ac_session_t* session); void ac_session_close(struct ac_session_t* session); void ac_session_release_reference(struct ac_session_t* session); diff --git a/src/common/capwap_element.c b/src/common/capwap_element.c index cef68a0..ec7ddc8 100644 --- a/src/common/capwap_element.c +++ b/src/common/capwap_element.c @@ -648,6 +648,22 @@ int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct ca break; } + + case CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST: { + if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_ADD_WLAN)) { + return 0; + } + + break; + } + + case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: { + if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) { + return 0; + } + + break; + } } } else if (IS_FLAG_K_HEADER(packet->rxmngpacket->header)) { /* Keep alive data message require session id */ @@ -656,7 +672,7 @@ int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct ca } } - return 1; + return -1; } /* */ diff --git a/src/common/capwap_element_80211_addwlan.c b/src/common/capwap_element_80211_addwlan.c index 1cc35fb..9e33703 100644 --- a/src/common/capwap_element_80211_addwlan.c +++ b/src/common/capwap_element_80211_addwlan.c @@ -138,7 +138,7 @@ static void* capwap_80211_addwlan_element_parsing(capwap_message_elements_handle func->read_u8(handle, &data->tunnelmode); func->read_u8(handle, &data->suppressssid); - length -= (19 + data->keylength); + length = func->read_ready(handle); if (!length || (length > CAPWAP_ADD_WLAN_SSID_LENGTH)) { capwap_80211_addwlan_element_free((void*)data); capwap_logging_debug("Invalid IEEE 802.11 Add WLAN element: invalid ssid"); diff --git a/src/common/capwap_element_80211_addwlan.h b/src/common/capwap_element_80211_addwlan.h index 04573b0..0fdb85a 100644 --- a/src/common/capwap_element_80211_addwlan.h +++ b/src/common/capwap_element_80211_addwlan.h @@ -3,7 +3,7 @@ #define CAPWAP_ELEMENT_80211_ADD_WLAN 1024 -#define CAPWAP_ADD_WLAN_GROUPTSC_LENGTH 4 +#define CAPWAP_ADD_WLAN_GROUPTSC_LENGTH 6 #define CAPWAP_ADD_WLAN_SSID_LENGTH 32 #define CAPWAP_ADD_WLAN_CAPABILITY_ESS 0x8000 diff --git a/src/wtp/wtp.c b/src/wtp/wtp.c index 0559b8f..0d70b12 100644 --- a/src/wtp/wtp.c +++ b/src/wtp/wtp.c @@ -98,6 +98,7 @@ static int wtp_init(void) { g_wtp.mtu = CAPWAP_MTU_DEFAULT; g_wtp.requestfragmentpacket = capwap_list_create(); g_wtp.responsefragmentpacket = capwap_list_create(); + g_wtp.remoteseqnumber = WTP_INIT_REMOTE_SEQUENCE; /* AC information */ g_wtp.discoverytype.type = CAPWAP_DISCOVERYTYPE_TYPE_UNKNOWN; diff --git a/src/wtp/wtp.h b/src/wtp/wtp.h index 5f1e696..334d1df 100644 --- a/src/wtp/wtp.h +++ b/src/wtp/wtp.h @@ -36,6 +36,8 @@ #define WTP_DEFAULT_DTLS_SESSION_DELETE 5 #define WTP_DEFAULT_FAILED_DTLS_SESSION_RETRY 3 +#define WTP_INIT_REMOTE_SEQUENCE 0xff + /* WTP State machine */ struct wtp_state { unsigned long state; diff --git a/src/wtp/wtp_dfa_run.c b/src/wtp/wtp_dfa_run.c index 638634b..8de930e 100644 --- a/src/wtp/wtp_dfa_run.c +++ b/src/wtp/wtp_dfa_run.c @@ -98,6 +98,49 @@ static void receive_reset_request(struct capwap_parsed_packet* packet) { } } +/* */ +static void receive_ieee80211_wlan_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; + struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_SUCCESS }; + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, g_wtp.mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); + /* CAPWAP_ELEMENT_80211_ASSIGN_BSSID */ /* TODO */ + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + + /* IEEE802.11 WLAN 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 IEEE802.11 WLAN 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 IEEE802.11 WLAN Configuration response packet"); + } + } +} + /* */ void wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); @@ -158,7 +201,7 @@ void wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_contr } case CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST: { - /* TODO */ + receive_ieee80211_wlan_configuration_request(packet); break; } }