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); }
int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap_parsed_packet* packet) { unsigned short binding; unsigned short bodylength; ASSERT(rxmngpacket != NULL); ASSERT(packet != NULL); /* */ memset(packet, 0, sizeof(struct capwap_parsed_packet)); packet->rxmngpacket = rxmngpacket; packet->messages = capwap_list_create(); binding = GET_WBID_HEADER(packet->rxmngpacket->header); /* Position reader to capwap body */ memcpy(&rxmngpacket->readpos, &rxmngpacket->readbodypos, sizeof(struct read_block_from_pos)); /* */ bodylength = rxmngpacket->ctrlmsg.length - CAPWAP_CONTROL_MESSAGE_MIN_LENGTH; while (bodylength > 0) { struct capwap_message_element_id id = { .vendor = 0 }; uint16_t msglength; struct capwap_list_item* itemlist; struct capwap_message_element_itemlist* messageelement; void *element; const struct capwap_message_elements_ops* read_ops; /* Get type and length */ rxmngpacket->readerpacketallowed = sizeof(struct capwap_message_element); if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &id.type) != sizeof(uint16_t) || rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &msglength) != sizeof(uint16_t) || msglength > bodylength) return INVALID_MESSAGE_ELEMENT; /* Allowed to parsing only the size of message element */ rxmngpacket->readerpacketallowed = msglength; /* Check binding */ if (IS_80211_MESSAGE_ELEMENTS(id) && (binding != CAPWAP_WIRELESS_BINDING_IEEE80211)) return UNRECOGNIZED_MESSAGE_ELEMENT; log_printf(LOG_DEBUG, "MESSAGE ELEMENT: %d", id.type); if (id.type == CAPWAP_ELEMENT_VENDORPAYLOAD_TYPE) { struct capwap_message_element_id vendor_id; if (msglength < 7) { log_printf(LOG_DEBUG, "Invalid Vendor Specific Payload element: underbuffer"); return INVALID_MESSAGE_ELEMENT; } if ((msglength - 6) > CAPWAP_VENDORPAYLOAD_MAXLENGTH) { log_printf(LOG_DEBUG, "Invalid Vendor Specific Payload element: overbuffer"); return INVALID_MESSAGE_ELEMENT; } rxmngpacket->read_ops.read_u32((capwap_message_elements_handle)rxmngpacket, &vendor_id.vendor); rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &vendor_id.type); log_printf(LOG_DEBUG, "VENDOR MESSAGE ELEMENT: %06x:%d", vendor_id.vendor, vendor_id.type); read_ops = capwap_get_message_element_ops(vendor_id); log_printf(LOG_DEBUG, "vendor read_ops: %p", read_ops); if (read_ops) { id = vendor_id; element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops); } else { read_ops = capwap_get_message_element_ops(id); element = capwap_unknown_vendorpayload_element_parsing((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops, msglength - 6, vendor_id); } } else { /* Reader function */ read_ops = capwap_get_message_element_ops(id); log_printf(LOG_DEBUG, "read_ops: %p", read_ops); if (!read_ops) return UNRECOGNIZED_MESSAGE_ELEMENT; /* Get message element */ element = read_ops->parse((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops); } if (!element) return INVALID_MESSAGE_ELEMENT; /* */ itemlist = capwap_get_message_element(packet, id); if (read_ops->category == CAPWAP_MESSAGE_ELEMENT_SINGLE) { /* Check for multiple message element */ if (itemlist) { return INVALID_MESSAGE_ELEMENT; } /* Create new message element */ itemlist = capwap_itemlist_create(sizeof(struct capwap_message_element_itemlist)); messageelement = (struct capwap_message_element_itemlist*)itemlist->item; messageelement->id = id; messageelement->category = CAPWAP_MESSAGE_ELEMENT_SINGLE; messageelement->data = element; /* */ capwap_itemlist_insert_after(packet->messages, NULL, itemlist); } else if (read_ops->category == CAPWAP_MESSAGE_ELEMENT_ARRAY) { struct capwap_array* arraymessageelement; if (itemlist) { messageelement = (struct capwap_message_element_itemlist*)itemlist->item; arraymessageelement = (struct capwap_array*)messageelement->data; } else { arraymessageelement = capwap_array_create(sizeof(void*), 0, 0); /* */ itemlist = capwap_itemlist_create(sizeof(struct capwap_message_element_itemlist)); messageelement = (struct capwap_message_element_itemlist*)itemlist->item; messageelement->id = id; messageelement->category = CAPWAP_MESSAGE_ELEMENT_ARRAY; messageelement->data = (void*)arraymessageelement; /* */ capwap_itemlist_insert_after(packet->messages, NULL, itemlist); } /* */ *(void **)capwap_array_get_item_pointer(arraymessageelement, arraymessageelement->count) = element; } /* Check if read all data of message element */ if (rxmngpacket->readerpacketallowed) { return INVALID_MESSAGE_ELEMENT; } /* */ bodylength -= (msglength + sizeof(struct capwap_message_element)); } return PARSING_COMPLETE; } /* */ int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct capwap_array* returnedmessage) { unsigned short binding; struct capwap_resultcode_element* resultcode; ASSERT(packet != NULL); ASSERT(packet->rxmngpacket != NULL); binding = GET_WBID_HEADER(packet->rxmngpacket->header); switch (packet->rxmngpacket->ctrlmsg.type) { case CAPWAP_DISCOVERY_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DISCOVERYTYPE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE)) { if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) { return 0; } } else { return 0; } } break; } case CAPWAP_DISCOVERY_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) && capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) && (capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6))) { return 0; } /* Check if packet contains Result Code with Error Message */ resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE); if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) { return 0; } break; } case CAPWAP_JOIN_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCATION) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPNAME) && capwap_get_message_element(packet, CAPWAP_ELEMENT_SESSIONID) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_ECNSUPPORT) && (capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV6))) { if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) { return 0; } } else { return 0; } } break; } case CAPWAP_JOIN_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) && capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) && capwap_get_message_element(packet, CAPWAP_ELEMENT_ECNSUPPORT) && (capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6)) && (capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCALIPV6))) { return 0; } /* Check if packet contains Result Code with Error Message */ resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE); if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) { return 0; } break; } case CAPWAP_CONFIGURATION_STATUS_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) && capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOADMSTATE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_STATISTICSTIMER) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT)) { if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) { return 0; } } else { return 0; } } break; } case CAPWAP_CONFIGURATION_STATUS_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_TIMERS) && capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) && capwap_get_message_element(packet, CAPWAP_ELEMENT_IDLETIMEOUT) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFALLBACK) && (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACIPV4LIST) || capwap_get_message_element(packet, CAPWAP_ELEMENT_ACIPV6LIST))) { return 0; } /* Check if packet contains Result Code with Error Message */ resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE); if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) { return 0; } break; } case CAPWAP_CONFIGURATION_UPDATE_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAMEPRIORITY) || capwap_get_message_element(packet, CAPWAP_ELEMENT_ACTIMESTAMP) || capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDMACACL) || capwap_get_message_element(packet, CAPWAP_ELEMENT_TIMERS) || capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) || capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETEMACACL) || capwap_get_message_element(packet, CAPWAP_ELEMENT_IDLETIMEOUT) || capwap_get_message_element(packet, CAPWAP_ELEMENT_LOCATION) || capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOADMSTATE) || capwap_get_message_element(packet, CAPWAP_ELEMENT_STATISTICSTIMER) || capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFALLBACK) || capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPNAME) || capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPSTATICIPADDRESS) || capwap_get_message_element(packet, CAPWAP_ELEMENT_IMAGEIDENTIFIER) || capwap_get_message_element(packet, CAPWAP_ELEMENT_VENDORPAYLOAD)) { return 0; } break; } case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: { return 0; } case CAPWAP_WTP_EVENT_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD) || capwap_get_message_element(packet, CAPWAP_ELEMENT_DUPLICATEIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_DUPLICATEIPV6) || capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPRADIOSTAT) || capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT) || capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETESTATION) || capwap_get_message_element(packet, CAPWAP_ELEMENT_VENDORPAYLOAD)) { return 0; } break; } case CAPWAP_WTP_EVENT_RESPONSE: { return 0; } case CAPWAP_CHANGE_STATE_EVENT_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RADIOOPRSTATE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) { return 0; } break; } case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: { return 0; } case CAPWAP_ECHO_REQUEST: { return 0; } case CAPWAP_ECHO_RESPONSE: { return 0; } case CAPWAP_IMAGE_DATA_REQUEST: { return 0; } case CAPWAP_IMAGE_DATA_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) { return 0; } break; } case CAPWAP_RESET_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_IMAGEIDENTIFIER)) { return 0; } break; } case CAPWAP_RESET_RESPONSE: { return 0; } case CAPWAP_PRIMARY_DISCOVERY_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DISCOVERYTYPE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPBOARDDATA) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE) && capwap_get_message_element(packet, CAPWAP_ELEMENT_WTPMACTYPE)) { if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION)) { return 0; } } else { return 0; } } break; } case CAPWAP_PRIMARY_DISCOVERY_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ACDESCRIPTION) && capwap_get_message_element(packet, CAPWAP_ELEMENT_ACNAME) && (capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV4) || capwap_get_message_element(packet, CAPWAP_ELEMENT_CONTROLIPV6))) { return 0; } /* Check if packet contains Result Code with Error Message */ resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE); if (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) { return 0; } break; } case CAPWAP_DATA_TRANSFER_REQUEST: { /* TODO */ break; } case CAPWAP_DATA_TRANSFER_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) { return 0; } break; } case CAPWAP_CLEAR_CONFIGURATION_REQUEST: { return 0; } case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) { return 0; } break; } case CAPWAP_STATION_CONFIGURATION_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_ADDSTATION)) { if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_STATION)) { return 0; } } else { return 0; } } else if (capwap_get_message_element(packet, CAPWAP_ELEMENT_DELETESTATION)) { return 0; } break; } case CAPWAP_STATION_CONFIGURATION_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) { return 0; } break; } case CAPWAP_IEEE80211_WLAN_CONFIGURATION_REQUEST: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_ADD_WLAN) || capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_UPDATE_WLAN) || capwap_get_message_element(packet, CAPWAP_ELEMENT_80211_DELETE_WLAN)) { return 0; } break; } case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: { if (capwap_get_message_element(packet, CAPWAP_ELEMENT_RESULTCODE)) { return 0; } break; } } return -1; }
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); } }