Improve memory administration for tx/rx packet manager

This commit is contained in:
vemax78
2013-05-27 21:33:23 +02:00
parent 9157cc278b
commit 6c55b4d71f
126 changed files with 5383 additions and 7894 deletions

View File

@ -22,11 +22,11 @@ static int ac_init(void) {
g_ac.binding = capwap_array_create(sizeof(unsigned short), 0);
/* Standard name */
strcpy(g_ac.acname.name, AC_STANDARD_NAME);
strcpy((char*)g_ac.acname.name, AC_STANDARD_NAME);
/* Descriptor */
g_ac.descriptor.stationlimit = AC_DEFAULT_MAXSTATION;
g_ac.descriptor.wtplimit = AC_DEFAULT_MAXSESSIONS;
g_ac.descriptor.maxwtp = AC_DEFAULT_MAXSESSIONS;
g_ac.descriptor.security = 0;
g_ac.descriptor.rmacfield = CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED;
g_ac.descriptor.dtlspolicy = CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED;
@ -44,8 +44,8 @@ static int ac_init(void) {
g_ac.dfa.wtpfallback.mode = AC_DEFAULT_WTP_FALLBACK_MODE;
/* */
g_ac.dfa.acipv4list = capwap_array_create(sizeof(struct capwap_acipv4list_element), 0);
g_ac.dfa.acipv6list = capwap_array_create(sizeof(struct capwap_acipv6list_element), 0);
g_ac.dfa.acipv4list.addresses = capwap_array_create(sizeof(struct in_addr), 0);
g_ac.dfa.acipv6list.addresses = capwap_array_create(sizeof(struct in6_addr), 0);
/* */
g_ac.dfa.rfcWaitJoin = AC_DEFAULT_WAITJOIN_INTERVAL;
@ -72,8 +72,8 @@ static void ac_destroy(void) {
capwap_array_free(g_ac.binding);
/* */
capwap_array_free(g_ac.dfa.acipv4list);
capwap_array_free(g_ac.dfa.acipv6list);
capwap_array_free(g_ac.dfa.acipv4list.addresses);
capwap_array_free(g_ac.dfa.acipv6list.addresses);
/* Sessions */
capwap_list_free(g_ac.sessions);
@ -152,7 +152,7 @@ static int ac_parsing_configuration_1_0(config_t* config) {
return 0;
}
strcpy(g_ac.acname.name, configString);
strcpy((char*)g_ac.acname.name, configString);
}
/* Set binding of AC */
@ -190,7 +190,7 @@ static int ac_parsing_configuration_1_0(config_t* config) {
/* Set max wtp of AC */
if (config_lookup_int(config, "application.descriptor.maxwtp", &configLongInt) == CONFIG_TRUE) {
if ((configLongInt > 0) && (configLongInt < 65536)) {
g_ac.descriptor.wtplimit = (unsigned short)configLongInt;
g_ac.descriptor.maxwtp = (unsigned short)configLongInt;
} else {
capwap_logging_error("Invalid configuration file, unknown application.descriptor.maxwtp value");
return 0;
@ -266,7 +266,7 @@ static int ac_parsing_configuration_1_0(config_t* config) {
desc->vendor = (unsigned long)configVendor;
desc->type = type;
desc->length = lengthValue;
strcpy(desc->data, configValue);
strcpy((char*)desc->data, configValue);
} else {
capwap_logging_error("Invalid configuration file, application.descriptor.info.value string length exceeded");
return 0;

View File

@ -55,8 +55,8 @@ struct ac_state {
struct capwap_wtpfallback_element wtpfallback;
/* */
capwap_acipv4list_element_array* acipv4list;
capwap_acipv6list_element_array* acipv6list;
struct capwap_acipv4list_element acipv4list;
struct capwap_acipv6list_element acipv6list;
/* */
int rfcWaitJoin;

View File

@ -4,115 +4,73 @@
#include "ac_session.h"
/* */
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
unsigned long i;
unsigned short binding;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
unsigned short binding;
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* TODO: gestione richiesta */
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CONFIGURATION_STATUS_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
struct capwap_element_configurationstatus_request configurationstatusrequest;
/* Configuration Status request info*/
capwap_init_element_configurationstatus_request(&configurationstatusrequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_configurationstatus_request(&configurationstatusrequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* responsepacket;
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* TODO: gestione richiesta */
/* Add message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TIMERS, &session->dfa.timers);
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
for (i = 0; i < packet->messageelements.radioadmstate->count; i++) {
struct capwap_decrypterrorreportperiod_element report;
struct capwap_radioadmstate_element* radioadm = *(struct capwap_radioadmstate_element**)capwap_array_get_item_pointer(packet->messageelements.radioadmstate, i);
/* Prepare configuration status response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CONFIGURATION_STATUS_RESPONSE, buildpacket->ctrlmsg.seq);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TIMERS_ELEMENT(&session->dfa.timers));
for (i = 0; i < configurationstatusrequest.radioadmstatus->count; i++) {
struct capwap_decrypterrorreportperiod_element report;
struct capwap_radioadmstate_element* radioadm = (struct capwap_radioadmstate_element*)capwap_array_get_item_pointer(configurationstatusrequest.radioadmstatus, i);
report.radioid = radioadm->radioid;
report.interval = session->dfa.decrypterrorreport_interval;
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_DECRYPTERRORREPORTPERIOD_ELEMENT(&report));
}
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_IDLETIMEOUT_ELEMENT(&session->dfa.idletimeout));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_WTPFALLBACK_ELEMENT(&session->dfa.wtpfallback));
if (session->dfa.acipv4list->count > 0) {
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV4LIST_ELEMENT(session->dfa.acipv4list));
}
if (session->dfa.acipv6list->count > 0) {
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV6LIST_ELEMENT(session->dfa.acipv6list));
}
/* CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
if (!capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* Send configuration status response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send configuration status response packet");
break;
}
}
/* Change status */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
capwap_set_timeout(session->dfa.rfcChangeStatePendingTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
} else {
capwap_logging_debug("Warning: build invalid configuration status response packet");
}
/* Free memory */
capwap_build_packet_free(responsepacket);
}
/* Free */
capwap_free_element_configurationstatus_request(&configurationstatusrequest, binding);
}
}
/* Free */
capwap_build_packet_free(buildpacket);
report.radioid = radioadm->radioid;
report.interval = session->dfa.decrypterrorreport_interval;
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD, &report);
}
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_IDLETIMEOUT, &session->dfa.idletimeout);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPFALLBACK, &session->dfa.wtpfallback);
if (session->dfa.acipv4list.addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, &session->dfa.acipv4list);
}
if (session->dfa.acipv6list.addresses->count > 0) {
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, &session->dfa.acipv6list);
}
/* CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
/* Configure 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->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Send Configure response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send configuration status response packet");
}
/* Change state */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
capwap_set_timeout(session->dfa.rfcChangeStatePendingTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
/* Configure timeout */
ac_dfa_change_state(session, CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE);
@ -123,6 +81,6 @@ int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* p
}
/* */
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
return ac_session_teardown_connection(session);
}

