Reengineering the timeout manager. Allows to create an arbitrary number of timer
with the possibility to invoke a callback function on timeout.
This commit is contained in:
26
src/ac/ac.c
26
src/ac/ac.c
@ -48,22 +48,16 @@ static int ac_init(void) {
|
||||
g_ac.dfa.transport.type = CAPWAP_UDP_TRANSPORT;
|
||||
|
||||
/* */
|
||||
g_ac.dfa.timers.discovery = AC_DEFAULT_DISCOVERY_INTERVAL;
|
||||
g_ac.dfa.timers.echorequest = AC_DEFAULT_ECHO_INTERVAL;
|
||||
g_ac.dfa.decrypterrorreport_interval = AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL;
|
||||
g_ac.dfa.idletimeout.timeout = AC_DEFAULT_IDLE_TIMEOUT_INTERVAL;
|
||||
g_ac.dfa.wtpfallback.mode = AC_DEFAULT_WTP_FALLBACK_MODE;
|
||||
g_ac.dfa.timers.discovery = AC_DISCOVERY_INTERVAL / 1000;
|
||||
g_ac.dfa.timers.echorequest = AC_ECHO_INTERVAL / 1000;
|
||||
g_ac.dfa.decrypterrorreport_interval = AC_DECRYPT_ERROR_PERIOD_INTERVAL / 1000;
|
||||
g_ac.dfa.idletimeout.timeout = AC_IDLE_TIMEOUT_INTERVAL / 1000;
|
||||
g_ac.dfa.wtpfallback.mode = AC_WTP_FALLBACK_MODE;
|
||||
|
||||
/* */
|
||||
g_ac.dfa.acipv4list.addresses = capwap_array_create(sizeof(struct in_addr), 0, 0);
|
||||
g_ac.dfa.acipv6list.addresses = capwap_array_create(sizeof(struct in6_addr), 0, 0);
|
||||
|
||||
/* */
|
||||
g_ac.dfa.rfcWaitJoin = AC_DEFAULT_WAITJOIN_INTERVAL;
|
||||
g_ac.dfa.rfcWaitDTLS = AC_DEFAULT_WAITDTLS_INTERVAL;
|
||||
g_ac.dfa.rfcChangeStatePendingTimer = AC_DEFAULT_CHANGE_STATE_PENDING_TIMER;
|
||||
g_ac.dfa.rfcDataCheckTimer = AC_DEFAULT_DATA_CHECK_TIMER;
|
||||
|
||||
/* Sessions */
|
||||
g_ac.sessions = capwap_list_create();
|
||||
g_ac.sessionsdata = capwap_list_create();
|
||||
@ -352,8 +346,9 @@ static int ac_parsing_configuration_1_0(config_t* config) {
|
||||
|
||||
/* Set Timer of AC */
|
||||
if (config_lookup_int(config, "application.timer.discovery", &configInt) == CONFIG_TRUE) {
|
||||
if ((configInt >= AC_DEFAULT_DISCOVERY_INTERVAL) && (configInt <= AC_MAX_DISCOVERY_INTERVAL)) {
|
||||
g_ac.dfa.timers.discovery = (unsigned char)configInt;
|
||||
configInt *= 1000; /* Set timeout in ms */
|
||||
if ((configInt >= AC_MIN_DISCOVERY_INTERVAL) && (configInt <= AC_MAX_DISCOVERY_INTERVAL)) {
|
||||
g_ac.dfa.timers.discovery = (unsigned char)(configInt / 1000);
|
||||
} else {
|
||||
capwap_logging_error("Invalid configuration file, invalid application.timer.discovery value");
|
||||
return 0;
|
||||
@ -361,8 +356,9 @@ static int ac_parsing_configuration_1_0(config_t* config) {
|
||||
}
|
||||
|
||||
if (config_lookup_int(config, "application.timer.echorequest", &configInt) == CONFIG_TRUE) {
|
||||
if ((configInt > 0) && (configInt < AC_MAX_ECHO_INTERVAL)) {
|
||||
g_ac.dfa.timers.echorequest = (unsigned char)configInt;
|
||||
configInt *= 1000;
|
||||
if ((configInt >= AC_MIN_ECHO_INTERVAL) && (configInt <= AC_MAX_ECHO_INTERVAL)) {
|
||||
g_ac.dfa.timers.echorequest = (unsigned char)(configInt / 1000);
|
||||
} else {
|
||||
capwap_logging_error("Invalid configuration file, invalid application.timer.echorequest value");
|
||||
return 0;
|
||||
|
62
src/ac/ac.h
62
src/ac/ac.h
@ -26,31 +26,37 @@
|
||||
#define AC_ERROR_MEMORY_LEAK 1
|
||||
|
||||
/* Min and max dfa values */
|
||||
#define AC_MIN_WAITDTLS_INTERVAL 30
|
||||
#define AC_DEFAULT_WAITDTLS_INTERVAL 60
|
||||
#define AC_MIN_WAITJOIN_INTERVAL 20
|
||||
#define AC_DEFAULT_WAITJOIN_INTERVAL 60
|
||||
#define AC_DEFAULT_CHANGE_STATE_PENDING_TIMER 25
|
||||
#define AC_MIN_DISCOVERY_INTERVAL 2
|
||||
#define AC_DEFAULT_DISCOVERY_INTERVAL 20
|
||||
#define AC_MAX_DISCOVERY_INTERVAL 180
|
||||
#define AC_DEFAULT_ECHO_INTERVAL 30
|
||||
#define AC_MAX_ECHO_INTERVAL 256
|
||||
#define AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL 120
|
||||
#define AC_DEFAULT_IDLE_TIMEOUT_INTERVAL 300
|
||||
#define AC_DEFAULT_WTP_FALLBACK_MODE CAPWAP_WTP_FALLBACK_ENABLED
|
||||
#define AC_DEFAULT_DATA_CHECK_TIMER 30
|
||||
#define AC_MAX_DATA_CHECK_TIMER 256
|
||||
#define AC_DEFAULT_RETRANSMIT_INTERVAL 3
|
||||
#define AC_MAX_RETRANSMIT 5
|
||||
#define AC_DEFAULT_DTLS_SESSION_DELETE 5
|
||||
#define AC_DTLS_INTERVAL 60000
|
||||
|
||||
/* AC DFA */
|
||||
#define AC_JOIN_INTERVAL 60000
|
||||
|
||||
#define AC_CHANGE_STATE_PENDING_INTERVAL 25000
|
||||
|
||||
#define AC_DATA_CHECK_INTERVAL 30000
|
||||
|
||||
#define AC_RETRANSMIT_INTERVAL 3000
|
||||
#define AC_MAX_RETRANSMIT 5
|
||||
|
||||
#define AC_DTLS_SESSION_DELETE_INTERVAL 5000
|
||||
|
||||
#define AC_MIN_ECHO_INTERVAL 1000
|
||||
#define AC_ECHO_INTERVAL 30000
|
||||
#define AC_MAX_ECHO_INTERVAL 256000
|
||||
|
||||
#define AC_MAX_DATA_KEEPALIVE_INTERVAL 256000
|
||||
|
||||
#define AC_MIN_DISCOVERY_INTERVAL 2000
|
||||
#define AC_DISCOVERY_INTERVAL 20000
|
||||
#define AC_MAX_DISCOVERY_INTERVAL 180000
|
||||
|
||||
#define AC_DECRYPT_ERROR_PERIOD_INTERVAL 120000
|
||||
#define AC_IDLE_TIMEOUT_INTERVAL 300000
|
||||
#define AC_WTP_FALLBACK_MODE CAPWAP_WTP_FALLBACK_ENABLED
|
||||
|
||||
/* */
|
||||
struct ac_state {
|
||||
/* */
|
||||
struct capwap_ecnsupport_element ecn;
|
||||
struct capwap_transport_element transport;
|
||||
|
||||
struct capwap_timers_element timers;
|
||||
unsigned short decrypterrorreport_interval;
|
||||
struct capwap_idletimeout_element idletimeout;
|
||||
@ -59,20 +65,6 @@ struct ac_state {
|
||||
/* */
|
||||
struct capwap_acipv4list_element acipv4list;
|
||||
struct capwap_acipv6list_element acipv6list;
|
||||
|
||||
/* */
|
||||
int rfcWaitJoin;
|
||||
int rfcChangeStatePendingTimer;
|
||||
int rfcDataCheckTimer;
|
||||
int rfcDTLSSessionDelete;
|
||||
|
||||
/* Request retransmit */
|
||||
int rfcRetransmitInterval;
|
||||
int rfcRetransmitCount;
|
||||
int rfcMaxRetransmit;
|
||||
|
||||
/* Dtls */
|
||||
int rfcWaitDTLS;
|
||||
};
|
||||
|
||||
/* AC */
|
||||
|
@ -708,66 +708,61 @@ static uint32_t ac_dfa_state_configure_create_response(struct ac_session_t* sess
|
||||
|
||||
/* */
|
||||
void ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
struct ac_soap_response* response;
|
||||
struct capwap_header_data capwapheader;
|
||||
struct capwap_packet_txmng* txmngpacket;
|
||||
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
|
||||
|
||||
ASSERT(session != NULL);
|
||||
|
||||
if (packet) {
|
||||
struct ac_soap_response* response;
|
||||
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
/* Create response */
|
||||
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
|
||||
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
|
||||
/* Create response */
|
||||
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
|
||||
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
|
||||
|
||||
/* Parsing request and add message element for respone message */
|
||||
response = ac_dfa_state_configure_parsing_request(session, packet);
|
||||
if (response) {
|
||||
result = ac_dfa_state_configure_create_response(session, packet, response, txmngpacket);
|
||||
ac_soapclient_free_response(response);
|
||||
/* Parsing request and add message element for respone message */
|
||||
response = ac_dfa_state_configure_parsing_request(session, packet);
|
||||
if (response) {
|
||||
result = ac_dfa_state_configure_create_response(session, packet, response, txmngpacket);
|
||||
ac_soapclient_free_response(response);
|
||||
}
|
||||
|
||||
/* With error add result code message element */
|
||||
if (!CAPWAP_RESULTCODE_OK(result)) {
|
||||
struct capwap_resultcode_element resultcode = { .code = result };
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
||||
|
||||
/* */
|
||||
if (result == CAPWAP_RESULTCODE_FAILURE) {
|
||||
/* TODO: Add AC List Message Elements */
|
||||
}
|
||||
}
|
||||
|
||||
/* With error add result code message element */
|
||||
if (!CAPWAP_RESULTCODE_OK(result)) {
|
||||
struct capwap_resultcode_element resultcode = { .code = result };
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* */
|
||||
if (result == CAPWAP_RESULTCODE_FAILURE) {
|
||||
/* TODO: Add AC List Message Elements */
|
||||
}
|
||||
}
|
||||
/* Free packets manager */
|
||||
capwap_packet_txmng_free(txmngpacket);
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
/* Save remote sequence number */
|
||||
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
|
||||
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
|
||||
|
||||
/* Free packets manager */
|
||||
capwap_packet_txmng_free(txmngpacket);
|
||||
/* Send Configure response to WTP */
|
||||
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
|
||||
capwap_logging_debug("Warning: error to send configuration status response packet");
|
||||
}
|
||||
|
||||
/* 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->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
/* 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 */
|
||||
if (CAPWAP_RESULTCODE_OK(result)) {
|
||||
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
|
||||
capwap_timeout_set(session->dfa.rfcChangeStatePendingTimer, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
} else {
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
/* Change state */
|
||||
if (CAPWAP_RESULTCODE_OK(result)) {
|
||||
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_CHANGE_STATE_PENDING_INTERVAL, ac_dfa_state_datacheck_timeout, session, NULL);
|
||||
} else {
|
||||
/* Configure timeout */
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
}
|
||||
|
@ -172,68 +172,68 @@ static uint32_t ac_dfa_state_datacheck_create_response(struct ac_session_t* sess
|
||||
return CAPWAP_RESULTCODE_SUCCESS;
|
||||
}
|
||||
|
||||
/* */
|
||||
void ac_dfa_state_datacheck_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
|
||||
ac_session_teardown((struct ac_session_t*)context); /* Configure timeout */
|
||||
}
|
||||
|
||||
/* */
|
||||
void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
struct ac_soap_response* response;
|
||||
struct capwap_header_data capwapheader;
|
||||
struct capwap_packet_txmng* txmngpacket;
|
||||
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
|
||||
|
||||
ASSERT(session != NULL);
|
||||
|
||||
if (packet) {
|
||||
struct ac_soap_response* response;
|
||||
uint32_t result = CAPWAP_RESULTCODE_FAILURE;
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
/* Create response */
|
||||
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
|
||||
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
|
||||
/* Create response */
|
||||
capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header));
|
||||
txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu);
|
||||
|
||||
/* Parsing request and add message element for respone message */
|
||||
response = ac_dfa_state_datacheck_parsing_request(session, packet);
|
||||
if (response) {
|
||||
result = ac_dfa_state_datacheck_create_response(session, packet, response, txmngpacket);
|
||||
ac_soapclient_free_response(response);
|
||||
/* Parsing request and add message element for respone message */
|
||||
response = ac_dfa_state_datacheck_parsing_request(session, packet);
|
||||
if (response) {
|
||||
result = ac_dfa_state_datacheck_create_response(session, packet, response, txmngpacket);
|
||||
ac_soapclient_free_response(response);
|
||||
}
|
||||
|
||||
/* With error add result code message element */
|
||||
if (!CAPWAP_RESULTCODE_OK(result)) {
|
||||
struct capwap_resultcode_element resultcode = { .code = result };
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
||||
|
||||
/* */
|
||||
if (result == CAPWAP_RESULTCODE_FAILURE) {
|
||||
/* TODO: Add AC List Message Elements */
|
||||
}
|
||||
}
|
||||
|
||||
/* With error add result code message element */
|
||||
if (!CAPWAP_RESULTCODE_OK(result)) {
|
||||
struct capwap_resultcode_element resultcode = { .code = result };
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* */
|
||||
if (result == CAPWAP_RESULTCODE_FAILURE) {
|
||||
/* TODO: Add AC List Message Elements */
|
||||
}
|
||||
}
|
||||
/* Free packets manager */
|
||||
capwap_packet_txmng_free(txmngpacket);
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
/* Save remote sequence number */
|
||||
session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq;
|
||||
capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash);
|
||||
|
||||
/* Free packets manager */
|
||||
capwap_packet_txmng_free(txmngpacket);
|
||||
/* Send Change event response to WTP */
|
||||
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
/* Response is already created and saved. When receive a re-request, DFA autoresponse */
|
||||
capwap_logging_debug("Warning: error to send change event response packet");
|
||||
}
|
||||
|
||||
/* 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->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
/* 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 */
|
||||
if (CAPWAP_RESULTCODE_OK(result)) {
|
||||
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
|
||||
capwap_timeout_set(session->dfa.rfcDataCheckTimer, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
} else {
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
/* Change state */
|
||||
if (CAPWAP_RESULTCODE_OK(result)) {
|
||||
ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_DATA_CHECK_INTERVAL, ac_dfa_state_datacheck_timeout, session, NULL);
|
||||
} else {
|
||||
/* Configure timeout */
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
}
|
||||
@ -242,7 +242,5 @@ void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_p
|
||||
void ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
ASSERT(session != NULL);
|
||||
|
||||
if (!packet) {
|
||||
ac_session_teardown(session); /* Configure timeout */
|
||||
}
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
|
@ -21,6 +21,11 @@ static int ac_bio_data_send(struct capwap_dtls* dtls, char* buffer, int length,
|
||||
return capwap_sendto(sessiondata->connection.socket.socket[sessiondata->connection.socket.type], buffer, length, &sessiondata->connection.localaddr, &sessiondata->connection.remoteaddr);
|
||||
}
|
||||
|
||||
/* */
|
||||
void ac_dtls_setup_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
|
||||
ac_session_teardown((struct ac_session_t*)context); /* Configure timeout */
|
||||
}
|
||||
|
||||
/* */
|
||||
int ac_dtls_setup(struct ac_session_t* session) {
|
||||
ASSERT(session != NULL);
|
||||
@ -36,7 +41,7 @@ int ac_dtls_setup(struct ac_session_t* session) {
|
||||
|
||||
/* Wait DTLS handshake complete */
|
||||
ac_dfa_change_state(session, CAPWAP_DTLS_CONNECT_STATE);
|
||||
capwap_timeout_set(session->dfa.rfcWaitDTLS, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_DTLS_INTERVAL, ac_dtls_setup_timeout, session, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -6,4 +6,5 @@
|
||||
/* */
|
||||
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
/* TODO */
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
|
@ -578,8 +578,14 @@ static uint32_t ac_dfa_state_join_create_response(struct ac_session_t* session,
|
||||
return CAPWAP_RESULTCODE_SUCCESS;
|
||||
}
|
||||
|
||||
/* */
|
||||
void ac_dfa_state_join_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
|
||||
ac_session_teardown((struct ac_session_t*)context); /* Join timeout */
|
||||
}
|
||||
|
||||
/* */
|
||||
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
unsigned short binding;
|
||||
struct ac_soap_response* response;
|
||||
struct capwap_header_data capwapheader;
|
||||
struct capwap_packet_txmng* txmngpacket;
|
||||
@ -588,99 +594,94 @@ void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet
|
||||
struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE };
|
||||
|
||||
ASSERT(session != NULL);
|
||||
|
||||
if (packet) {
|
||||
unsigned short binding;
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
/* Check binding */
|
||||
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
|
||||
if (ac_valid_binding(binding)) {
|
||||
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) {
|
||||
/* Get sessionid and verify unique id */
|
||||
sessionid = (struct capwap_sessionid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_SESSIONID);
|
||||
if (!ac_has_sessionid(sessionid)) {
|
||||
char* wtpid;
|
||||
/* Check binding */
|
||||
binding = GET_WBID_HEADER(packet->rxmngpacket->header);
|
||||
if (ac_valid_binding(binding)) {
|
||||
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) {
|
||||
/* Get sessionid and verify unique id */
|
||||
sessionid = (struct capwap_sessionid_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_SESSIONID);
|
||||
if (!ac_has_sessionid(sessionid)) {
|
||||
char* wtpid;
|
||||
|
||||
/* Checking macaddress for detect if WTP already connected */
|
||||
wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA);
|
||||
/* Checking macaddress for detect if WTP already connected */
|
||||
wtpboarddata = (struct capwap_wtpboarddata_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_WTPBOARDDATA);
|
||||
|
||||
/* Get printable WTPID */
|
||||
wtpid = ac_get_printable_wtpid(wtpboarddata);
|
||||
if (wtpid && !ac_has_wtpid(wtpid)) {
|
||||
/* Request authorization of Backend for complete join */
|
||||
response = ac_soap_authorizewtpsession(session, wtpid);
|
||||
if (response) {
|
||||
resultcode.code = ac_dfa_state_join_check_authorizejoin(session, response);
|
||||
ac_soapclient_free_response(response);
|
||||
} else {
|
||||
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
|
||||
}
|
||||
/* Get printable WTPID */
|
||||
wtpid = ac_get_printable_wtpid(wtpboarddata);
|
||||
if (wtpid && !ac_has_wtpid(wtpid)) {
|
||||
/* Request authorization of Backend for complete join */
|
||||
response = ac_soap_authorizewtpsession(session, wtpid);
|
||||
if (response) {
|
||||
resultcode.code = ac_dfa_state_join_check_authorizejoin(session, response);
|
||||
ac_soapclient_free_response(response);
|
||||
} else {
|
||||
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
|
||||
}
|
||||
|
||||
/* */
|
||||
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
|
||||
session->wtpid = wtpid;
|
||||
memcpy(&session->sessionid, sessionid, sizeof(struct capwap_sessionid_element));
|
||||
session->binding = binding;
|
||||
} else {
|
||||
capwap_free(wtpid);
|
||||
}
|
||||
} else {
|
||||
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE;
|
||||
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE;
|
||||
}
|
||||
|
||||
/* */
|
||||
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
|
||||
session->wtpid = wtpid;
|
||||
memcpy(&session->sessionid, sessionid, sizeof(struct capwap_sessionid_element));
|
||||
session->binding = binding;
|
||||
} else {
|
||||
capwap_free(wtpid);
|
||||
}
|
||||
} else {
|
||||
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
|
||||
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE;
|
||||
}
|
||||
} else {
|
||||
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
|
||||
resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
|
||||
}
|
||||
} else {
|
||||
resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
|
||||
/* */
|
||||
/* */
|
||||
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
|
||||
response = ac_dfa_state_join_parsing_request(session, packet);
|
||||
if (response) {
|
||||
resultcode.code = ac_dfa_state_join_create_response(session, packet, response, txmngpacket);
|
||||
ac_soapclient_free_response(response);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add always result code message element */
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* 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 Join response to WTP */
|
||||
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
|
||||
response = ac_dfa_state_join_parsing_request(session, packet);
|
||||
if (response) {
|
||||
resultcode.code = ac_dfa_state_join_create_response(session, packet, response, txmngpacket);
|
||||
ac_soapclient_free_response(response);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add always result code message element */
|
||||
capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode);
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* 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 Join response to WTP */
|
||||
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->responsefragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
if (CAPWAP_RESULTCODE_OK(resultcode.code)) {
|
||||
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
|
||||
} else {
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_state_join_timeout, session, NULL);
|
||||
} else {
|
||||
/* Error to send packets */
|
||||
capwap_logging_debug("Warning: error to send join response packet");
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
} else {
|
||||
/* Join timeout */
|
||||
/* Error to send packets */
|
||||
capwap_logging_debug("Warning: error to send join response packet");
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
}
|
||||
@ -688,19 +689,15 @@ void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet
|
||||
/* */
|
||||
void ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
ASSERT(session != NULL);
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
if (packet) {
|
||||
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
|
||||
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
|
||||
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);
|
||||
ac_dfa_state_imagedata(session, packet);
|
||||
} else {
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
|
||||
ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
|
||||
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);
|
||||
ac_dfa_state_imagedata(session, packet);
|
||||
} else {
|
||||
/* Join timeout */
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
}
|
||||
|
@ -5,41 +5,23 @@
|
||||
|
||||
/* */
|
||||
void ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
ASSERT(session != NULL);
|
||||
unsigned short binding;
|
||||
|
||||
if (packet) {
|
||||
unsigned short binding;
|
||||
ASSERT(session != NULL);
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
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)) {
|
||||
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 (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
|
||||
capwap_logging_warning("Receive Reset Response with error: %d", (int)resultcode->code);
|
||||
}
|
||||
|
||||
/* */
|
||||
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)) {
|
||||
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 (resultcode && !CAPWAP_RESULTCODE_OK(resultcode->code)) {
|
||||
capwap_logging_warning("Receive Reset Response with error: %d", (int)resultcode->code);
|
||||
}
|
||||
|
||||
/* */
|
||||
ac_free_reference_last_request(session);
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
} else {
|
||||
/* No Reset Response received */
|
||||
session->dfa.rfcRetransmitCount++;
|
||||
if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) {
|
||||
/* Timeout reset state */
|
||||
ac_free_reference_last_request(session);
|
||||
ac_session_teardown(session);
|
||||
} else {
|
||||
/* Retransmit Reset Request */
|
||||
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
capwap_logging_debug("Warning: error to resend reset request packet");
|
||||
}
|
||||
|
||||
/* Update timeout */
|
||||
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
}
|
||||
ac_free_reference_last_request(session);
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
}
|
||||
|
@ -78,94 +78,75 @@ static void receive_ieee80211_wlan_configuration_response(struct ac_session_t* s
|
||||
/* */
|
||||
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
ASSERT(session != NULL);
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
if (packet) {
|
||||
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 */
|
||||
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(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_CHANGE_STATE_EVENT_REQUEST: {
|
||||
/* TODO */
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_ECHO_REQUEST: {
|
||||
if (!receive_echo_request(session, packet)) {
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
} else {
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: {
|
||||
/* TODO */
|
||||
|
||||
/* */
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_WTP_EVENT_REQUEST: {
|
||||
/* TODO */
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_DATA_TRANSFER_REQUEST: {
|
||||
/* TODO */
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_DATA_TRANSFER_RESPONSE: {
|
||||
/* TODO */
|
||||
|
||||
/* */
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_STATION_CONFIGURATION_RESPONSE: {
|
||||
/* TODO */
|
||||
|
||||
/* */
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case CAPWAP_IEEE80211_WLAN_CONFIGURATION_RESPONSE: {
|
||||
receive_ieee80211_wlan_configuration_response(session, packet);
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((session->requestfragmentpacket->count > 0)) {
|
||||
/* No response received */
|
||||
session->dfa.rfcRetransmitCount++;
|
||||
if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) {
|
||||
/* Timeout */
|
||||
ac_free_reference_last_request(session);
|
||||
ac_session_teardown(session);
|
||||
} else {
|
||||
/* Retransmit request */
|
||||
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
capwap_logging_debug("Warning: error to resend request packet");
|
||||
/* */
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update timeout */
|
||||
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
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: {
|
||||
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: {
|
||||
/* TODO */
|
||||
|
||||
/* */
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
}
|
||||
|
@ -503,16 +503,13 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres
|
||||
|
||||
/* */
|
||||
session->timeout = capwap_timeout_init();
|
||||
session->idtimercontrol = capwap_timeout_createtimer(session->timeout);
|
||||
|
||||
/* Duplicate state for DFA */
|
||||
memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state));
|
||||
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.addresses->count == 0) && (session->dfa.acipv6list.addresses->count == 0)) {
|
||||
if (acaddress->ss_family == AF_INET) {
|
||||
@ -588,6 +585,8 @@ static struct ac_session_data_t* ac_create_session_data(struct sockaddr_storage*
|
||||
|
||||
/* */
|
||||
sessiondata->timeout = capwap_timeout_init();
|
||||
sessiondata->idtimercontrol = capwap_timeout_createtimer(sessiondata->timeout);
|
||||
sessiondata->idtimerkeepalivedead = capwap_timeout_createtimer(sessiondata->timeout);
|
||||
|
||||
/* Connection info */
|
||||
memcpy(&sessiondata->connection.socket, sock, sizeof(struct capwap_socket));
|
||||
|
@ -39,10 +39,9 @@ static int ac_session_action_resetwtp(struct ac_session_t* session, struct ac_no
|
||||
|
||||
/* Send Reset Request to WTP */
|
||||
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
session->dfa.rfcRetransmitCount = 0;
|
||||
capwap_timeout_killall(session->timeout);
|
||||
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
session->retransmitcount = 0;
|
||||
ac_dfa_change_state(session, CAPWAP_RESET_STATE);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
|
||||
} else {
|
||||
capwap_logging_debug("Warning: error to send reset request packet");
|
||||
ac_free_reference_last_request(session);
|
||||
@ -94,9 +93,8 @@ static int ac_session_action_addwlan(struct ac_session_t* session, struct ac_not
|
||||
|
||||
/* Send WLAN Configuration Request to WTP */
|
||||
if (capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
session->dfa.rfcRetransmitCount = 0;
|
||||
capwap_timeout_killall(session->timeout);
|
||||
capwap_timeout_set(session->dfa.rfcRetransmitInterval, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
session->retransmitcount = 0;
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
|
||||
} else {
|
||||
capwap_logging_debug("Warning: error to send reset request packet");
|
||||
ac_free_reference_last_request(session);
|
||||
@ -139,7 +137,7 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses
|
||||
|
||||
if (valid) {
|
||||
ac_dfa_change_state(session, CAPWAP_RUN_STATE);
|
||||
capwap_timeout_set(AC_MAX_ECHO_INTERVAL, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_MAX_ECHO_INTERVAL, ac_dfa_teardown_timeout, session, NULL);
|
||||
} else {
|
||||
result = CAPWAP_ERROR_CLOSE;
|
||||
}
|
||||
@ -165,7 +163,6 @@ static int ac_session_action_execute(struct ac_session_t* session, struct ac_ses
|
||||
/* */
|
||||
static int ac_network_read(struct ac_session_t* session, void* buffer, int length) {
|
||||
int result = 0;
|
||||
long indextimer;
|
||||
long waittimeout;
|
||||
|
||||
ASSERT(session != NULL);
|
||||
@ -213,7 +210,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
|
||||
if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (session->dtls.action == CAPWAP_DTLS_ACTION_DATA)) {
|
||||
if (session->state == CAPWAP_DTLS_CONNECT_STATE) {
|
||||
ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
|
||||
capwap_timeout_set(session->dfa.rfcWaitJoin, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_state_join_timeout, session, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -233,10 +230,10 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
|
||||
|
||||
capwap_lock_exit(&session->sessionlock);
|
||||
|
||||
/* Update timeout */
|
||||
capwap_timeout_update(session->timeout);
|
||||
waittimeout = capwap_timeout_get(session->timeout, &indextimer);
|
||||
if ((waittimeout <= 0) && (indextimer != CAPWAP_TIMER_UNDEF)) {
|
||||
/* Get timeout */
|
||||
waittimeout = capwap_timeout_getcoming(session->timeout);
|
||||
if (!waittimeout) {
|
||||
capwap_timeout_hasexpired(session->timeout);
|
||||
return AC_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
@ -250,6 +247,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt
|
||||
/* */
|
||||
static void ac_dfa_execute(struct ac_session_t* session, struct capwap_parsed_packet* packet) {
|
||||
ASSERT(session != NULL);
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
/* Execute state */
|
||||
switch (session->state) {
|
||||
@ -481,16 +479,14 @@ static void ac_session_run(struct ac_session_t* session) {
|
||||
} else {
|
||||
/* Wait Join request */
|
||||
ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
|
||||
capwap_timeout_set(session->dfa.rfcWaitJoin, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_JOIN_INTERVAL, ac_dfa_state_join_timeout, session, NULL);
|
||||
}
|
||||
|
||||
while (session->state != CAPWAP_DTLS_TEARDOWN_STATE) {
|
||||
/* Get packet */
|
||||
length = ac_network_read(session, buffer, sizeof(buffer));
|
||||
if (length < 0) {
|
||||
if (length == AC_ERROR_TIMEOUT) {
|
||||
ac_dfa_execute(session, NULL);
|
||||
} else if ((length == CAPWAP_ERROR_SHUTDOWN) || (length == CAPWAP_ERROR_CLOSE)) {
|
||||
if ((length == CAPWAP_ERROR_SHUTDOWN) || (length == CAPWAP_ERROR_CLOSE)) {
|
||||
ac_session_teardown(session);
|
||||
}
|
||||
} else if (length > 0) {
|
||||
@ -602,7 +598,7 @@ static void ac_session_run(struct ac_session_t* session) {
|
||||
}
|
||||
|
||||
/* Wait teardown timeout before kill session */
|
||||
capwap_timeout_wait(session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
capwap_timeout_wait(AC_DTLS_SESSION_DELETE_INTERVAL);
|
||||
ac_dfa_state_teardown(session);
|
||||
|
||||
/* Release reference session */
|
||||
@ -668,11 +664,6 @@ void ac_session_teardown(struct ac_session_t* session) {
|
||||
capwap_crypt_close(&session->dtls);
|
||||
}
|
||||
|
||||
/* */
|
||||
capwap_timeout_killall(session->timeout);
|
||||
capwap_timeout_set(session->dfa.rfcDTLSSessionDelete, session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE);
|
||||
|
||||
/* Cancel all notify event */
|
||||
if (session->notifyevent->first) {
|
||||
char buffer[5];
|
||||
@ -692,6 +683,10 @@ void ac_session_teardown(struct ac_session_t* session) {
|
||||
capwap_itemlist_free(capwap_itemlist_remove(session->notifyevent, session->notifyevent->first));
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE);
|
||||
capwap_timeout_unset(session->timeout, session->idtimercontrol);
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -835,3 +830,32 @@ struct ac_soap_response* ac_session_send_soap_request(struct ac_session_t* sessi
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/* */
|
||||
void ac_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
|
||||
struct ac_session_t* session = (struct ac_session_t*)context;
|
||||
|
||||
if (!session->requestfragmentpacket->count) {
|
||||
ac_session_teardown(session);
|
||||
} else {
|
||||
session->retransmitcount++;
|
||||
if (session->retransmitcount >= AC_MAX_RETRANSMIT) {
|
||||
/* Timeout reset state */
|
||||
ac_free_reference_last_request(session);
|
||||
ac_session_teardown(session);
|
||||
} else {
|
||||
/* Retransmit Reset Request */
|
||||
capwap_logging_debug("Retransmition request packet");
|
||||
if (!capwap_crypt_sendto_fragmentpacket(&session->dtls, session->connection.socket.socket[session->connection.socket.type], session->requestfragmentpacket, &session->connection.localaddr, &session->connection.remoteaddr)) {
|
||||
capwap_logging_error("Error to send request packet");
|
||||
}
|
||||
|
||||
/* Update timeout */
|
||||
capwap_timeout_set(session->timeout, session->idtimercontrol, AC_RETRANSMIT_INTERVAL, ac_dfa_retransmition_timeout, session, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ac_dfa_teardown_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param) {
|
||||
ac_session_teardown((struct ac_session_t*)context);
|
||||
}
|
||||
|
@ -66,7 +66,10 @@ struct ac_session_data_t {
|
||||
unsigned short mtu;
|
||||
struct capwap_connection connection;
|
||||
struct capwap_dtls dtls;
|
||||
struct timeout_control* timeout;
|
||||
|
||||
struct capwap_timeout* timeout;
|
||||
unsigned long idtimercontrol;
|
||||
unsigned long idtimerkeepalivedead;
|
||||
|
||||
capwap_event_t waitpacket;
|
||||
capwap_lock_t sessionlock;
|
||||
@ -105,7 +108,9 @@ struct ac_session_t {
|
||||
unsigned short mtu;
|
||||
struct capwap_dtls dtls;
|
||||
struct capwap_connection connection;
|
||||
struct timeout_control* timeout;
|
||||
|
||||
struct capwap_timeout* timeout;
|
||||
unsigned long idtimercontrol;
|
||||
|
||||
capwap_event_t waitpacket;
|
||||
capwap_lock_t sessionlock;
|
||||
@ -121,6 +126,7 @@ struct ac_session_t {
|
||||
struct capwap_list* requestfragmentpacket;
|
||||
struct capwap_list* responsefragmentpacket;
|
||||
unsigned char lastrecvpackethash[16];
|
||||
int retransmitcount;
|
||||
};
|
||||
|
||||
/* Session */
|
||||
@ -162,16 +168,29 @@ void ac_msgqueue_notify_closethread(pthread_t threadid);
|
||||
/* */
|
||||
int ac_dtls_setup(struct ac_session_t* session);
|
||||
int ac_dtls_data_setup(struct ac_session_data_t* sessiondata);
|
||||
void ac_dtls_setup_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
|
||||
|
||||
/* */
|
||||
void ac_dfa_retransmition_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
|
||||
void ac_dfa_teardown_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
|
||||
|
||||
/* */
|
||||
void ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
void ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
void ac_dfa_state_join_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
|
||||
|
||||
void ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
|
||||
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
|
||||
void ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
void ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
void ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
void ac_dfa_state_datacheck_timeout(struct capwap_timeout* timeout, unsigned long index, void* context, void* param);
|
||||
|
||||
void ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
|
||||
void ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet);
|
||||
|
||||
void ac_dfa_state_teardown(struct ac_session_t* session);
|
||||
|
||||
/* Soap function */
|
||||
|
@ -17,7 +17,6 @@ static int ac_session_data_action_execute(struct ac_session_data_t* sessiondata,
|
||||
|
||||
/* */
|
||||
static int ac_network_read(struct ac_session_data_t* sessiondata, void* buffer, int length) {
|
||||
long indextimer;
|
||||
long waittimeout;
|
||||
int result = CAPWAP_ERROR_AGAIN;
|
||||
|
||||
@ -63,8 +62,8 @@ static int ac_network_read(struct ac_session_data_t* sessiondata, void* buffer,
|
||||
if (result == CAPWAP_ERROR_AGAIN) {
|
||||
/* Check is handshake complete */
|
||||
if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (sessiondata->dtls.action == CAPWAP_DTLS_ACTION_DATA)) {
|
||||
capwap_timeout_kill(sessiondata->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
capwap_timeout_set(AC_MAX_DATA_CHECK_TIMER, sessiondata->timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD);
|
||||
capwap_timeout_unset(sessiondata->timeout, sessiondata->idtimercontrol);
|
||||
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -83,10 +82,10 @@ static int ac_network_read(struct ac_session_data_t* sessiondata, void* buffer,
|
||||
|
||||
capwap_lock_exit(&sessiondata->sessionlock);
|
||||
|
||||
/* Update timeout */
|
||||
capwap_timeout_update(sessiondata->timeout);
|
||||
waittimeout = capwap_timeout_get(sessiondata->timeout, &indextimer);
|
||||
if ((waittimeout <= 0) && (indextimer != CAPWAP_TIMER_UNDEF)) {
|
||||
/* Get timeout */
|
||||
waittimeout = capwap_timeout_getcoming(sessiondata->timeout);
|
||||
if (!waittimeout) {
|
||||
capwap_timeout_hasexpired(sessiondata->timeout);
|
||||
return AC_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
@ -312,13 +311,13 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
|
||||
/* Create DTLS channel */
|
||||
if (sessiondata->enabledtls) {
|
||||
if (ac_dtls_data_setup(sessiondata)) {
|
||||
capwap_timeout_set(AC_DEFAULT_WAITDTLS_INTERVAL, sessiondata->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
|
||||
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimercontrol, AC_DTLS_INTERVAL, NULL, NULL, NULL);
|
||||
} else {
|
||||
capwap_logging_debug("Unable to start DTLS data");
|
||||
sessiondata->running = 0;
|
||||
}
|
||||
} else {
|
||||
capwap_timeout_set(AC_MAX_DATA_CHECK_TIMER, sessiondata->timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD);
|
||||
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* */
|
||||
@ -356,7 +355,7 @@ static void ac_session_data_run(struct ac_session_data_t* sessiondata) {
|
||||
ac_session_data_keepalive(sessiondata, &packet);
|
||||
|
||||
/* Update timeout */
|
||||
capwap_timeout_set(AC_MAX_DATA_CHECK_TIMER, sessiondata->timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD);
|
||||
capwap_timeout_set(sessiondata->timeout, sessiondata->idtimerkeepalivedead, AC_MAX_DATA_KEEPALIVE_INTERVAL, NULL, NULL, NULL);
|
||||
} else {
|
||||
/* TODO */
|
||||
}
|
||||
|
Reference in New Issue
Block a user