From 324f1fea8823784a1084f6fde9f95beec3b6a64c Mon Sep 17 00:00:00 2001 From: vemax78 Date: Wed, 21 Aug 2013 22:29:48 +0200 Subject: [PATCH] Add join SOAP event --- src/ac/ac_dfa_join.c | 454 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 445 insertions(+), 9 deletions(-) diff --git a/src/ac/ac_dfa_join.c b/src/ac/ac_dfa_join.c index aad145b..7493215 100644 --- a/src/ac/ac_dfa_join.c +++ b/src/ac/ac_dfa_join.c @@ -4,6 +4,7 @@ #include "ac_session.h" #include "ac_backend.h" #include +#include /* */ static int ac_dfa_state_join_check_authorizejoin(struct ac_session_t* session, struct ac_soap_response* response) { @@ -17,19 +18,269 @@ static int ac_dfa_state_join_check_authorizejoin(struct ac_session_t* session, s /* */ 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] + }, + WTPRadioInformation: [ + + IEEE80211WTPRadioInformation: { + RadioID: [int], + IEEE80211nMode: [bool], + IEEE80211gMode: [bool], + IEEE80211bMode: [bool], + IEEE80211aMode: [bool] + } + ] + 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); + + /* WTPRadioInformation */ + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + struct capwap_array* wtpradioinformation = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); + + jsonarray = json_object_new_array(); + for (i = 0; i < wtpradioinformation->count; i++) { + struct json_object* jsonradio; + struct capwap_80211_wtpradioinformation_element* radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i); + + jsonradio = json_object_new_object(); + json_object_object_add(jsonradio, "RadioID", json_object_new_int((int)radio->radioid)); + json_object_object_add(jsonradio, "IEEE80211nMode", json_object_new_boolean(((radio->radiotype & CAPWAP_RADIO_TYPE_80211N) ? 1: 0))); + json_object_object_add(jsonradio, "IEEE80211gMode", json_object_new_boolean(((radio->radiotype & CAPWAP_RADIO_TYPE_80211G) ? 1: 0))); + json_object_object_add(jsonradio, "IEEE80211bMode", json_object_new_boolean(((radio->radiotype & CAPWAP_RADIO_TYPE_80211B) ? 1: 0))); + json_object_object_add(jsonradio, "IEEE80211aMode", json_object_new_boolean(((radio->radiotype & CAPWAP_RADIO_TYPE_80211A) ? 1: 0))); + json_object_array_add(jsonarray, jsonradio); + } + + jsonhash = json_object_new_object(); + json_object_object_add(jsonhash, "IEEE80211WTPRadioInformation", jsonarray); + json_object_object_add(jsonparam, "WTPRadioInformation", jsonhash); + } + + /* 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_INET, (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))); @@ -48,10 +299,12 @@ static struct ac_soap_response* ac_dfa_state_join_parsing_request(struct ac_sess /* */ 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); @@ -62,6 +315,26 @@ static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session, /* Receive SOAP response with JSON result { + WTPRadioInformation: [ + + IEEE80211WTPRadioInformation: { + RadioID: [int], + IEEE80211nMode: [bool], + IEEE80211gMode: [bool], + IEEE80211bMode: [bool], + IEEE80211aMode: [bool] + } + ] + ACIPv4List: [ + { + ACIPAddress: [string] + } + ], + ACIPv6List: [ + { + ACIPAddress: [string] + } + ] } */ @@ -87,30 +360,89 @@ static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session, /* Add message elements response, every local value can be overwrite from backend server */ - /* Update statistics */ + /* 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 capwap_array* wtpradioinformation = (struct capwap_array*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); - for (i = 0; i < wtpradioinformation->count; i++) { - struct capwap_80211_wtpradioinformation_element* radio; + /* */ + jsonelement = NULL; + if (jsonroot) { + jsonelement = json_object_object_get(jsonroot, "WTPRadioInformation"); + if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) { + length = json_object_array_length(jsonelement); + } else { + jsonelement = NULL; + } + } - radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i); - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, radio); + /* */ + for (i = 0; i < wtpradioinformation->count; i++) { + struct capwap_80211_wtpradioinformation_element radio; + + /* Override WTP Radio Information value with SOAP response */ + memcpy(&radio, *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(wtpradioinformation, i), sizeof(struct capwap_80211_wtpradioinformation_element)); + if (jsonelement && length) { + 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; + + /* RadioID */ + jsonitem = json_object_object_get(jsonvalue, "RadioID"); + if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { + if ((int)radio.radioid == json_object_get_int(jsonitem)) { + radio.radiotype = 0; + + /* IEEE80211nMode */ + jsonitem = json_object_object_get(jsonvalue, "IEEE80211nMode"); + if (jsonitem && (json_object_get_type(jsonitem) == json_type_boolean)) { + radio.radiotype |= (json_object_get_boolean(jsonitem) ? CAPWAP_RADIO_TYPE_80211N : 0); + } + + /* IEEE80211gMode */ + jsonitem = json_object_object_get(jsonvalue, "IEEE80211gMode"); + if (jsonitem && (json_object_get_type(jsonitem) == json_type_boolean)) { + radio.radiotype |= (json_object_get_boolean(jsonitem) ? CAPWAP_RADIO_TYPE_80211G : 0); + } + + /* IEEE80211bMode */ + jsonitem = json_object_object_get(jsonvalue, "IEEE80211bMode"); + if (jsonitem && (json_object_get_type(jsonitem) == json_type_boolean)) { + radio.radiotype |= (json_object_get_boolean(jsonitem) ? CAPWAP_RADIO_TYPE_80211B : 0); + } + + /* IEEE80211aMode */ + jsonitem = json_object_object_get(jsonvalue, "IEEE80211aMode"); + if (jsonitem && (json_object_get_type(jsonitem) == json_type_boolean)) { + radio.radiotype |= (json_object_get_boolean(jsonitem) ? CAPWAP_RADIO_TYPE_80211A : 0); + } + + break; + } + } + } + } + } + + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &radio); } } + /* 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; @@ -131,6 +463,7 @@ static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session, capwap_list_free(controllist); + /* CAPWAP Local IP Address */ if (session->acctrladdress.ss_family == AF_INET) { struct capwap_localipv4_element addr; @@ -143,9 +476,112 @@ static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session, capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV6, &addr); } - /* CAPWAP_CREATE_ACIPV4LIST_ELEMENT */ /* TODO */ - /* CAPWAP_CREATE_ACIPV6LIST_ELEMENT */ /* TODO */ + /* ACIPv4List */ + jsonelement = NULL; + if (jsonroot) { + jsonelement = 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 = 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) { + struct sockaddr_storage address; + if (capwap_address_from_string(value, &address)) { + /* Accept only IPv4 address */ + if (address.ss_family == AF_INET) { + struct sockaddr_in* address_in = (struct sockaddr_in*)&address; + struct in_addr* responseaddress_in = (struct in_addr*)capwap_array_get_item_pointer(responseacipv4list->addresses, responseacipv4list->addresses->count); + memcpy(responseaddress_in, &address_in->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 = 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 = 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) { + struct sockaddr_storage address; + if (capwap_address_from_string(value, &address)) { + /* Accept only IPv6 address */ + if (address.ss_family == AF_INET6) { + struct sockaddr_in6* address_in6 = (struct sockaddr_in6*)&address; + struct in6_addr* responseaddress_in6 = (struct in6_addr*)capwap_array_get_item_pointer(responseacipv6list->addresses, responseacipv6list->addresses->count); + memcpy(responseaddress_in6, &address_in6->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_CREATE_IMAGEIDENTIFIER_ELEMENT */ /* TODO */ /* CAPWAP_CREATE_MAXIMUMMESSAGELENGTH_ELEMENT */ /* TODO */ /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */