From 516f129fce43ea6cf2a90c9bcffaa5327dd9d215 Mon Sep 17 00:00:00 2001 From: vemax78 Date: Thu, 7 Nov 2013 22:06:29 +0100 Subject: [PATCH] Cleaning WTP DFA code --- src/wtp/wtp.c | 6 - src/wtp/wtp_dfa.c | 591 +++++++++++++----------------------- src/wtp/wtp_dfa.h | 61 ++-- src/wtp/wtp_dfa_configure.c | 196 +++++++----- src/wtp/wtp_dfa_datacheck.c | 163 +++------- src/wtp/wtp_dfa_discovery.c | 291 ++++++++---------- src/wtp/wtp_dfa_dtls.c | 137 +++++---- src/wtp/wtp_dfa_idle.c | 130 ++++---- src/wtp/wtp_dfa_imagedata.c | 8 - src/wtp/wtp_dfa_join.c | 212 +++---------- src/wtp/wtp_dfa_reset.c | 6 +- src/wtp/wtp_dfa_run.c | 31 +- src/wtp/wtp_dfa_sulking.c | 29 +- 13 files changed, 714 insertions(+), 1147 deletions(-) diff --git a/src/wtp/wtp.c b/src/wtp/wtp.c index 90e0d32..0559b8f 100644 --- a/src/wtp/wtp.c +++ b/src/wtp/wtp.c @@ -1382,15 +1382,9 @@ int main(int argc, char** argv) { capwap_logging_info("Startup WTP"); - /* Start WTP */ - wtp_dfa_change_state(CAPWAP_START_TO_IDLE_STATE); - /* Complete configuration WTP */ result = wtp_configure(); if (result == CAPWAP_SUCCESSFUL) { - /* Init complete */ - wtp_dfa_change_state(CAPWAP_IDLE_STATE); - /* Running WTP */ result = wtp_dfa_running(); diff --git a/src/wtp/wtp_dfa.c b/src/wtp/wtp_dfa.c index fcc8c23..2fc133d 100644 --- a/src/wtp/wtp_dfa.c +++ b/src/wtp/wtp_dfa.c @@ -87,231 +87,55 @@ static void wtp_send_invalid_request(struct capwap_packet_rxmng* rxmngpacket, st } /* WTP Execute state */ -static int wtp_dfa_execute(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int action = WTP_DFA_NO_PACKET; - +static void wtp_dfa_execute(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { switch (g_wtp.dfa.state) { case CAPWAP_IDLE_STATE: { - action = wtp_dfa_state_idle(packet, timeout); + wtp_dfa_state_idle(packet, timeout); break; } - case CAPWAP_IDLE_TO_DISCOVERY_STATE: { - action = wtp_dfa_state_idle_to_discovery(packet, timeout); - break; - } - - case CAPWAP_IDLE_TO_DTLS_SETUP_STATE: { - action = wtp_dfa_state_idle_to_dtlssetup(packet, timeout); - break; - } - case CAPWAP_DISCOVERY_STATE: { - action = wtp_dfa_state_discovery(packet, timeout); + wtp_dfa_state_discovery(packet, timeout); break; } - - case CAPWAP_DISCOVERY_TO_SULKING_STATE: { - action = wtp_dfa_state_discovery_to_sulking(packet, timeout); - break; - } - - case CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE: { - action = wtp_dfa_state_discovery_to_dtlssetup(packet, timeout); - break; - } - + case CAPWAP_SULKING_STATE: { - action = wtp_dfa_state_sulking(packet, timeout); + wtp_dfa_state_sulking(packet, timeout); break; } - case CAPWAP_SULKING_TO_IDLE_STATE: { - action = wtp_dfa_state_sulking_to_idle(packet, timeout); - break; - } - - case CAPWAP_DTLS_SETUP_STATE: { - action = wtp_dfa_state_dtlssetup(packet, timeout); - break; - } - - case CAPWAP_DTLS_SETUP_TO_IDLE_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_DTLS_SETUP_TO_SULKING_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_DTLS_SETUP_TO_AUTHORIZE_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_AUTHORIZE_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_AUTHORIZE_TO_DTLS_SETUP_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_AUTHORIZE_TO_DTLS_CONNECT_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_AUTHORIZE_TO_DTLS_TEARDOWN_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - case CAPWAP_DTLS_CONNECT_STATE: { - action = wtp_dfa_state_dtlsconnect(packet, timeout); - break; - } - - case CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_dtlsconnect_to_dtlsteardown(packet, timeout); - break; - } - - case CAPWAP_DTLS_CONNECT_TO_JOIN_STATE: { - action = wtp_dfa_state_dtlsconnect_to_join(packet, timeout); - break; - } - - case CAPWAP_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_dtlsteardown(packet, timeout); - break; - } - - case CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE: { - action = wtp_dfa_state_dtlsteardown_to_idle(packet, timeout); - break; - } - - case CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE: { - action = wtp_dfa_state_dtlsteardown_to_sulking(packet, timeout); - break; - } - - case CAPWAP_JOIN_STATE: { - action = wtp_dfa_state_join(packet, timeout); - break; - } - - case CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_join_to_dtlsteardown(packet, timeout); - break; - } - - case CAPWAP_JOIN_TO_IMAGE_DATA_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_JOIN_TO_CONFIGURE_STATE: { - action = wtp_dfa_state_join_to_configure(packet, timeout); - break; - } - - case CAPWAP_IMAGE_DATA_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_IMAGE_DATA_TO_RESET_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_IMAGE_DATA_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_imagedata_to_dtlsteardown(packet, timeout); - break; - } - - case CAPWAP_CONFIGURE_STATE: { - action = wtp_dfa_state_configure(packet, timeout); - break; - } - - case CAPWAP_CONFIGURE_TO_RESET_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_configure_to_dtlsteardown(packet, timeout); - break; - } - - case CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE: { - action = wtp_dfa_state_configure_to_datacheck(packet, timeout); - break; - } - - case CAPWAP_RESET_STATE: { - action = wtp_dfa_state_reset(packet, timeout); - break; - } - - case CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - case CAPWAP_DATA_CHECK_STATE: { - action = wtp_dfa_state_datacheck(packet, timeout); - break; - } - - case CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_datacheck_to_dtlsteardown(packet, timeout); - break; - } - - case CAPWAP_DATA_CHECK_TO_RUN_STATE: { - action = wtp_dfa_state_datacheck_to_run(packet, timeout); - break; - } - - case CAPWAP_RUN_STATE: { - action = wtp_dfa_state_run(packet, timeout); - break; - } - - case CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_run_to_dtlsteardown(packet, timeout); - break; - } - - case CAPWAP_RUN_TO_RESET_STATE: { - /* Never called with this state */ - ASSERT(0); + wtp_teardown_connection(timeout); break; } - case CAPWAP_DEAD_STATE: { - /* Never called with this state */ - ASSERT(0); + case CAPWAP_DTLS_TEARDOWN_STATE: { + wtp_dfa_state_dtlsteardown(packet, timeout); + break; + } + + case CAPWAP_JOIN_STATE: { + wtp_dfa_state_join(packet, timeout); + break; + } + + case CAPWAP_CONFIGURE_STATE: { + wtp_dfa_state_configure(packet, timeout); + break; + } + + case CAPWAP_RESET_STATE: { + wtp_dfa_state_reset(packet, timeout); + break; + } + + case CAPWAP_DATA_CHECK_STATE: { + wtp_dfa_state_datacheck(packet, timeout); + break; + } + + case CAPWAP_RUN_STATE: { + wtp_dfa_state_run(packet, timeout); break; } @@ -320,15 +144,12 @@ static int wtp_dfa_execute(struct capwap_parsed_packet* packet, struct timeout_c break; } } - - return action; } /* WTP state machine */ int wtp_dfa_running(void) { int res; int result = CAPWAP_SUCCESSFUL; - int action = WTP_DFA_NO_PACKET; struct timeout_control timeout; char bufferencrypt[CAPWAP_MAX_PACKET_SIZE]; @@ -368,211 +189,213 @@ int wtp_dfa_running(void) { signal(SIGINT, wtp_signal_handler); signal(SIGTERM, wtp_signal_handler); - while (action != WTP_DFA_EXIT) { + /* Init complete, start DFA */ + wtp_dfa_change_state(CAPWAP_IDLE_STATE); + wtp_dfa_state_idle(NULL, &timeout); + + /* */ + while (g_wtp.dfa.state != CAPWAP_DEAD_STATE) { /* If request wait packet from AC */ isrecvpacket = 0; - if ((action == WTP_DFA_ACCEPT_PACKET) || (action == WTP_DFA_DROP_PACKET)) { - buffer = bufferencrypt; - buffersize = CAPWAP_MAX_PACKET_SIZE; - index = capwap_recvfrom(fds, fdscount, buffer, &buffersize, &recvfromaddr, &recvtoaddr, &timeout); - if (!g_wtp.running) { - capwap_logging_debug("Closing WTP, Teardown connection"); + buffer = bufferencrypt; + buffersize = CAPWAP_MAX_PACKET_SIZE; + index = capwap_recvfrom(fds, fdscount, buffer, &buffersize, &recvfromaddr, &recvtoaddr, &timeout); + if (!g_wtp.running) { + capwap_logging_debug("Closing WTP, Teardown connection"); - /* Manual teardown */ - index = CAPWAP_RECV_ERROR_TIMEOUT; - wtp_teardown_connection(&timeout); + /* Manual teardown */ + index = CAPWAP_RECV_ERROR_TIMEOUT; + wtp_teardown_connection(&timeout); - /* Wait RFC teardown timeout */ - capwap_wait_timeout(&timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - } + /* Wait RFC teardown timeout */ + capwap_wait_timeout(&timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + } - if (index >= 0) { - if ((action == WTP_DFA_DROP_PACKET) || g_wtp.teardown) { - /* Drop packet */ - continue; - } else { - int check; + if (index >= 0) { + if (g_wtp.teardown) { + /* Drop packet */ + continue; + } else { + int check; - /* Retrieve network information */ - capwap_get_network_socket(&g_wtp.net, &socket, fds[index].fd); + /* Retrieve network information */ + capwap_get_network_socket(&g_wtp.net, &socket, fds[index].fd); - /* Check source */ - if (socket.isctrlsocket && (g_wtp.acctrladdress.ss_family != AF_UNSPEC)) { - if (capwap_compare_ip(&g_wtp.acctrladdress, &recvfromaddr)) { - /* Unknown source */ - continue; - } - } else if (!socket.isctrlsocket && (g_wtp.acdataaddress.ss_family != AF_UNSPEC)) { - if (capwap_compare_ip(&g_wtp.acdataaddress, &recvfromaddr)) { - /* Unknown source */ - continue; - } + /* Check source */ + if (socket.isctrlsocket && (g_wtp.acctrladdress.ss_family != AF_UNSPEC)) { + if (capwap_compare_ip(&g_wtp.acctrladdress, &recvfromaddr)) { + /* Unknown source */ + continue; } + } else if (!socket.isctrlsocket && (g_wtp.acdataaddress.ss_family != AF_UNSPEC)) { + if (capwap_compare_ip(&g_wtp.acdataaddress, &recvfromaddr)) { + /* Unknown source */ + continue; + } + } - /* Check of packet */ - check = capwap_sanity_check(socket.isctrlsocket, g_wtp.dfa.state, buffer, buffersize, g_wtp.ctrldtls.enable, g_wtp.datadtls.enable); - if (check == CAPWAP_DTLS_PACKET) { - struct capwap_dtls* dtls = (socket.isctrlsocket ? &g_wtp.ctrldtls : &g_wtp.datadtls); + /* Check of packet */ + check = capwap_sanity_check(socket.isctrlsocket, g_wtp.dfa.state, buffer, buffersize, g_wtp.ctrldtls.enable, g_wtp.datadtls.enable); + if (check == CAPWAP_DTLS_PACKET) { + struct capwap_dtls* dtls = (socket.isctrlsocket ? &g_wtp.ctrldtls : &g_wtp.datadtls); - if (dtls->enable) { - int oldaction = dtls->action; + if (dtls->enable) { + int oldaction = dtls->action; - /* Decrypt packet */ - buffersize = capwap_decrypt_packet(dtls, buffer, buffersize, bufferplain, CAPWAP_MAX_PACKET_SIZE); - if (buffersize > 0) { - buffer = bufferplain; - check = CAPWAP_PLAIN_PACKET; - } else if (buffersize == CAPWAP_ERROR_AGAIN) { - /* Check is handshake complete */ - if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (dtls->action == CAPWAP_DTLS_ACTION_DATA)) { - if (socket.isctrlsocket) { - if (g_wtp.dfa.state == CAPWAP_DTLS_CONNECT_STATE) { - check = CAPWAP_NONE_PACKET; - wtp_dfa_change_state(CAPWAP_DTLS_CONNECT_TO_JOIN_STATE); - action = WTP_DFA_NO_PACKET; - } else { - /* TODO */ /* Connection error */ - check = CAPWAP_WRONG_PACKET; - } + /* Decrypt packet */ + buffersize = capwap_decrypt_packet(dtls, buffer, buffersize, bufferplain, CAPWAP_MAX_PACKET_SIZE); + if (buffersize > 0) { + buffer = bufferplain; + check = CAPWAP_PLAIN_PACKET; + } else if (buffersize == CAPWAP_ERROR_AGAIN) { + /* Check is handshake complete */ + if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (dtls->action == CAPWAP_DTLS_ACTION_DATA)) { + if (socket.isctrlsocket) { + if (g_wtp.dfa.state == CAPWAP_DTLS_CONNECT_STATE) { + check = CAPWAP_NONE_PACKET; + wtp_send_join(&timeout); } else { - if (g_wtp.dfa.state == CAPWAP_DATA_CHECK_TO_RUN_STATE) { - check = CAPWAP_NONE_PACKET; - action = WTP_DFA_NO_PACKET; - } else { - /* TODO */ /* Connection error */ - check = CAPWAP_WRONG_PACKET; - } + check = CAPWAP_WRONG_PACKET; + wtp_teardown_connection(&timeout); + } + } else { + if (g_wtp.dfa.state == CAPWAP_DATA_CHECK_STATE) { + check = CAPWAP_NONE_PACKET; + wtp_start_datachannel(&timeout); + } else { + check = CAPWAP_WRONG_PACKET; + wtp_teardown_connection(&timeout); } } - - continue; /* Next packet */ - } else { - if ((oldaction == CAPWAP_DTLS_ACTION_DATA) && (dtls->action == CAPWAP_DTLS_ACTION_SHUTDOWN)) { - action = wtp_teardown_connection(&timeout); - } - - continue; /* Next packet */ } + + continue; /* Next packet */ } else { - continue; /* Drop packet */ + if ((oldaction == CAPWAP_DTLS_ACTION_DATA) && (dtls->action == CAPWAP_DTLS_ACTION_SHUTDOWN)) { + wtp_teardown_connection(&timeout); + } + + continue; /* Next packet */ + } + } else { + continue; /* Drop packet */ + } + } else if (check == CAPWAP_WRONG_PACKET) { + capwap_logging_debug("Warning: sanity check failure"); + /* Drop packet */ + continue; + } + + /* */ + if (check == CAPWAP_PLAIN_PACKET) { + struct capwap_packet_rxmng* rxmngpacket; + + /* Detect local address */ + if (recvtoaddr.ss_family == AF_UNSPEC) { + if (capwap_get_localaddress_by_remoteaddress(&recvtoaddr, &recvfromaddr, g_wtp.net.bind_interface, (!(g_wtp.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) { + struct sockaddr_storage sockinfo; + socklen_t sockinfolen = sizeof(struct sockaddr_storage); + + memset(&sockinfo, 0, sizeof(struct sockaddr_storage)); + if (getsockname(fds[index].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) { + break; + } + + CAPWAP_SET_NETWORK_PORT(&recvtoaddr, CAPWAP_GET_NETWORK_PORT(&sockinfo)); } - } else if (check == CAPWAP_WRONG_PACKET) { - capwap_logging_debug("Warning: sanity check failure"); - /* Drop packet */ - continue; } /* */ - if (check == CAPWAP_PLAIN_PACKET) { - struct capwap_packet_rxmng* rxmngpacket; + if (socket.isctrlsocket) { + capwap_logging_debug("Receive control packet"); + } else { + capwap_logging_debug("Receive data packet"); + } - /* Detect local address */ - if (recvtoaddr.ss_family == AF_UNSPEC) { - if (capwap_get_localaddress_by_remoteaddress(&recvtoaddr, &recvfromaddr, g_wtp.net.bind_interface, (!(g_wtp.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) { - struct sockaddr_storage sockinfo; - socklen_t sockinfolen = sizeof(struct sockaddr_storage); + /* Defragment management */ + rxmngpacket = wtp_get_packet_rxmng(socket.isctrlsocket); - memset(&sockinfo, 0, sizeof(struct sockaddr_storage)); - if (getsockname(fds[index].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) { - break; - } + /* If request, defragmentation packet */ + check = capwap_packet_rxmng_add_recv_packet(rxmngpacket, buffer, buffersize); + if (check == CAPWAP_REQUEST_MORE_FRAGMENT) { + continue; + } else if (check != CAPWAP_RECEIVE_COMPLETE_PACKET) { + /* Discard fragments */ + wtp_free_packet_rxmng(socket.isctrlsocket); + continue; + } - CAPWAP_SET_NETWORK_PORT(&recvtoaddr, CAPWAP_GET_NETWORK_PORT(&sockinfo)); + /* Receive all fragment */ + memcpy(&connection.socket, &socket, sizeof(struct capwap_socket)); + memcpy(&connection.localaddr, &recvtoaddr, sizeof(struct sockaddr_storage)); + memcpy(&connection.remoteaddr, &recvfromaddr, sizeof(struct sockaddr_storage)); + + /* Check for already response to packet */ + if (socket.isctrlsocket) { + if (capwap_recv_retrasmitted_request(&g_wtp.ctrldtls, rxmngpacket, &connection, g_wtp.lastrecvpackethash, g_wtp.responsefragmentpacket)) { + wtp_free_packet_rxmng(socket.isctrlsocket); + capwap_logging_debug("Retrasmitted packet"); + continue; + } + + /* Check message type */ + res = capwap_check_message_type(rxmngpacket); + if (res != VALID_MESSAGE_TYPE) { + if (res == INVALID_REQUEST_MESSAGE_TYPE) { + capwap_logging_warning("Unexpected Unrecognized Request, send Response Packet with error"); + wtp_send_invalid_request(rxmngpacket, &connection, CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST); } + + capwap_logging_debug("Invalid message type"); + wtp_free_packet_rxmng(socket.isctrlsocket); + continue; + } + } + + /* Parsing packet */ + res = capwap_parsing_packet(rxmngpacket, &connection, &packet); + if (res != PARSING_COMPLETE) { + if (socket.isctrlsocket && (res == UNRECOGNIZED_MESSAGE_ELEMENT) && capwap_is_request_type(rxmngpacket->ctrlmsg.type)) { + capwap_logging_warning("Unrecognized Message Element, send Response Packet with error"); + wtp_send_invalid_request(rxmngpacket, &connection, CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT); + /* TODO: add the unrecognized message element */ } /* */ - if (socket.isctrlsocket) { - capwap_logging_debug("Receive control packet"); - } else { - capwap_logging_debug("Receive data packet"); - } - - /* Defragment management */ - rxmngpacket = wtp_get_packet_rxmng(socket.isctrlsocket); - - /* If request, defragmentation packet */ - check = capwap_packet_rxmng_add_recv_packet(rxmngpacket, buffer, buffersize); - if (check == CAPWAP_REQUEST_MORE_FRAGMENT) { - continue; - } else if (check != CAPWAP_RECEIVE_COMPLETE_PACKET) { - /* Discard fragments */ - wtp_free_packet_rxmng(socket.isctrlsocket); - continue; - } - - /* Receive all fragment */ - memcpy(&connection.socket, &socket, sizeof(struct capwap_socket)); - memcpy(&connection.localaddr, &recvtoaddr, sizeof(struct sockaddr_storage)); - memcpy(&connection.remoteaddr, &recvfromaddr, sizeof(struct sockaddr_storage)); - - /* Check for already response to packet */ - if (socket.isctrlsocket) { - if (capwap_recv_retrasmitted_request(&g_wtp.ctrldtls, rxmngpacket, &connection, g_wtp.lastrecvpackethash, g_wtp.responsefragmentpacket)) { - wtp_free_packet_rxmng(socket.isctrlsocket); - capwap_logging_debug("Retrasmitted packet"); - continue; - } - - /* Check message type */ - res = capwap_check_message_type(rxmngpacket); - if (res != VALID_MESSAGE_TYPE) { - if (res == INVALID_REQUEST_MESSAGE_TYPE) { - capwap_logging_warning("Unexpected Unrecognized Request, send Response Packet with error"); - wtp_send_invalid_request(rxmngpacket, &connection, CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST); - } - - capwap_logging_debug("Invalid message type"); - wtp_free_packet_rxmng(socket.isctrlsocket); - continue; - } - } - - /* Parsing packet */ - res = capwap_parsing_packet(rxmngpacket, &connection, &packet); - if (res != PARSING_COMPLETE) { - if (socket.isctrlsocket && (res == UNRECOGNIZED_MESSAGE_ELEMENT) && capwap_is_request_type(rxmngpacket->ctrlmsg.type)) { - capwap_logging_warning("Unrecognized Message Element, send Response Packet with error"); - wtp_send_invalid_request(rxmngpacket, &connection, CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT); - /* TODO: add the unrecognized message element */ - } - - /* */ - capwap_free_parsed_packet(&packet); - wtp_free_packet_rxmng(socket.isctrlsocket); - capwap_logging_debug("Failed parsing packet"); - continue; - } - - /* Validate packet */ - if (capwap_validate_parsed_packet(&packet, NULL)) { - if (socket.isctrlsocket && capwap_is_request_type(rxmngpacket->ctrlmsg.type)) { - capwap_logging_warning("Missing Mandatory Message Element, send Response Packet with error"); - wtp_send_invalid_request(rxmngpacket, &connection, CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT); - } - - /* */ - capwap_free_parsed_packet(&packet); - wtp_free_packet_rxmng(socket.isctrlsocket); - capwap_logging_debug("Failed validation parsed packet"); - continue; - } - - /* Receive a complete packet */ - isrecvpacket = 1; + capwap_free_parsed_packet(&packet); + wtp_free_packet_rxmng(socket.isctrlsocket); + capwap_logging_debug("Failed parsing packet"); + continue; } + + /* Validate packet */ + if (capwap_validate_parsed_packet(&packet, NULL)) { + if (socket.isctrlsocket && capwap_is_request_type(rxmngpacket->ctrlmsg.type)) { + capwap_logging_warning("Missing Mandatory Message Element, send Response Packet with error"); + wtp_send_invalid_request(rxmngpacket, &connection, CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT); + } + + /* */ + capwap_free_parsed_packet(&packet); + wtp_free_packet_rxmng(socket.isctrlsocket); + capwap_logging_debug("Failed validation parsed packet"); + continue; + } + + /* Receive a complete packet */ + isrecvpacket = 1; } - } else if (index == CAPWAP_RECV_ERROR_INTR) { - /* Ignore recv */ - continue; - } else if (index == CAPWAP_RECV_ERROR_SOCKET) { - /* Socket close */ - break; } + } else if (index == CAPWAP_RECV_ERROR_INTR) { + /* Ignore recv */ + continue; + } else if (index == CAPWAP_RECV_ERROR_SOCKET) { + /* Socket close */ + break; } /* Execute state */ - action = wtp_dfa_execute((isrecvpacket ? &packet : NULL), &timeout); + wtp_dfa_execute((isrecvpacket ? &packet : NULL), &timeout); /* Free memory */ capwap_free_parsed_packet(&packet); diff --git a/src/wtp/wtp_dfa.h b/src/wtp/wtp_dfa.h index 6094f64..8854f41 100644 --- a/src/wtp/wtp_dfa.h +++ b/src/wtp/wtp_dfa.h @@ -6,12 +6,6 @@ #include "capwap_protocol.h" #include "capwap_element.h" -/* Execute WTP DFA */ -#define WTP_DFA_NO_PACKET 1 -#define WTP_DFA_ACCEPT_PACKET 2 -#define WTP_DFA_DROP_PACKET 3 -#define WTP_DFA_EXIT 4 - /* */ /* TODO da rifare */ struct wtp_discovery_response { struct capwap_array* controlipv4; @@ -24,7 +18,7 @@ void wtp_free_discovery_response_array(void); int wtp_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param); /* */ -int wtp_teardown_connection(struct timeout_control* timeout); +void wtp_teardown_connection(struct timeout_control* timeout); /* */ void wtp_free_packet_rxmng(int isctrlmsg); @@ -35,43 +29,24 @@ void wtp_free_reference_last_response(void); int wtp_dfa_running(void); void wtp_dfa_change_state(int state); -int wtp_dfa_state_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_idle_to_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_idle_to_dtlssetup(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +/* */ +void wtp_start_dtlssetup(struct timeout_control* timeout); +void wtp_start_datachannel(struct timeout_control* timeout); -int wtp_dfa_state_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_discovery_to_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_discovery_to_dtlssetup(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +/* */ +void wtp_send_join(struct timeout_control* timeout); +void wtp_send_configure(struct timeout_control* timeout); +void wtp_send_datacheck(struct timeout_control* timeout); -int wtp_dfa_state_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_sulking_to_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_dtlssetup(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsconnect(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsconnect_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsteardown_to_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsteardown_to_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_dtlsconnect_to_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_join_to_configure(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_join_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_imagedata_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_configure(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_configure_to_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_configure_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_datacheck_to_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_datacheck_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_run_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); - -int wtp_dfa_state_reset(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +/* */ +void wtp_dfa_state_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_configure(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout); +void wtp_dfa_state_reset(struct capwap_parsed_packet* packet, struct timeout_control* timeout); #endif /* __WTP_DFA_HEADER__ */ diff --git a/src/wtp/wtp_dfa_configure.c b/src/wtp/wtp_dfa_configure.c index e71841d..15ff0f3 100644 --- a/src/wtp/wtp_dfa_configure.c +++ b/src/wtp/wtp_dfa_configure.c @@ -6,90 +6,79 @@ #include "wtp_dfa.h" /* */ -static unsigned long wtp_configure_ac(struct capwap_parsed_packet* packet) { - struct capwap_timers_element* timers; - 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 Configure Status Response with error: %d", (int)resultcode->code); - return CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE; - } - - /* TODO: gestione richiesta */ - - /* */ - timers = (struct capwap_timers_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_TIMERS); - g_wtp.dfa.rfcMaxDiscoveryInterval = timers->discovery; - g_wtp.dfa.rfcEchoInterval = timers->echorequest; - - return CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE; -} - -/* */ -int wtp_dfa_state_configure(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int status = WTP_DFA_ACCEPT_PACKET; - - ASSERT(timeout != NULL); - - if (packet) { - unsigned short binding; - - /* */ - binding = GET_WBID_HEADER(packet->rxmngpacket->header); - if (packet->rxmngpacket->isctrlpacket && (binding == g_wtp.binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_RESPONSE) && ((g_wtp.localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { - /* Valid packet, free request packet */ - wtp_free_reference_last_request(); - - /* Parsing response values */ - wtp_dfa_change_state(wtp_configure_ac(packet)); - status = WTP_DFA_NO_PACKET; - } - } else { - /* No Configuration status response received */ - g_wtp.dfa.rfcRetransmitCount++; - if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { - /* Timeout join state */ - wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; - } else { - /* Retransmit configuration status request */ - if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send configuration status request packet"); - } - - /* Update timeout */ - capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - } - } - - return status; -} - -int wtp_dfa_state_configure_to_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { +void wtp_send_configure(struct timeout_control* timeout) { + int i; struct capwap_header_data capwapheader; struct capwap_packet_txmng* txmngpacket; - int status = WTP_DFA_NO_PACKET; - struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_SUCCESS }; ASSERT(timeout != NULL); - ASSERT(packet == NULL); /* Build packet */ capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); - txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_REQUEST, g_wtp.localseqnumber++, g_wtp.mtu); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_REQUEST, g_wtp.localseqnumber++, g_wtp.mtu); /* Add message element */ - wtp_create_radioopsstate_element(txmngpacket); - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_wtp.acname); + wtp_create_radioadmstate_element(txmngpacket); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_STATISTICSTIMER, &g_wtp.statisticstimer); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPREBOOTSTAT, &g_wtp.rebootstat); + /* CAPWAP_ELEMENT_ACNAMEPRIORITY */ /* TODO */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &g_wtp.transport); + /* CAPWAP_ELEMENT_WTPSTATICIPADDRESS */ /* TODO */ - /* CAPWAP_ELEMENT_RETURNEDMESSAGE */ /* TODO */ - /* CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM */ /* TODO */ - /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + for (i = 0; i < g_wtp.radios->count; i++) { + struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i); - /* Change State Event request complete, get fragment packets */ + /* Set message element */ + if ((radio->status == WTP_RADIO_ENABLED) && radio->radioinformation.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &radio->radioinformation); + + if (radio->radioinformation.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ANTENNA, &radio->antenna); + } + + if (radio->directsequencecontrol.radioid && (radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL, &radio->directsequencecontrol); + } + + if (radio->macoperation.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MACOPERATION, &radio->macoperation); + } + + if (radio->multidomaincapability.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY, &radio->multidomaincapability); + } + + if (radio->ofdmcontrol.radioid && (radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_OFDMCONTROL, &radio->ofdmcontrol); + } + + if (radio->supportedrates.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_SUPPORTEDRATES, &radio->supportedrates); + } + + if (radio->txpower.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWER, &radio->txpower); + } + + if (radio->txpowerlevel.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWERLEVEL, &radio->txpowerlevel); + } + + if (radio->radioconfig.radioid) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTP_RADIO_CONF, &radio->radioconfig); + } + } else { + struct capwap_80211_wtpradioinformation_element element = { (uint8_t)radio->radioid, 0 }; + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &element); + } + } + } + + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + + /* Configuration Status request complete, get fragment packets */ wtp_free_reference_last_request(); capwap_packet_txmng_get_fragment_packets(txmngpacket, g_wtp.requestfragmentpacket, g_wtp.fragmentid); if (g_wtp.requestfragmentpacket->count > 1) { @@ -99,26 +88,67 @@ int wtp_dfa_state_configure_to_datacheck(struct capwap_parsed_packet* packet, st /* Free packets manager */ capwap_packet_txmng_free(txmngpacket); - /* Send Change State Event request to AC */ + /* Send Configuration Status request to AC */ if (capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { g_wtp.dfa.rfcRetransmitCount = 0; capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - wtp_dfa_change_state(CAPWAP_DATA_CHECK_STATE); - status = WTP_DFA_ACCEPT_PACKET; + wtp_dfa_change_state(CAPWAP_CONFIGURE_STATE); } else { /* Error to send packets */ - capwap_logging_debug("Warning: error to send change state event request packet"); + capwap_logging_debug("Warning: error to send configuration status request packet"); wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); + wtp_teardown_connection(timeout); } - - return status; } /* */ -int wtp_dfa_state_configure_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(packet == NULL); +void wtp_dfa_state_configure(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { + struct capwap_timers_element* timers; + struct capwap_resultcode_element* resultcode; + ASSERT(timeout != NULL); - return wtp_teardown_connection(timeout); + if (packet) { + unsigned short binding; + + /* */ + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + if (packet->rxmngpacket->isctrlpacket && (binding == g_wtp.binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_RESPONSE) && ((g_wtp.localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { + /* Valid packet, free request packet */ + wtp_free_reference_last_request(); + + /* 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 Configure Status Response with error: %d", (int)resultcode->code); + wtp_teardown_connection(timeout); + } else { + /* TODO: gestione richiesta */ + + /* */ + timers = (struct capwap_timers_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_TIMERS); + g_wtp.dfa.rfcMaxDiscoveryInterval = timers->discovery; + g_wtp.dfa.rfcEchoInterval = timers->echorequest; + + /* Send change state event packet */ + wtp_send_datacheck(timeout); + } + } + } else { + /* No Configuration status response received */ + g_wtp.dfa.rfcRetransmitCount++; + if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { + /* Timeout join state */ + wtp_free_reference_last_request(); + wtp_teardown_connection(timeout); + } else { + /* Retransmit configuration status request */ + if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { + capwap_logging_debug("Warning: error to send configuration status request packet"); + } + + /* Update timeout */ + capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + } + } } diff --git a/src/wtp/wtp_dfa_datacheck.c b/src/wtp/wtp_dfa_datacheck.c index 4ac5379..6e6caeb 100644 --- a/src/wtp/wtp_dfa_datacheck.c +++ b/src/wtp/wtp_dfa_datacheck.c @@ -4,53 +4,70 @@ #include "wtp_dfa.h" /* */ -static unsigned long wtp_datacheck_ac(struct capwap_parsed_packet* packet) { - struct capwap_resultcode_element* resultcode; +void wtp_send_datacheck(struct timeout_control* timeout) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_SUCCESS }; - /* 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 Data Check Response with error: %d", (int)resultcode->code); - return CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE; + ASSERT(timeout != NULL); + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_REQUEST, g_wtp.localseqnumber++, g_wtp.mtu); + + /* Add message element */ + wtp_create_radioopsstate_element(txmngpacket); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); + + /* CAPWAP_ELEMENT_RETURNEDMESSAGE */ /* TODO */ + /* CAPWAP_ELEMENT_80211_WTP_RADIO_FAIL_ALARM */ /* TODO */ + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ + + /* Change State Event request complete, get fragment packets */ + wtp_free_reference_last_request(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, g_wtp.requestfragmentpacket, g_wtp.fragmentid); + if (g_wtp.requestfragmentpacket->count > 1) { + g_wtp.fragmentid++; } - /* TODO: gestione richiesta */ + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); - return CAPWAP_DATA_CHECK_TO_RUN_STATE; + /* Send Change State Event request to AC */ + if (capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { + g_wtp.dfa.rfcRetransmitCount = 0; + capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_DATA_CHECK_STATE); + } else { + /* Error to send packets */ + capwap_logging_debug("Warning: error to send change state event request packet"); + wtp_free_reference_last_request(); + wtp_teardown_connection(timeout); + } } /* */ -int wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int status = WTP_DFA_ACCEPT_PACKET; +void wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { + unsigned short binding; + struct capwap_resultcode_element* resultcode; ASSERT(timeout != NULL); if (packet) { - unsigned short binding; - - /* */ binding = GET_WBID_HEADER(packet->rxmngpacket->header); - - if (packet->rxmngpacket->isctrlpacket) { - if (binding == g_wtp.binding) { - if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CHANGE_STATE_EVENT_RESPONSE) { - if ((g_wtp.localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq) { - if (packet->rxmngpacket->packetlength > 0) { - int a = packet->rxmngpacket->packetlength; - a++; - } - } - } - } - } - if (packet->rxmngpacket->isctrlpacket && (binding == g_wtp.binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CHANGE_STATE_EVENT_RESPONSE) && ((g_wtp.localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { /* Valid packet, free request packet */ wtp_free_reference_last_request(); - /* Parsing response values */ - wtp_dfa_change_state(wtp_datacheck_ac(packet)); - status = WTP_DFA_NO_PACKET; + /* 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 Data Check Response with error: %d", (int)resultcode->code); + wtp_teardown_connection(timeout); + } else { + /* TODO: gestione richiesta */ + wtp_start_datachannel(timeout); + } } } else { /* No change state response received */ @@ -58,10 +75,9 @@ int wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet, struct timeout_ if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { /* Timeout join state */ wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; + wtp_teardown_connection(timeout); } else { - /* Retransmit change state request */ + /* Retransmit change state request */ if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { capwap_logging_debug("Warning: error to send change state request packet"); } @@ -70,83 +86,4 @@ int wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet, struct timeout_ capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } } - - return status; -} - -/* */ -int wtp_dfa_state_datacheck_to_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - struct capwap_list* txfragpacket; - struct capwap_header_data capwapheader; - struct capwap_packet_txmng* txmngpacket; - int status = WTP_DFA_ACCEPT_PACKET; - - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - /* If need, create DTLS Data channel crypted */ - if (g_wtp.dtlsdatapolicy & CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED) { - if (!g_wtp.datadtls.enable) { - /* Create DTLS data session before send data keepalive */ - if (capwap_crypt_createsession(&g_wtp.datadtls, CAPWAP_DTLS_DATA_SESSION, &g_wtp.dtlscontext, wtp_bio_send, NULL)) { - if (capwap_crypt_open(&g_wtp.datadtls, &g_wtp.acdataaddress) == CAPWAP_HANDSHAKE_CONTINUE) { - /* Wait complete dtls handshake */ - capwap_set_timeout(g_wtp.dfa.rfcWaitDTLS, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - return WTP_DFA_ACCEPT_PACKET; - } else { - /* TODO error */ - } - } else { - /* TODO error */ - } - } else if (g_wtp.datadtls.action != CAPWAP_DTLS_ACTION_DATA) { - wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); - return WTP_DFA_NO_PACKET; - } - } - - /* Build packet */ - capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); - capwap_header_set_keepalive_flag(&capwapheader, 1); - txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, g_wtp.mtu); /* CAPWAP_DONT_FRAGMENT */ - - /* Add message element */ - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_SESSIONID, &g_wtp.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 AC */ - if (capwap_crypt_sendto_fragmentpacket(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txfragpacket, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress)) { - capwap_kill_timeout(timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - capwap_set_timeout(g_wtp.dfa.rfcEchoInterval, timeout, CAPWAP_TIMER_CONTROL_ECHO); - capwap_set_timeout(g_wtp.dfa.rfcDataChannelDeadInterval, timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); - wtp_dfa_change_state(CAPWAP_RUN_STATE); - } else { - /* Error to send packets */ - capwap_logging_debug("Warning: error to send data channel keepalive packet"); - wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; - } - } else { - capwap_logging_debug("Warning: error to send data channel keepalive packet, fragment packet"); - wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; - } - - /* Free packets manager */ - capwap_list_free(txfragpacket); - capwap_packet_txmng_free(txmngpacket); - - /* */ - return status; -} - -/* */ -int wtp_dfa_state_datacheck_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(packet == NULL); - ASSERT(timeout != NULL); - - return wtp_teardown_connection(timeout); } diff --git a/src/wtp/wtp_dfa_discovery.c b/src/wtp/wtp_dfa_discovery.c index 3af5fe0..f619f02 100644 --- a/src/wtp/wtp_dfa_discovery.c +++ b/src/wtp/wtp_dfa_discovery.c @@ -21,10 +21,9 @@ void wtp_free_discovery_response_array(void) { } /* */ -int wtp_dfa_state_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { +void wtp_dfa_state_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { struct capwap_array* controlip; - int status = WTP_DFA_ACCEPT_PACKET; - + ASSERT(timeout != NULL); if (packet) { @@ -68,115 +67,138 @@ int wtp_dfa_state_discovery(struct capwap_parsed_packet* packet, struct timeout_ } } } - } else if (g_wtp.acdiscoveryresponse->count > 0) { - int i, j, w; - int countwtp = -1; - int indexpreferred = -1; - - struct sockaddr_storage checkaddr; - struct sockaddr_in* checkaddripv4; - struct sockaddr_in6* checkaddripv6; - - /* */ - g_wtp.acctrladdress.ss_family = AF_UNSPEC; - - /* Selected by preferred or less WTP by AC */ - for (i = 0; i < g_wtp.acdiscoveryresponse->count; i++) { - struct wtp_discovery_response* response = (struct wtp_discovery_response*)capwap_array_get_item_pointer(g_wtp.acdiscoveryresponse, i); - - /* AC with IPv4 */ - if ((g_wtp.net.sock_family == AF_UNSPEC) || (g_wtp.net.sock_family == AF_INET)) { - for (w = 0; w < response->controlipv4->count; w++) { - struct capwap_controlipv4_element* controlipv4 = (struct capwap_controlipv4_element*)capwap_array_get_item_pointer(response->controlipv4, w); - - /* Create IPv4 address */ - memset(&checkaddr, 0, sizeof(struct sockaddr_storage)); - checkaddripv4 = (struct sockaddr_in*)&checkaddr; - checkaddripv4->sin_family = AF_INET; - checkaddripv4->sin_port = htons(CAPWAP_CONTROL_PORT); - memcpy(&checkaddripv4->sin_addr, &controlipv4->address, sizeof(struct in_addr)); - - /* Check for preferred AC */ - for (j = 0; j < ((indexpreferred != -1) ? indexpreferred : g_wtp.acpreferedarray->count); j++) { - struct sockaddr_storage* acpreferredaddr = (struct sockaddr_storage*)capwap_array_get_item_pointer(g_wtp.acpreferedarray, j); - - if (!capwap_compare_ip(acpreferredaddr, &checkaddr)) { - indexpreferred = j; - memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); - break; - } - } - - /* Check by number of WTP */ - if (indexpreferred == -1) { - if ((countwtp == -1) || (countwtp > controlipv4->wtpcount)) { - countwtp = controlipv4->wtpcount; - memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); - } - } - } - } - - /* AC with IPv6 */ - if ((g_wtp.net.sock_family == AF_UNSPEC) || (g_wtp.net.sock_family == AF_INET6)) { - for (w = 0; w < response->controlipv6->count; w++) { - struct capwap_controlipv6_element* controlipv6 = (struct capwap_controlipv6_element*)capwap_array_get_item_pointer(response->controlipv6, w); - - /* Create IPv6 address */ - memset(&checkaddr, 0, sizeof(struct sockaddr_storage)); - checkaddripv6 = (struct sockaddr_in6*)&checkaddr; - checkaddripv6->sin6_family = AF_INET6; - checkaddripv6->sin6_port = htons(CAPWAP_CONTROL_PORT); - memcpy(&checkaddripv6->sin6_addr, &controlipv6->address, sizeof(struct in6_addr)); - - /* Check for preferred AC */ - for (j = 0; j < ((indexpreferred != -1) ? indexpreferred : g_wtp.acpreferedarray->count); j++) { - struct sockaddr_storage* acpreferredaddr = (struct sockaddr_storage*)capwap_array_get_item_pointer(g_wtp.acpreferedarray, j); - - if (!capwap_compare_ip(acpreferredaddr, &checkaddr)) { - indexpreferred = j; - memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); - break; - } - } - - /* Check by number of WTP */ - if (indexpreferred == -1) { - if ((countwtp == -1) || (countwtp > controlipv6->wtpcount)) { - countwtp = controlipv6->wtpcount; - memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); - } - } - } - } - } - - /* Free memory */ - wtp_free_discovery_response_array(); - - /* Change state if found AC */ - if (g_wtp.acctrladdress.ss_family != AF_UNSPEC) { - memcpy(&g_wtp.acdataaddress, &g_wtp.acctrladdress, sizeof(struct sockaddr_storage)); - CAPWAP_SET_NETWORK_PORT(&g_wtp.acdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.acdataaddress) + 1); - wtp_dfa_change_state(CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE); - } - - status = WTP_DFA_NO_PACKET; } else { + if (g_wtp.acdiscoveryresponse->count > 0) { + int i, j, w; + int countwtp = -1; + int indexpreferred = -1; + + struct sockaddr_storage checkaddr; + struct sockaddr_in* checkaddripv4; + struct sockaddr_in6* checkaddripv6; + + /* */ + g_wtp.acctrladdress.ss_family = AF_UNSPEC; + + /* Selected by preferred or less WTP by AC */ + for (i = 0; i < g_wtp.acdiscoveryresponse->count; i++) { + struct wtp_discovery_response* response = (struct wtp_discovery_response*)capwap_array_get_item_pointer(g_wtp.acdiscoveryresponse, i); + + /* AC with IPv4 */ + if ((g_wtp.net.sock_family == AF_UNSPEC) || (g_wtp.net.sock_family == AF_INET)) { + for (w = 0; w < response->controlipv4->count; w++) { + struct capwap_controlipv4_element* controlipv4 = (struct capwap_controlipv4_element*)capwap_array_get_item_pointer(response->controlipv4, w); + + /* Create IPv4 address */ + memset(&checkaddr, 0, sizeof(struct sockaddr_storage)); + checkaddripv4 = (struct sockaddr_in*)&checkaddr; + checkaddripv4->sin_family = AF_INET; + checkaddripv4->sin_port = htons(CAPWAP_CONTROL_PORT); + memcpy(&checkaddripv4->sin_addr, &controlipv4->address, sizeof(struct in_addr)); + + /* Check for preferred AC */ + for (j = 0; j < ((indexpreferred != -1) ? indexpreferred : g_wtp.acpreferedarray->count); j++) { + struct sockaddr_storage* acpreferredaddr = (struct sockaddr_storage*)capwap_array_get_item_pointer(g_wtp.acpreferedarray, j); + + if (!capwap_compare_ip(acpreferredaddr, &checkaddr)) { + indexpreferred = j; + memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); + break; + } + } + + /* Check by number of WTP */ + if (indexpreferred == -1) { + if ((countwtp == -1) || (countwtp > controlipv4->wtpcount)) { + countwtp = controlipv4->wtpcount; + memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); + } + } + } + } + + /* AC with IPv6 */ + if ((g_wtp.net.sock_family == AF_UNSPEC) || (g_wtp.net.sock_family == AF_INET6)) { + for (w = 0; w < response->controlipv6->count; w++) { + struct capwap_controlipv6_element* controlipv6 = (struct capwap_controlipv6_element*)capwap_array_get_item_pointer(response->controlipv6, w); + + /* Create IPv6 address */ + memset(&checkaddr, 0, sizeof(struct sockaddr_storage)); + checkaddripv6 = (struct sockaddr_in6*)&checkaddr; + checkaddripv6->sin6_family = AF_INET6; + checkaddripv6->sin6_port = htons(CAPWAP_CONTROL_PORT); + memcpy(&checkaddripv6->sin6_addr, &controlipv6->address, sizeof(struct in6_addr)); + + /* Check for preferred AC */ + for (j = 0; j < ((indexpreferred != -1) ? indexpreferred : g_wtp.acpreferedarray->count); j++) { + struct sockaddr_storage* acpreferredaddr = (struct sockaddr_storage*)capwap_array_get_item_pointer(g_wtp.acpreferedarray, j); + + if (!capwap_compare_ip(acpreferredaddr, &checkaddr)) { + indexpreferred = j; + memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); + break; + } + } + + /* Check by number of WTP */ + if (indexpreferred == -1) { + if ((countwtp == -1) || (countwtp > controlipv6->wtpcount)) { + countwtp = controlipv6->wtpcount; + memcpy(&g_wtp.acctrladdress, &checkaddr, sizeof(struct sockaddr_storage)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, 1)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); + } + } + } + } + } + + /* Free memory */ + wtp_free_discovery_response_array(); + + /* Change state if found AC */ + if (g_wtp.acctrladdress.ss_family != AF_UNSPEC) { + memcpy(&g_wtp.acdataaddress, &g_wtp.acctrladdress, sizeof(struct sockaddr_storage)); + CAPWAP_SET_NETWORK_PORT(&g_wtp.acdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.acdataaddress) + 1); + + /* Retrieve local address */ + if (capwap_get_localaddress_by_remoteaddress(&g_wtp.wtpctrladdress, &g_wtp.acctrladdress, g_wtp.net.bind_interface, (!(g_wtp.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) { + struct sockaddr_storage sockinfo; + socklen_t sockinfolen = sizeof(struct sockaddr_storage); + + memset(&sockinfo, 0, sizeof(struct sockaddr_storage)); + if (!getsockname(g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], (struct sockaddr*)&sockinfo, &sockinfolen)) { + CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpctrladdress, CAPWAP_GET_NETWORK_PORT(&sockinfo)); + + /* */ + memcpy(&g_wtp.wtpdataaddress, &g_wtp.wtpctrladdress, sizeof(struct sockaddr_storage)); + CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.wtpdataaddress) + 1); + + /* */ + if (!g_wtp.enabledtls) { + wtp_send_join(timeout); /* Bypass DTLS connection */ + } else { + wtp_start_dtlssetup(timeout); /* Create DTLS connection */ + } + + return; + } + } + } + } + /* No Discovery response received */ g_wtp.dfa.rfcDiscoveryCount++; if (g_wtp.dfa.rfcDiscoveryCount >= g_wtp.dfa.rfcMaxDiscoveries) { /* Timeout discovery state */ - wtp_dfa_change_state(CAPWAP_DISCOVERY_TO_SULKING_STATE); - status = WTP_DFA_NO_PACKET; + capwap_set_timeout(g_wtp.dfa.rfcSilentInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_SULKING_STATE); } else { int i; struct capwap_header_data capwapheader; @@ -234,59 +256,4 @@ int wtp_dfa_state_discovery(struct capwap_parsed_packet* packet, struct timeout_ capwap_set_timeout(g_wtp.dfa.rfcDiscoveryInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } } - - return status; -} - -/* */ -int wtp_dfa_state_discovery_to_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - capwap_set_timeout(g_wtp.dfa.rfcSilentInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - wtp_dfa_change_state(CAPWAP_SULKING_STATE); - - return WTP_DFA_DROP_PACKET; -} - -/* */ -int wtp_dfa_state_discovery_to_dtlssetup(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int status = WTP_DFA_ACCEPT_PACKET; - - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - /* Retrieve local address */ - if (!capwap_get_localaddress_by_remoteaddress(&g_wtp.wtpctrladdress, &g_wtp.acctrladdress, g_wtp.net.bind_interface, (!(g_wtp.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) { - wtp_dfa_change_state(CAPWAP_DISCOVERY_TO_SULKING_STATE); - status = WTP_DFA_NO_PACKET; - } else { - struct sockaddr_storage sockinfo; - socklen_t sockinfolen = sizeof(struct sockaddr_storage); - - memset(&sockinfo, 0, sizeof(struct sockaddr_storage)); - if (getsockname(g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], (struct sockaddr*)&sockinfo, &sockinfolen) < 0) { - wtp_dfa_change_state(CAPWAP_DTLS_SETUP_TO_SULKING_STATE); - status = WTP_DFA_NO_PACKET; - } else { - CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpctrladdress, CAPWAP_GET_NETWORK_PORT(&sockinfo)); - - /* */ - memcpy(&g_wtp.wtpdataaddress, &g_wtp.wtpctrladdress, sizeof(struct sockaddr_storage)); - CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.wtpdataaddress) + 1); - - /* */ - if (!g_wtp.enabledtls) { - /* Bypass DTLS connection */ - wtp_dfa_change_state(CAPWAP_DTLS_CONNECT_TO_JOIN_STATE); - status = WTP_DFA_NO_PACKET; - } else { - /* Create DTLS connection */ - wtp_dfa_change_state(CAPWAP_DTLS_SETUP_STATE); - status = WTP_DFA_NO_PACKET; - } - } - } - - return status; } diff --git a/src/wtp/wtp_dfa_dtls.c b/src/wtp/wtp_dfa_dtls.c index 883dae3..9588a5e 100644 --- a/src/wtp/wtp_dfa_dtls.c +++ b/src/wtp/wtp_dfa_dtls.c @@ -12,48 +12,92 @@ int wtp_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param } /* */ -int wtp_dfa_state_dtlssetup(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int status = WTP_DFA_ACCEPT_PACKET; - +void wtp_start_dtlssetup(struct timeout_control* timeout) { ASSERT(timeout != NULL); - ASSERT(packet == NULL); /* Create DTLS session */ if (!capwap_crypt_createsession(&g_wtp.ctrldtls, CAPWAP_DTLS_CONTROL_SESSION, &g_wtp.dtlscontext, wtp_bio_send, NULL)) { - wtp_dfa_change_state(CAPWAP_DTLS_SETUP_TO_IDLE_STATE); - status = WTP_DFA_NO_PACKET; + capwap_set_timeout(g_wtp.dfa.rfcSilentInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_SULKING_STATE); } else { if (capwap_crypt_open(&g_wtp.ctrldtls, &g_wtp.acctrladdress) == CAPWAP_HANDSHAKE_ERROR) { - wtp_dfa_change_state(CAPWAP_DTLS_SETUP_TO_IDLE_STATE); - status = WTP_DFA_NO_PACKET; + capwap_set_timeout(g_wtp.dfa.rfcSilentInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_SULKING_STATE); } else { - wtp_dfa_change_state(CAPWAP_DTLS_CONNECT_STATE); capwap_set_timeout(g_wtp.dfa.rfcWaitDTLS, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_DTLS_CONNECT_STATE); + } + } +} + +/* */ +void wtp_start_datachannel(struct timeout_control* timeout) { + struct capwap_list* txfragpacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + + ASSERT(timeout != NULL); + + /* If need, create DTLS Data channel crypted */ + if (g_wtp.dtlsdatapolicy & CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED) { + if (!g_wtp.datadtls.enable) { + /* Create DTLS data session before send data keepalive */ + if (capwap_crypt_createsession(&g_wtp.datadtls, CAPWAP_DTLS_DATA_SESSION, &g_wtp.dtlscontext, wtp_bio_send, NULL)) { + if (capwap_crypt_open(&g_wtp.datadtls, &g_wtp.acdataaddress) == CAPWAP_HANDSHAKE_CONTINUE) { + capwap_set_timeout(g_wtp.dfa.rfcWaitDTLS, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); /* Wait complete dtls handshake */ + } else { + wtp_teardown_connection(timeout); + } + } else { + wtp_teardown_connection(timeout); + } + + return; + } else if (g_wtp.datadtls.action != CAPWAP_DTLS_ACTION_DATA) { + wtp_teardown_connection(timeout); + return; } } - return status; -} + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); + capwap_header_set_keepalive_flag(&capwapheader, 1); + txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, g_wtp.mtu); /* CAPWAP_DONT_FRAGMENT */ -/* */ -int wtp_dfa_state_dtlsconnect(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - wtp_dfa_change_state(CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE); - return WTP_DFA_NO_PACKET; -} + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_SESSIONID, &g_wtp.sessionid); -/* */ -int wtp_dfa_state_dtlsconnect_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(packet == NULL); - ASSERT(timeout != NULL); + /* 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 AC */ + if (capwap_crypt_sendto_fragmentpacket(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txfragpacket, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress)) { + /* Reset AC Prefered List Position */ + g_wtp.acpreferedselected = 0; - return wtp_teardown_connection(timeout); + /* Set timer */ + capwap_kill_timeout(timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + capwap_set_timeout(g_wtp.dfa.rfcEchoInterval, timeout, CAPWAP_TIMER_CONTROL_ECHO); + capwap_set_timeout(g_wtp.dfa.rfcDataChannelDeadInterval, timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); + wtp_dfa_change_state(CAPWAP_RUN_STATE); + } else { + /* Error to send packets */ + capwap_logging_debug("Warning: error to send data channel keepalive packet"); + wtp_teardown_connection(timeout); + } + } else { + capwap_logging_debug("Warning: error to send data channel keepalive packet, fragment packet"); + wtp_teardown_connection(timeout); + } + + /* Free packets manager */ + capwap_list_free(txfragpacket); + capwap_packet_txmng_free(txmngpacket); } /* Teardown connection */ -int wtp_teardown_connection(struct timeout_control* timeout) { +void wtp_teardown_connection(struct timeout_control* timeout) { ASSERT(timeout != NULL); g_wtp.teardown = 1; @@ -62,7 +106,7 @@ int wtp_teardown_connection(struct timeout_control* timeout) { if (g_wtp.ctrldtls.enable) { capwap_crypt_close(&g_wtp.ctrldtls); } - + /* DTLS Data */ if (g_wtp.datadtls.enable) { capwap_crypt_close(&g_wtp.datadtls); @@ -72,19 +116,21 @@ int wtp_teardown_connection(struct timeout_control* timeout) { capwap_killall_timeout(timeout); capwap_set_timeout(g_wtp.dfa.rfcDTLSSessionDelete, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); wtp_dfa_change_state(CAPWAP_DTLS_TEARDOWN_STATE); - return WTP_DFA_DROP_PACKET; } /* */ -int wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { +void wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); - ASSERT(packet == NULL); - + + if (packet) { + return; + } + /* Free and reset resource */ if (g_wtp.ctrldtls.enable) { capwap_crypt_freesession(&g_wtp.ctrldtls); } - + if (g_wtp.datadtls.enable) { capwap_crypt_freesession(&g_wtp.datadtls); } @@ -103,33 +149,14 @@ int wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet, struct timeo /* */ if (!g_wtp.running) { - return WTP_DFA_EXIT; + wtp_dfa_change_state(CAPWAP_DEAD_STATE); } else if ((g_wtp.dfa.rfcFailedDTLSSessionCount >= g_wtp.dfa.rfcMaxFailedDTLSSessionRetry) || (g_wtp.dfa.rfcFailedDTLSAuthFailCount >= g_wtp.dfa.rfcMaxFailedDTLSSessionRetry)) { - wtp_dfa_change_state(CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE); + capwap_set_timeout(g_wtp.dfa.rfcSilentInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_SULKING_STATE); } else { - wtp_dfa_change_state(CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE); + capwap_set_timeout(0, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_IDLE_STATE); } /* TODO controllare se è richiesto il ravvio del sistema */ - return WTP_DFA_NO_PACKET; -} - -/* */ -int wtp_dfa_state_dtlsteardown_to_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - capwap_set_timeout(g_wtp.dfa.rfcSilentInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - wtp_dfa_change_state(CAPWAP_SULKING_STATE); - - return WTP_DFA_DROP_PACKET; -} - -/* */ -int wtp_dfa_state_dtlsteardown_to_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - wtp_dfa_change_state(CAPWAP_IDLE_STATE); - return WTP_DFA_NO_PACKET; } diff --git a/src/wtp/wtp_dfa_idle.c b/src/wtp/wtp_dfa_idle.c index 5d8c6b9..1e05fe5 100644 --- a/src/wtp/wtp_dfa_idle.c +++ b/src/wtp/wtp_dfa_idle.c @@ -3,93 +3,69 @@ #include "wtp_dfa.h" /* */ -int wtp_dfa_state_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { +void wtp_dfa_state_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); - ASSERT(packet == NULL); - /* Remove teardown flag */ - g_wtp.teardown = 0; - - if (!g_wtp.acdiscoveryrequest && (g_wtp.acpreferedarray->count > 0)) { - /* Found in configuration file the AC address */ - memcpy(&g_wtp.acctrladdress, capwap_array_get_item_pointer(g_wtp.acpreferedarray, g_wtp.acpreferedselected), sizeof(struct sockaddr_storage)); - memcpy(&g_wtp.acdataaddress, &g_wtp.acctrladdress, sizeof(struct sockaddr_storage)); - CAPWAP_SET_NETWORK_PORT(&g_wtp.acdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.acdataaddress) + 1); - - /* Configure socket */ - capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, CAPWAP_CTRL_SOCKET)); - capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acdataaddress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); - - /* */ - g_wtp.acpreferedselected = (g_wtp.acpreferedselected + 1) % g_wtp.acpreferedarray->count; - - /* Connect */ - wtp_dfa_change_state(CAPWAP_IDLE_TO_DTLS_SETUP_STATE); - } else { - /* Search AC */ - wtp_dfa_change_state(CAPWAP_IDLE_TO_DISCOVERY_STATE); + /* Ignore packets */ + if (packet) { + return; } - - capwap_kill_timeout(timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - return WTP_DFA_NO_PACKET; -} -/* Prepare to discovery AC */ -int wtp_dfa_state_idle_to_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(timeout != NULL); - ASSERT(packet == NULL); + /* Remove teardown */ + g_wtp.teardown = 0; + capwap_killall_timeout(timeout); + + /* */ + if (!g_wtp.acdiscoveryrequest && (g_wtp.acpreferedarray->count > 0)) { + while (g_wtp.acpreferedselected < g_wtp.acpreferedarray->count) { + /* Found in configuration file the AC address */ + memcpy(&g_wtp.acctrladdress, capwap_array_get_item_pointer(g_wtp.acpreferedarray, g_wtp.acpreferedselected), sizeof(struct sockaddr_storage)); + memcpy(&g_wtp.acdataaddress, &g_wtp.acctrladdress, sizeof(struct sockaddr_storage)); + CAPWAP_SET_NETWORK_PORT(&g_wtp.acdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.acdataaddress) + 1); + + /* Next AC */ + g_wtp.acpreferedselected++; + + /* Configure socket */ + capwap_get_network_socket(&g_wtp.net, &g_wtp.acctrlsock, capwap_get_socket(&g_wtp.net, g_wtp.acctrladdress.ss_family, IPPROTO_UDP, CAPWAP_CTRL_SOCKET)); + capwap_get_network_socket(&g_wtp.net, &g_wtp.acdatasock, capwap_get_socket(&g_wtp.net, g_wtp.acdataaddress.ss_family, (g_wtp.transport.type == CAPWAP_UDP_TRANSPORT ? IPPROTO_UDP : IPPROTO_UDPLITE), CAPWAP_DATA_SOCKET)); + + /* Retrieve local address */ + if (capwap_get_localaddress_by_remoteaddress(&g_wtp.wtpctrladdress, &g_wtp.acctrladdress, g_wtp.net.bind_interface, (!(g_wtp.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) { + struct sockaddr_storage sockinfo; + socklen_t sockinfolen = sizeof(struct sockaddr_storage); + + memset(&sockinfo, 0, sizeof(struct sockaddr_storage)); + if (!getsockname(g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], (struct sockaddr*)&sockinfo, &sockinfolen)) { + CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpctrladdress, CAPWAP_GET_NETWORK_PORT(&sockinfo)); + + /* */ + memcpy(&g_wtp.wtpdataaddress, &g_wtp.wtpctrladdress, sizeof(struct sockaddr_storage)); + CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.wtpdataaddress) + 1); + + /* */ + if (!g_wtp.enabledtls) { + wtp_send_join(timeout); /* Bypass DTLS connection */ + } else { + wtp_start_dtlssetup(timeout); /* Create DTLS connection */ + } + + return; + } + } + } + } + + /* Discovery AC */ + g_wtp.acpreferedselected = 0; /* Set discovery interval */ g_wtp.dfa.rfcDiscoveryInterval = capwap_get_rand(g_wtp.dfa.rfcMaxDiscoveryInterval - WTP_MIN_DISCOVERY_INTERVAL) + WTP_MIN_DISCOVERY_INTERVAL; g_wtp.dfa.rfcDiscoveryCount = 0; - + /* Change state */ wtp_dfa_change_state(CAPWAP_DISCOVERY_STATE); - + /* Wait before send Discovery Request */ capwap_set_timeout(g_wtp.dfa.rfcDiscoveryInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - - return WTP_DFA_DROP_PACKET; -} - -/* Prepare to connect with AC */ -int wtp_dfa_state_idle_to_dtlssetup(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int status = WTP_DFA_ACCEPT_PACKET; - - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - /* Retrieve local address */ - if (!capwap_get_localaddress_by_remoteaddress(&g_wtp.wtpctrladdress, &g_wtp.acctrladdress, g_wtp.net.bind_interface, (!(g_wtp.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) { - wtp_dfa_change_state(CAPWAP_IDLE_STATE); - status = WTP_DFA_NO_PACKET; - } else { - struct sockaddr_storage sockinfo; - socklen_t sockinfolen = sizeof(struct sockaddr_storage); - - memset(&sockinfo, 0, sizeof(struct sockaddr_storage)); - if (getsockname(g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], (struct sockaddr*)&sockinfo, &sockinfolen) < 0) { - wtp_dfa_change_state(CAPWAP_IDLE_STATE); - status = WTP_DFA_NO_PACKET; - } else { - CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpctrladdress, CAPWAP_GET_NETWORK_PORT(&sockinfo)); - - /* */ - memcpy(&g_wtp.wtpdataaddress, &g_wtp.wtpctrladdress, sizeof(struct sockaddr_storage)); - CAPWAP_SET_NETWORK_PORT(&g_wtp.wtpdataaddress, CAPWAP_GET_NETWORK_PORT(&g_wtp.wtpdataaddress) + 1); - - /* */ - if (!g_wtp.enabledtls) { - /* Bypass DTLS connection */ - wtp_dfa_change_state(CAPWAP_DTLS_CONNECT_TO_JOIN_STATE); - status = WTP_DFA_NO_PACKET; - } else { - /* Create DTLS connection */ - wtp_dfa_change_state(CAPWAP_DTLS_SETUP_STATE); - status = WTP_DFA_NO_PACKET; - } - } - } - - return status; } diff --git a/src/wtp/wtp_dfa_imagedata.c b/src/wtp/wtp_dfa_imagedata.c index 3d18ae3..c5efe02 100644 --- a/src/wtp/wtp_dfa_imagedata.c +++ b/src/wtp/wtp_dfa_imagedata.c @@ -1,11 +1,3 @@ #include "wtp.h" #include "capwap_dfa.h" #include "wtp_dfa.h" - -/* */ -int wtp_dfa_state_imagedata_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(packet == NULL); - ASSERT(timeout != NULL); - - return wtp_teardown_connection(timeout); -} diff --git a/src/wtp/wtp_dfa_join.c b/src/wtp/wtp_dfa_join.c index dc209fc..649172f 100644 --- a/src/wtp/wtp_dfa_join.c +++ b/src/wtp/wtp_dfa_join.c @@ -6,54 +6,15 @@ #include "wtp_dfa.h" /* */ -static unsigned long wtp_join_ac(struct capwap_parsed_packet* packet) { - struct capwap_acdescriptor_element* acdescriptor; - struct capwap_acname_element* acname; - 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 Join Response with error: %d", (int)resultcode->code); - return CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE; - } - - /* TODO: gestione richiesta - CAPWAP_JOIN_TO_IMAGE_DATA_STATE <-> CAPWAP_JOIN_TO_CONFIGURE_STATE - */ - - /* Check DTLS data policy */ - acdescriptor = (struct capwap_acdescriptor_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ACDESCRIPTION); - if (!(g_wtp.validdtlsdatapolicy & acdescriptor->dtlspolicy)) { - return CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE; - } - - /* AC name associated */ - acname = (struct capwap_acname_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ACNAME); - g_wtp.acname.name = (uint8_t*)capwap_duplicate_string((const char*)acname->name); - - /* DTLS data policy */ - g_wtp.dtlsdatapolicy = acdescriptor->dtlspolicy & g_wtp.validdtlsdatapolicy; - - return CAPWAP_JOIN_TO_CONFIGURE_STATE; -} - -/* */ -int wtp_dfa_state_dtlsconnect_to_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { +void wtp_send_join(struct timeout_control* timeout) { struct capwap_header_data capwapheader; struct capwap_packet_txmng* txmngpacket; - int status = WTP_DFA_NO_PACKET; - -#ifdef DEBUG - char sessionname[33]; -#endif ASSERT(timeout != NULL); - ASSERT(packet == NULL); - + /* Reset DTLS counter */ g_wtp.dfa.rfcFailedDTLSSessionCount = 0; - + /* Update status radio */ g_wtp.descriptor.radiosinuse = wtp_update_radio_in_use(); @@ -61,8 +22,12 @@ int wtp_dfa_state_dtlsconnect_to_join(struct capwap_parsed_packet* packet, struc capwap_sessionid_generate(&g_wtp.sessionid); #ifdef DEBUG - capwap_sessionid_printf(&g_wtp.sessionid, sessionname); - capwap_logging_debug("Create WTP sessionid: %s", sessionname); + do { + char sessionname[33]; + + capwap_sessionid_printf(&g_wtp.sessionid, sessionname); + capwap_logging_debug("Create WTP sessionid: %s", sessionname); + } while (0); #endif /* Build packet */ @@ -116,35 +81,54 @@ int wtp_dfa_state_dtlsconnect_to_join(struct capwap_parsed_packet* packet, struc g_wtp.dfa.rfcRetransmitCount = 0; capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); wtp_dfa_change_state(CAPWAP_JOIN_STATE); - status = WTP_DFA_ACCEPT_PACKET; } else { /* Error to send packets */ capwap_logging_debug("Warning: error to send join request packet"); wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE); + wtp_teardown_connection(timeout); } - - return status; } /* */ -int wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int status = WTP_DFA_ACCEPT_PACKET; - +void wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { + unsigned short binding; + struct capwap_acdescriptor_element* acdescriptor; + struct capwap_acname_element* acname; + struct capwap_resultcode_element* resultcode; + ASSERT(timeout != NULL); if (packet) { - unsigned short binding; - - /* */ binding = GET_WBID_HEADER(packet->rxmngpacket->header); if (packet->rxmngpacket->isctrlpacket && (binding == g_wtp.binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_RESPONSE) && ((g_wtp.localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { /* Valid packet, free request packet */ wtp_free_reference_last_request(); - /* Parsing response values */ - wtp_dfa_change_state(wtp_join_ac(packet)); - status = WTP_DFA_NO_PACKET; + /* 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 Join Response with error: %d", (int)resultcode->code); + wtp_teardown_connection(timeout); + } else { + /* TODO: gestione richiesta CAPWAP_IMAGE_DATA_STATE <-> CAPWAP_CONFIGURE_STATE */ + + /* Check DTLS data policy */ + acdescriptor = (struct capwap_acdescriptor_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ACDESCRIPTION); + if (g_wtp.validdtlsdatapolicy & acdescriptor->dtlspolicy) { + /* AC name associated */ + acname = (struct capwap_acname_element*)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_ACNAME); + g_wtp.acname.name = (uint8_t*)capwap_duplicate_string((const char*)acname->name); + + /* DTLS data policy */ + g_wtp.dtlsdatapolicy = acdescriptor->dtlspolicy & g_wtp.validdtlsdatapolicy; + + /* Send configuration packet */ + wtp_send_configure(timeout); + } else { + capwap_logging_warning("Receive Join Response with invalid DTLS data policy"); + wtp_teardown_connection(timeout); + } + } } } else { /* No Join response received */ @@ -152,8 +136,7 @@ int wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_contr if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { /* Timeout join state */ wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; + wtp_teardown_connection(timeout); } else { /* Retransmit join request */ if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { @@ -164,115 +147,4 @@ int wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_contr capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } } - - return status; -} - -/* */ -int wtp_dfa_state_join_to_configure(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int i; - struct capwap_header_data capwapheader; - struct capwap_packet_txmng* txmngpacket; - int status = WTP_DFA_NO_PACKET; - - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - /* Build packet */ - capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); - txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_REQUEST, g_wtp.localseqnumber++, g_wtp.mtu); - - /* Add message element */ - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_wtp.acname); - wtp_create_radioadmstate_element(txmngpacket); - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_STATISTICSTIMER, &g_wtp.statisticstimer); - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPREBOOTSTAT, &g_wtp.rebootstat); - /* CAPWAP_ELEMENT_ACNAMEPRIORITY */ /* TODO */ - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &g_wtp.transport); - /* CAPWAP_ELEMENT_WTPSTATICIPADDRESS */ /* TODO */ - - if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - for (i = 0; i < g_wtp.radios->count; i++) { - struct wtp_radio* radio = (struct wtp_radio*)capwap_array_get_item_pointer(g_wtp.radios, i); - - /* Set message element */ - if ((radio->status == WTP_RADIO_ENABLED) && radio->radioinformation.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &radio->radioinformation); - - if (radio->radioinformation.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_ANTENNA, &radio->antenna); - } - - if (radio->directsequencecontrol.radioid && (radio->radioinformation.radiotype & (CAPWAP_RADIO_TYPE_80211B | CAPWAP_RADIO_TYPE_80211G))) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL, &radio->directsequencecontrol); - } - - if (radio->macoperation.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MACOPERATION, &radio->macoperation); - } - - if (radio->multidomaincapability.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY, &radio->multidomaincapability); - } - - if (radio->ofdmcontrol.radioid && (radio->radioinformation.radiotype & CAPWAP_RADIO_TYPE_80211A)) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_OFDMCONTROL, &radio->ofdmcontrol); - } - - if (radio->supportedrates.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_SUPPORTEDRATES, &radio->supportedrates); - } - - if (radio->txpower.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWER, &radio->txpower); - } - - if (radio->txpowerlevel.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_TXPOWERLEVEL, &radio->txpowerlevel); - } - - if (radio->radioconfig.radioid) { - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTP_RADIO_CONF, &radio->radioconfig); - } - } else { - struct capwap_80211_wtpradioinformation_element element = { (uint8_t)radio->radioid, 0 }; - capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &element); - } - } - } - - /* CAPWAP_ELEMENT_VENDORPAYLOAD */ /* TODO */ - - /* Configuration Status request complete, get fragment packets */ - wtp_free_reference_last_request(); - capwap_packet_txmng_get_fragment_packets(txmngpacket, g_wtp.requestfragmentpacket, g_wtp.fragmentid); - if (g_wtp.requestfragmentpacket->count > 1) { - g_wtp.fragmentid++; - } - - /* Free packets manager */ - capwap_packet_txmng_free(txmngpacket); - - /* Send Configuration Status request to AC */ - if (capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - g_wtp.dfa.rfcRetransmitCount = 0; - capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - wtp_dfa_change_state(CAPWAP_CONFIGURE_STATE); - status = WTP_DFA_ACCEPT_PACKET; - } else { - /* Error to send packets */ - capwap_logging_debug("Warning: error to send configuration status request packet"); - wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE); - } - - return status; -} - -/* */ -int wtp_dfa_state_join_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(packet == NULL); - ASSERT(timeout != NULL); - - return wtp_teardown_connection(timeout); } diff --git a/src/wtp/wtp_dfa_reset.c b/src/wtp/wtp_dfa_reset.c index 3a7eff5..91aa34e 100644 --- a/src/wtp/wtp_dfa_reset.c +++ b/src/wtp/wtp_dfa_reset.c @@ -3,9 +3,9 @@ #include "wtp_dfa.h" /* */ -int wtp_dfa_state_reset(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(packet == NULL); +void wtp_dfa_state_reset(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); - return wtp_teardown_connection(timeout); + /* TODO */ + wtp_teardown_connection(timeout); } diff --git a/src/wtp/wtp_dfa_run.c b/src/wtp/wtp_dfa_run.c index 5fa27e3..638634b 100644 --- a/src/wtp/wtp_dfa_run.c +++ b/src/wtp/wtp_dfa_run.c @@ -99,9 +99,7 @@ static void receive_reset_request(struct capwap_parsed_packet* packet) { } /* */ -int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - int status = WTP_DFA_ACCEPT_PACKET; - +void wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); if (packet) { @@ -154,8 +152,8 @@ int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_contro case CAPWAP_RESET_REQUEST: { receive_reset_request(packet); + capwap_set_timeout(0, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); wtp_dfa_change_state(CAPWAP_RESET_STATE); - status = WTP_DFA_NO_PACKET; break; } @@ -188,8 +186,7 @@ int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_contro if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { /* Timeout run state */ wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; + wtp_teardown_connection(timeout); } else { /* Retransmit request */ if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.requestfragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { @@ -207,8 +204,7 @@ int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_contro g_wtp.dfa.rfcRetransmitCount = 0; capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } else { - wtp_dfa_change_state(CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; + wtp_teardown_connection(timeout); } } else if (capwap_is_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVE)) { struct capwap_list* txfragpacket; @@ -234,13 +230,11 @@ int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_contro } else { /* Error to send packets */ capwap_logging_debug("Warning: error to send data channel keepalive packet"); - wtp_dfa_change_state(CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; + wtp_teardown_connection(timeout); } } else { capwap_logging_debug("Warning: error to send data channel keepalive packet, fragment packet"); - wtp_dfa_change_state(CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; + wtp_teardown_connection(timeout); } /* Free packets manager */ @@ -249,18 +243,7 @@ int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_contro } else if (capwap_is_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD)) { /* Data Keep-Alive timeout */ capwap_kill_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); - wtp_dfa_change_state(CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); - status = WTP_DFA_NO_PACKET; + wtp_teardown_connection(timeout); } } - - return status; -} - -/* */ -int wtp_dfa_state_run_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(packet == NULL); - ASSERT(timeout != NULL); - - return wtp_teardown_connection(timeout); } diff --git a/src/wtp/wtp_dfa_sulking.c b/src/wtp/wtp_dfa_sulking.c index 14d5351..1f22ee6 100644 --- a/src/wtp/wtp_dfa_sulking.c +++ b/src/wtp/wtp_dfa_sulking.c @@ -3,25 +3,16 @@ #include "wtp_dfa.h" /* */ -int wtp_dfa_state_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { +void wtp_dfa_state_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - wtp_dfa_change_state(CAPWAP_SULKING_TO_IDLE_STATE); - return WTP_DFA_NO_PACKET; -} - -/* */ -int wtp_dfa_state_sulking_to_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { - ASSERT(timeout != NULL); - ASSERT(packet == NULL); - - g_wtp.dfa.rfcDiscoveryCount = 0; - g_wtp.dfa.rfcFailedDTLSSessionCount = 0; - g_wtp.dfa.rfcFailedDTLSAuthFailCount = 0; - - wtp_dfa_change_state(CAPWAP_IDLE_STATE); - - return WTP_DFA_NO_PACKET; + if (!packet) { + g_wtp.dfa.rfcDiscoveryCount = 0; + g_wtp.dfa.rfcFailedDTLSSessionCount = 0; + g_wtp.dfa.rfcFailedDTLSAuthFailCount = 0; + + /* */ + capwap_set_timeout(0, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + wtp_dfa_change_state(CAPWAP_IDLE_STATE); + } }