View File

@ -4,91 +4,48 @@
#include "ac_session.h"
/* */
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet) {
unsigned long i;
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
unsigned short binding;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
unsigned short binding;
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
/* TODO: gestione richiesta */
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CHANGE_STATE_EVENT_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
struct capwap_element_changestateevent_request changeeventrequest;
/* Change event request info */
capwap_init_element_changestateevent_request(&changeeventrequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_changestateevent_request(&changeeventrequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* responsepacket;
/* Create response */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
/* TODO: gestione richiesta */
/* Add message element */
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Prepare change event response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, buildpacket->ctrlmsg.seq);
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
if (!capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* Send change event response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send change event response packet");
break;
}
}
/* Change status */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
capwap_set_timeout(session->dfa.rfcDataCheckTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
} else {
capwap_logging_debug("Warning: build invalid configuration status response packet");
}
/* Free memory */
capwap_build_packet_free(responsepacket);
}
/* Free */
capwap_free_element_changestateevent_request(&changeeventrequest, binding);
}
}
/* Free */
capwap_build_packet_free(buildpacket);
/* Change event 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->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Send Change event response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send change event response packet");
}
/* Change state */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
capwap_set_timeout(session->dfa.rfcDataCheckTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
/* Configure timeout */
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
@ -99,59 +56,54 @@ int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* p
}
/* */
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_list* txfragpacket;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
/* Wait Data Channel Keep-Alive packet */
if (!packet->socket.isctrlsocket) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
struct capwap_sessionid_element sessionid;
if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
int result;
capwap_fragment_packet_array* txfragpacket;
/* Receive data packet keepalive, response with same packet */
txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0);
if (!result) {
struct capwap_packet* txpacket;
ASSERT(txfragpacket->count == 1);
txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) {
capwap_logging_debug("Warning: error to send data channel keepalive packet");
result = -1;
}
}
/* */
capwap_fragment_free(txfragpacket);
capwap_array_free(txfragpacket);
if (!result) {
/* Capwap handshake complete */
ac_dfa_change_state(session, CAPWAP_RUN_STATE);
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
if (!packet->rxmngpacket->isctrlpacket && IS_FLAG_K_HEADER(packet->rxmngpacket->header)) {
if (!memcmp(packet->messageelements.sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
int result = 0;
/* Build packet */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
capwap_header_set_keepalive_flag(&capwapheader, 1);
txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, session->mtu);
/* Add message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_SESSIONID, &session->sessionid);
/* Data keepalive complete, get fragment packets into local list */
txfragpacket = capwap_list_create();
capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, 0);
if (txfragpacket->count == 1) {
/* Send Data keepalive to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->datadtls, session->datasocket.socket[session->datasocket.type], txfragpacket, &session->acdataaddress, &session->wtpdataaddress)) {
result = 1;
} else {
capwap_logging_debug("Warning: error to send data channel keepalive packet");
}
} else {
capwap_logging_debug("Warning: error to send data channel keepalive packet, fragment packet");
}
/* Free packets manager */
capwap_list_free(txfragpacket);
capwap_packet_txmng_free(txmngpacket);
if (result) {
/* Capwap handshake complete */
ac_dfa_change_state(session, CAPWAP_RUN_STATE);
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
/* Free */
capwap_build_packet_free(buildpacket);
}
}
} else {
@ -164,6 +116,6 @@ int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_pa
}
/* */
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
return ac_session_teardown_connection(session);
}

View File

@ -14,7 +14,7 @@ int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param)
}
/* */
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
@ -37,7 +37,7 @@ int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* p
}
/* */
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet == NULL);
@ -46,6 +46,6 @@ int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet*
}
/* */
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
return ac_session_teardown_connection(session);
}

View File

@ -4,7 +4,7 @@
#include "ac_session.h"
/* */
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
/* TODO */
@ -13,6 +13,6 @@ int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* p
}
/* */
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
return ac_session_teardown_connection(session);
}

View File

