static void* ac_json_80211_wtpradiofailalarm_createmessageelement(struct json_object* jsonparent, uint16_t radioid) { struct json_object* jsonitem; struct capwap_80211_wtpradiofailalarm_element* wtpradiofailalarm; wtpradiofailalarm = (struct capwap_80211_wtpradiofailalarm_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradiofailalarm_element)); memset(wtpradiofailalarm, 0, sizeof(struct capwap_80211_wtpradiofailalarm_element)); wtpradiofailalarm->radioid = radioid; /* */ jsonitem = compat_json_object_object_get(jsonparent, "Type"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { wtpradiofailalarm->type = (uint8_t)json_object_get_int(jsonitem); } else { capwap_free(wtpradiofailalarm); return NULL; } /* */ jsonitem = compat_json_object_object_get(jsonparent, "Status"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { wtpradiofailalarm->status = (uint8_t)json_object_get_int(jsonitem); } else { capwap_free(wtpradiofailalarm); return NULL; } return wtpradiofailalarm; }
static void* ac_json_80211_ofdmcontrol_createmessageelement(struct json_object* jsonparent, uint16_t radioid) { struct json_object* jsonitem; struct capwap_80211_ofdmcontrol_element* ofdmcontrol; ofdmcontrol = (struct capwap_80211_ofdmcontrol_element*)capwap_alloc(sizeof(struct capwap_80211_ofdmcontrol_element)); memset(ofdmcontrol, 0, sizeof(struct capwap_80211_ofdmcontrol_element)); ofdmcontrol->radioid = radioid; /* */ jsonitem = compat_json_object_object_get(jsonparent, "CurrentChan"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { ofdmcontrol->currentchannel = (uint8_t)json_object_get_int(jsonitem); } else { capwap_free(ofdmcontrol); return NULL; } jsonitem = compat_json_object_object_get(jsonparent, "BandSupport"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { ofdmcontrol->bandsupport = (uint8_t)json_object_get_int(jsonitem) & CAPWAP_OFDMCONTROL_BAND_MASK; } else { capwap_free(ofdmcontrol); return NULL; } jsonitem = compat_json_object_object_get(jsonparent, "TIThreshold"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { ofdmcontrol->tithreshold = (uint32_t)json_object_get_int(jsonitem); } else { capwap_free(ofdmcontrol); return NULL; } return ofdmcontrol; }
static int ac_backend_parsing_event(struct json_object* jsonitem) { int result = -1; struct json_object* jsonvalue; ASSERT(jsonitem != NULL); /* Receive event into JSON result { EventID: [int], Action: [string], Params: { <Depends on the Action> } } */ /* Get EventID */ jsonvalue = compat_json_object_object_get(jsonitem, "EventID"); if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_string)) { const char* idevent = json_object_get_string(jsonvalue); /* Get Action */ jsonvalue = compat_json_object_object_get(jsonitem, "Action"); if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_string)) { const char* action = json_object_get_string(jsonvalue); if (action) { jsonvalue = compat_json_object_object_get(jsonitem, "Params"); if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) { /* Parsing params according to the action */ if (!strcmp(action, "CloseWTPSession")) { result = ac_backend_parsing_closewtpsession_event(idevent, jsonvalue); } else if (!strcmp(action, "ResetWTP")) { result = ac_backend_parsing_resetwtp_event(idevent, jsonvalue); } else if (!strcmp(action, "AddWLAN")) { result = ac_backend_parsing_addwlan_event(idevent, jsonvalue); } else if (!strcmp(action, "UpdateWLAN")) { result = ac_backend_parsing_updatewlan_event(idevent, jsonvalue); } else if (!strcmp(action, "DeleteWLAN")) { result = ac_backend_parsing_deletewlan_event(idevent, jsonvalue); } /* Notify result action */ ac_backend_soap_update_event(idevent, (!result ? SOAP_EVENT_STATUS_RUNNING : SOAP_EVENT_STATUS_GENERIC_ERROR)); } } } } return result; }
static int ac_update_configuration_datachannelinterfaces(void* data, void* param) { int i; int mtu; int length; const char* bridge; struct ac_if_datachannel* iface = (struct ac_if_datachannel*)data; struct array_list* interfaces = (struct array_list*)param; /* Search interface */ length = array_list_length(interfaces); for (i = 0; i < length; i++) { struct json_object* jsonvalue = array_list_get_idx(interfaces, i); if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) { struct json_object* jsonindex = compat_json_object_object_get(jsonvalue, "Index"); if (jsonindex && (json_object_get_type(jsonindex) == json_type_int)) { if (iface->index == (unsigned long)json_object_get_int(jsonindex)) { if (!ac_update_configuration_getdatachannel_params(jsonvalue, &mtu, &bridge)) { /* TODO update interface */ } /* Interface found */ array_list_put_idx(interfaces, i, NULL); break; } } } } return ((i == length) ? HASH_DELETE_AND_CONTINUE : HASH_CONTINUE); }
static int ac_update_configuration_getdatachannel_params(struct json_object* jsonvalue, int* mtu, const char** bridge) { int result = -1; struct json_object* jsonmtu; /* */ jsonmtu = compat_json_object_object_get(jsonvalue, "MTU"); if (jsonmtu && (json_object_get_type(jsonmtu) == json_type_int)) { *mtu = json_object_get_int(jsonmtu); if ((*mtu >= MIN_MTU) && (*mtu <= MAX_MTU)) { struct json_object* jsonbridge = compat_json_object_object_get(jsonvalue, "Bridge"); *bridge = ((jsonbridge && (json_object_get_type(jsonmtu) == json_type_string)) ? json_object_get_string(jsonbridge) : NULL); result = 0; } } return result; }
static void* ac_json_80211_wtpradioinformation_createmessageelement(struct json_object* jsonparent, uint16_t radioid) { struct json_object* jsonitem; struct capwap_80211_wtpradioinformation_element* wtpradioinformation; wtpradioinformation = (struct capwap_80211_wtpradioinformation_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioinformation_element)); memset(wtpradioinformation, 0, sizeof(struct capwap_80211_wtpradioinformation_element)); wtpradioinformation->radioid = radioid; /* */ jsonitem = compat_json_object_object_get(jsonparent, "Mode"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { wtpradioinformation->radiotype = (uint32_t)json_object_get_int(jsonitem) & CAPWAP_RADIO_TYPE_MASK; } else { capwap_free(wtpradioinformation); return NULL; } return wtpradioinformation; }
static int ac_backend_parsing_closewtpsession_event(const char* idevent, struct json_object* jsonparams) { int result = -1; struct ac_session_t* session; struct json_object* jsonwtpid; /* Params CloseWTPSession Action { WTPId: [string] } */ /* WTPId */ jsonwtpid = compat_json_object_object_get(jsonparams, "WTPId"); if (!jsonwtpid || (json_object_get_type(jsonwtpid) != json_type_string)) { return -1; } /* Get session */ session = ac_search_session_from_wtpid(json_object_get_string(jsonwtpid)); if (session) { struct ac_session_notify_event_t notify; /* Notify Request to Complete Event */ strcpy(notify.idevent, idevent); notify.action = NOTIFY_ACTION_CHANGE_STATE; notify.session_state = CAPWAP_DEAD_STATE; ac_session_send_action(session, AC_SESSION_ACTION_NOTIFY_EVENT, 0, (void*)¬ify, sizeof(struct ac_session_notify_event_t)); /* Async close session */ capwap_logging_debug("Receive close wtp session for WTP %s", session->wtpid); ac_session_send_action(session, AC_SESSION_ACTION_CLOSE, 0, NULL, 0); /* */ ac_session_release_reference(session); result = 0; } return result; }
static int ac_session_action_authorizestation_response(struct ac_session_t* session, struct ac_soap_response* response, struct ac_notify_station_configuration_ieee8011_add_station* notify) { int result = -1; int ifindex = -1; uint16_t vlan = 0; struct ac_if_datachannel* datachannel; struct ac_wlan* wlan; struct json_object* jsonroot; struct json_object* jsonsection; struct json_object* jsonelement; struct capwap_header_data capwapheader; struct capwap_packet_txmng* txmngpacket; struct capwap_addstation_element addstation; struct capwap_80211_station_element station; /* Receive SOAP response with JSON result { DataChannelInterface: { Index: [int], VLAN: [int/string] }, } */ /* */ jsonroot = ac_soapclient_parse_json_response(response); if (!jsonroot) { return -1; } /* */ jsonsection = compat_json_object_object_get(jsonroot, "DataChannelInterface"); if (jsonsection && (json_object_get_type(jsonsection) == json_type_object)) { jsonelement = compat_json_object_object_get(jsonsection, "Index"); if (jsonelement && (json_object_get_type(jsonelement) == json_type_int)) { unsigned long index = (unsigned long)json_object_get_int(jsonelement); /* Retrieve interface index */ capwap_rwlock_rdlock(&g_ac.ifdatachannellock); datachannel = (struct ac_if_datachannel*)capwap_hash_search(g_ac.ifdatachannel, &index); if (datachannel) { ifindex = datachannel->ifindex; } capwap_rwlock_unlock(&g_ac.ifdatachannellock); /* Prepare request */ if (ifindex >= 0) { wlan = ac_wlans_get_bssid_with_wlanid(session, notify->radioid, notify->wlanid); if (wlan) { memset(&addstation, 0, sizeof(struct capwap_addstation_element)); addstation.radioid = notify->radioid; addstation.length = MACADDRESS_EUI48_LENGTH; addstation.address = notify->address; if (wlan->tunnelmode == CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL) { jsonelement = compat_json_object_object_get(jsonsection, "VLAN"); if (jsonelement && (json_object_get_type(jsonelement) == json_type_string)) { const char* wtpvlan = json_object_get_string(jsonelement); if (wtpvlan && (strlen(wtpvlan) < CAPWAP_ADDSTATION_VLAN_MAX_LENGTH)) { addstation.vlan = (uint8_t*)wtpvlan; /* Free with jsonroot */ } } } /* */ memset(&station, 0, sizeof(struct capwap_80211_station_element)); station.radioid = notify->radioid; station.associationid = notify->associationid; memcpy(station.address, notify->address, MACADDRESS_EUI48_LENGTH); station.capabilities = notify->capabilities; station.wlanid = notify->wlanid; station.supportedratescount = notify->supportedratescount; memcpy(station.supportedrates, notify->supportedrates, station.supportedratescount); /* Build packet */ capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding); txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_STATION_CONFIGURATION_REQUEST, session->localseqnumber, session->mtu); /* Add message element */ capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ADDSTATION, &addstation); capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_STATION, &station); /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ /* Station Configuration Request complete, get fragment packets */ capwap_packet_txmng_get_fragment_packets(txmngpacket, session->requestfragmentpacket, session->fragmentid); if (session->requestfragmentpacket->count > 1) { session->fragmentid++; } /* Free packets manager */ capwap_packet_txmng_free(txmngpacket); /* Send Station Configuration Request to WTP */ if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->requestfragmentpacket)) { /* Retrive VLAN */ if (wlan->tunnelmode != CAPWAP_ADD_WLAN_TUNNELMODE_LOCAL) { jsonelement = compat_json_object_object_get(jsonroot, "DataChannelInterface.VLAN"); if (jsonelement && (json_object_get_type(jsonelement) == json_type_int)) { int acvlan = json_object_get_int(jsonelement); if ((acvlan > 0) && (acvlan < VLAN_MAX)) { vlan = (uint16_t)acvlan; } } } /* Authorize station also into kernel module */ if (!ac_kmod_authorize_station(&session->sessionid, addstation.address, ifindex, notify->radioid, notify->wlanid, vlan)) { result = 0; session->retransmitcount = 0; capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL); } else { capwap_logging_warning("Unable to authorize station into kernel module data channel"); ac_free_reference_last_request(session); ac_session_teardown(session); } } else { capwap_logging_debug("Warning: error to send Station Configuration Request packet"); ac_free_reference_last_request(session); ac_session_teardown(session); } } } } } /* */ json_object_put(jsonroot); return result; }
static int ac_backend_parsing_resetwtp_event(const char* idevent, struct json_object* jsonparams) { int result = -1; struct ac_session_t* session; struct json_object* jsonwtpid; struct json_object* jsonimage; struct json_object* jsonvendor; struct json_object* jsondata; /* Params ResetWTP Action { WTPId: [string], ImageIdentifier: { Vendor: [int], Data: [string] } } */ /* WTPId */ jsonwtpid = compat_json_object_object_get(jsonparams, "WTPId"); if (!jsonwtpid || (json_object_get_type(jsonwtpid) != json_type_string)) { return -1; } /* ImageIdentifier */ jsonimage = compat_json_object_object_get(jsonparams, "ImageIdentifier"); if (!jsonimage || (json_object_get_type(jsonimage) != json_type_object)) { return -1; } jsonvendor = compat_json_object_object_get(jsonimage, "Vendor"); jsondata = compat_json_object_object_get(jsonimage, "Data"); if (!jsonvendor || !jsondata || (json_object_get_type(jsonvendor) != json_type_int) || (json_object_get_type(jsondata) != json_type_string)) { return -1; } /* Get session */ session = ac_search_session_from_wtpid(json_object_get_string(jsonwtpid)); if (session) { const char* name = json_object_get_string(jsondata); if (name && *name) { int length; struct ac_notify_reset_t* reset; struct ac_session_notify_event_t notify; /* Notification data */ length = sizeof(struct ac_notify_reset_t) + strlen(name) + 1; reset = (struct ac_notify_reset_t*)capwap_alloc(length); /* */ reset->vendor = (uint32_t)json_object_get_int(jsonvendor); strcpy((char*)reset->name, name); /* Notify Request to Complete Event */ strcpy(notify.idevent, idevent); notify.action = NOTIFY_ACTION_CHANGE_STATE; notify.session_state = CAPWAP_DEAD_STATE; ac_session_send_action(session, AC_SESSION_ACTION_NOTIFY_EVENT, 0, (void*)¬ify, sizeof(struct ac_session_notify_event_t)); /* Notify Action */ capwap_logging_debug("Receive reset request for WTP %s", session->wtpid); ac_session_send_action(session, AC_SESSION_ACTION_RESET_WTP, 0, (void*)reset, length); result = 0; /* */ capwap_free(reset); } ac_session_release_reference(session); } return result; }
static int ac_backend_parsing_addwlan_event(const char* idevent, struct json_object* jsonparams) { int result = -1; struct ac_session_t* session; struct json_object* jsonwtpid; struct json_object* jsonradioid; struct json_object* jsonwlanid; struct json_object* jsoncapability; struct json_object* jsonqos; struct json_object* jsonauthtype; struct json_object* jsonmacmode; struct json_object* jsontunnelmode; struct json_object* jsonhidessid; struct json_object* jsonssid; const char* ssid; /* Params AddWLAN Action { WTPID: [string], RadioID: [int], WLANID: [int], Capability: [int], Key: { TODO }, DefaultQoS: [int], AuthType: [int], MACMode: [int], TunnelMode: [int], SuppressSSID: [bool], SSID: [string], IE: { TODO } } */ /* WTPID */ jsonwtpid = compat_json_object_object_get(jsonparams, "WTPID"); if (!jsonwtpid || (json_object_get_type(jsonwtpid) != json_type_string)) { return -1; } /* RadioID */ jsonradioid = compat_json_object_object_get(jsonparams, "RadioID"); if (!jsonradioid || (json_object_get_type(jsonradioid) != json_type_int)) { return -1; } /* WLANID */ jsonwlanid = compat_json_object_object_get(jsonparams, "WLANID"); if (!jsonwlanid || (json_object_get_type(jsonwlanid) != json_type_int)) { return -1; } /* Capability */ jsoncapability = compat_json_object_object_get(jsonparams, "Capability"); if (!jsoncapability || (json_object_get_type(jsoncapability) != json_type_int)) { return -1; } /* Key */ /* TODO */ /* DefaultQoS */ jsonqos = compat_json_object_object_get(jsonparams, "DefaultQoS"); if (!jsonqos || (json_object_get_type(jsonqos) != json_type_int)) { return -1; } /* AuthType */ jsonauthtype = compat_json_object_object_get(jsonparams, "AuthType"); if (!jsonauthtype || (json_object_get_type(jsonauthtype) != json_type_int)) { return -1; } /* MACMode */ jsonmacmode = compat_json_object_object_get(jsonparams, "MACMode"); if (!jsonmacmode || (json_object_get_type(jsonmacmode) != json_type_int)) { return -1; } /* TunnelMode */ jsontunnelmode = compat_json_object_object_get(jsonparams, "TunnelMode"); if (!jsontunnelmode || (json_object_get_type(jsontunnelmode) != json_type_int)) { return -1; } /* SuppressSSID */ jsonhidessid = compat_json_object_object_get(jsonparams, "SuppressSSID"); if (!jsonhidessid || (json_object_get_type(jsonhidessid) != json_type_boolean)) { return -1; } /* SSID */ jsonssid = compat_json_object_object_get(jsonparams, "SSID"); if (jsonssid && (json_object_get_type(jsonssid) == json_type_string)) { ssid = json_object_get_string(jsonssid); if (strlen(ssid) > CAPWAP_ADD_WLAN_SSID_LENGTH) { return -1; } } else { return -1; } /* IE */ /* TODO */ /* Get session */ session = ac_search_session_from_wtpid(json_object_get_string(jsonwtpid)); if (session) { int length; struct ac_notify_addwlan_t* addwlan; struct ac_session_notify_event_t notify; /* Notification data */ length = sizeof(struct ac_notify_addwlan_t); addwlan = (struct ac_notify_addwlan_t*)capwap_alloc(length); /* */ addwlan->radioid = (uint8_t)json_object_get_int(jsonradioid); addwlan->wlanid = (uint8_t)json_object_get_int(jsonwlanid); addwlan->capability = (uint16_t)json_object_get_int(jsoncapability); addwlan->qos = (uint8_t)json_object_get_int(jsonqos); addwlan->authmode = (uint8_t)json_object_get_int(jsonauthtype); addwlan->macmode = (uint8_t)json_object_get_int(jsonmacmode); addwlan->tunnelmode = (uint8_t)json_object_get_int(jsontunnelmode); addwlan->suppressssid = (uint8_t)(json_object_get_boolean(jsonhidessid) ? 1 : 0); strcpy(addwlan->ssid, ssid); /* Notify Request to Complete Event */ strcpy(notify.idevent, idevent); notify.action = NOTIFY_ACTION_RECEIVE_RESPONSE_CONTROLMESSAGE; notify.ctrlmsg_type = CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE; ac_session_send_action(session, AC_SESSION_ACTION_NOTIFY_EVENT, 0, (void*)¬ify, sizeof(struct ac_session_notify_event_t)); /* Notify Action */ capwap_logging_debug("Receive AddWLAN request for WTP %s with SSID: %s", session->wtpid, addwlan->ssid); ac_session_send_action(session, AC_SESSION_ACTION_ADDWLAN, 0, (void*)addwlan, length); /* */ ac_session_release_reference(session); capwap_free(addwlan); result = 0; } return result; }
static void* ac_json_80211_wtpradioconf_createmessageelement(struct json_object* jsonparent, uint16_t radioid) { struct json_object* jsonitem; struct capwap_80211_wtpradioconf_element* wtpradioconf; wtpradioconf = (struct capwap_80211_wtpradioconf_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioconf_element)); memset(wtpradioconf, 0, sizeof(struct capwap_80211_wtpradioconf_element)); wtpradioconf->radioid = radioid; /* */ jsonitem = compat_json_object_object_get(jsonparent, "ShortPreamble"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { wtpradioconf->shortpreamble = (uint8_t)json_object_get_int(jsonitem); } else { capwap_free(wtpradioconf); return NULL; } jsonitem = compat_json_object_object_get(jsonparent, "NumBSSIDs"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { wtpradioconf->maxbssid = (uint8_t)json_object_get_int(jsonitem); } else { capwap_free(wtpradioconf); return NULL; } jsonitem = compat_json_object_object_get(jsonparent, "DTIMPeriod"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { wtpradioconf->dtimperiod = (uint8_t)json_object_get_int(jsonitem); } else { capwap_free(wtpradioconf); return NULL; } jsonitem = compat_json_object_object_get(jsonparent, "BSSID"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) { if (!capwap_scanf_macaddress((unsigned char*)wtpradioconf->bssid, json_object_get_string(jsonitem), MACADDRESS_EUI48_LENGTH)) { capwap_free(wtpradioconf); return NULL; } } else { capwap_free(wtpradioconf); return NULL; } jsonitem = compat_json_object_object_get(jsonparent, "BeaconPeriod"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_int)) { wtpradioconf->beaconperiod = (uint16_t)json_object_get_int(jsonitem); } else { capwap_free(wtpradioconf); return NULL; } jsonitem = compat_json_object_object_get(jsonparent, "CountryString"); if (jsonitem && (json_object_get_type(jsonitem) == json_type_string)) { const char* country = json_object_get_string(jsonitem); if (strlen(country) == (CAPWAP_WTP_RADIO_CONF_COUNTRY_LENGTH - 1)) { strcpy((char*)wtpradioconf->country, country); } else { capwap_free(wtpradioconf); return NULL; } } else { capwap_free(wtpradioconf); return NULL; } return wtpradioconf; }
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; }
static void ac_update_configuration(struct json_object* jsonroot) { int i; int mtu; int length; const char* bridge; struct json_object* jsonelement; struct ac_if_datachannel* datachannel; ASSERT(jsonroot != NULL); /* Params { DataChannelInterfaces: [ { Index: [int], MTU: [int], Bridge: [string] } ] } */ /* DataChannelInterfaces */ jsonelement = compat_json_object_object_get(jsonroot, "DataChannelInterfaces"); if (jsonelement && (json_object_get_type(jsonelement) == json_type_array)) { struct array_list* interfaces = json_object_get_array(jsonelement); capwap_rwlock_wrlock(&g_ac.ifdatachannellock); /* Update and Remove active interfaces*/ capwap_hash_foreach(g_ac.ifdatachannel, ac_update_configuration_datachannelinterfaces, interfaces); /* Add new interfaces*/ length = array_list_length(interfaces); for (i = 0; i < length; i++) { struct json_object* jsonvalue = array_list_get_idx(interfaces, i); if (jsonvalue && (json_object_get_type(jsonvalue) == json_type_object)) { struct json_object* jsonindex = compat_json_object_object_get(jsonvalue, "Index"); if (jsonindex && (json_object_get_type(jsonindex) == json_type_int)) { int index = json_object_get_int(jsonindex); if ((index >= 0) && (index < AC_IFACE_MAX_INDEX) && !ac_update_configuration_getdatachannel_params(jsonvalue, &mtu, &bridge)) { datachannel = (struct ac_if_datachannel*)capwap_alloc(sizeof(struct ac_if_datachannel)); memset(datachannel, 0, sizeof(struct ac_if_datachannel)); /* */ datachannel->index = (unsigned long)index; datachannel->mtu = mtu; if (bridge && (strlen(bridge) < IFNAMSIZ)) { strcpy(datachannel->bridge, bridge); } /* */ if (!ac_update_configuration_create_datachannelinterfaces(datachannel)) { capwap_hash_add(g_ac.ifdatachannel, (void*)datachannel); } else { capwap_free(datachannel); } } } } } capwap_rwlock_unlock(&g_ac.ifdatachannellock); } }