void wtp_radio_close(void) { int i; ASSERT(g_wtp.radios != NULL); for (i = 0; i < g_wtp.radios->count; i++) { struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i); if (radio->antenna.selections) { capwap_array_free(radio->antenna.selections); } for (i = 0; i < radio->wlan->count; i++) { struct wtp_radio_wlan *wlan = (struct wtp_radio_wlan *)capwap_array_get_item_pointer(radio->wlan, i); /* Destroy BSS interface */ if (wlan->wlanhandle) wifi_wlan_destroy(wlan->wlanhandle); } capwap_array_free(radio->wlan); } capwap_array_resize(g_wtp.radios, 0); }
static void capwap_acipv6list_element_free(void* data) { struct capwap_acipv6list_element* element = (struct capwap_acipv6list_element*)data; ASSERT(data != NULL); capwap_array_free(element->addresses); capwap_free(data); }
static void capwap_80211_antenna_element_free(void* data) { struct capwap_80211_antenna_element* element = (struct capwap_80211_antenna_element*)data; ASSERT(data != NULL); ASSERT(element->selections != NULL); capwap_array_free(element->selections); capwap_free(data); }
void wtp_radio_free(void) { ASSERT(g_wtp.radios != NULL); if (g_wtp.radios->count > 0) { wtp_radio_close(); } capwap_array_free(g_wtp.radios); capwap_hash_free(g_wtp.aclstations); }
static void capwap_acdescriptor_element_free(void* data) { int i; struct capwap_acdescriptor_element* element = (struct capwap_acdescriptor_element*)data; ASSERT(element != NULL); ASSERT(element->descsubelement != NULL); /* */ for (i = 0; i < element->descsubelement->count; i++) { struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i); if (desc->data) { capwap_free(desc->data); } } capwap_array_free(element->descsubelement); capwap_free(data); }
void capwap_free_parsed_packet(struct capwap_parsed_packet* packet) { int i; struct capwap_list_item* itemlist; struct capwap_message_element_itemlist* messageelement; const struct capwap_message_elements_ops* msgops; ASSERT(packet != NULL); if (packet->rxmngpacket && packet->messages) { itemlist = packet->messages->first; while (itemlist) { messageelement = (struct capwap_message_element_itemlist*)itemlist->item; if (messageelement->data) { msgops = capwap_get_message_element_ops(messageelement->id); if (messageelement->category == CAPWAP_MESSAGE_ELEMENT_SINGLE) { msgops->free(messageelement->data); } else if (messageelement->category == CAPWAP_MESSAGE_ELEMENT_ARRAY) { struct capwap_array* arraymessageelement = (struct capwap_array*)messageelement->data; for (i = 0; i < arraymessageelement->count; i++) { msgops->free(*(void**)capwap_array_get_item_pointer(arraymessageelement, i)); } /* */ capwap_array_free(arraymessageelement); } } /* */ itemlist = itemlist->next; } /* */ packet->rxmngpacket = NULL; capwap_list_free(packet->messages); packet->messages = NULL; } }
/* Release reference of session */ static void ac_session_destroy(struct ac_session_t* session) { #ifdef DEBUG char sessionname[33]; #endif ASSERT(session != NULL); #ifdef DEBUG capwap_sessionid_printf(&session->sessionid, sessionname); capwap_logging_debug("Release Session AC %s", sessionname); #endif /* Release last reference */ capwap_lock_enter(&session->sessionlock); session->count--; /* Terminate SOAP request pending */ if (session->soaprequest) { ac_soapclient_shutdown_request(session->soaprequest); } /* Check if all reference is release */ while (session->count > 0) { #ifdef DEBUG capwap_logging_debug("Wait for release Session AC %s (count=%d)", sessionname, session->count); #endif /* */ capwap_event_reset(&session->changereference); capwap_lock_exit(&session->sessionlock); /* Wait */ capwap_event_wait(&session->changereference); capwap_lock_enter(&session->sessionlock); } capwap_lock_exit(&session->sessionlock); /* Close data channel */ ac_kmod_delete_datasession(&session->sessionid); /* Free DTSL Control */ capwap_crypt_freesession(&session->dtls); /* Free resource */ while (session->packets->count > 0) { capwap_itemlist_free(capwap_itemlist_remove_head(session->packets)); } /* Free WLANS */ ac_wlans_destroy(session); /* */ capwap_event_destroy(&session->changereference); capwap_event_destroy(&session->waitpacket); capwap_lock_destroy(&session->sessionlock); capwap_list_free(session->action); capwap_list_free(session->packets); /* Free fragments packet */ if (session->rxmngpacket) { capwap_packet_rxmng_free(session->rxmngpacket); } capwap_list_free(session->requestfragmentpacket); capwap_list_free(session->responsefragmentpacket); capwap_list_free(session->notifyevent); capwap_timeout_free(session->timeout); /* Free DFA resource */ capwap_array_free(session->dfa.acipv4list.addresses); capwap_array_free(session->dfa.acipv6list.addresses); if (session->wtpid) { capwap_free(session->wtpid); } /* Free item */ capwap_itemlist_free(session->itemlist); }
int wtp_radio_setconfiguration(struct capwap_parsed_packet* packet) { int i; int result = 0; struct capwap_array* updateitems; ASSERT(packet != NULL); /* */ updateitems = capwap_array_create(sizeof(struct wtp_update_configuration_item), 0, 1); /* */ switch (GET_WBID_HEADER(packet->rxmngpacket->header)) { case CAPWAP_WIRELESS_BINDING_IEEE80211: wtp_radio_setconfiguration_80211(packet, updateitems); break; } log_printf(LOG_DEBUG, "wtp_radio_setconfiguration result #1: %d", result); /* Update radio frequency */ for (i = 0; (i < updateitems->count) && !result; i++) { struct wtp_update_configuration_item* item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, i); switch (item->type) { case WTP_UPDATE_FREQUENCY_DSSS: result = wifi_device_setfrequency(item->radio->devicehandle, WIFI_BAND_2GHZ, item->radio->radioinformation.radiotype, item->radio->directsequencecontrol.currentchannel); break; case WTP_UPDATE_FREQUENCY_OFDM: result = wifi_device_setfrequency(item->radio->devicehandle, WIFI_BAND_5GHZ, item->radio->radioinformation.radiotype, item->radio->ofdmcontrol.currentchannel); break; } } log_printf(LOG_DEBUG, "wtp_radio_setconfiguration result #2: %d", result); /* Update radio configuration */ for (i = 0; (i < updateitems->count) && !result; i++) { struct wtp_update_configuration_item* item = (struct wtp_update_configuration_item*)capwap_array_get_item_pointer(updateitems, i); switch (item->type) { case WTP_UPDATE_RATES: result = wifi_device_updaterates(item->radio->devicehandle, item->radio->rateset.rateset, item->radio->rateset.ratesetcount); break; case WTP_UPDATE_CONFIGURATION: { struct device_setconfiguration_params params; memset(¶ms, 0, sizeof(struct device_setconfiguration_params)); params.shortpreamble = ((item->radio->radioconfig.shortpreamble == CAPWAP_WTP_RADIO_CONF_SHORTPREAMBLE_ENABLE) ? 1 : 0); params.maxbssid = item->radio->radioconfig.maxbssid; params.dtimperiod = item->radio->radioconfig.dtimperiod; memcpy(params.bssid, item->radio->radioconfig.bssid, ETH_ALEN); params.beaconperiod = item->radio->radioconfig.beaconperiod; memcpy(params.country, item->radio->radioconfig.country, WIFI_COUNTRY_LENGTH); result = wifi_device_setconfiguration(item->radio->devicehandle, ¶ms); break; } case WTP_UPDATE_TX_QUEUE: result = wifi_device_settxqueue(item->radio->devicehandle, &item->radio->qos); break; } } log_printf(LOG_DEBUG, "wtp_radio_setconfiguration result #3: %d", result); /* */ capwap_array_free(updateitems); return result; }
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; 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); /* Receive SOAP response with JSON result { WTPRadioInformation: [ <IEEE 802.11 BINDING> IEEE80211WTPRadioInformation: { RadioID: [int], Mode: [int] } ] ACIPv4List: [ { ACIPAddress: [string] } ], ACIPv6List: [ { ACIPAddress: [string] } ] <IEEE 802.11 BINDING> WTPRadio: [ { RadioID: [int], IEEE80211WTPRadioInformation: { Mode: [int] } } ] } */ /* Add message elements response, every local value can be overwrite from backend server */ jsonroot = ac_soapclient_parse_json_response(response); if (!jsonroot) { return CAPWAP_RESULTCODE_FAILURE; } /* 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, j); 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, j); 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; }