@ -4,227 +4,130 @@
#include "ac_session.h"
/* */
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int i;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
int status = AC_DFA_ACCEPT_PACKET;
struct capwap_resultcode_element resultcode = { CAPWAP_RESULTCODE_FAILURE };
struct capwap_build_packet* responsepacket;
struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE };
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
int validpacket;
unsigned long checkpacket;
struct capwap_array* returnedmessagearray = NULL;
capwap_unrecognized_element_array* unrecognizedarray;
struct capwap_element_join_request joinrequest;
unsigned short binding = GET_WBID_HEADER(&buildpacket->header);
unsigned short binding;
/* */
unrecognizedarray = capwap_array_create(sizeof(struct unrecognized_info), 0);
/* */
checkpacket = capwap_build_packet_validate(buildpacket, unrecognizedarray);
if (!checkpacket) {
if (ac_valid_binding(binding)) {
if (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_JOIN_REQUEST) {
resultcode.code = CAPWAP_RESULTCODE_SUCCESS;
} else {
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
}
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
}
/* Check binding */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if (ac_valid_binding(binding)) {
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) {
resultcode.code = CAPWAP_RESULTCODE_SUCCESS;
/* Get sessionid */
memcpy(&session->sessionid, packet->messageelements.sessionid, sizeof(struct capwap_sessionid_element));
/* Get binding */
session->binding = binding;
} else {
if ((checkpacket & CAPWAP_MISSING_MANDATORY_MSG_ELEMENT) != 0) {
resultcode.code = CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT;
} else if ((checkpacket & CAPWAP_UNRECOGNIZED_MSG_ELEMENT) != 0) {
struct capwap_list_item* itemelement;
resultcode.code = CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT;
returnedmessagearray = capwap_array_create(sizeof(struct capwap_returnedmessage_element), unrecognizedarray->count);
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
}
} else {
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
}
for (i = 0; i < unrecognizedarray->count; i++) {
struct unrecognized_info* reasoninfo = capwap_array_get_item_pointer(unrecognizedarray, i);
/* Search element */
itemelement = buildpacket->elementslist->first;
while (itemelement != NULL) {
struct capwap_message_element* elementitem = (struct capwap_message_element*)itemelement->item;
if (ntohs(elementitem->type) == reasoninfo->element) {
struct capwap_returnedmessage_element* returnedelement = capwap_array_get_item_pointer(returnedmessagearray, i);
unsigned short length = sizeof(struct capwap_message_element) + ntohs(elementitem->length);
/* 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);
returnedelement->reason = reasoninfo->reason;
returnedelement->length = min(length, CAPWAP_RETURNED_MESSAGE_MAX_LENGTH);
memcpy(&returnedelement->message[0], elementitem, returnedelement->length);
break;
}
/* Next */
itemelement = itemelement->next;
}
}
/* Add message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
/* Check is valid packet after parsing request */
if ((resultcode.code == CAPWAP_RESULTCODE_SUCCESS) || (resultcode.code == CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED)) {
struct capwap_list* controllist;
struct capwap_list_item* item;
/* Update statistics */
ac_update_statistics();
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname);
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
for (i = 0; i < packet->messageelements.ieee80211.wtpradioinformation->count; i++) {
struct capwap_80211_wtpradioinformation_element* radio;
radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(packet->messageelements.ieee80211.wtpradioinformation, i);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, radio);
}
}
/* */
capwap_array_free(unrecognizedarray);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ECNSUPPORT, &session->dfa.ecn);
/* */
capwap_init_element_join_request(&joinrequest, binding);
if (resultcode.code == CAPWAP_RESULTCODE_SUCCESS) {
/* Parsing elements list */
if (capwap_parsing_element_join_request(&joinrequest, buildpacket->elementslist->first)) {
/* TODO: gestione richiesta */
/* Get information from any local address */
controllist = capwap_list_create();
ac_get_control_information(controllist);
for (item = controllist->first; item != NULL; item = item->next) {
struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
if (sessioncontrol->localaddress.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_family == AF_INET6) {
struct capwap_controlipv6_element element;
/* Get sessionid */
memcpy(&session->sessionid, joinrequest.sessionid, sizeof(struct capwap_sessionid_element));
/* Get binding */
session->binding = binding;
resultcode.code = CAPWAP_RESULTCODE_SUCCESS;
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);
}
}
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Prepare join response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_JOIN_RESPONSE, buildpacket->ctrlmsg.seq);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RESULTCODE_ELEMENT(&resultcode));
capwap_list_free(controllist);
/* Check is valid packet after parsing request */
validpacket = (((resultcode.code == CAPWAP_RESULTCODE_SUCCESS) || (resultcode.code == CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED)) ? 1 : 0);
if (validpacket) {
struct capwap_list* controllist;
struct capwap_list_item* item;
/* Update statistics */
ac_update_statistics();
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname));
if (session->acctrladdress.ss_family == AF_INET) {
struct capwap_localipv4_element addr;
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
for (i = 0; i < joinrequest.binding.ieee80211.wtpradioinformation->count; i++) {
struct capwap_80211_wtpradioinformation_element* radio;
radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(joinrequest.binding.ieee80211.wtpradioinformation, i);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio));
}
} else {
capwap_logging_debug("Unknown capwap binding");
}
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ECNSUPPORT_ELEMENT(&session->dfa.ecn));
memcpy(&addr.address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV4, &addr);
} else if (session->acctrladdress.ss_family == AF_INET6) {
struct capwap_localipv6_element addr;
/* Get information from any local address */
controllist = capwap_list_create();
ac_get_control_information(controllist);
for (item = controllist->first; item != NULL; item = item->next) {
struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
if (sessioncontrol->localaddress.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_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element));
} else if (sessioncontrol->localaddress.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_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element));
}
}
capwap_list_free(controllist);
if (session->acctrladdress.ss_family == AF_INET) {
struct capwap_localipv4_element addr;
memcpy(&addr.address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV4_ELEMENT(&addr));
} else if (session->acctrladdress.ss_family == AF_INET6) {
struct capwap_localipv6_element addr;
memcpy(&addr.address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV6_ELEMENT(&addr));
}
/* CAPWAP_CREATE_ACIPV4LIST_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_ACIPV6LIST_ELEMENT */ /* TODO */
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TRANSPORT_ELEMENT(&session->dfa.transport));
/* CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_MAXIMUMMESSAGELENGTH_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
} else if (resultcode.code == CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT) {
ASSERT(returnedmessagearray != NULL);
for (i = 0; i < returnedmessagearray->count; i++) {
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RETURNEDMESSAGE_ELEMENT(capwap_array_get_item_pointer(returnedmessagearray, i)));
}
capwap_array_free(returnedmessagearray);
memcpy(&addr.address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV6, &addr);
}
/* Validate packet */
if (!validpacket || !capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* CAPWAP_CREATE_ACIPV4LIST_ELEMENT */ /* TODO */
/* CAPWAP_CREATE_ACIPV6LIST_ELEMENT */ /* TODO */
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 */
}
/* Send join response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* 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++;
}
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send join response packet");
break;
}
}
}
} else {
capwap_logging_debug("Warning: build invalid join response packet");
}
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Free memory */
capwap_build_packet_free(responsepacket);
capwap_free_element_join_request(&joinrequest, binding);
capwap_build_packet_free(buildpacket);
/* Change state */
if (validpacket) {
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
} else {
ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
/* Send Join response to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
} else {
/* Error to send packets */
capwap_logging_debug("Warning: error to send join response packet");
ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
} else {
/* Join timeout */
@ -236,26 +139,21 @@ int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet
}
/* */
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
unsigned short lengthpayload;
lengthpayload = packet->packetsize - GET_HLEN_HEADER(packet->header) * 4;
if (lengthpayload >= sizeof(struct capwap_control_message)) {
struct capwap_control_message* ctrlmsg = (struct capwap_control_message*)packet->payload;
unsigned long type = ntohl(ctrlmsg->type);
if (type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
status = ac_dfa_state_configure(session, packet);
} else if (type == CAPWAP_IMAGE_DATA_REQUEST) {
ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE);
status = ac_dfa_state_imagedata(session, packet);
}
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
status = 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);
status = ac_dfa_state_imagedata(session, packet);
} else {
ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
} else {
/* Join timeout */
@ -267,6 +165,6 @@ int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* pa
}
/* */
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
return ac_session_teardown_connection(session);
}

View File

