freewtp/src/ac/ac_dfa_run.c

301 lines
11 KiB
C

#include "ac.h"
#include "capwap_dfa.h"
#include "capwap_array.h"
#include "capwap_array.h"
#include "ac_session.h"
#include "ac_wlans.h"
/* */
static int receive_echo_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int validsession = 0;
struct ac_soap_response* response;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
/* Check session */
response = ac_soap_checkwtpsession(session, session->wtpid);
if (response) {
if ((response->responsecode == HTTP_RESULT_OK) && response->xmlResponseReturn) {
xmlChar* xmlResult = xmlNodeGetContent(response->xmlResponseReturn);
if (xmlResult) {
if (!xmlStrcmp(xmlResult, (const xmlChar *)"true")) {
validsession = 1;
}
xmlFree(xmlResult);
}
}
ac_soapclient_free_response(response);
}
if (!validsession) {
return -1;
}
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_ECHO_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* Add message element */
/* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */
/* Echo 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;
#ifdef DEBUG
{
char sessionname[33];
capwap_sessionid_printf(&session->sessionid, sessionname);
capwap_logging_debug("Send Echo Response to %s", sessionname);
}
#endif
/* Send Configure response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->responsefragmentpacket)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send echo response packet");
}
return 0;
}
/* */
static void execute_ieee80211_wlan_configuration_addwlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
struct ac_wlan* wlan;
struct capwap_80211_addwlan_element* addwlan;
struct capwap_80211_assignbssid_element* assignbssid;
/* */
addwlan = (struct capwap_80211_addwlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN);
/* Get BSSID */
assignbssid = (struct capwap_80211_assignbssid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_ASSIGN_BSSID);
if (assignbssid && (assignbssid->radioid == addwlan->radioid) && (assignbssid->wlanid == addwlan->wlanid)) {
wlan = ac_wlans_create_bssid(&session->wlans->devices[assignbssid->radioid - 1], assignbssid->wlanid, assignbssid->bssid, addwlan);
/* Assign BSSID to session */
ac_wlans_assign_bssid(session, wlan);
}
}
/* */
static void execute_ieee80211_wlan_configuration_updatewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
//struct capwap_80211_updatewlan_element* updatewlan;
/* */
//updatewlan = (struct capwap_80211_updatewlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN);
}
/* */
static void execute_ieee80211_wlan_configuration_deletewlan(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
//struct capwap_80211_deletewlan_element* deletewlan;
/* */
//deletewlan = (struct capwap_80211_deletewlan_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN);
}
/* */
static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_parsed_packet requestpacket;
struct capwap_packet_rxmng* rxmngrequestpacket;
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);
if (CAPWAP_RESULTCODE_OK(resultcode->code)) {
rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket);
if (rxmngrequestpacket) {
if (capwap_parsing_packet(rxmngrequestpacket, &requestpacket) == PARSING_COMPLETE) {
/* Detect type of IEEE802.11 WLAN Configuration Request */
if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_80211_ADD_WLAN)) {
execute_ieee80211_wlan_configuration_addwlan(session, packet, &requestpacket);
} else if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_80211_UPDATE_WLAN)) {
execute_ieee80211_wlan_configuration_updatewlan(session, packet, &requestpacket);
} else if (capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_80211_DELETE_WLAN)) {
execute_ieee80211_wlan_configuration_deletewlan(session, packet, &requestpacket);
}
}
/* */
capwap_free_parsed_packet(&requestpacket);
capwap_packet_rxmng_free(rxmngrequestpacket);
}
} else {
capwap_logging_warning("Receive IEEE802.11 WLAN Configuration Response with error: %d", (int)resultcode->code);
}
/* */
ac_free_reference_last_request(session);
}
/* */
static void execute_ieee80211_station_configuration_response_addstation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
struct ac_wlan* wlan;
struct ac_station* station;
struct capwap_addstation_element* addstation;
struct capwap_80211_station_element* station80211;
struct capwap_resultcode_element* resultcode;
/* */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
addstation = (struct capwap_addstation_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_ADDSTATION);
/* */
if (GET_WBID_HEADER(packet->rxmngpacket->header) == CAPWAP_WIRELESS_BINDING_IEEE80211) {
station80211 = (struct capwap_80211_station_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_80211_STATION);
if (station80211) {
wlan = ac_wlans_get_bssid_with_wlanid(session, station80211->radioid, station80211->wlanid);
if (wlan) {
station = ac_stations_get_station(session, station80211->radioid, wlan->address, addstation->address);
if (station) {
if (CAPWAP_RESULTCODE_OK(resultcode->code)) {
capwap_logging_info("Authorized station: %s", station->addrtext);
/* */
station->flags |= AC_STATION_FLAGS_AUTHORIZED;
capwap_timeout_deletetimer(session->timeout, station->idtimeout);
station->idtimeout = CAPWAP_TIMEOUT_INDEX_NO_SET;
} else {
ac_stations_delete_station(session, station);
}
}
}
}
}
}
/* */
static void execute_ieee80211_station_configuration_response_deletestation(struct ac_session_t* session, struct capwap_parsed_packet* packet, struct capwap_parsed_packet* requestpacket) {
struct ac_station* station;
struct capwap_resultcode_element* resultcode;
struct capwap_deletestation_element* deletestation;
/* */
resultcode = (struct capwap_resultcode_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_RESULTCODE);
deletestation = (struct capwap_deletestation_element*)capwap_get_message_element_data(requestpacket, CAPWAP_ELEMENT_DELETESTATION);
/* */
station = ac_stations_get_station(session, deletestation->radioid, NULL, deletestation->address);
if (station) {
capwap_logging_info("Deauthorized station: %s with %d result code", station->addrtext, (int)resultcode->code);
/* */
ac_stations_delete_station(session, station);
}
}
/* */
static void receive_ieee80211_station_configuration_response(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_packet_rxmng* rxmngrequestpacket;
struct capwap_parsed_packet requestpacket;
/* Parsing request message */
rxmngrequestpacket = capwap_packet_rxmng_create_from_requestfragmentpacket(session->requestfragmentpacket);
if (capwap_parsing_packet(rxmngrequestpacket, &requestpacket) == PARSING_COMPLETE) {
if (capwap_get_message_element(&requestpacket, CAPWAP_ELEMENT_ADDSTATION)) {
execute_ieee80211_station_configuration_response_addstation(session, packet, &requestpacket);
} else if (capwap_get_message_element_data(&requestpacket, CAPWAP_ELEMENT_DELETESTATION)) {
execute_ieee80211_station_configuration_response_deletestation(session, packet, &requestpacket);
}
}
/* */
capwap_free_parsed_packet(&requestpacket);
capwap_packet_rxmng_free(rxmngrequestpacket);
ac_free_reference_last_request(session);
}
/* */
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet != NULL);
if (capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type) || ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) {
switch (packet->rxmngpacket->ctrlmsg.type) {
case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_CHANGE_STATE_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_ECHO_REQUEST: {
#ifdef DEBUG
{
char sessionname[33];
capwap_sessionid_printf(&session->sessionid, sessionname);
capwap_logging_debug("Receive Echo Request from %s", sessionname);
}
#endif
if (!receive_echo_request(session, packet)) {
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
} else {
ac_session_teardown(session);
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_WTP_EVENT_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
/* TODO */
/* */
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
receive_ieee80211_station_configuration_response(session, packet);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: {
receive_ieee80211_wlan_configuration_response(session, packet);
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
break;
}
}
}
}