static int ac_backend_soap_update_event(const char* idevent, int status) { int result = 0; char buffer[256]; struct ac_soap_request* request = NULL; struct ac_http_soap_server* server; ASSERT(g_ac_backend.soaprequest == NULL); ASSERT(g_ac_backend.backendsessionid != NULL); /* Get HTTP Soap Server */ server = ac_backend_get_server(); /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Build Soap Request */ if (!g_ac_backend.endthread) { request = ac_soapclient_create_request("updateBackendEvent", SOAP_NAMESPACE_URI); if (request) { ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid); ac_soapclient_add_param(request, "xs:string", "idevent", idevent); ac_soapclient_add_param(request, "xs:int", "status", capwap_itoa(status, buffer)); g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server); } } capwap_lock_exit(&g_ac_backend.lock); /* */ if (!g_ac_backend.soaprequest) { if (request) { ac_soapclient_free_request(request); } return 0; } /* Send Request & Recv Response */ if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) { struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest); if (response) { ac_soapclient_free_response(response); } } /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Free resource */ ac_soapclient_close_request(g_ac_backend.soaprequest, 1); g_ac_backend.soaprequest = NULL; capwap_lock_exit(&g_ac_backend.lock); return result; }
/* Teardown connection */ void ac_session_teardown(struct ac_session_t* session) { ASSERT(session != NULL); /* Remove session from list */ capwap_rwlock_wrlock(&g_ac.sessionslock); capwap_itemlist_remove(g_ac.sessions, session->itemlist); capwap_rwlock_unlock(&g_ac.sessionslock); /* Remove all pending packets */ while (session->packets->count > 0) { capwap_itemlist_free(capwap_itemlist_remove_head(session->packets)); } /* Close DTSL Control */ if (session->dtls.enable) { capwap_crypt_close(&session->dtls); } /* Cancel all notify event */ if (session->notifyevent->first) { char buffer[5]; struct ac_soap_response* response; capwap_itoa(SOAP_EVENT_STATUS_CANCEL, buffer); while (session->notifyevent->first != NULL) { struct ac_session_notify_event_t* notify = (struct ac_session_notify_event_t*)session->notifyevent->first->item; /* Cancel event */ response = ac_soap_updatebackendevent(session, notify->idevent, buffer); if (response) { ac_soapclient_free_response(response); } /* Remove notify event */ capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, session->notifyevent->first)); } } /* Remove timer */ if (session->idtimercontrol != CAPWAP_TIMEOUT_INDEX_NO_SET) { capwap_timeout_unset(session->timeout, session->idtimercontrol); session->idtimercontrol = CAPWAP_TIMEOUT_INDEX_NO_SET; } if (session->idtimerkeepalivedead != CAPWAP_TIMEOUT_INDEX_NO_SET) { capwap_timeout_unset(session->timeout, session->idtimerkeepalivedead); session->idtimerkeepalivedead = CAPWAP_TIMEOUT_INDEX_NO_SET; } /* */ ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE); }
static void ac_backend_soap_leave(void) { struct ac_soap_request* request; struct ac_http_soap_server* server; ASSERT(g_ac_backend.soaprequest == NULL); /* */ if (!g_ac_backend.backendstatus || !g_ac_backend.backendsessionid) { return; } /* Get HTTP Soap Server */ server = ac_backend_get_server(); /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Build Soap Request */ request = ac_soapclient_create_request("leaveBackend", SOAP_NAMESPACE_URI); if (request) { ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid); g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server); } capwap_lock_exit(&g_ac_backend.lock); /* */ if (!g_ac_backend.soaprequest) { if (request) { ac_soapclient_free_request(request); } return; } /* Send Request & Recv Response */ if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) { struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest); if (response) { ac_soapclient_free_response(response); } } /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Free resource */ ac_soapclient_close_request(g_ac_backend.soaprequest, 1); g_ac_backend.soaprequest = NULL; capwap_lock_exit(&g_ac_backend.lock); }
/* Change WTP state machine */ void ac_dfa_change_state(struct ac_session_t* session, int state) { struct capwap_list_item* search; ASSERT(session != NULL); if (state != session->state) { #ifdef DEBUG char sessionname[33]; capwap_sessionid_printf(&session->sessionid, sessionname); capwap_logging_debug("Session AC %s change state from %s to %s", sessionname, capwap_dfa_getname(session->state), capwap_dfa_getname(state)); #endif session->state = state; /* Search into notify event */ search = session->notifyevent->first; while (search != NULL) { struct ac_session_notify_event_t* notify = (struct ac_session_notify_event_t*)search->item; if ((notify->action == NOTIFY_ACTION_CHANGE_STATE) && (notify->session_state == state)) { char buffer[4]; struct ac_soap_response* response; /* */ response = ac_soap_updatebackendevent(session, notify->idevent, capwap_itoa(SOAP_EVENT_STATUS_COMPLETE, buffer)); if (response) { ac_soapclient_free_response(response); } /* Remove notify event */ capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, search)); break; } search = search->next; } } }
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 ac_soap_response* response; 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_NO_ERROR; } /* Need authorization of Director */ response = ac_session_action_authorizestation_request(session, notify->radioid, notify->wlanid, notify->address); if (response) { if (ac_session_action_authorizestation_response(session, response, notify)) { capwap_logging_info("Station is not authorized"); /* TODO kickoff station */ } ac_soapclient_free_response(response); } return AC_NO_ERROR; }
static void ac_session_run(struct ac_session_t* session) { int res; int check; int length; struct capwap_list_item* search; char buffer[CAPWAP_MAX_PACKET_SIZE]; ASSERT(session != NULL); /* Configure DFA */ if (g_ac.enabledtls) { if (!ac_dtls_setup(session)) { ac_session_teardown(session); /* Teardown connection */ } } else { /* Wait Join request */ ac_dfa_change_state(session, CAPWAP_JOIN_STATE); capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_teardown_timeout, session, NULL); } while (session->state != CAPWAP_DTLS_TEARDOWN_STATE) { /* Get packet */ length = ac_network_read(session, buffer, sizeof(buffer)); if (length < 0) { if ((length == CAPWAP_ERROR_SHUTDOWN) || (length == CAPWAP_ERROR_CLOSE)) { ac_session_teardown(session); } } else if (length > 0) { /* Check generic capwap packet */ check = capwap_sanity_check(CAPWAP_UNDEF_STATE, buffer, length, 0); if (check == CAPWAP_PLAIN_PACKET) { struct capwap_parsed_packet packet; /* Defragment management */ if (!session->rxmngpacket) { session->rxmngpacket = capwap_packet_rxmng_create_message(); } /* If request, defragmentation packet */ check = capwap_packet_rxmng_add_recv_packet(session->rxmngpacket, buffer, length); if (check == CAPWAP_RECEIVE_COMPLETE_PACKET) { /* Receive all fragment */ if (capwap_is_request_type(session->rxmngpacket->ctrlmsg.type) && (session->remotetype == session->rxmngpacket->ctrlmsg.type) && (session->remoteseqnumber == session->rxmngpacket->ctrlmsg.seq)) { /* Retransmit response */ if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) { capwap_logging_error("Error to resend response packet"); } else { capwap_logging_debug("Retrasmitted control packet"); } } else { /* Check message type */ res = capwap_check_message_type(session->rxmngpacket); if (res == VALID_MESSAGE_TYPE) { res = capwap_parsing_packet(session->rxmngpacket, &packet); if (res == PARSING_COMPLETE) { int hasrequest = capwap_is_request_type(session->rxmngpacket->ctrlmsg.type); /* Validate packet */ if (!capwap_validate_parsed_packet(&packet, NULL)) { /* Search into notify event */ search = session->notifyevent->first; while (search != NULL) { struct ac_session_notify_event_t* notify = (struct ac_session_notify_event_t*)search->item; if (hasrequest && (notify->action == NOTIFY_ACTION_RECEIVE_REQUEST_CONTROLMESSAGE)) { char buffer[4]; struct ac_soap_response* response; /* */ response = ac_soap_updatebackendevent(session, notify->idevent, capwap_itoa(SOAP_EVENT_STATUS_COMPLETE, buffer)); if (response) { ac_soapclient_free_response(response); } /* Remove notify event */ capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, search)); break; } else if (!hasrequest && (notify->action == NOTIFY_ACTION_RECEIVE_RESPONSE_CONTROLMESSAGE)) { char buffer[4]; struct ac_soap_response* response; 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); 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); } /* Remove notify event */ capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, search)); break; } search = search->next; } /* */ ac_dfa_execute(session, &packet); } else { capwap_logging_debug("Failed validation parsed control packet"); if (capwap_is_request_type(session->rxmngpacket->ctrlmsg.type)) { capwap_logging_warning("Missing Mandatory Message Element, send Response Packet with error"); ac_send_invalid_request(session, CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT); } } } else { capwap_logging_debug("Failed parsing packet"); if ((res == UNRECOGNIZED_MESSAGE_ELEMENT) && capwap_is_request_type(session->rxmngpacket->ctrlmsg.type)) { capwap_logging_warning("Unrecognized Message Element, send Response Packet with error"); ac_send_invalid_request(session, CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT); /* TODO: add the unrecognized message element */ } } } else { capwap_logging_debug("Invalid message type"); if (res == INVALID_REQUEST_MESSAGE_TYPE) { capwap_logging_warning("Unexpected Unrecognized Request, send Response Packet with error"); ac_send_invalid_request(session, CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST); } } } /* Free memory */ capwap_free_parsed_packet(&packet); if (session->rxmngpacket) { capwap_packet_rxmng_free(session->rxmngpacket); session->rxmngpacket = NULL; } } else if (check != CAPWAP_REQUEST_MORE_FRAGMENT) { /* Discard fragments */ if (session->rxmngpacket) { capwap_packet_rxmng_free(session->rxmngpacket); session->rxmngpacket = NULL; } } } } } /* Wait teardown timeout before kill session */ capwap_timeout_wait(AC_DTLS_SESSION_DELETE_INTERVAL); ac_dfa_state_teardown(session); /* Release reference session */ ac_session_destroy(session); }
static int ac_session_action_execute(struct ac_session_t* session, struct ac_session_action* action) { int result = AC_NO_ERROR; switch (action->action) { case AC_SESSION_ACTION_CLOSE: { result = CAPWAP_ERROR_CLOSE; break; } case AC_SESSION_ACTION_RESET_WTP: { 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; } case AC_SESSION_ACTION_RECV_KEEPALIVE: { #ifdef DEBUG { char sessionname[33]; capwap_sessionid_printf(&session->sessionid, sessionname); capwap_logging_debug("Receive Keep-Alive from %s", sessionname); } #endif /* Send keep-alive response */ //ac_kmod_send_keepalive(&session->sessionid); capwap_timeout_set(session->timeout, session->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, ac_dfa_teardown_timeout, session, NULL); /* */ if (session->state == CAPWAP_DATA_CHECK_TO_RUN_STATE) { struct ac_soap_response* response; /* Capwap handshake complete, notify event to backend */ response = ac_soap_runningwtpsession(session, session->wtpid); if (response) { if (response->responsecode == HTTP_RESULT_OK) { ac_dfa_change_state(session, CAPWAP_RUN_STATE); capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL); } else { result = CAPWAP_ERROR_CLOSE; } ac_soapclient_free_response(response); } else { result = CAPWAP_ERROR_CLOSE; } } break; } case AC_SESSION_ACTION_RECV_IEEE80211_MGMT_PACKET: { result = ac_session_action_recv_ieee80211_mgmt_packet(session, (struct capwap_header*)action->data, action->length); break; } case AC_SESSION_ACTION_NOTIFY_EVENT: { struct capwap_list_item* item; /* Copy event into queue */ item = capwap_itemlist_create(sizeof(struct ac_session_notify_event_t)); memcpy(item->item, action->data, sizeof(struct ac_session_notify_event_t)); capwap_itemlist_insert_after(session->notifyevent, NULL, item); break; } case AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_ADD_STATION: { result = ac_session_action_station_configuration_ieee8011_add_station(session, (struct ac_notify_station_configuration_ieee8011_add_station*)action->data); break; } case AC_SESSION_ACTION_STATION_CONFIGURATION_IEEE80211_DELETE_STATION: { result = ac_session_action_station_configuration_ieee8011_delete_station(session, (struct ac_notify_station_configuration_ieee8011_delete_station*)action->data); break; } case AC_SESSION_ACTION_STATION_ROAMING: { struct ac_station* station; /* Delete station */ station = ac_stations_get_station(session, RADIOID_ANY, NULL, (uint8_t*)action->data); if (station) { ac_stations_delete_station(session, station); } break; } } return result; }
static int ac_backend_soap_waitevent(void) { int result = -1; struct ac_soap_request* request = NULL; struct ac_http_soap_server* server; struct json_object* jsonroot = NULL; ASSERT(g_ac_backend.soaprequest == NULL); ASSERT(g_ac_backend.backendsessionid != NULL); /* Get HTTP Soap Server */ server = ac_backend_get_server(); /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Build Soap Request */ if (!g_ac_backend.endthread) { request = ac_soapclient_create_request("waitBackendEvent", SOAP_NAMESPACE_URI); if (request) { ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid); g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server); /* Change result timeout */ g_ac_backend.soaprequest->responsetimeout = SOAP_PROTOCOL_RESPONSE_WAIT_EVENT_TIMEOUT; } } capwap_lock_exit(&g_ac_backend.lock); /* */ if (!g_ac_backend.soaprequest) { if (request) { ac_soapclient_free_request(request); } return -1; } /* Send Request & Recv Response */ if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) { struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest); if (response) { /* Wait event result */ jsonroot = ac_soapclient_parse_json_response(response); ac_soapclient_free_response(response); } } /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Free resource */ ac_soapclient_close_request(g_ac_backend.soaprequest, 1); g_ac_backend.soaprequest = NULL; capwap_lock_exit(&g_ac_backend.lock); /* Parsing JSON command after close event request */ if (jsonroot) { if (json_object_get_type(jsonroot) == json_type_array) { int i; int length; /* Parsing every message into JSON result */ length = json_object_array_length(jsonroot); if (!length) { result = 0; } else { for (i = 0; i < length; i++) { struct json_object* jsonitem = json_object_array_get_idx(jsonroot, i); if (jsonitem && (json_object_get_type(jsonitem) == json_type_object)) { result = ac_backend_parsing_event(jsonitem); if (result) { break; } } } } } /* Free JSON */ json_object_put(jsonroot); } return result; }
static int ac_backend_soap_join(int forcereset) { struct ac_soap_request* request = NULL; struct ac_http_soap_server* server; ASSERT(g_ac_backend.soaprequest == NULL); ASSERT(g_ac_backend.backendsessionid == NULL); /* Get HTTP Soap Server */ server = ac_backend_get_server(); /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Build Soap Request */ if (!g_ac_backend.endthread) { request = ac_soapclient_create_request("joinBackend", SOAP_NAMESPACE_URI); if (request) { ac_soapclient_add_param(request, "xs:string", "idac", g_ac.backendacid); ac_soapclient_add_param(request, "xs:string", "version", g_ac.backendversion); ac_soapclient_add_param(request, "xs:boolean", "forcereset", (forcereset ? "true" : "false")); g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server); } } capwap_lock_exit(&g_ac_backend.lock); /* */ if (!g_ac_backend.soaprequest) { if (request) { ac_soapclient_free_request(request); } return -1; } /* Send Request & Recv Response */ if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) { struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest); if (response) { /* Get join result */ if ((response->responsecode == HTTP_RESULT_OK) && response->xmlResponseReturn) { xmlChar* xmlResult = xmlNodeGetContent(response->xmlResponseReturn); if (xmlStrlen(xmlResult)) { g_ac_backend.backendsessionid = capwap_duplicate_string((const char*)xmlResult); } xmlFree(xmlResult); } /* */ ac_soapclient_free_response(response); } } /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Free resource */ ac_soapclient_close_request(g_ac_backend.soaprequest, 1); g_ac_backend.soaprequest = NULL; capwap_lock_exit(&g_ac_backend.lock); /* Retrieve AC configuration */ if (g_ac_backend.backendsessionid && forcereset) { if (ac_backend_soap_getconfiguration()) { capwap_logging_error("Unable to get AC configuration from Backend Server"); capwap_free(g_ac_backend.backendsessionid); g_ac_backend.backendsessionid = NULL; } } return (g_ac_backend.backendsessionid ? 0 : -1); }
static int ac_backend_soap_getconfiguration(void) { int result = -1; struct ac_soap_request* request = NULL; struct ac_http_soap_server* server; struct json_object* jsonroot = NULL; ASSERT(g_ac_backend.soaprequest == NULL); ASSERT(g_ac_backend.backendsessionid != NULL); /* Get HTTP Soap Server */ server = ac_backend_get_server(); /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Build Soap Request */ if (!g_ac_backend.endthread) { request = ac_soapclient_create_request("getConfiguration", SOAP_NAMESPACE_URI); if (request) { ac_soapclient_add_param(request, "xs:string", "idsession", g_ac_backend.backendsessionid); g_ac_backend.soaprequest = ac_soapclient_prepare_request(request, server); } } capwap_lock_exit(&g_ac_backend.lock); /* */ if (!g_ac_backend.soaprequest) { if (request) { ac_soapclient_free_request(request); } return -1; } /* Send Request & Recv Response */ if (ac_soapclient_send_request(g_ac_backend.soaprequest, "")) { struct ac_soap_response* response = ac_soapclient_recv_response(g_ac_backend.soaprequest); if (response) { /* Get Configuration result */ jsonroot = ac_soapclient_parse_json_response(response); ac_soapclient_free_response(response); } } /* Critical section */ capwap_lock_enter(&g_ac_backend.lock); /* Free resource */ ac_soapclient_close_request(g_ac_backend.soaprequest, 1); g_ac_backend.soaprequest = NULL; capwap_lock_exit(&g_ac_backend.lock); /* Send JSON command to primary thread */ if (jsonroot) { result = ac_msgqueue_update_configuration(jsonroot); if (result) { json_object_put(jsonroot); } } return result; }
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet) { unsigned short binding; struct ac_soap_response* response; struct capwap_header_data capwapheader; struct capwap_packet_txmng* txmngpacket; struct capwap_sessionid_element* sessionid; struct capwap_wtpboarddata_element* wtpboarddata; struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE }; ASSERT(session != NULL); ASSERT(packet != NULL); /* Check binding */ binding = GET_WBID_HEADER(packet->rxmngpacket->header); if (ac_valid_binding(binding)) { if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) { /* Get sessionid and verify unique id */ sessionid = (struct capwap_sessionid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_SESSIONID); if (!ac_has_sessionid(sessionid)) { char* wtpid; /* Checking macaddress for detect if WTP already connected */ wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA); /* Get printable WTPID */ wtpid = ac_get_printable_wtpid(wtpboarddata); if (wtpid && !ac_has_wtpid(wtpid)) { /* Request authorization of Backend for complete join */ response = ac_soap_authorizewtpsession(session, wtpid); if (response) { resultcode.code = ac_dfa_state_join_check_authorizejoin(session, response); ac_soapclient_free_response(response); } else { resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE; } } else { capwap_logging_info("WTP Id %s already used in another session", wtpid); resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE; } /* */ if (CAPWAP_RESULTCODE_OK(resultcode.code)) { session->wtpid = wtpid; memcpy(&session->sessionid, sessionid, sizeof(struct capwap_sessionid_element)); session->binding = binding; } else if (wtpid) { capwap_free(wtpid); } } else { char sessionname[33]; capwap_sessionid_printf(sessionid, sessionname); capwap_logging_info("Session Id %s already used in another session", sessionname); resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE; } } else { resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE; } } else { resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED; } /* Create response */ capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding); txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_JOIN_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu); /* */ if (CAPWAP_RESULTCODE_OK(resultcode.code)) { response = ac_dfa_state_join_parsing_request(session, packet); if (response) { resultcode.code = ac_dfa_state_join_create_response(session, packet, response, txmngpacket); ac_soapclient_free_response(response); } } /* Add always result code message element */ capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); /* Join response complete, get fragment packets */ ac_free_reference_last_response(session); capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid); if (session->responsefragmentpacket->count > 1) { session->fragmentid++; } /* Free packets manager */ capwap_packet_txmng_free(txmngpacket); /* Save remote sequence number */ session->remotetype = packet->rxmngpacket->ctrlmsg.type; session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq; /* Send Join response to WTP */ if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) { if (CAPWAP_RESULTCODE_OK(resultcode.code)) { ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE); capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_teardown_timeout, session, NULL); } else { ac_session_teardown(session); } } else { /* Error to send packets */ capwap_logging_debug("Warning: error to send join response packet"); ac_session_teardown(session); } }