@ -4,69 +4,34 @@
#include "ac_session.h"
/* */
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
if (!capwap_compare_ip(&session->wtpctrladdress, &packet->remoteaddr)) {
struct capwap_build_packet* buildpacket;
unsigned short binding;
/* Parsing packet */
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
unsigned short binding;
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if ((binding == session->binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) {
struct capwap_element_reset_response resetresponse;
/* Valid packet, free request packet */
ac_free_reference_last_request(session);
/* Configuration status response info */
capwap_init_element_reset_response(&resetresponse, binding);
/* Parsing elements list */
if (capwap_parsing_element_reset_response(&resetresponse, buildpacket->elementslist->first)) {
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
/* Free join response */
capwap_free_element_reset_response(&resetresponse, binding);
}
}
/* Free */
capwap_build_packet_free(buildpacket);
}
/* */
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if ((binding == session->binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) {
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
} else {
int i;
/* No Configuration status response received */
session->dfa.rfcRetransmitCount++;
if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) {
/* Timeout join state */
/* Timeout reset state */
ac_free_reference_last_request(session);
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
} else {
/* Retransmit configuration request */
for (i = 0; i < session->requestfragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
capwap_logging_debug("Warning: error to send configuration status request packet");
break;
}
if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->requestfragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
capwap_logging_debug("Warning: error to resend reset request packet");
}
/* Update timeout */
capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
}
@ -76,6 +41,6 @@ int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packe
}
/* */
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
return ac_session_teardown_connection(session);
}

View File

@ -4,185 +4,148 @@
#include "ac_session.h"
/* */
static int receive_echo_request(struct ac_session_t* session, struct capwap_build_packet* buildpacket, struct capwap_packet* packet) {
unsigned long i;
unsigned short binding;
static int receive_echo_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
ASSERT(session != NULL);
ASSERT(buildpacket != NULL);
ASSERT(packet != NULL);
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
if (ac_valid_binding(binding) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
struct capwap_element_echo_request echorequest;
/* Echo request info*/
capwap_init_element_echo_request(&echorequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_echo_request(&echorequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* responsepacket;
/* 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);
/* Create response */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Add message element */
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
/* Prepare echo response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_ECHO_RESPONSE, buildpacket->ctrlmsg.seq);
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* 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++;
}
if (!capwap_build_packet_validate(responsepacket, NULL)) {
int result;
/* Free old reference for this request */
ac_free_reference_last_response(session);
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Send echo response to WTP */
result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Save remote sequence number */
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
/* Save remote sequence number */
session->remoteseqnumber = buildpacket->ctrlmsg.seq;
capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
/* Send */
for (i = 0; i < session->responsefragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
capwap_logging_debug("Warning: error to send echo response packet");
break;
}
}
}
}
/* Free memory */
capwap_build_packet_free(responsepacket);
}
/* Free */
capwap_free_element_echo_request(&echorequest, binding);
/* Send Configure response to WTP */
if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
/* 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;
}
/* */
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet) {
static int ac_send_data_keepalive(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
struct capwap_list* txfragpacket;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
int result = -1;
/* Build packet */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
capwap_header_set_keepalive_flag(&capwapheader, 1);
txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, session->mtu);
/* Add message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_SESSIONID, &session->sessionid);
/* Data keepalive complete, get fragment packets into local list */
txfragpacket = capwap_list_create();
capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, 0);
if (txfragpacket->count == 1) {
/* Send Data keepalive to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->datadtls, session->datasocket.socket[session->datasocket.type], txfragpacket, &session->acdataaddress, &session->wtpdataaddress)) {
result = 0;
} else {
capwap_logging_debug("Warning: error to send data channel keepalive packet");
}
} else {
capwap_logging_debug("Warning: error to send data channel keepalive packet, fragment packet");
}
/* Free packets manager */
capwap_list_free(txfragpacket);
capwap_packet_txmng_free(txmngpacket);
return result;
}
/* */
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int status = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
if (packet) {
struct capwap_build_packet* buildpacket;
buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
if (packet->socket.isctrlsocket) {
unsigned long typemsg = ntohl(buildpacket->ctrlmsg.type);
if (capwap_is_request_type(typemsg) || ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) {
switch (typemsg) {
case CAPWAP_CONFIGURATION_UPDATE_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_ECHO_REQUEST: {
if (!receive_echo_request(session, buildpacket, packet)) {
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_WTP_EVENT_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
}
}
} else {
if (IS_FLAG_K_HEADER(&buildpacket->header)) {
struct capwap_sessionid_element sessionid;
if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
int result;
capwap_fragment_packet_array* txfragpacket;
/* Receive data packet keepalive, response with same packet */
txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0);
if (!result) {
struct capwap_packet* txpacket;
ASSERT(txfragpacket->count == 1);
txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) {
capwap_logging_debug("Warning: error to send data channel keepalive packet");
result = -1;
}
}
/* */
capwap_fragment_free(txfragpacket);
capwap_array_free(txfragpacket);
if (result) {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
}
}
} else {
if (packet->rxmngpacket->isctrlpacket) {
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_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_ECHO_REQUEST: {
if (!receive_echo_request(session, packet)) {
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
} else {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
break;
}
case CAPWAP_CLEAR_CONFIGURATION_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_WTP_EVENT_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_REQUEST: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
case CAPWAP_DATA_TRANSFER_RESPONSE: {
/* TODO */
capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
break;
}
}
}
/* Free */
capwap_build_packet_free(buildpacket);
} else {
if (IS_FLAG_K_HEADER(packet->rxmngpacket->header)) {
if (!memcmp(packet->messageelements.sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
if (ac_send_data_keepalive(session, packet)) {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
status = AC_DFA_NO_PACKET;
}
}
} else {
/* TODO */
}
}
} else {
ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
@ -193,71 +156,49 @@ int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet)
}
/* */
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int status = AC_DFA_NO_PACKET;
struct capwap_build_packet* buildpacket;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
ASSERT(session != NULL);
ASSERT(packet == NULL);
/* Build packet */
buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, session->binding);
buildpacket->isctrlmsg = 1;
/* Prepare reset request */
capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_RESET_REQUEST, session->localseqnumber++);
capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT(&session->startupimage));
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_RESET_REQUEST, session->localseqnumber++, session->mtu);
/* Add message element */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_IMAGEIDENTIFIER, &session->startupimage);
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
if (!capwap_build_packet_validate(buildpacket, NULL)) {
int i;
int result;
/* Free old reference for this request */
ac_free_reference_last_request(session);
/* Send reset request to WTP */
result = capwap_fragment_build_packet(buildpacket, session->requestfragmentpacket, session->mtu, session->fragmentid);
if (result >= 0) {
if (result == 1) {
session->fragmentid++;
}
/* Send */
for (i = 0; i < session->requestfragmentpacket->count; i++) {
struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i);
ASSERT(txpacket != NULL);
if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
capwap_logging_debug("Warning: error to send reset request packet");
result = -1;
break;
}
}
}
if (result == -1) {
/* Error to send packets */
ac_free_reference_last_request(session);
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
} else {
session->dfa.rfcRetransmitCount = 0;
capwap_killall_timeout(&session->timeout);
capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
ac_dfa_change_state(session, CAPWAP_RESET_STATE);
status = AC_DFA_ACCEPT_PACKET;
}
/* Reset request complete, get fragment packets */
ac_free_reference_last_request(session);
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 Configure response to WTP */
if (capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->requestfragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
session->dfa.rfcRetransmitCount = 0;
capwap_killall_timeout(&session->timeout);
capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
ac_dfa_change_state(session, CAPWAP_RESET_STATE);
status = AC_DFA_ACCEPT_PACKET;
} else {
capwap_logging_debug("Warning: error to send reset request packet");
ac_free_reference_last_request(session);
ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
}
/* Free memory */
capwap_build_packet_free(buildpacket);
return status;
}
/* */
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
return ac_session_teardown_connection(session);
}

