#include "ac.h" #include "capwap_dfa.h" #include "capwap_array.h" #include "ac_session.h" #include "ac_backend.h" #include "ac_json.h" #include #include /* */ static int ac_dfa_state_join_check_authorizejoin(struct ac_session_t* session, struct ac_soap_response* response) { xmlChar* xmlResult; if ((response->responsecode != HTTP_RESULT_OK) || !response->xmlResponseReturn) { /* TODO: check return failed code */ return CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE; } // Check return value xmlResult = xmlNodeGetContent(response->xmlResponseReturn); if (!xmlResult) { return CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE; } else if (xmlStrcmp(xmlResult, (const xmlChar *)"true")) { xmlFree(xmlResult); return CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE; } xmlFree(xmlResult); return CAPWAP_RESULTCODE_SUCCESS; } /* */ static struct ac_soap_response* ac_dfa_state_join_parsing_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int i; const char* jsonmessage; char* base64confstatus; struct json_object* jsonarray; struct json_object* jsonparam; struct json_object* jsonhash; struct ac_soap_response* response; struct capwap_location_element* location; struct capwap_wtpboarddata_element* wtpboarddata; struct capwap_wtpdescriptor_element* wtpdescriptor; struct capwap_wtpname_element* wtpname; struct capwap_wtpframetunnelmode_element* wtpframetunnelmode; struct capwap_wtpmactype_element* wtpmactype; struct capwap_ecnsupport_element* ecnsupport; struct capwap_localipv4_element* localipv4; struct capwap_localipv6_element* localipv6; struct capwap_wtprebootstat_element* wtprebootstat; unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header); /* Create SOAP request with JSON param { Binding: { Type: [int] } LocationData: { Location: [string] }, WTPBoardData: { VendorIdentifier: [int], BoardDataSubElement: [ { BoardDataType: [int], BoardDataValue: [base64] } ] }, WTPDescriptor: { MaxRadios: [int], RadiosInUse: [int], EncryptionSubElement: [ { WBID: [int], EncryptionCapabilities: [int] } ], DescriptorSubElement: [ { DescriptorVendorIdentifier: [int], DescriptorType: [int], DescriptorData: [string] } ] }, WTPName: { Name: [string] }, WTPFrameTunnelMode: { NativeFrameTunnel: [bool] FrameTunnelMode8023: [bool], LocalBridge: [bool] }, WTPMACType: { Type: [int] }, WTPRadio: [ { RadioID: [int], IEEE80211WTPRadioInformation: { Mode: [int] } } ] ECNSupport: { Mode: [int] } CAPWAPLocalIPv4Address: { Address: [string] }, CAPWAPLocalIPv6Address: { Address: [string] }, WTPRebootStatistics: { RebootCount: [int], ACInitiatedCount: [int], LinkFailureCount: [int], SWFailureCount: [int], HWFailureCount: [int], OtherFailureCount: [int], UnknownFailureCount: [int], LastFailureType: [int] } } */ /* */ jsonparam = json_object_new_object(); /* Binding */ jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "Type", json_object_new_int((int)binding)); json_object_object_add(jsonparam, "Binding", jsonhash); /* LocationData */ location = (struct capwap_location_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_LOCATION); jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "Location", json_object_new_string((char*)location->value)); json_object_object_add(jsonparam, "LocationData", jsonhash); /* WTPBoardData */ wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA); jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "VendorIdentifier", json_object_new_int((int)wtpboarddata->vendor)); jsonarray = json_object_new_array(); for (i = 0; i < wtpboarddata->boardsubelement->count; i++) { char* base64data; int base64length; struct json_object* jsonboard; struct capwap_wtpboarddata_board_subelement* wtpboarddata_board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(wtpboarddata->boardsubelement, i); /* Encoded base64 board data */ base64data = (char*)capwap_alloc(AC_BASE64_ENCODE_LENGTH((int)wtpboarddata_board->length)); base64length = ac_base64_binary_encode((const char*)wtpboarddata_board->data, (int)wtpboarddata_board->length, base64data); base64data[base64length] = 0; jsonboard = json_object_new_object(); json_object_object_add(jsonboard, "BoardDataType", json_object_new_int((int)wtpboarddata_board->type)); json_object_object_add(jsonboard, "BoardDataValue", json_object_new_string(base64data)); json_object_array_add(jsonarray, jsonboard); capwap_free(base64data); } json_object_object_add(jsonhash, "BoardDataSubElement", jsonarray); json_object_object_add(jsonparam, "WTPBoardData", jsonhash); /* WTPDescriptor */ wtpdescriptor = (struct capwap_wtpdescriptor_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPDESCRIPTOR); jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "MaxRadios", json_object_new_int((int)wtpdescriptor->maxradios)); json_object_object_add(jsonhash, "RadiosInUse", json_object_new_int((int)wtpdescriptor->radiosinuse)); jsonarray = json_object_new_array(); for (i = 0; i < wtpdescriptor->encryptsubelement->count; i++) { struct json_object* jsonencrypt; struct capwap_wtpdescriptor_encrypt_subelement* wtpdescriptor_encrypt = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(wtpdescriptor->encryptsubelement, i); jsonencrypt = json_object_new_object(); json_object_object_add(jsonencrypt, "WBID", json_object_new_int((int)wtpdescriptor_encrypt->wbid)); json_object_object_add(jsonencrypt, "EncryptionCapabilities", json_object_new_int((int)wtpdescriptor_encrypt->capabilities)); json_object_array_add(jsonarray, jsonencrypt); } json_object_object_add(jsonhash, "EncryptionSubElement", jsonarray); jsonarray = json_object_new_array(); for (i = 0; i < wtpdescriptor->descsubelement->count; i++) { struct json_object* jsondesc; struct capwap_wtpdescriptor_desc_subelement* wtpdescriptor_desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(wtpdescriptor->descsubelement, i); jsondesc = json_object_new_object(); json_object_object_add(jsondesc, "DescriptorVendorIdentifier", json_object_new_int((int)wtpdescriptor_desc->vendor)); json_object_object_add(jsondesc, "DescriptorType", json_object_new_int((int)wtpdescriptor_desc->type)); json_object_object_add(jsondesc, "DescriptorData", json_object_new_string((char*)wtpdescriptor_desc->data)); json_object_array_add(jsonarray, jsondesc); } json_object_object_add(jsonhash, "DescriptorSubElement", jsonarray); json_object_object_add(jsonparam, "WTPDescriptor", jsonhash); /* WTPName */ wtpname = (struct capwap_wtpname_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPNAME); jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "Name", json_object_new_string((char*)wtpname->name)); json_object_object_add(jsonparam, "WTPName", jsonhash); /* WTPFrameTunnelMode */ wtpframetunnelmode = (struct capwap_wtpframetunnelmode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE); jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "NativeFrameTunnel", json_object_new_boolean(((wtpframetunnelmode->mode & CAPWAP_WTP_NATIVE_FRAME_TUNNEL) ? 1 : 0))); json_object_object_add(jsonhash, "FrameTunnelMode8023", json_object_new_boolean(((wtpframetunnelmode->mode & CAPWAP_WTP_8023_FRAME_TUNNEL) ? 1 : 0))); json_object_object_add(jsonhash, "LocalBridge", json_object_new_boolean(((wtpframetunnelmode->mode & CAPWAP_WTP_LOCAL_BRIDGING) ? 1 : 0))); json_object_object_add(jsonparam, "WTPFrameTunnelMode", jsonhash); /* WTPMACType */ wtpmactype = (struct capwap_wtpmactype_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPMACTYPE); jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "Type", json_object_new_int((int)wtpmactype->type)); json_object_object_add(jsonparam, "WTPMACType", jsonhash); /* Binding message */ if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { struct ac_json_ieee80211_wtpradio wtpradio; struct capwap_list_item* search = packet->messages->first; /* Reording message by radioid and management */ ac_json_ieee80211_init(&wtpradio); while (search) { struct capwap_message_element_itemlist* messageelement = (struct capwap_message_element_itemlist*)search->item; /* Parsing only IEEE 802.11 message element */ if (IS_80211_MESSAGE_ELEMENTS(messageelement->type)) { if (!ac_json_ieee80211_parsingmessageelement(&wtpradio, messageelement)) { json_object_put(jsonparam); return NULL; } } /* Next */ search = search->next; } /* Generate JSON tree */ jsonarray = ac_json_ieee80211_getjson(&wtpradio); json_object_object_add(jsonparam, IEEE80211_BINDING_JSON_ROOT, jsonarray); /* Free resource */ ac_json_ieee80211_free(&wtpradio); } /* ECNSupport */ ecnsupport = (struct capwap_ecnsupport_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ECNSUPPORT); jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "Mode", json_object_new_int((int)ecnsupport->flag)); json_object_object_add(jsonparam, "ECNSupport", jsonhash); /* CAPWAPLocalIPv4Address */ localipv4 = (struct capwap_localipv4_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_LOCALIPV4); if (localipv4) { char ipbuffer[INET_ADDRSTRLEN]; jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "Address", json_object_new_string(inet_ntop(AF_INET, (void*)&localipv4->address, ipbuffer, INET_ADDRSTRLEN))); json_object_object_add(jsonparam, "CAPWAPLocalIPv4Address", jsonhash); } /* CAPWAPLocalIPv6Address */ localipv6 = (struct capwap_localipv6_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_LOCALIPV6); if (localipv6) { char ipbuffer[INET6_ADDRSTRLEN]; jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "Address", json_object_new_string(inet_ntop(AF_INET6, (void*)&localipv6->address, ipbuffer, INET6_ADDRSTRLEN))); json_object_object_add(jsonparam, "CAPWAPLocalIPv6Address", jsonhash); } /* WTPRebootStatistics */ wtprebootstat = (struct capwap_wtprebootstat_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPREBOOTSTAT); if (wtprebootstat) { jsonhash = json_object_new_object(); json_object_object_add(jsonhash, "RebootCount", json_object_new_int((int)wtprebootstat->rebootcount)); json_object_object_add(jsonhash, "ACInitiatedCount", json_object_new_int((int)wtprebootstat->acinitiatedcount)); json_object_object_add(jsonhash, "LinkFailureCount", json_object_new_int((int)wtprebootstat->linkfailurecount)); json_object_object_add(jsonhash, "SWFailureCount", json_object_new_int((int)wtprebootstat->swfailurecount)); json_object_object_add(jsonhash, "HWFailureCount", json_object_new_int((int)wtprebootstat->hwfailurecount)); json_object_object_add(jsonhash, "OtherFailureCount", json_object_new_int((int)wtprebootstat->otherfailurecount)); json_object_object_add(jsonhash, "UnknownFailureCount", json_object_new_int((int)wtprebootstat->unknownfailurecount)); json_object_object_add(jsonhash, "LastFailureType", json_object_new_int((int)wtprebootstat->lastfailuretype)); json_object_object_add(jsonparam, "WTPRebootStatistics", jsonhash); } /* Get JSON param and convert base64 */ jsonmessage = json_object_to_json_string(jsonparam); base64confstatus = capwap_alloc(AC_BASE64_ENCODE_LENGTH(strlen(jsonmessage))); ac_base64_string_encode(jsonmessage, base64confstatus); /* Send message */ response = ac_soap_joinwtpsession(session, session->wtpid, base64confstatus); /* Free JSON */ json_object_put(jsonparam); capwap_free(base64confstatus); return response; } /* */ static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct ac_soap_response* response, struct capwap_packet_txmng* txmngpacket) { int i; int j; int length; char* json; xmlChar* xmlResult; struct json_object* jsonroot; struct json_object* jsonelement; struct capwap_list* controllist; struct capwap_list_item* item; unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header); if ((response->responsecode != HTTP_RESULT_OK) || !response->xmlResponseReturn) { return CAPWAP_RESULTCODE_FAILURE; } /* Receive SOAP response with JSON result { WTPRadioInformation: [ IEEE80211WTPRadioInformation: { RadioID: [int], Mode: [int] } ] ACIPv4List: [ { ACIPAddress: [string] } ], ACIPv6List: [ { ACIPAddress: [string] } ] WTPRadio: [ { RadioID: [int], IEEE80211WTPRadioInformation: { Mode: [int] } } ] } */ /* Decode base64 result */ xmlResult = xmlNodeGetContent(response->xmlResponseReturn); if (!xmlResult) { return CAPWAP_RESULTCODE_FAILURE; } length = xmlStrlen(xmlResult); if (!length) { xmlFree(xmlResult); return CAPWAP_RESULTCODE_FAILURE; } json = (char*)capwap_alloc(AC_BASE64_DECODE_LENGTH(length)); ac_base64_string_decode((const char*)xmlResult, json); xmlFree(xmlResult); /* Parsing JSON result */ jsonroot = json_tokener_parse(json); capwap_free(json); /* Add message elements response, every local value can be overwrite from backend server */ /* AC Descriptor */ ac_update_statistics(); capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor); /* AC Name */ capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname); /* WTP Radio Information */ if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { struct ac_json_ieee80211_wtpradio wtpradio; struct capwap_array* wtpradioinformation = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); /* */ ac_json_ieee80211_init(&wtpradio); /* */ jsonelement = compat_json_object_object_get(jsonroot, IEEE80211_BINDING_JSON_ROOT); if (jsonelement) { ac_json_ieee80211_parsingjson(&wtpradio, jsonelement); } /* Copy WTP Radio Information if not present into SOAP response */ for (i = 0; i < wtpradioinformation->count; i++) { ac_json_ieee80211_addmessageelement(&wtpradio, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i), 0); } /* */ ac_json_ieee80211_buildpacket(&wtpradio, txmngpacket); /* Free resource */ ac_json_ieee80211_free(&wtpradio); } /* ECN Support */ capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ECNSUPPORT, &session->dfa.ecn); /* Get information from any local address */ controllist = capwap_list_create(); ac_get_control_information(controllist); /* CAPWAP Control IP Address */ for (item = controllist->first; item != NULL; item = item->next) { struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item; if (sessioncontrol->localaddress.ss.ss_family == AF_INET) { struct capwap_controlipv4_element element; memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr)); element.wtpcount = sessioncontrol->count; capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element); } else if (sessioncontrol->localaddress.ss.ss_family == AF_INET6) { struct capwap_controlipv6_element element; memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr)); element.wtpcount = sessioncontrol->count; capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element); } } capwap_list_free(controllist); /* CAPWAP Local IP Address */ if (session->dtls.localaddr.ss.ss_family == AF_INET) { struct capwap_localipv4_element addr; memcpy(&addr.address, &session->dtls.localaddr.sin.sin_addr, sizeof(struct in_addr)); capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV4, &addr); } else if (session->dtls.localaddr.ss.ss_family == AF_INET6) { struct capwap_localipv6_element addr; memcpy(&addr.address, &session->dtls.localaddr.sin6.sin6_addr, sizeof(struct in6_addr)); capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV6, &addr); } /* ACIPv4List */ jsonelement = NULL; if (jsonroot) { jsonelement = compat_json_object_object_get(jsonroot, "ACIPv4List"); if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) { length = json_object_array_length(jsonelement); } else { jsonelement = NULL; } } if (jsonelement) { struct capwap_acipv4list_element* responseacipv4list; responseacipv4list = (struct capwap_acipv4list_element*)capwap_alloc(sizeof(struct capwap_acipv4list_element)); responseacipv4list->addresses = capwap_array_create(sizeof(struct in_addr), 0, 0); for (j = 0; j < length; j++) { struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, i); if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) { struct json_object* jsonitem; /* ACIPAddress */ jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) { const char* value = json_object_get_string(jsonitem); if (value) { union sockaddr_capwap address; if (capwap_address_from_string(value, &address)) { /* Accept only IPv4 address */ if (address.ss.ss_family == AF_INET) { struct in_addr* responseaddress_in = (struct in_addr*)capwap_array_get_item_pointer(responseacipv4list->addresses, responseacipv4list->addresses->count); memcpy(responseaddress_in, &address.sin.sin_addr, sizeof(struct in_addr)); } } } } } } if (responseacipv4list->addresses->count > 0) { capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, responseacipv4list); } capwap_array_free(responseacipv4list->addresses); capwap_free(responseacipv4list); } else if (session->dfa.acipv4list.addresses->count > 0) { capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, &session->dfa.acipv4list); } /* ACIPv6List */ jsonelement = NULL; if (jsonroot) { jsonelement = compat_json_object_object_get(jsonroot, "ACIPv6List"); if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) { length = json_object_array_length(jsonelement); } else { jsonelement = NULL; } } if (jsonelement) { int j; struct capwap_acipv6list_element* responseacipv6list; responseacipv6list = (struct capwap_acipv6list_element*)capwap_alloc(sizeof(struct capwap_acipv6list_element)); responseacipv6list->addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0); for (j = 0; j < length; j++) { struct json_object* jsonvalue = json_object_array_get_idx(jsonelement, i); if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) { struct json_object* jsonitem; /* ACIPAddress */ jsonitem = compat_json_object_object_get(jsonvalue, "ACIPAddress"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) { const char* value = json_object_get_string(jsonitem); if (value) { union sockaddr_capwap address; if (capwap_address_from_string(value, &address)) { /* Accept only IPv6 address */ if (address.ss.ss_family == AF_INET6) { struct in6_addr* responseaddress_in6 = (struct in6_addr*)capwap_array_get_item_pointer(responseacipv6list->addresses, responseacipv6list->addresses->count); memcpy(responseaddress_in6, &address.sin6.sin6_addr, sizeof(struct in6_addr)); } } } } } } if (responseacipv6list->addresses->count > 0) { capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, responseacipv6list); } capwap_array_free(responseacipv6list->addresses); capwap_free(responseacipv6list); } else if (session->dfa.acipv6list.addresses->count > 0) { capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, &session->dfa.acipv6list); } /* CAPWAP Transport Protocol */ capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &session->dfa.transport); /* CAPWAP_ELEMENT_IMAGEIDENTIFIER */ /* TODO */ /* CAPWAP_ELEMENT_MAXIMUMLENGTH */ /* TODO */ /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ if (jsonroot) { json_object_put(jsonroot); } return CAPWAP_RESULTCODE_SUCCESS; } /* */ 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); } } /* */ void ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet) { ASSERT(session != NULL); ASSERT(packet != NULL); if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) { ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE); ac_dfa_state_configure(session, packet); } else if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_IMAGE_DATA_REQUEST) { ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE); ac_dfa_state_imagedata(session, packet); } else { ac_session_teardown(session); } }