View File

@ -4,7 +4,7 @@
#include "ac_session.h"
/* */
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet == NULL);
@ -14,7 +14,7 @@ int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* pa
}
/* */
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet) {
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
ASSERT(session != NULL);
ASSERT(packet == NULL);

View File

@ -88,44 +88,39 @@ void ac_discovery_add_packet(void* buffer, int buffersize, int sock, struct sock
}
/* */
static struct capwap_build_packet* ac_create_discovery_response(struct capwap_build_packet* packet, struct capwap_element_discovery_request* discoveryrequest, struct sockaddr_storage* sender) {
static struct capwap_packet_txmng* ac_create_discovery_response(struct capwap_parsed_packet* packet) {
int i;
unsigned short binding;
struct capwap_list* controllist;
struct capwap_list_item* item;
struct capwap_build_packet* responsepacket;
struct capwap_header_data capwapheader;
struct capwap_packet_txmng* txmngpacket;
ASSERT(packet != NULL);
ASSERT(discoveryrequest != NULL);
ASSERT(sender != NULL);
/* Check is valid binding */
binding = GET_WBID_HEADER(&packet->header);
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
if (!ac_valid_binding(binding)) {
return NULL;
}
/* Build packet */
responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
responsepacket->isctrlmsg = 1;
/* Update statistics */
ac_update_statistics();
/* Prepare discovery response */
capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_DISCOVERY_RESPONSE, packet->ctrlmsg.seq);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor));
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname));
/* Build packet */
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding);
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_DISCOVERY_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, g_ac.mtu);
/* Prepare discovery response */
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname);
if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
for (i = 0; i < discoveryrequest->binding.ieee80211.wtpradioinformation->count; i++) {
for (i = 0; i < packet->messageelements.ieee80211.wtpradioinformation->count; i++) {
struct capwap_80211_wtpradioinformation_element* radio;
radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(discoveryrequest->binding.ieee80211.wtpradioinformation, i);
capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio));
radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(packet->messageelements.ieee80211.wtpradioinformation, i);
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, radio);
}
} else {
capwap_logging_debug("Unknown capwap binding");
}
/* Get information from any local address */
@ -137,24 +132,24 @@ static struct capwap_build_packet* ac_create_discovery_response(struct capwap_bu
if (sessioncontrol->localaddress.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_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element));
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element);
} else if (sessioncontrol->localaddress.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_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element));
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element);
}
}
capwap_list_free(controllist);
capwap_list_free(controllist);
/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */
return responsepacket;
return txmngpacket;
}
/* Cleanup info discovery */
@ -167,21 +162,21 @@ static void ac_discovery_cleanup(void) {
static void ac_discovery_run(void) {
int sizedata;
struct capwap_list_item* itempacket;
struct capwap_build_packet* buildpacket;
struct ac_discovery_packet* packet;
unsigned short binding;
struct ac_discovery_packet* acpacket;
struct capwap_parsed_packet packet;
struct capwap_packet_rxmng* rxmngpacket;
while (!g_ac_discovery.endthread) {
/* Get packet */
capwap_lock_enter(&g_ac_discovery.packetslock);
itempacket = NULL;
if (g_ac_discovery.packets->count > 0) {
itempacket = capwap_itemlist_remove_head(g_ac_discovery.packets);
}
capwap_lock_exit(&g_ac_discovery.packetslock);
if (!itempacket) {
/* Wait packet with timeout*/
if (!capwap_event_wait_timeout(&g_ac_discovery.waitpacket, AC_DISCOVERY_CLEANUP_TIMEOUT)) {
@ -190,74 +185,56 @@ static void ac_discovery_run(void) {
continue;
}
/* */
packet = (struct ac_discovery_packet*)itempacket->item;
acpacket = (struct ac_discovery_packet*)itempacket->item;
sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet);
/* Parsing packet */
buildpacket = capwap_rx_packet_create(packet->data, sizedata, 1);
if (buildpacket) {
if (!capwap_build_packet_validate(buildpacket, NULL)) {
struct capwap_element_discovery_request discoveryrequest;
/* */
binding = GET_WBID_HEADER(&buildpacket->header);
capwap_init_element_discovery_request(&discoveryrequest, binding);
/* Parsing elements list */
if (capwap_parsing_element_discovery_request(&discoveryrequest, buildpacket->elementslist->first)) {
struct capwap_build_packet* txpacket;
capwap_fragment_packet_array* responsefragmentpacket = NULL;
/* Accept only discovery request don't fragment */
rxmngpacket = capwap_packet_rxmng_create_message(1);
if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, acpacket->data, sizedata) == CAPWAP_RECEIVE_COMPLETE_PACKET) {
/* Validate message */
if (capwap_check_message_type(rxmngpacket) == VALID_MESSAGE_TYPE) {
/* Parsing packet */
if (!capwap_parsing_packet(rxmngpacket, NULL, &packet)) {
/* Validate packet */
if (!capwap_validate_parsed_packet(&packet, NULL)) {
struct capwap_packet_txmng* txmngpacket;
/* Creare discovery response */
txpacket = ac_create_discovery_response(buildpacket, &discoveryrequest, &packet->sender);
if (txpacket) {
int result = -1;
if (!capwap_build_packet_validate(txpacket, NULL)) {
responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
result = capwap_fragment_build_packet(txpacket, responsefragmentpacket, g_ac.mtu, g_ac_discovery.fragmentid);
if (result == 1) {
/* Creare discovery response */
txmngpacket = ac_create_discovery_response(&packet);
if (txmngpacket) {
struct capwap_list* responsefragmentpacket;
/* Discovery response complete, get fragment packets */
responsefragmentpacket = capwap_list_create();
capwap_packet_txmng_get_fragment_packets(txmngpacket, responsefragmentpacket, g_ac_discovery.fragmentid);
if (responsefragmentpacket->count > 1) {
g_ac_discovery.fragmentid++;
}
} else {
capwap_logging_debug("Warning: build invalid discovery response packet");
}
capwap_build_packet_free(txpacket);
/* Send discovery response to WTP */
if (result >= 0) {
int i;
for (i = 0; i < responsefragmentpacket->count; i++) {
struct capwap_packet* sendpacket = (struct capwap_packet*)capwap_array_get_item_pointer(responsefragmentpacket, i);
ASSERT(sendpacket != NULL);
if (!capwap_sendto(packet->sendsock, sendpacket->header, sendpacket->packetsize, NULL, &packet->sender)) {
capwap_logging_debug("Warning: error to send discovery response packet");
break;
}
/* Free packets manager */
capwap_packet_txmng_free(txmngpacket);
/* Send discovery response to WTP */
if (!capwap_sendto_fragmentpacket(acpacket->sendsock, responsefragmentpacket, NULL, &acpacket->sender)) {
capwap_logging_debug("Warning: error to send discovery response packet");
}
/* Don't buffering a packets sent */
capwap_list_free(responsefragmentpacket);
}
}
/* Don't buffering a packets sent */
if (responsefragmentpacket) {
capwap_fragment_free(responsefragmentpacket);
capwap_array_free(responsefragmentpacket);
}
}
/* Free discovery request */
capwap_free_element_discovery_request(&discoveryrequest, binding);
/* Free resource */
capwap_free_parsed_packet(&packet);
}
/* */
capwap_build_packet_free(buildpacket);
}
/* Free resource */
capwap_packet_rxmng_free(rxmngpacket);
/* Free packet */
capwap_itemlist_free(itempacket);
}

View File

@ -58,44 +58,68 @@ static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_st
/* */
static struct ac_session_t* ac_get_session_from_keepalive(void* buffer, int buffersize) {
struct capwap_parsed_packet packet;
struct capwap_packet_rxmng* rxmngpacket;
struct ac_session_t* result = NULL;
struct capwap_build_packet* buildpacket;
ASSERT(buffer != NULL);
ASSERT(buffersize > 0);
buildpacket = capwap_rx_packet_create(buffer, buffersize, 0);
if (buildpacket) {
struct capwap_sessionid_element sessionid;
if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
/* Build receive manager CAPWAP message */
rxmngpacket = capwap_packet_rxmng_create_message(0);
if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, buffer, buffersize) != CAPWAP_RECEIVE_COMPLETE_PACKET) {
/* Accept only keep alive without fragmentation */
capwap_packet_rxmng_free(rxmngpacket);
capwap_logging_debug("Receive data keep alive packet fragmentated");
return NULL;
}
/* Validate message */
if (capwap_check_message_type(rxmngpacket) != VALID_MESSAGE_TYPE) {
/* Invalid message */
capwap_packet_rxmng_free(rxmngpacket);
capwap_logging_debug("Invalid data packet message type");
return NULL;
}
/* Parsing packet */
if (!capwap_parsing_packet(rxmngpacket, NULL, &packet)) {
/* Validate packet */
if (!capwap_validate_parsed_packet(&packet, NULL)) {
struct capwap_list_item* search;
ASSERT(packet.messageelements.sessionid != NULL);
capwap_lock_enter(&g_ac.sessionslock);
search = g_ac.sessions->first;
while (search != NULL) {
struct ac_session_t* session = (struct ac_session_t*)search->item;
ASSERT(session != NULL);
if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
if (!memcmp(packet.messageelements.sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
session->count++;
result = session;
break;
}
search = search->next;
search = search->next;
}
capwap_lock_exit(&g_ac.sessionslock);
} else {
capwap_logging_debug("Failed validation parsed data packet");
}
/* Free */
capwap_build_packet_free(buildpacket);
} else {
capwap_logging_debug("Failed parsing data packet");
}
return result;
/* Free resource */
capwap_free_parsed_packet(&packet);
capwap_packet_rxmng_free(rxmngpacket);
return result;
}
/* Close session */
@ -117,7 +141,7 @@ static void ac_close_sessions() {
ac_close_session(session);
search = search->next;
search = search->next;
}
capwap_lock_exit(&g_ac.sessionslock);
@ -246,7 +270,7 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
int result;
struct capwap_list_item* itemlist;
struct ac_session_t* session;
ASSERT(acaddress != NULL);
ASSERT(wtpaddress != NULL);
ASSERT(ctrlsock != NULL);
@ -263,37 +287,36 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
/* Duplicate state for DFA */
memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state));
session->dfa.acipv4list = capwap_array_clone(g_ac.dfa.acipv4list);
session->dfa.acipv6list = capwap_array_clone(g_ac.dfa.acipv6list);
session->dfa.acipv4list.addresses = capwap_array_clone(g_ac.dfa.acipv4list.addresses);
session->dfa.acipv6list.addresses = capwap_array_clone(g_ac.dfa.acipv6list.addresses);
session->dfa.rfcRetransmitInterval = AC_DEFAULT_RETRANSMIT_INTERVAL;
session->dfa.rfcMaxRetransmit = AC_MAX_RETRANSMIT;
session->dfa.rfcDTLSSessionDelete = AC_DEFAULT_DTLS_SESSION_DELETE;
/* Add default AC list if empty*/
if ((session->dfa.acipv4list->count == 0) && (session->dfa.acipv6list->count == 0)) {
if ((session->dfa.acipv4list.addresses->count == 0) && (session->dfa.acipv6list.addresses->count == 0)) {
if (session->acctrladdress.ss_family == AF_INET) {
struct capwap_acipv4list_element* acip = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(session->dfa.acipv4list, 0);
memcpy(&acip->address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
struct in_addr* acip = (struct in_addr*)capwap_array_get_item_pointer(session->dfa.acipv4list.addresses, 0);
memcpy(acip, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
} else if (session->acctrladdress.ss_family == AF_INET6) {
struct capwap_acipv6list_element* acip = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(session->dfa.acipv6list, 0);
memcpy(&acip->address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
struct in6_addr* acip = (struct in6_addr*)capwap_array_get_item_pointer(session->dfa.acipv6list.addresses, 0);
memcpy(acip, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
}
}
/* Init */
capwap_event_init(&session->waitpacket);
capwap_lock_init(&session->packetslock);
session->controlpackets = capwap_list_create();
session->datapackets = capwap_list_create();
session->requestfragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
session->responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
session->rxfragmentpacket = capwap_defragment_init_list();
session->requestfragmentpacket = capwap_list_create();
session->responsefragmentpacket = capwap_list_create();
session->mtu = g_ac.mtu;
session->state = CAPWAP_IDLE_STATE;
/* Update session list */
capwap_lock_enter(&g_ac.sessionslock);
capwap_itemlist_insert_after(g_ac.sessions, NULL, itemlist);
@ -323,10 +346,10 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
/* Update statistics */
void ac_update_statistics(void) {
g_ac.descriptor.station = 0; /* TODO */
g_ac.descriptor.stations = 0; /* TODO */
capwap_lock_enter(&g_ac.sessionslock);
g_ac.descriptor.wtp = g_ac.sessions->count;
g_ac.descriptor.activewtp = g_ac.sessions->count;
capwap_lock_exit(&g_ac.sessionslock);
}
@ -344,7 +367,7 @@ int ac_execute(void) {
int result = CAPWAP_SUCCESSFUL;
int index;
int check;
int check;
int isctrlsocket = 0;
struct sockaddr_storage recvfromaddr;
struct sockaddr_storage recvtoaddr;
@ -400,15 +423,15 @@ int ac_execute(void) {
if (getsockname(fds[index].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) {
break;
}
CAPWAP_SET_NETWORK_PORT(&recvtoaddr, CAPWAP_GET_NETWORK_PORT(&sockinfo));
}
}
/* Search the AC session */
isctrlsocket = ((index < (fdscount / 2)) ? 1 : 0);
session = ac_search_session_from_wtpaddress(&recvfromaddr, isctrlsocket);
if (session) {
/* Add packet*/
ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 0);
@ -418,38 +441,38 @@ int ac_execute(void) {
} else {
if (isctrlsocket) {
unsigned short sessioncount;
/* Get current session number */
capwap_lock_enter(&g_ac.sessionslock);
sessioncount = g_ac.sessions->count;
capwap_lock_exit(&g_ac.sessionslock);
/* PreParsing packet for reduce a DoS attack */
check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, buffersize, g_ac.enabledtls, 0);
if (check == CAPWAP_PLAIN_PACKET) {
struct capwap_header* header = (struct capwap_header*)buffer;
/* Accepted only packet without fragmentation */
if (!IS_FLAG_F_HEADER(header)) {
int headersize = GET_HLEN_HEADER(header) * 4;
if (buffersize >= (headersize + sizeof(struct capwap_control_message))) {
struct capwap_control_message* control = (struct capwap_control_message*)((char*)buffer + headersize);
unsigned long type = ntohl(control->type);
if (type == CAPWAP_DISCOVERY_REQUEST) {
if (sessioncount < g_ac.descriptor.wtplimit) {
if (sessioncount < g_ac.descriptor.maxwtp) {
ac_discovery_add_packet(buffer, buffersize, fds[index].fd, &recvfromaddr);
}
} else if (!g_ac.enabledtls && (type == CAPWAP_JOIN_REQUEST)) {
if (sessioncount < g_ac.descriptor.wtplimit) {
if (sessioncount < g_ac.descriptor.maxwtp) {
/* Retrive socket info */
capwap_get_network_socket(&g_ac.net, &ctrlsock, fds[index].fd);
/* Create a new session */
session = ac_create_session(&recvfromaddr, &recvtoaddr, &ctrlsock);
if (session) {
ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 1);
/* Release reference */
ac_session_release_reference(session);
}
@ -459,7 +482,7 @@ int ac_execute(void) {
}
} else if (check == CAPWAP_DTLS_PACKET) {
/* Need create a new sessione for check if it is a valid DTLS handshake */
if (sessioncount < g_ac.descriptor.wtplimit) {
if (sessioncount < g_ac.descriptor.maxwtp) {
/* TODO prevent dos attack add filtering ip for multiple error */
/* Retrive socket info */
@ -512,7 +535,7 @@ int ac_execute(void) {
/* Wait that list is changed */
capwap_logging_debug("Waiting for %d session terminate", count);
capwap_event_wait(&g_ac.changesessionlist);
capwap_event_wait(&g_ac.changesessionlist);
}
/* Free handshark session */

View File

@ -27,6 +27,11 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
struct capwap_list_item* itempacket;
*isctrlpacket = ((session->controlpackets->count > 0) ? 1 : 0);
if (*isctrlpacket) {
capwap_logging_debug("Receive control packet");
} else {
capwap_logging_debug("Receive data packet");
}
/* Get packet */
itempacket = capwap_itemlist_remove_head((*isctrlpacket ? session->controlpackets : session->datapackets));
@ -70,7 +75,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
return result;
}
capwap_lock_exit(&session->packetslock);
/* Update timeout */
@ -88,7 +93,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
}
/* */
static int ac_dfa_execute(struct ac_session_t* session, struct capwap_packet* packet) {
static int ac_dfa_execute(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
int action = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
@ -366,12 +371,47 @@ static int ac_dfa_execute(struct ac_session_t* session, struct capwap_packet* pa
return action;
}
/* */
static struct capwap_packet_rxmng* ac_get_packet_rxmng(struct ac_session_t* session, int isctrlmsg) {
struct capwap_packet_rxmng* rxmngpacket = NULL;
if (isctrlmsg) {
if (!session->rxmngctrlpacket) {
session->rxmngctrlpacket = capwap_packet_rxmng_create_message(1);
}
rxmngpacket = session->rxmngctrlpacket;
} else {
if (!session->rxmngdatapacket) {
session->rxmngdatapacket = capwap_packet_rxmng_create_message(0);
}
rxmngpacket = session->rxmngdatapacket;
}
return rxmngpacket;
}
/* */
static void ac_free_packet_rxmng(struct ac_session_t* session, int isctrlmsg) {
if (isctrlmsg && session->rxmngctrlpacket) {
capwap_packet_rxmng_free(session->rxmngctrlpacket);
session->rxmngctrlpacket = NULL;
} else if (!isctrlmsg && session->rxmngdatapacket) {
capwap_packet_rxmng_free(session->rxmngdatapacket);
session->rxmngdatapacket = NULL;
}
}
/* */
static void ac_session_run(struct ac_session_t* session) {
int res;
int check;
int length;
int isctrlsocket;
int action = AC_DFA_ACCEPT_PACKET;
struct capwap_connection connection;
char buffer[CAPWAP_MAX_PACKET_SIZE];
int action = AC_DFA_ACCEPT_PACKET;
ASSERT(session != NULL);
@ -402,35 +442,66 @@ static void ac_session_run(struct ac_session_t* session) {
/* Check generic capwap packet */
check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, length, 0, 0);
if (check == CAPWAP_PLAIN_PACKET) {
struct capwap_packet packet;
check = capwap_defragment_packets(&session->wtpctrladdress, buffer, length, session->rxfragmentpacket, &packet);
struct capwap_parsed_packet packet;
struct capwap_packet_rxmng* rxmngpacket;
/* Defragment management */
rxmngpacket = ac_get_packet_rxmng(session, isctrlsocket);
/* If request, defragmentation packet */
check = capwap_packet_rxmng_add_recv_packet(rxmngpacket, buffer, length);
if (check == CAPWAP_RECEIVE_COMPLETE_PACKET) {
int ignorepacket = 0;
/* Receive all fragment */
memcpy(&connection.socket, (isctrlsocket ? &session->ctrlsocket : &session->datasocket), sizeof(struct capwap_socket));
memcpy(&connection.localaddr, (isctrlsocket ? &session->acctrladdress : &session->acdataaddress), sizeof(struct sockaddr_storage));
memcpy(&connection.remoteaddr, (isctrlsocket ? &session->wtpctrladdress : &session->wtpdataaddress), sizeof(struct sockaddr_storage));
if (isctrlsocket) {
/* Check for already response to packet */
if (capwap_recv_retrasmitted_request(&session->ctrldtls, &packet, session->remoteseqnumber, session->lastrecvpackethash, &session->ctrlsocket, session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
ignorepacket = 1;
}
/* Check message type */
if (!capwap_check_message_type(&session->ctrldtls, &packet, session->mtu)) {
if (!capwap_recv_retrasmitted_request(&session->ctrldtls, rxmngpacket, &connection, session->lastrecvpackethash, session->responsefragmentpacket)) {
/* Check message type */
res = capwap_check_message_type(rxmngpacket);
if (res != VALID_MESSAGE_TYPE) {
if (res == INVALID_REQUEST_MESSAGE_TYPE) {
/*TODO wtp_send_invalid_request(rxmngpacket, &connection);*/
}
ignorepacket = 1;
capwap_logging_debug("Invalid message type");
}
} else {
ignorepacket = 1;
capwap_logging_debug("Retrasmitted packet");
}
}
/* Parsing packet */
if (!ignorepacket) {
if (!capwap_parsing_packet(rxmngpacket, &connection, &packet)) {
/* Validate packet */
if (capwap_validate_parsed_packet(&packet, NULL)) {
/* TODO gestione errore risposta */
ignorepacket = 1;
capwap_logging_debug("Failed validation parsed packet");
}
} else {
ignorepacket = 1;
capwap_logging_debug("Failed parsing packet");
}
}
/* */
if (!ignorepacket && (action == AC_DFA_ACCEPT_PACKET)) {
memcpy(&packet.socket, (isctrlsocket ? &session->ctrlsocket : &session->datasocket), sizeof(struct capwap_socket));
action = ac_dfa_execute(session, &packet);
}
/* Free packet */
capwap_free_packet(&packet);
/* Free memory */
capwap_free_parsed_packet(&packet);
ac_free_packet_rxmng(session, isctrlsocket);
} else if (check != CAPWAP_REQUEST_MORE_FRAGMENT) {
/* Discard fragments */
capwap_defragment_remove_sender(session->rxfragmentpacket, &session->wtpctrladdress);
ac_free_packet_rxmng(session, isctrlsocket);
}
}
}
@ -508,27 +579,27 @@ int ac_session_release_reference(struct ac_session_t* session) {
capwap_lock_exit(&session->packetslock);
capwap_list_free(session->controlpackets);
capwap_list_free(session->datapackets);
capwap_defragment_free_list(session->rxfragmentpacket);
/* Free fragments packet */
capwap_fragment_free(session->requestfragmentpacket);
capwap_fragment_free(session->responsefragmentpacket);
capwap_array_free(session->requestfragmentpacket);
capwap_array_free(session->responsefragmentpacket);
ac_free_packet_rxmng(session, 1);
ac_free_packet_rxmng(session, 0);
capwap_list_free(session->requestfragmentpacket);
capwap_list_free(session->responsefragmentpacket);
/* Free DFA resource */
capwap_array_free(session->dfa.acipv4list);
capwap_array_free(session->dfa.acipv6list);
capwap_array_free(session->dfa.acipv4list.addresses);
capwap_array_free(session->dfa.acipv6list.addresses);
/* Remove item from list */
remove = 1;
capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessions, search));
capwap_event_signal(&g_ac.changesessionlist);
break;
}
search = search->next;
search = search->next;
}
}
@ -547,7 +618,7 @@ void* ac_session_thread(void* param) {
/* Thread exit */
pthread_exit(NULL);
return NULL;
return NULL;
}
/* */
@ -596,22 +667,22 @@ void ac_get_control_information(struct capwap_list* controllist) {
}
}
}
/* */
capwap_lock_exit(&g_ac.sessionslock);
capwap_lock_exit(&g_ac.sessionslock);
}
/* */
void ac_free_reference_last_request(struct ac_session_t* session) {
ASSERT(session);
capwap_fragment_free(session->requestfragmentpacket);
capwap_list_flush(session->requestfragmentpacket);
}
/* */
void ac_free_reference_last_response(struct ac_session_t* session) {
ASSERT(session);
capwap_fragment_free(session->responsefragmentpacket);
capwap_list_flush(session->responsefragmentpacket);
memset(&session->lastrecvpackethash[0], 0, sizeof(session->lastrecvpackethash));
}

View File

@ -51,9 +51,10 @@ struct ac_session_t {
unsigned char remoteseqnumber;
unsigned short mtu;
unsigned short fragmentid;
capwap_fragment_list* rxfragmentpacket;
capwap_fragment_packet_array* requestfragmentpacket;
capwap_fragment_packet_array* responsefragmentpacket;
struct capwap_packet_rxmng* rxmngctrlpacket;
struct capwap_packet_rxmng* rxmngdatapacket;
struct capwap_list* requestfragmentpacket;
struct capwap_list* responsefragmentpacket;
unsigned char lastrecvpackethash[16];
unsigned long state;
@ -73,40 +74,40 @@ void ac_free_reference_last_request(struct ac_session_t* session);
void ac_free_reference_last_response(struct ac_session_t* session);
/* */
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
/* */
int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param);
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
/* */
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
/* */
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
/* */
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
/* */
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
/* */
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
/* */
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet);
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_parsed_packet* packet);
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_parsed_packet* packet);
#endif /* __AC_SESSION_HEADER__ */