diff --git a/src/ac/ac.c b/src/ac/ac.c index 07620cb..3323199 100644 --- a/src/ac/ac.c +++ b/src/ac/ac.c @@ -22,11 +22,11 @@ static int ac_init(void) { g_ac.binding = capwap_array_create(sizeof(unsigned short), 0); /* Standard name */ - strcpy(g_ac.acname.name, AC_STANDARD_NAME); + strcpy((char*)g_ac.acname.name, AC_STANDARD_NAME); /* Descriptor */ g_ac.descriptor.stationlimit = AC_DEFAULT_MAXSTATION; - g_ac.descriptor.wtplimit = AC_DEFAULT_MAXSESSIONS; + g_ac.descriptor.maxwtp = AC_DEFAULT_MAXSESSIONS; g_ac.descriptor.security = 0; g_ac.descriptor.rmacfield = CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED; g_ac.descriptor.dtlspolicy = CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED; @@ -44,8 +44,8 @@ static int ac_init(void) { g_ac.dfa.wtpfallback.mode = AC_DEFAULT_WTP_FALLBACK_MODE; /* */ - g_ac.dfa.acipv4list = capwap_array_create(sizeof(struct capwap_acipv4list_element), 0); - g_ac.dfa.acipv6list = capwap_array_create(sizeof(struct capwap_acipv6list_element), 0); + g_ac.dfa.acipv4list.addresses = capwap_array_create(sizeof(struct in_addr), 0); + g_ac.dfa.acipv6list.addresses = capwap_array_create(sizeof(struct in6_addr), 0); /* */ g_ac.dfa.rfcWaitJoin = AC_DEFAULT_WAITJOIN_INTERVAL; @@ -72,8 +72,8 @@ static void ac_destroy(void) { capwap_array_free(g_ac.binding); /* */ - capwap_array_free(g_ac.dfa.acipv4list); - capwap_array_free(g_ac.dfa.acipv6list); + capwap_array_free(g_ac.dfa.acipv4list.addresses); + capwap_array_free(g_ac.dfa.acipv6list.addresses); /* Sessions */ capwap_list_free(g_ac.sessions); @@ -152,7 +152,7 @@ static int ac_parsing_configuration_1_0(config_t* config) { return 0; } - strcpy(g_ac.acname.name, configString); + strcpy((char*)g_ac.acname.name, configString); } /* Set binding of AC */ @@ -190,7 +190,7 @@ static int ac_parsing_configuration_1_0(config_t* config) { /* Set max wtp of AC */ if (config_lookup_int(config, "application.descriptor.maxwtp", &configLongInt) == CONFIG_TRUE) { if ((configLongInt > 0) && (configLongInt < 65536)) { - g_ac.descriptor.wtplimit = (unsigned short)configLongInt; + g_ac.descriptor.maxwtp = (unsigned short)configLongInt; } else { capwap_logging_error("Invalid configuration file, unknown application.descriptor.maxwtp value"); return 0; @@ -266,7 +266,7 @@ static int ac_parsing_configuration_1_0(config_t* config) { desc->vendor = (unsigned long)configVendor; desc->type = type; desc->length = lengthValue; - strcpy(desc->data, configValue); + strcpy((char*)desc->data, configValue); } else { capwap_logging_error("Invalid configuration file, application.descriptor.info.value string length exceeded"); return 0; diff --git a/src/ac/ac.h b/src/ac/ac.h index 3bdc460..c19a6f7 100644 --- a/src/ac/ac.h +++ b/src/ac/ac.h @@ -55,8 +55,8 @@ struct ac_state { struct capwap_wtpfallback_element wtpfallback; /* */ - capwap_acipv4list_element_array* acipv4list; - capwap_acipv6list_element_array* acipv6list; + struct capwap_acipv4list_element acipv4list; + struct capwap_acipv6list_element acipv6list; /* */ int rfcWaitJoin; diff --git a/src/ac/ac_dfa_configure.c b/src/ac/ac_dfa_configure.c index 8657db3..9f2bbd4 100644 --- a/src/ac/ac_dfa_configure.c +++ b/src/ac/ac_dfa_configure.c @@ -4,115 +4,73 @@ #include "ac_session.h" /* */ -int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet) { unsigned long i; + unsigned short binding; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; int status = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); if (packet) { - struct capwap_build_packet* buildpacket; - - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - unsigned short binding; + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + /* TODO: gestione richiesta */ - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CONFIGURATION_STATUS_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) { - struct capwap_element_configurationstatus_request configurationstatusrequest; - - /* Configuration Status request info*/ - capwap_init_element_configurationstatus_request(&configurationstatusrequest, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_configurationstatus_request(&configurationstatusrequest, buildpacket->elementslist->first)) { - struct capwap_build_packet* responsepacket; + /* Create response */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CONFIGURATION_STATUS_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu); - /* TODO: gestione richiesta */ + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TIMERS, &session->dfa.timers); - /* Create response */ - responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding); - responsepacket->isctrlmsg = 1; + for (i = 0; i < packet->messageelements.radioadmstate->count; i++) { + struct capwap_decrypterrorreportperiod_element report; + struct capwap_radioadmstate_element* radioadm = *(struct capwap_radioadmstate_element**)capwap_array_get_item_pointer(packet->messageelements.radioadmstate, i); - /* Prepare configuration status response */ - capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CONFIGURATION_STATUS_RESPONSE, buildpacket->ctrlmsg.seq); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TIMERS_ELEMENT(&session->dfa.timers)); - - for (i = 0; i < configurationstatusrequest.radioadmstatus->count; i++) { - struct capwap_decrypterrorreportperiod_element report; - struct capwap_radioadmstate_element* radioadm = (struct capwap_radioadmstate_element*)capwap_array_get_item_pointer(configurationstatusrequest.radioadmstatus, i); - - report.radioid = radioadm->radioid; - report.interval = session->dfa.decrypterrorreport_interval; - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_DECRYPTERRORREPORTPERIOD_ELEMENT(&report)); - } - - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_IDLETIMEOUT_ELEMENT(&session->dfa.idletimeout)); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_WTPFALLBACK_ELEMENT(&session->dfa.wtpfallback)); - - if (session->dfa.acipv4list->count > 0) { - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV4LIST_ELEMENT(session->dfa.acipv4list)); - } - - if (session->dfa.acipv6list->count > 0) { - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV6LIST_ELEMENT(session->dfa.acipv6list)); - } - - /* CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT */ /* TODO */ - /* CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT */ /* TODO */ - /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - - if (!capwap_build_packet_validate(responsepacket, NULL)) { - int result; - - /* Free old reference for this request */ - ac_free_reference_last_response(session); - - /* Send configuration status response to WTP */ - result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid); - if (result >= 0) { - if (result == 1) { - session->fragmentid++; - } - - /* Save remote sequence number */ - session->remoteseqnumber = buildpacket->ctrlmsg.seq; - capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash); - - /* Send */ - for (i = 0; i < session->responsefragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) { - /* Response is already created and saved. When receive a re-request, DFA autoresponse */ - capwap_logging_debug("Warning: error to send configuration status response packet"); - break; - } - } - - /* Change status */ - ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE); - capwap_set_timeout(session->dfa.rfcChangeStatePendingTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - } - } else { - capwap_logging_debug("Warning: build invalid configuration status response packet"); - } - - /* Free memory */ - capwap_build_packet_free(responsepacket); - } - - /* Free */ - capwap_free_element_configurationstatus_request(&configurationstatusrequest, binding); - } - } - - /* Free */ - capwap_build_packet_free(buildpacket); + report.radioid = radioadm->radioid; + report.interval = session->dfa.decrypterrorreport_interval; + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD, &report); } + + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_IDLETIMEOUT, &session->dfa.idletimeout); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPFALLBACK, &session->dfa.wtpfallback); + + if (session->dfa.acipv4list.addresses->count > 0) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV4LIST, &session->dfa.acipv4list); + } + + if (session->dfa.acipv6list.addresses->count > 0) { + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACIPV6LIST, &session->dfa.acipv6list); + } + + /* CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT */ /* TODO */ + /* CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT */ /* TODO */ + /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ + + /* Configure response complete, get fragment packets */ + ac_free_reference_last_response(session); + capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid); + if (session->responsefragmentpacket->count > 1) { + session->fragmentid++; + } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Save remote sequence number */ + session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq; + capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash); + + /* Send Configure response to WTP */ + if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) { + /* Response is already created and saved. When receive a re-request, DFA autoresponse */ + capwap_logging_debug("Warning: error to send configuration status response packet"); + } + + /* Change state */ + ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE); + capwap_set_timeout(session->dfa.rfcChangeStatePendingTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } else { /* Configure timeout */ ac_dfa_change_state(session, CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE); @@ -123,6 +81,6 @@ int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* p } /* */ -int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { return ac_session_teardown_connection(session); } diff --git a/src/ac/ac_dfa_datacheck.c b/src/ac/ac_dfa_datacheck.c index c42aeea..8576d38 100644 --- a/src/ac/ac_dfa_datacheck.c +++ b/src/ac/ac_dfa_datacheck.c @@ -4,91 +4,48 @@ #include "ac_session.h" /* */ -int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet) { - unsigned long i; +int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet) { + unsigned short binding; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; int status = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); if (packet) { - struct capwap_build_packet* buildpacket; - - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - unsigned short binding; + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + /* TODO: gestione richiesta */ - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CHANGE_STATE_EVENT_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) { - struct capwap_element_changestateevent_request changeeventrequest; - - /* Change event request info */ - capwap_init_element_changestateevent_request(&changeeventrequest, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_changestateevent_request(&changeeventrequest, buildpacket->elementslist->first)) { - struct capwap_build_packet* responsepacket; + /* Create response */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu); - /* TODO: gestione richiesta */ + /* Add message element */ + /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - /* Create response */ - responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding); - responsepacket->isctrlmsg = 1; - - /* Prepare change event response */ - capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, buildpacket->ctrlmsg.seq); - /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - - if (!capwap_build_packet_validate(responsepacket, NULL)) { - int result; - - /* Free old reference for this request */ - ac_free_reference_last_response(session); - - /* Send change event response to WTP */ - result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid); - if (result >= 0) { - if (result == 1) { - session->fragmentid++; - } - - /* Save remote sequence number */ - session->remoteseqnumber = buildpacket->ctrlmsg.seq; - capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash); - - /* Send */ - for (i = 0; i < session->responsefragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) { - /* Response is already created and saved. When receive a re-request, DFA autoresponse */ - capwap_logging_debug("Warning: error to send change event response packet"); - break; - } - } - - /* Change status */ - ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE); - capwap_set_timeout(session->dfa.rfcDataCheckTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - } - } else { - capwap_logging_debug("Warning: build invalid configuration status response packet"); - } - - /* Free memory */ - capwap_build_packet_free(responsepacket); - } - - /* Free */ - capwap_free_element_changestateevent_request(&changeeventrequest, binding); - } - } - - /* Free */ - capwap_build_packet_free(buildpacket); + /* Change event response complete, get fragment packets */ + ac_free_reference_last_response(session); + capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid); + if (session->responsefragmentpacket->count > 1) { + session->fragmentid++; } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Save remote sequence number */ + session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq; + capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash); + + /* Send Change event response to WTP */ + if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) { + /* Response is already created and saved. When receive a re-request, DFA autoresponse */ + capwap_logging_debug("Warning: error to send change event response packet"); + } + + /* Change state */ + ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE); + capwap_set_timeout(session->dfa.rfcDataCheckTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } else { /* Configure timeout */ ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); @@ -99,59 +56,54 @@ int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* p } /* */ -int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) { + struct capwap_list* txfragpacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; int status = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); if (packet) { /* Wait Data Channel Keep-Alive packet */ - if (!packet->socket.isctrlsocket) { - struct capwap_build_packet* buildpacket; - - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - struct capwap_sessionid_element sessionid; - - if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) { - if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) { - int result; - capwap_fragment_packet_array* txfragpacket; - - /* Receive data packet keepalive, response with same packet */ - txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0); - if (!result) { - struct capwap_packet* txpacket; - - ASSERT(txfragpacket->count == 1); - - txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) { - capwap_logging_debug("Warning: error to send data channel keepalive packet"); - result = -1; - } - } - - /* */ - capwap_fragment_free(txfragpacket); - capwap_array_free(txfragpacket); - - if (!result) { - /* Capwap handshake complete */ - ac_dfa_change_state(session, CAPWAP_RUN_STATE); - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - } else { - ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); - status = AC_DFA_NO_PACKET; - } + if (!packet->rxmngpacket->isctrlpacket && IS_FLAG_K_HEADER(packet->rxmngpacket->header)) { + if (!memcmp(packet->messageelements.sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) { + int result = 0; + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header)); + capwap_header_set_keepalive_flag(&capwapheader, 1); + txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, session->mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_SESSIONID, &session->sessionid); + + /* Data keepalive complete, get fragment packets into local list */ + txfragpacket = capwap_list_create(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, 0); + if (txfragpacket->count == 1) { + /* Send Data keepalive to WTP */ + if (capwap_crypt_sendto_fragmentpacket(&session->datadtls, session->datasocket.socket[session->datasocket.type], txfragpacket, &session->acdataaddress, &session->wtpdataaddress)) { + result = 1; + } else { + capwap_logging_debug("Warning: error to send data channel keepalive packet"); } + } else { + capwap_logging_debug("Warning: error to send data channel keepalive packet, fragment packet"); + } + + /* Free packets manager */ + capwap_list_free(txfragpacket); + capwap_packet_txmng_free(txmngpacket); + + if (result) { + /* Capwap handshake complete */ + ac_dfa_change_state(session, CAPWAP_RUN_STATE); + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + } else { + ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); + status = AC_DFA_NO_PACKET; } - - /* Free */ - capwap_build_packet_free(buildpacket); } } } else { @@ -164,6 +116,6 @@ int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_pa } /* */ -int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { return ac_session_teardown_connection(session); } diff --git a/src/ac/ac_dfa_dtls.c b/src/ac/ac_dfa_dtls.c index f2a37c5..78e7e30 100644 --- a/src/ac/ac_dfa_dtls.c +++ b/src/ac/ac_dfa_dtls.c @@ -14,7 +14,7 @@ int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param) } /* */ -int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int status = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); @@ -37,7 +37,7 @@ int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* p } /* */ -int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_parsed_packet* packet) { ASSERT(session != NULL); ASSERT(packet == NULL); @@ -46,6 +46,6 @@ int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* } /* */ -int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { return ac_session_teardown_connection(session); } diff --git a/src/ac/ac_dfa_imagedata.c b/src/ac/ac_dfa_imagedata.c index afb7d5a..d76ccb9 100644 --- a/src/ac/ac_dfa_imagedata.c +++ b/src/ac/ac_dfa_imagedata.c @@ -4,7 +4,7 @@ #include "ac_session.h" /* */ -int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int status = AC_DFA_ACCEPT_PACKET; /* TODO */ @@ -13,6 +13,6 @@ int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* p } /* */ -int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { return ac_session_teardown_connection(session); } diff --git a/src/ac/ac_dfa_join.c b/src/ac/ac_dfa_join.c index 99eaf57..4fdeefc 100644 --- a/src/ac/ac_dfa_join.c +++ b/src/ac/ac_dfa_join.c @@ -4,227 +4,130 @@ #include "ac_session.h" /* */ -int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int i; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; int status = AC_DFA_ACCEPT_PACKET; - struct capwap_resultcode_element resultcode = { CAPWAP_RESULTCODE_FAILURE }; - struct capwap_build_packet* responsepacket; + struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_FAILURE }; ASSERT(session != NULL); if (packet) { - struct capwap_build_packet* buildpacket; - - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - int validpacket; - unsigned long checkpacket; - struct capwap_array* returnedmessagearray = NULL; - capwap_unrecognized_element_array* unrecognizedarray; - struct capwap_element_join_request joinrequest; - unsigned short binding = GET_WBID_HEADER(&buildpacket->header); + unsigned short binding; - /* */ - unrecognizedarray = capwap_array_create(sizeof(struct unrecognized_info), 0); - - /* */ - checkpacket = capwap_build_packet_validate(buildpacket, unrecognizedarray); - if (!checkpacket) { - if (ac_valid_binding(binding)) { - if (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_JOIN_REQUEST) { - resultcode.code = CAPWAP_RESULTCODE_SUCCESS; - } else { - resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE; - } - } else { - resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED; - } + /* Check binding */ + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + if (ac_valid_binding(binding)) { + if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_JOIN_REQUEST) { + resultcode.code = CAPWAP_RESULTCODE_SUCCESS; + + /* Get sessionid */ + memcpy(&session->sessionid, packet->messageelements.sessionid, sizeof(struct capwap_sessionid_element)); + + /* Get binding */ + session->binding = binding; } else { - if ((checkpacket & CAPWAP_MISSING_MANDATORY_MSG_ELEMENT) != 0) { - resultcode.code = CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT; - } else if ((checkpacket & CAPWAP_UNRECOGNIZED_MSG_ELEMENT) != 0) { - struct capwap_list_item* itemelement; - - resultcode.code = CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT; - returnedmessagearray = capwap_array_create(sizeof(struct capwap_returnedmessage_element), unrecognizedarray->count); + resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE; + } + } else { + resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED; + } - for (i = 0; i < unrecognizedarray->count; i++) { - struct unrecognized_info* reasoninfo = capwap_array_get_item_pointer(unrecognizedarray, i); - - /* Search element */ - itemelement = buildpacket->elementslist->first; - while (itemelement != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)itemelement->item; - - if (ntohs(elementitem->type) == reasoninfo->element) { - struct capwap_returnedmessage_element* returnedelement = capwap_array_get_item_pointer(returnedmessagearray, i); - unsigned short length = sizeof(struct capwap_message_element) + ntohs(elementitem->length); + /* Create response */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_JOIN_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu); - returnedelement->reason = reasoninfo->reason; - returnedelement->length = min(length, CAPWAP_RETURNED_MESSAGE_MAX_LENGTH); - memcpy(&returnedelement->message[0], elementitem, returnedelement->length); - - break; - } - - /* Next */ - itemelement = itemelement->next; - } - } + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); + + /* Check is valid packet after parsing request */ + if ((resultcode.code == CAPWAP_RESULTCODE_SUCCESS) || (resultcode.code == CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED)) { + struct capwap_list* controllist; + struct capwap_list_item* item; + + /* Update statistics */ + ac_update_statistics(); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname); + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + for (i = 0; i < packet->messageelements.ieee80211.wtpradioinformation->count; i++) { + struct capwap_80211_wtpradioinformation_element* radio; + + radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(packet->messageelements.ieee80211.wtpradioinformation, i); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, radio); } } - /* */ - capwap_array_free(unrecognizedarray); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ECNSUPPORT, &session->dfa.ecn); - /* */ - capwap_init_element_join_request(&joinrequest, binding); - if (resultcode.code == CAPWAP_RESULTCODE_SUCCESS) { - /* Parsing elements list */ - if (capwap_parsing_element_join_request(&joinrequest, buildpacket->elementslist->first)) { - /* TODO: gestione richiesta */ + /* Get information from any local address */ + controllist = capwap_list_create(); + ac_get_control_information(controllist); + + for (item = controllist->first; item != NULL; item = item->next) { + struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item; + + if (sessioncontrol->localaddress.ss_family == AF_INET) { + struct capwap_controlipv4_element element; + + memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr)); + element.wtpcount = sessioncontrol->count; + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element); + } else if (sessioncontrol->localaddress.ss_family == AF_INET6) { + struct capwap_controlipv6_element element; - /* Get sessionid */ - memcpy(&session->sessionid, joinrequest.sessionid, sizeof(struct capwap_sessionid_element)); - - /* Get binding */ - session->binding = binding; - - resultcode.code = CAPWAP_RESULTCODE_SUCCESS; + memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr)); + element.wtpcount = sessioncontrol->count; + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element); } } - - /* Create response */ - responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding); - responsepacket->isctrlmsg = 1; - /* Prepare join response */ - capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_JOIN_RESPONSE, buildpacket->ctrlmsg.seq); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RESULTCODE_ELEMENT(&resultcode)); + capwap_list_free(controllist); - /* Check is valid packet after parsing request */ - validpacket = (((resultcode.code == CAPWAP_RESULTCODE_SUCCESS) || (resultcode.code == CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED)) ? 1 : 0); - if (validpacket) { - struct capwap_list* controllist; - struct capwap_list_item* item; - - /* Update statistics */ - ac_update_statistics(); - - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor)); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname)); + if (session->acctrladdress.ss_family == AF_INET) { + struct capwap_localipv4_element addr; - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - for (i = 0; i < joinrequest.binding.ieee80211.wtpradioinformation->count; i++) { - struct capwap_80211_wtpradioinformation_element* radio; - - radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(joinrequest.binding.ieee80211.wtpradioinformation, i); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio)); - } - } else { - capwap_logging_debug("Unknown capwap binding"); - } - - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ECNSUPPORT_ELEMENT(&session->dfa.ecn)); + memcpy(&addr.address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV4, &addr); + } else if (session->acctrladdress.ss_family == AF_INET6) { + struct capwap_localipv6_element addr; - /* Get information from any local address */ - controllist = capwap_list_create(); - ac_get_control_information(controllist); - - for (item = controllist->first; item != NULL; item = item->next) { - struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item; - - if (sessioncontrol->localaddress.ss_family == AF_INET) { - struct capwap_controlipv4_element element; - - memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr)); - element.wtpcount = sessioncontrol->count; - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element)); - } else if (sessioncontrol->localaddress.ss_family == AF_INET6) { - struct capwap_controlipv6_element element; - - memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr)); - element.wtpcount = sessioncontrol->count; - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element)); - } - } - - capwap_list_free(controllist); - - if (session->acctrladdress.ss_family == AF_INET) { - struct capwap_localipv4_element addr; - - memcpy(&addr.address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr)); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV4_ELEMENT(&addr)); - } else if (session->acctrladdress.ss_family == AF_INET6) { - struct capwap_localipv6_element addr; - - memcpy(&addr.address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr)); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV6_ELEMENT(&addr)); - } - - /* CAPWAP_CREATE_ACIPV4LIST_ELEMENT */ /* TODO */ - /* CAPWAP_CREATE_ACIPV6LIST_ELEMENT */ /* TODO */ - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TRANSPORT_ELEMENT(&session->dfa.transport)); - /* CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT */ /* TODO */ - /* CAPWAP_CREATE_MAXIMUMMESSAGELENGTH_ELEMENT */ /* TODO */ - /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - } else if (resultcode.code == CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT) { - ASSERT(returnedmessagearray != NULL); - - for (i = 0; i < returnedmessagearray->count; i++) { - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RETURNEDMESSAGE_ELEMENT(capwap_array_get_item_pointer(returnedmessagearray, i))); - } - - capwap_array_free(returnedmessagearray); + memcpy(&addr.address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV6, &addr); } - /* Validate packet */ - if (!validpacket || !capwap_build_packet_validate(responsepacket, NULL)) { - int result; - - /* Free old reference for this request */ - ac_free_reference_last_response(session); + /* CAPWAP_CREATE_ACIPV4LIST_ELEMENT */ /* TODO */ + /* CAPWAP_CREATE_ACIPV6LIST_ELEMENT */ /* TODO */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &session->dfa.transport); + /* CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT */ /* TODO */ + /* CAPWAP_CREATE_MAXIMUMMESSAGELENGTH_ELEMENT */ /* TODO */ + /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ + } - /* Send join response to WTP */ - result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid); - if (result >= 0) { - if (result == 1) { - session->fragmentid++; - } + /* Join response complete, get fragment packets */ + ac_free_reference_last_response(session); + capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid); + if (session->responsefragmentpacket->count > 1) { + session->fragmentid++; + } - /* Save remote sequence number */ - session->remoteseqnumber = buildpacket->ctrlmsg.seq; - capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash); + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); - /* Send */ - for (i = 0; i < session->responsefragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) { - /* Response is already created and saved. When receive a re-request, DFA autoresponse */ - capwap_logging_debug("Warning: error to send join response packet"); - break; - } - } - } - } else { - capwap_logging_debug("Warning: build invalid join response packet"); - } + /* Save remote sequence number */ + session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq; + capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash); - /* Free memory */ - capwap_build_packet_free(responsepacket); - capwap_free_element_join_request(&joinrequest, binding); - capwap_build_packet_free(buildpacket); - - /* Change state */ - if (validpacket) { - ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE); - } else { - ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE); - status = AC_DFA_NO_PACKET; - } + /* Send Join response to WTP */ + if (capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) { + ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE); + } else { + /* Error to send packets */ + capwap_logging_debug("Warning: error to send join response packet"); + ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE); + status = AC_DFA_NO_PACKET; } } else { /* Join timeout */ @@ -236,26 +139,21 @@ int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet } /* */ -int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int status = AC_DFA_ACCEPT_PACKET; - + ASSERT(session != NULL); - + if (packet) { - unsigned short lengthpayload; - - lengthpayload = packet->packetsize - GET_HLEN_HEADER(packet->header) * 4; - if (lengthpayload >= sizeof(struct capwap_control_message)) { - struct capwap_control_message* ctrlmsg = (struct capwap_control_message*)packet->payload; - unsigned long type = ntohl(ctrlmsg->type); - - if (type == CAPWAP_CONFIGURATION_STATUS_REQUEST) { - ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE); - status = ac_dfa_state_configure(session, packet); - } else if (type == CAPWAP_IMAGE_DATA_REQUEST) { - ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE); - status = ac_dfa_state_imagedata(session, packet); - } + if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_CONFIGURATION_STATUS_REQUEST) { + ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE); + status = ac_dfa_state_configure(session, packet); + } else if (packet->rxmngpacket->ctrlmsg.type == CAPWAP_IMAGE_DATA_REQUEST) { + ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE); + status = ac_dfa_state_imagedata(session, packet); + } else { + ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE); + status = AC_DFA_NO_PACKET; } } else { /* Join timeout */ @@ -267,6 +165,6 @@ int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* pa } /* */ -int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { return ac_session_teardown_connection(session); } diff --git a/src/ac/ac_dfa_reset.c b/src/ac/ac_dfa_reset.c index 02b8976..8753608 100644 --- a/src/ac/ac_dfa_reset.c +++ b/src/ac/ac_dfa_reset.c @@ -4,69 +4,34 @@ #include "ac_session.h" /* */ -int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int status = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); if (packet) { - if (!capwap_compare_ip(&session->wtpctrladdress, &packet->remoteaddr)) { - struct capwap_build_packet* buildpacket; + unsigned short binding; - /* Parsing packet */ - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - unsigned short binding; - - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if ((binding == session->binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) { - struct capwap_element_reset_response resetresponse; - - /* Valid packet, free request packet */ - ac_free_reference_last_request(session); - - /* Configuration status response info */ - capwap_init_element_reset_response(&resetresponse, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_reset_response(&resetresponse, buildpacket->elementslist->first)) { - ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE); - status = AC_DFA_NO_PACKET; - } - - /* Free join response */ - capwap_free_element_reset_response(&resetresponse, binding); - } - } - - /* Free */ - capwap_build_packet_free(buildpacket); - } + /* */ + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + if ((binding == session->binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { + ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE); + status = AC_DFA_NO_PACKET; } } else { - int i; - /* No Configuration status response received */ session->dfa.rfcRetransmitCount++; if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) { - /* Timeout join state */ + /* Timeout reset state */ ac_free_reference_last_request(session); ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE); status = AC_DFA_NO_PACKET; } else { /* Retransmit configuration request */ - for (i = 0; i < session->requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) { - capwap_logging_debug("Warning: error to send configuration status request packet"); - break; - } + if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->requestfragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) { + capwap_logging_debug("Warning: error to resend reset request packet"); } - + /* Update timeout */ capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } @@ -76,6 +41,6 @@ int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packe } /* */ -int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { return ac_session_teardown_connection(session); } diff --git a/src/ac/ac_dfa_run.c b/src/ac/ac_dfa_run.c index 1ebea6b..884a18a 100644 --- a/src/ac/ac_dfa_run.c +++ b/src/ac/ac_dfa_run.c @@ -4,185 +4,148 @@ #include "ac_session.h" /* */ -static int receive_echo_request(struct ac_session_t* session, struct capwap_build_packet* buildpacket, struct capwap_packet* packet) { - unsigned long i; - unsigned short binding; +static int receive_echo_request(struct ac_session_t* session, struct capwap_parsed_packet* packet) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; ASSERT(session != NULL); - ASSERT(buildpacket != NULL); ASSERT(packet != NULL); - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if (ac_valid_binding(binding) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) { - struct capwap_element_echo_request echorequest; - - /* Echo request info*/ - capwap_init_element_echo_request(&echorequest, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_echo_request(&echorequest, buildpacket->elementslist->first)) { - struct capwap_build_packet* responsepacket; + /* Create response */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header)); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_ECHO_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, session->mtu); - /* Create response */ - responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding); - responsepacket->isctrlmsg = 1; + /* Add message element */ + /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - /* Prepare echo response */ - capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_ECHO_RESPONSE, buildpacket->ctrlmsg.seq); - /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ + /* Echo response complete, get fragment packets */ + ac_free_reference_last_response(session); + capwap_packet_txmng_get_fragment_packets(txmngpacket, session->responsefragmentpacket, session->fragmentid); + if (session->responsefragmentpacket->count > 1) { + session->fragmentid++; + } - if (!capwap_build_packet_validate(responsepacket, NULL)) { - int result; - - /* Free old reference for this request */ - ac_free_reference_last_response(session); + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); - /* Send echo response to WTP */ - result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid); - if (result >= 0) { - if (result == 1) { - session->fragmentid++; - } + /* Save remote sequence number */ + session->remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq; + capwap_get_packet_digest(packet->rxmngpacket, packet->connection, session->lastrecvpackethash); - /* Save remote sequence number */ - session->remoteseqnumber = buildpacket->ctrlmsg.seq; - capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash); - - /* Send */ - for (i = 0; i < session->responsefragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) { - /* Response is already created and saved. When receive a re-request, DFA autoresponse */ - capwap_logging_debug("Warning: error to send echo response packet"); - break; - } - } - } - } - - /* Free memory */ - capwap_build_packet_free(responsepacket); - } - - /* Free */ - capwap_free_element_echo_request(&echorequest, binding); + /* Send Configure response to WTP */ + if (!capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) { + /* Response is already created and saved. When receive a re-request, DFA autoresponse */ + capwap_logging_debug("Warning: error to send echo response packet"); } return 0; } /* */ -int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet) { +static int ac_send_data_keepalive(struct ac_session_t* session, struct capwap_parsed_packet* packet) { + struct capwap_list* txfragpacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + int result = -1; + + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->rxmngpacket->header)); + capwap_header_set_keepalive_flag(&capwapheader, 1); + txmngpacket = capwap_packet_txmng_create_data_message(&capwapheader, session->mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_SESSIONID, &session->sessionid); + + /* Data keepalive complete, get fragment packets into local list */ + txfragpacket = capwap_list_create(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, txfragpacket, 0); + if (txfragpacket->count == 1) { + /* Send Data keepalive to WTP */ + if (capwap_crypt_sendto_fragmentpacket(&session->datadtls, session->datasocket.socket[session->datasocket.type], txfragpacket, &session->acdataaddress, &session->wtpdataaddress)) { + result = 0; + } else { + capwap_logging_debug("Warning: error to send data channel keepalive packet"); + } + } else { + capwap_logging_debug("Warning: error to send data channel keepalive packet, fragment packet"); + } + + /* Free packets manager */ + capwap_list_free(txfragpacket); + capwap_packet_txmng_free(txmngpacket); + + return result; +} + +/* */ +int ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int status = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); if (packet) { - struct capwap_build_packet* buildpacket; - - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - if (packet->socket.isctrlsocket) { - unsigned long typemsg = ntohl(buildpacket->ctrlmsg.type); - - if (capwap_is_request_type(typemsg) || ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) { - switch (typemsg) { - case CAPWAP_CONFIGURATION_UPDATE_REQUEST: { - /* TODO */ - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - break; - } - - case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: { - /* TODO */ - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - break; - } - - case CAPWAP_ECHO_REQUEST: { - if (!receive_echo_request(session, buildpacket, packet)) { - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - } else { - ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); - status = AC_DFA_NO_PACKET; - } - - break; - } - - case CAPWAP_CLEAR_CONFIGURATION_REQUEST: { - /* TODO */ - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - break; - } - - case CAPWAP_WTP_EVENT_RESPONSE: { - /* TODO */ - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - break; - } - - case CAPWAP_DATA_TRANSFER_REQUEST: { - /* TODO */ - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - break; - } - - case CAPWAP_DATA_TRANSFER_RESPONSE: { - /* TODO */ - capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - break; - } - } - } - } else { - if (IS_FLAG_K_HEADER(&buildpacket->header)) { - struct capwap_sessionid_element sessionid; - - if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) { - if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) { - int result; - capwap_fragment_packet_array* txfragpacket; - - /* Receive data packet keepalive, response with same packet */ - txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0); - if (!result) { - struct capwap_packet* txpacket; - - ASSERT(txfragpacket->count == 1); - - txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) { - capwap_logging_debug("Warning: error to send data channel keepalive packet"); - result = -1; - } - } - - /* */ - capwap_fragment_free(txfragpacket); - capwap_array_free(txfragpacket); - - if (result) { - ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); - status = AC_DFA_NO_PACKET; - } - } - } - } else { + if (packet->rxmngpacket->isctrlpacket) { + if (capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type) || ((session->localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { + switch (packet->rxmngpacket->ctrlmsg.type) { + case CAPWAP_CONFIGURATION_UPDATE_REQUEST: { /* TODO */ + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + break; + } + + case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: { + /* TODO */ + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + break; + } + + case CAPWAP_ECHO_REQUEST: { + if (!receive_echo_request(session, packet)) { + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + } else { + ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); + status = AC_DFA_NO_PACKET; + } + + break; + } + + case CAPWAP_CLEAR_CONFIGURATION_REQUEST: { + /* TODO */ + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + break; + } + + case CAPWAP_WTP_EVENT_RESPONSE: { + /* TODO */ + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + break; + } + + case CAPWAP_DATA_TRANSFER_REQUEST: { + /* TODO */ + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + break; + } + + case CAPWAP_DATA_TRANSFER_RESPONSE: { + /* TODO */ + capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + break; } } } - - /* Free */ - capwap_build_packet_free(buildpacket); + } else { + if (IS_FLAG_K_HEADER(packet->rxmngpacket->header)) { + if (!memcmp(packet->messageelements.sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) { + if (ac_send_data_keepalive(session, packet)) { + ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); + status = AC_DFA_NO_PACKET; + } + } + } else { + /* TODO */ + } } } else { ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); @@ -193,71 +156,49 @@ int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet) } /* */ -int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int status = AC_DFA_NO_PACKET; - struct capwap_build_packet* buildpacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; ASSERT(session != NULL); ASSERT(packet == NULL); /* Build packet */ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, session->binding); - buildpacket->isctrlmsg = 1; - - /* Prepare reset request */ - capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_RESET_REQUEST, session->localseqnumber++); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT(&session->startupimage)); + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, session->binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_RESET_REQUEST, session->localseqnumber++, session->mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_IMAGEIDENTIFIER, &session->startupimage); /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - if (!capwap_build_packet_validate(buildpacket, NULL)) { - int i; - int result; - - /* Free old reference for this request */ - ac_free_reference_last_request(session); - - /* Send reset request to WTP */ - result = capwap_fragment_build_packet(buildpacket, session->requestfragmentpacket, session->mtu, session->fragmentid); - if (result >= 0) { - if (result == 1) { - session->fragmentid++; - } - - /* Send */ - for (i = 0; i < session->requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) { - capwap_logging_debug("Warning: error to send reset request packet"); - result = -1; - break; - } - } - } - - if (result == -1) { - /* Error to send packets */ - ac_free_reference_last_request(session); - ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE); - } else { - session->dfa.rfcRetransmitCount = 0; - - capwap_killall_timeout(&session->timeout); - capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - - ac_dfa_change_state(session, CAPWAP_RESET_STATE); - status = AC_DFA_ACCEPT_PACKET; - } + /* Reset request complete, get fragment packets */ + ac_free_reference_last_request(session); + capwap_packet_txmng_get_fragment_packets(txmngpacket, session->requestfragmentpacket, session->fragmentid); + if (session->requestfragmentpacket->count > 1) { + session->fragmentid++; + } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Send Configure response to WTP */ + if (capwap_crypt_sendto_fragmentpacket(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], session->requestfragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) { + session->dfa.rfcRetransmitCount = 0; + capwap_killall_timeout(&session->timeout); + capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + ac_dfa_change_state(session, CAPWAP_RESET_STATE); + status = AC_DFA_ACCEPT_PACKET; + } else { + capwap_logging_debug("Warning: error to send reset request packet"); + ac_free_reference_last_request(session); + ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE); } - - /* Free memory */ - capwap_build_packet_free(buildpacket); return status; } /* */ -int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { return ac_session_teardown_connection(session); } diff --git a/src/ac/ac_dfa_teardown.c b/src/ac/ac_dfa_teardown.c index 1fc5377..dda1d0e 100644 --- a/src/ac/ac_dfa_teardown.c +++ b/src/ac/ac_dfa_teardown.c @@ -4,7 +4,7 @@ #include "ac_session.h" /* */ -int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_parsed_packet* packet) { ASSERT(session != NULL); ASSERT(packet == NULL); @@ -14,7 +14,7 @@ int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* pa } /* */ -int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet) { +int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_parsed_packet* packet) { ASSERT(session != NULL); ASSERT(packet == NULL); diff --git a/src/ac/ac_discovery.c b/src/ac/ac_discovery.c index 20c04cc..c1b9013 100644 --- a/src/ac/ac_discovery.c +++ b/src/ac/ac_discovery.c @@ -88,44 +88,39 @@ void ac_discovery_add_packet(void* buffer, int buffersize, int sock, struct sock } /* */ -static struct capwap_build_packet* ac_create_discovery_response(struct capwap_build_packet* packet, struct capwap_element_discovery_request* discoveryrequest, struct sockaddr_storage* sender) { +static struct capwap_packet_txmng* ac_create_discovery_response(struct capwap_parsed_packet* packet) { int i; unsigned short binding; struct capwap_list* controllist; struct capwap_list_item* item; - struct capwap_build_packet* responsepacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; ASSERT(packet != NULL); - ASSERT(discoveryrequest != NULL); - ASSERT(sender != NULL); /* Check is valid binding */ - binding = GET_WBID_HEADER(&packet->header); + binding = GET_WBID_HEADER(packet->rxmngpacket->header); if (!ac_valid_binding(binding)) { return NULL; } - /* Build packet */ - responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding); - responsepacket->isctrlmsg = 1; - /* Update statistics */ ac_update_statistics(); - - /* Prepare discovery response */ - capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_DISCOVERY_RESPONSE, packet->ctrlmsg.seq); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor)); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname)); + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_DISCOVERY_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, g_ac.mtu); + + /* Prepare discovery response */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACDESCRIPTION, &g_ac.descriptor); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ACNAME, &g_ac.acname); if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - for (i = 0; i < discoveryrequest->binding.ieee80211.wtpradioinformation->count; i++) { + for (i = 0; i < packet->messageelements.ieee80211.wtpradioinformation->count; i++) { struct capwap_80211_wtpradioinformation_element* radio; - radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(discoveryrequest->binding.ieee80211.wtpradioinformation, i); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio)); + radio = *(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(packet->messageelements.ieee80211.wtpradioinformation, i); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, radio); } - } else { - capwap_logging_debug("Unknown capwap binding"); } /* Get information from any local address */ @@ -137,24 +132,24 @@ static struct capwap_build_packet* ac_create_discovery_response(struct capwap_bu if (sessioncontrol->localaddress.ss_family == AF_INET) { struct capwap_controlipv4_element element; - + memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr)); element.wtpcount = sessioncontrol->count; - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV4, &element); } else if (sessioncontrol->localaddress.ss_family == AF_INET6) { struct capwap_controlipv6_element element; - + memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr)); element.wtpcount = sessioncontrol->count; - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_CONTROLIPV6, &element); } } - capwap_list_free(controllist); - + capwap_list_free(controllist); + /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - return responsepacket; + return txmngpacket; } /* Cleanup info discovery */ @@ -167,21 +162,21 @@ static void ac_discovery_cleanup(void) { static void ac_discovery_run(void) { int sizedata; struct capwap_list_item* itempacket; - struct capwap_build_packet* buildpacket; - struct ac_discovery_packet* packet; - unsigned short binding; - + struct ac_discovery_packet* acpacket; + struct capwap_parsed_packet packet; + struct capwap_packet_rxmng* rxmngpacket; + while (!g_ac_discovery.endthread) { /* Get packet */ capwap_lock_enter(&g_ac_discovery.packetslock); - + itempacket = NULL; if (g_ac_discovery.packets->count > 0) { itempacket = capwap_itemlist_remove_head(g_ac_discovery.packets); } - + capwap_lock_exit(&g_ac_discovery.packetslock); - + if (!itempacket) { /* Wait packet with timeout*/ if (!capwap_event_wait_timeout(&g_ac_discovery.waitpacket, AC_DISCOVERY_CLEANUP_TIMEOUT)) { @@ -190,74 +185,56 @@ static void ac_discovery_run(void) { continue; } - + /* */ - packet = (struct ac_discovery_packet*)itempacket->item; + acpacket = (struct ac_discovery_packet*)itempacket->item; sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet); - /* Parsing packet */ - buildpacket = capwap_rx_packet_create(packet->data, sizedata, 1); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - struct capwap_element_discovery_request discoveryrequest; - - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - capwap_init_element_discovery_request(&discoveryrequest, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_discovery_request(&discoveryrequest, buildpacket->elementslist->first)) { - struct capwap_build_packet* txpacket; - capwap_fragment_packet_array* responsefragmentpacket = NULL; + /* Accept only discovery request don't fragment */ + rxmngpacket = capwap_packet_rxmng_create_message(1); + if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, acpacket->data, sizedata) == CAPWAP_RECEIVE_COMPLETE_PACKET) { + /* Validate message */ + if (capwap_check_message_type(rxmngpacket) == VALID_MESSAGE_TYPE) { + /* Parsing packet */ + if (!capwap_parsing_packet(rxmngpacket, NULL, &packet)) { + /* Validate packet */ + if (!capwap_validate_parsed_packet(&packet, NULL)) { + struct capwap_packet_txmng* txmngpacket; - /* Creare discovery response */ - txpacket = ac_create_discovery_response(buildpacket, &discoveryrequest, &packet->sender); - if (txpacket) { - int result = -1; - - if (!capwap_build_packet_validate(txpacket, NULL)) { - responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - result = capwap_fragment_build_packet(txpacket, responsefragmentpacket, g_ac.mtu, g_ac_discovery.fragmentid); - if (result == 1) { + /* Creare discovery response */ + txmngpacket = ac_create_discovery_response(&packet); + if (txmngpacket) { + struct capwap_list* responsefragmentpacket; + + /* Discovery response complete, get fragment packets */ + responsefragmentpacket = capwap_list_create(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, responsefragmentpacket, g_ac_discovery.fragmentid); + if (responsefragmentpacket->count > 1) { g_ac_discovery.fragmentid++; } - } else { - capwap_logging_debug("Warning: build invalid discovery response packet"); - } - - capwap_build_packet_free(txpacket); - - /* Send discovery response to WTP */ - if (result >= 0) { - int i; - - for (i = 0; i < responsefragmentpacket->count; i++) { - struct capwap_packet* sendpacket = (struct capwap_packet*)capwap_array_get_item_pointer(responsefragmentpacket, i); - ASSERT(sendpacket != NULL); - - if (!capwap_sendto(packet->sendsock, sendpacket->header, sendpacket->packetsize, NULL, &packet->sender)) { - capwap_logging_debug("Warning: error to send discovery response packet"); - break; - } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Send discovery response to WTP */ + if (!capwap_sendto_fragmentpacket(acpacket->sendsock, responsefragmentpacket, NULL, &acpacket->sender)) { + capwap_logging_debug("Warning: error to send discovery response packet"); } + + /* Don't buffering a packets sent */ + capwap_list_free(responsefragmentpacket); } } - - /* Don't buffering a packets sent */ - if (responsefragmentpacket) { - capwap_fragment_free(responsefragmentpacket); - capwap_array_free(responsefragmentpacket); - } } - - /* Free discovery request */ - capwap_free_element_discovery_request(&discoveryrequest, binding); + + /* Free resource */ + capwap_free_parsed_packet(&packet); } - - /* */ - capwap_build_packet_free(buildpacket); } + /* Free resource */ + capwap_packet_rxmng_free(rxmngpacket); + /* Free packet */ capwap_itemlist_free(itempacket); } diff --git a/src/ac/ac_execute.c b/src/ac/ac_execute.c index 5bd4e48..1405631 100644 --- a/src/ac/ac_execute.c +++ b/src/ac/ac_execute.c @@ -58,44 +58,68 @@ static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_st /* */ static struct ac_session_t* ac_get_session_from_keepalive(void* buffer, int buffersize) { + struct capwap_parsed_packet packet; + struct capwap_packet_rxmng* rxmngpacket; struct ac_session_t* result = NULL; - struct capwap_build_packet* buildpacket; ASSERT(buffer != NULL); ASSERT(buffersize > 0); - buildpacket = capwap_rx_packet_create(buffer, buffersize, 0); - if (buildpacket) { - struct capwap_sessionid_element sessionid; - - if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) { + /* Build receive manager CAPWAP message */ + rxmngpacket = capwap_packet_rxmng_create_message(0); + if (capwap_packet_rxmng_add_recv_packet(rxmngpacket, buffer, buffersize) != CAPWAP_RECEIVE_COMPLETE_PACKET) { + /* Accept only keep alive without fragmentation */ + capwap_packet_rxmng_free(rxmngpacket); + capwap_logging_debug("Receive data keep alive packet fragmentated"); + return NULL; + } + + /* Validate message */ + if (capwap_check_message_type(rxmngpacket) != VALID_MESSAGE_TYPE) { + /* Invalid message */ + capwap_packet_rxmng_free(rxmngpacket); + capwap_logging_debug("Invalid data packet message type"); + return NULL; + } + + /* Parsing packet */ + if (!capwap_parsing_packet(rxmngpacket, NULL, &packet)) { + /* Validate packet */ + if (!capwap_validate_parsed_packet(&packet, NULL)) { struct capwap_list_item* search; + ASSERT(packet.messageelements.sessionid != NULL); + capwap_lock_enter(&g_ac.sessionslock); - + search = g_ac.sessions->first; while (search != NULL) { struct ac_session_t* session = (struct ac_session_t*)search->item; + ASSERT(session != NULL); - - if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) { + + if (!memcmp(packet.messageelements.sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) { session->count++; result = session; break; } - - search = search->next; + + search = search->next; } - + capwap_lock_exit(&g_ac.sessionslock); + } else { + capwap_logging_debug("Failed validation parsed data packet"); } - - /* Free */ - capwap_build_packet_free(buildpacket); + } else { + capwap_logging_debug("Failed parsing data packet"); } - - return result; + /* Free resource */ + capwap_free_parsed_packet(&packet); + capwap_packet_rxmng_free(rxmngpacket); + + return result; } /* Close session */ @@ -117,7 +141,7 @@ static void ac_close_sessions() { ac_close_session(session); - search = search->next; + search = search->next; } capwap_lock_exit(&g_ac.sessionslock); @@ -246,7 +270,7 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres int result; struct capwap_list_item* itemlist; struct ac_session_t* session; - + ASSERT(acaddress != NULL); ASSERT(wtpaddress != NULL); ASSERT(ctrlsock != NULL); @@ -263,37 +287,36 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres /* Duplicate state for DFA */ memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state)); - session->dfa.acipv4list = capwap_array_clone(g_ac.dfa.acipv4list); - session->dfa.acipv6list = capwap_array_clone(g_ac.dfa.acipv6list); + session->dfa.acipv4list.addresses = capwap_array_clone(g_ac.dfa.acipv4list.addresses); + session->dfa.acipv6list.addresses = capwap_array_clone(g_ac.dfa.acipv6list.addresses); session->dfa.rfcRetransmitInterval = AC_DEFAULT_RETRANSMIT_INTERVAL; session->dfa.rfcMaxRetransmit = AC_MAX_RETRANSMIT; session->dfa.rfcDTLSSessionDelete = AC_DEFAULT_DTLS_SESSION_DELETE; /* Add default AC list if empty*/ - if ((session->dfa.acipv4list->count == 0) && (session->dfa.acipv6list->count == 0)) { + if ((session->dfa.acipv4list.addresses->count == 0) && (session->dfa.acipv6list.addresses->count == 0)) { if (session->acctrladdress.ss_family == AF_INET) { - struct capwap_acipv4list_element* acip = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(session->dfa.acipv4list, 0); - memcpy(&acip->address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr)); + struct in_addr* acip = (struct in_addr*)capwap_array_get_item_pointer(session->dfa.acipv4list.addresses, 0); + memcpy(acip, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr)); } else if (session->acctrladdress.ss_family == AF_INET6) { - struct capwap_acipv6list_element* acip = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(session->dfa.acipv6list, 0); - memcpy(&acip->address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr)); + struct in6_addr* acip = (struct in6_addr*)capwap_array_get_item_pointer(session->dfa.acipv6list.addresses, 0); + memcpy(acip, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr)); } } - + /* Init */ capwap_event_init(&session->waitpacket); capwap_lock_init(&session->packetslock); session->controlpackets = capwap_list_create(); session->datapackets = capwap_list_create(); - session->requestfragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - session->responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - session->rxfragmentpacket = capwap_defragment_init_list(); - + session->requestfragmentpacket = capwap_list_create(); + session->responsefragmentpacket = capwap_list_create(); + session->mtu = g_ac.mtu; session->state = CAPWAP_IDLE_STATE; - + /* Update session list */ capwap_lock_enter(&g_ac.sessionslock); capwap_itemlist_insert_after(g_ac.sessions, NULL, itemlist); @@ -323,10 +346,10 @@ static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddres /* Update statistics */ void ac_update_statistics(void) { - g_ac.descriptor.station = 0; /* TODO */ + g_ac.descriptor.stations = 0; /* TODO */ capwap_lock_enter(&g_ac.sessionslock); - g_ac.descriptor.wtp = g_ac.sessions->count; + g_ac.descriptor.activewtp = g_ac.sessions->count; capwap_lock_exit(&g_ac.sessionslock); } @@ -344,7 +367,7 @@ int ac_execute(void) { int result = CAPWAP_SUCCESSFUL; int index; - int check; + int check; int isctrlsocket = 0; struct sockaddr_storage recvfromaddr; struct sockaddr_storage recvtoaddr; @@ -400,15 +423,15 @@ int ac_execute(void) { if (getsockname(fds[index].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) { break; } - + CAPWAP_SET_NETWORK_PORT(&recvtoaddr, CAPWAP_GET_NETWORK_PORT(&sockinfo)); } } - + /* Search the AC session */ isctrlsocket = ((index < (fdscount / 2)) ? 1 : 0); session = ac_search_session_from_wtpaddress(&recvfromaddr, isctrlsocket); - + if (session) { /* Add packet*/ ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 0); @@ -418,38 +441,38 @@ int ac_execute(void) { } else { if (isctrlsocket) { unsigned short sessioncount; - + /* Get current session number */ capwap_lock_enter(&g_ac.sessionslock); sessioncount = g_ac.sessions->count; capwap_lock_exit(&g_ac.sessionslock); - + /* PreParsing packet for reduce a DoS attack */ check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, buffersize, g_ac.enabledtls, 0); if (check == CAPWAP_PLAIN_PACKET) { struct capwap_header* header = (struct capwap_header*)buffer; - + /* Accepted only packet without fragmentation */ if (!IS_FLAG_F_HEADER(header)) { int headersize = GET_HLEN_HEADER(header) * 4; if (buffersize >= (headersize + sizeof(struct capwap_control_message))) { struct capwap_control_message* control = (struct capwap_control_message*)((char*)buffer + headersize); unsigned long type = ntohl(control->type); - + if (type == CAPWAP_DISCOVERY_REQUEST) { - if (sessioncount < g_ac.descriptor.wtplimit) { + if (sessioncount < g_ac.descriptor.maxwtp) { ac_discovery_add_packet(buffer, buffersize, fds[index].fd, &recvfromaddr); } } else if (!g_ac.enabledtls && (type == CAPWAP_JOIN_REQUEST)) { - if (sessioncount < g_ac.descriptor.wtplimit) { + if (sessioncount < g_ac.descriptor.maxwtp) { /* Retrive socket info */ capwap_get_network_socket(&g_ac.net, &ctrlsock, fds[index].fd); - + /* Create a new session */ session = ac_create_session(&recvfromaddr, &recvtoaddr, &ctrlsock); if (session) { ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 1); - + /* Release reference */ ac_session_release_reference(session); } @@ -459,7 +482,7 @@ int ac_execute(void) { } } else if (check == CAPWAP_DTLS_PACKET) { /* Need create a new sessione for check if it is a valid DTLS handshake */ - if (sessioncount < g_ac.descriptor.wtplimit) { + if (sessioncount < g_ac.descriptor.maxwtp) { /* TODO prevent dos attack add filtering ip for multiple error */ /* Retrive socket info */ @@ -512,7 +535,7 @@ int ac_execute(void) { /* Wait that list is changed */ capwap_logging_debug("Waiting for %d session terminate", count); - capwap_event_wait(&g_ac.changesessionlist); + capwap_event_wait(&g_ac.changesessionlist); } /* Free handshark session */ diff --git a/src/ac/ac_session.c b/src/ac/ac_session.c index 2d11a88..a9984fa 100644 --- a/src/ac/ac_session.c +++ b/src/ac/ac_session.c @@ -27,6 +27,11 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt struct capwap_list_item* itempacket; *isctrlpacket = ((session->controlpackets->count > 0) ? 1 : 0); + if (*isctrlpacket) { + capwap_logging_debug("Receive control packet"); + } else { + capwap_logging_debug("Receive data packet"); + } /* Get packet */ itempacket = capwap_itemlist_remove_head((*isctrlpacket ? session->controlpackets : session->datapackets)); @@ -70,7 +75,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt return result; } - + capwap_lock_exit(&session->packetslock); /* Update timeout */ @@ -88,7 +93,7 @@ static int ac_network_read(struct ac_session_t* session, void* buffer, int lengt } /* */ -static int ac_dfa_execute(struct ac_session_t* session, struct capwap_packet* packet) { +static int ac_dfa_execute(struct ac_session_t* session, struct capwap_parsed_packet* packet) { int action = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); @@ -366,12 +371,47 @@ static int ac_dfa_execute(struct ac_session_t* session, struct capwap_packet* pa return action; } +/* */ +static struct capwap_packet_rxmng* ac_get_packet_rxmng(struct ac_session_t* session, int isctrlmsg) { + struct capwap_packet_rxmng* rxmngpacket = NULL; + + if (isctrlmsg) { + if (!session->rxmngctrlpacket) { + session->rxmngctrlpacket = capwap_packet_rxmng_create_message(1); + } + + rxmngpacket = session->rxmngctrlpacket; + } else { + if (!session->rxmngdatapacket) { + session->rxmngdatapacket = capwap_packet_rxmng_create_message(0); + } + + rxmngpacket = session->rxmngdatapacket; + } + + return rxmngpacket; +} + +/* */ +static void ac_free_packet_rxmng(struct ac_session_t* session, int isctrlmsg) { + if (isctrlmsg && session->rxmngctrlpacket) { + capwap_packet_rxmng_free(session->rxmngctrlpacket); + session->rxmngctrlpacket = NULL; + } else if (!isctrlmsg && session->rxmngdatapacket) { + capwap_packet_rxmng_free(session->rxmngdatapacket); + session->rxmngdatapacket = NULL; + } +} + +/* */ static void ac_session_run(struct ac_session_t* session) { + int res; int check; int length; int isctrlsocket; - int action = AC_DFA_ACCEPT_PACKET; + struct capwap_connection connection; char buffer[CAPWAP_MAX_PACKET_SIZE]; + int action = AC_DFA_ACCEPT_PACKET; ASSERT(session != NULL); @@ -402,35 +442,66 @@ static void ac_session_run(struct ac_session_t* session) { /* Check generic capwap packet */ check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, length, 0, 0); if (check == CAPWAP_PLAIN_PACKET) { - struct capwap_packet packet; - - check = capwap_defragment_packets(&session->wtpctrladdress, buffer, length, session->rxfragmentpacket, &packet); + struct capwap_parsed_packet packet; + struct capwap_packet_rxmng* rxmngpacket; + + /* Defragment management */ + rxmngpacket = ac_get_packet_rxmng(session, isctrlsocket); + + /* If request, defragmentation packet */ + check = capwap_packet_rxmng_add_recv_packet(rxmngpacket, buffer, length); if (check == CAPWAP_RECEIVE_COMPLETE_PACKET) { int ignorepacket = 0; - + + /* Receive all fragment */ + memcpy(&connection.socket, (isctrlsocket ? &session->ctrlsocket : &session->datasocket), sizeof(struct capwap_socket)); + memcpy(&connection.localaddr, (isctrlsocket ? &session->acctrladdress : &session->acdataaddress), sizeof(struct sockaddr_storage)); + memcpy(&connection.remoteaddr, (isctrlsocket ? &session->wtpctrladdress : &session->wtpdataaddress), sizeof(struct sockaddr_storage)); + if (isctrlsocket) { - /* Check for already response to packet */ - if (capwap_recv_retrasmitted_request(&session->ctrldtls, &packet, session->remoteseqnumber, session->lastrecvpackethash, &session->ctrlsocket, session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) { - ignorepacket = 1; - } - - /* Check message type */ - if (!capwap_check_message_type(&session->ctrldtls, &packet, session->mtu)) { + if (!capwap_recv_retrasmitted_request(&session->ctrldtls, rxmngpacket, &connection, session->lastrecvpackethash, session->responsefragmentpacket)) { + /* Check message type */ + res = capwap_check_message_type(rxmngpacket); + if (res != VALID_MESSAGE_TYPE) { + if (res == INVALID_REQUEST_MESSAGE_TYPE) { + /*TODO wtp_send_invalid_request(rxmngpacket, &connection);*/ + } + + ignorepacket = 1; + capwap_logging_debug("Invalid message type"); + } + } else { ignorepacket = 1; + capwap_logging_debug("Retrasmitted packet"); } } - + + /* Parsing packet */ + if (!ignorepacket) { + if (!capwap_parsing_packet(rxmngpacket, &connection, &packet)) { + /* Validate packet */ + if (capwap_validate_parsed_packet(&packet, NULL)) { + /* TODO gestione errore risposta */ + ignorepacket = 1; + capwap_logging_debug("Failed validation parsed packet"); + } + } else { + ignorepacket = 1; + capwap_logging_debug("Failed parsing packet"); + } + } + /* */ if (!ignorepacket && (action == AC_DFA_ACCEPT_PACKET)) { - memcpy(&packet.socket, (isctrlsocket ? &session->ctrlsocket : &session->datasocket), sizeof(struct capwap_socket)); action = ac_dfa_execute(session, &packet); } - - /* Free packet */ - capwap_free_packet(&packet); + + /* Free memory */ + capwap_free_parsed_packet(&packet); + ac_free_packet_rxmng(session, isctrlsocket); } else if (check != CAPWAP_REQUEST_MORE_FRAGMENT) { /* Discard fragments */ - capwap_defragment_remove_sender(session->rxfragmentpacket, &session->wtpctrladdress); + ac_free_packet_rxmng(session, isctrlsocket); } } } @@ -508,27 +579,27 @@ int ac_session_release_reference(struct ac_session_t* session) { capwap_lock_exit(&session->packetslock); capwap_list_free(session->controlpackets); capwap_list_free(session->datapackets); - capwap_defragment_free_list(session->rxfragmentpacket); /* Free fragments packet */ - capwap_fragment_free(session->requestfragmentpacket); - capwap_fragment_free(session->responsefragmentpacket); - capwap_array_free(session->requestfragmentpacket); - capwap_array_free(session->responsefragmentpacket); + ac_free_packet_rxmng(session, 1); + ac_free_packet_rxmng(session, 0); + + capwap_list_free(session->requestfragmentpacket); + capwap_list_free(session->responsefragmentpacket); /* Free DFA resource */ - capwap_array_free(session->dfa.acipv4list); - capwap_array_free(session->dfa.acipv6list); + capwap_array_free(session->dfa.acipv4list.addresses); + capwap_array_free(session->dfa.acipv6list.addresses); /* Remove item from list */ remove = 1; capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessions, search)); capwap_event_signal(&g_ac.changesessionlist); - + break; } - - search = search->next; + + search = search->next; } } @@ -547,7 +618,7 @@ void* ac_session_thread(void* param) { /* Thread exit */ pthread_exit(NULL); - return NULL; + return NULL; } /* */ @@ -596,22 +667,22 @@ void ac_get_control_information(struct capwap_list* controllist) { } } } - + /* */ - capwap_lock_exit(&g_ac.sessionslock); + capwap_lock_exit(&g_ac.sessionslock); } /* */ void ac_free_reference_last_request(struct ac_session_t* session) { ASSERT(session); - capwap_fragment_free(session->requestfragmentpacket); + capwap_list_flush(session->requestfragmentpacket); } /* */ void ac_free_reference_last_response(struct ac_session_t* session) { ASSERT(session); - capwap_fragment_free(session->responsefragmentpacket); + capwap_list_flush(session->responsefragmentpacket); memset(&session->lastrecvpackethash[0], 0, sizeof(session->lastrecvpackethash)); } diff --git a/src/ac/ac_session.h b/src/ac/ac_session.h index 75d2af6..337d120 100644 --- a/src/ac/ac_session.h +++ b/src/ac/ac_session.h @@ -51,9 +51,10 @@ struct ac_session_t { unsigned char remoteseqnumber; unsigned short mtu; unsigned short fragmentid; - capwap_fragment_list* rxfragmentpacket; - capwap_fragment_packet_array* requestfragmentpacket; - capwap_fragment_packet_array* responsefragmentpacket; + struct capwap_packet_rxmng* rxmngctrlpacket; + struct capwap_packet_rxmng* rxmngdatapacket; + struct capwap_list* requestfragmentpacket; + struct capwap_list* responsefragmentpacket; unsigned char lastrecvpackethash[16]; unsigned long state; @@ -73,40 +74,40 @@ void ac_free_reference_last_request(struct ac_session_t* session); void ac_free_reference_last_response(struct ac_session_t* session); /* */ -int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_join(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); /* */ int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param); -int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); /* */ -int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); /* */ -int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); /* */ -int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); /* */ -int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_run(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); /* */ -int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); /* */ -int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet); -int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet); +int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_parsed_packet* packet); +int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_parsed_packet* packet); #endif /* __AC_SESSION_HEADER__ */ diff --git a/src/common/capwap_dtls.c b/src/common/capwap_dtls.c index 1f317fe..b5b7394 100644 --- a/src/common/capwap_dtls.c +++ b/src/common/capwap_dtls.c @@ -295,6 +295,12 @@ int capwap_crypt_init() { /* */ void capwap_crypt_free() { + /* Clear error queue */ + ERR_clear_error(); + ERR_remove_state(0); + ERR_remove_thread_state(NULL); + + /* */ #ifdef CAPWAP_MULTITHREADING_ENABLE int i; int numlocks; @@ -313,20 +319,17 @@ void capwap_crypt_free() { capwap_free(l_mutex_buffer); l_mutex_buffer = NULL; - #endif /* */ - ERR_remove_state(0); ERR_free_strings(); - + RAND_cleanup(); ENGINE_cleanup(); EVP_cleanup(); - + OBJ_cleanup(); CONF_modules_finish(); CONF_modules_free(); CONF_modules_unload(1); - CRYPTO_cleanup_all_ex_data(); sk_SSL_COMP_free (SSL_COMP_get_compression_methods()); } @@ -637,7 +640,9 @@ int capwap_crypt_createsession(struct capwap_dtls* dtls, int sessiontype, struct /* */ SSL_set_read_ahead((SSL*)dtls->sslsession, 1); - + + /* */ + ERR_clear_error(); if (dtlscontext->type == CAPWAP_DTLS_SERVER) { SSL_set_accept_state((SSL*)dtls->sslsession); } else { @@ -706,7 +711,7 @@ int capwap_crypt_open(struct capwap_dtls* dtls, struct sockaddr_storage* peeradd void capwap_crypt_close(struct capwap_dtls* dtls) { ASSERT(dtls != NULL); ASSERT(dtls->enable != 0); - + if ((dtls->action == CAPWAP_DTLS_ACTION_DATA) || (dtls->action == CAPWAP_DTLS_ACTION_SHUTDOWN)) { SSL_shutdown((SSL*)dtls->sslsession); } @@ -751,7 +756,7 @@ void capwap_crypt_change_dtls(struct capwap_dtls* dtls, struct capwap_dtls* newd /* */ void capwap_crypt_freesession(struct capwap_dtls* dtls) { ASSERT(dtls != NULL); - + /* Free SSL session */ if (dtls->sslsession) { struct capwap_app_data* appdata = (struct capwap_app_data*)SSL_get_ex_data(dtls->sslsession, 0); @@ -761,7 +766,13 @@ void capwap_crypt_freesession(struct capwap_dtls* dtls) { SSL_free((SSL*)dtls->sslsession); } - + + /* */ + ERR_clear_error(); + ERR_remove_state(0); + ERR_remove_thread_state(NULL); + + /* */ memset(dtls, 0, sizeof(struct capwap_dtls)); } @@ -785,6 +796,31 @@ int capwap_crypt_sendto(struct capwap_dtls* dtls, int sock, void* buffer, int si return SSL_write((SSL*)dtls->sslsession, buffer, size); } +/* */ +int capwap_crypt_sendto_fragmentpacket(struct capwap_dtls* dtls, int sock, struct capwap_list* fragmentlist, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr) { + struct capwap_list_item* item; + + ASSERT(sock >= 0); + ASSERT(fragmentlist != NULL); + ASSERT(sendtoaddr != NULL); + + item = fragmentlist->first; + while (item) { + struct capwap_fragment_packet_item* fragmentpacket = (struct capwap_fragment_packet_item*)item->item; + ASSERT(fragmentpacket != NULL); + ASSERT(fragmentpacket->offset > 0); + + if (!capwap_crypt_sendto(dtls, sock, fragmentpacket->buffer, fragmentpacket->offset, sendfromaddr, sendtoaddr)) { + return 0; + } + + /* */ + item = item->next; + } + + return 1; +} + /* */ int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize) { int sslerror; diff --git a/src/common/capwap_dtls.h b/src/common/capwap_dtls.h index 883633a..f8a3b63 100644 --- a/src/common/capwap_dtls.h +++ b/src/common/capwap_dtls.h @@ -1,6 +1,8 @@ #ifndef __CAPWAP_DTLS_HEADER__ #define __CAPWAP_DTLS_HEADER__ +#include "capwap_list.h" + #define CAPWAP_DTLS_CLIENT 0 #define CAPWAP_DTLS_SERVER 1 @@ -106,6 +108,7 @@ void capwap_crypt_change_bio_send(struct capwap_dtls* dtls, capwap_bio_send bios void capwap_crypt_change_dtls(struct capwap_dtls* dtls, struct capwap_dtls* newdtls); int capwap_crypt_sendto(struct capwap_dtls* dtls, int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr); +int capwap_crypt_sendto_fragmentpacket(struct capwap_dtls* dtls, int sock, struct capwap_list* fragmentlist, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr); int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize); #endif /* __CAPWAP_DTLS_HEADER__ */ diff --git a/src/common/capwap_element.c b/src/common/capwap_element.c index 1a89fce..b728f55 100644 --- a/src/common/capwap_element.c +++ b/src/common/capwap_element.c @@ -3,1371 +3,832 @@ #include "capwap_protocol.h" #include "capwap_array.h" -static struct capwap_message_elements_func standard_message_elements[CAPWAP_MESSAGE_ELEMENTS_COUNT] = { - /* CAPWAP_ELEMENT_ACDESCRIPTION */ { capwap_acdescriptor_element_create, capwap_acdescriptor_element_validate, capwap_acdescriptor_element_parsing, capwap_acdescriptor_element_free }, - /* CAPWAP_ELEMENT_ACIPV4LIST */ { capwap_acipv4list_element_create, capwap_acipv4list_element_validate, capwap_acipv4list_element_parsing, capwap_acipv4list_element_free }, - /* CAPWAP_ELEMENT_ACIPV6LIST */ { capwap_acipv6list_element_create, capwap_acipv6list_element_validate, capwap_acipv6list_element_parsing, capwap_acipv6list_element_free }, - /* CAPWAP_ELEMENT_ACNAME */ { capwap_acname_element_create, capwap_acname_element_validate, capwap_acname_element_parsing, capwap_acname_element_free }, - /* CAPWAP_ELEMENT_ACNAMEPRIORITY */ { capwap_acnamepriority_element_create, capwap_acnamepriority_element_validate, capwap_acnamepriority_element_parsing, capwap_acnamepriority_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* Reserved */ { NULL, NULL }, - /* CAPWAP_ELEMENT_CONTROLIPV4 */ { capwap_controlipv4_element_create, capwap_controlipv4_element_validate, capwap_controlipv4_element_parsing, capwap_controlipv4_element_free }, - /* CAPWAP_ELEMENT_CONTROLIPV6 */ { capwap_controlipv6_element_create, capwap_controlipv6_element_validate, capwap_controlipv6_element_parsing, capwap_controlipv6_element_free }, - /* CAPWAP_ELEMENT_TIMERS */ { capwap_timers_element_create, capwap_timers_element_validate, capwap_timers_element_parsing, capwap_timers_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD */ { capwap_decrypterrorreportperiod_element_create, capwap_decrypterrorreportperiod_element_validate, capwap_decrypterrorreportperiod_element_parsing, capwap_decrypterrorreportperiod_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* Reserved */ { NULL, NULL }, - /* CAPWAP_ELEMENT_DISCOVERYTYPE */ { capwap_discoverytype_element_create, capwap_discoverytype_element_validate, capwap_discoverytype_element_parsing, capwap_discoverytype_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_IDLETIMEOUT */ { capwap_idletimeout_element_create, capwap_idletimeout_element_validate, capwap_idletimeout_element_parsing, capwap_idletimeout_element_free }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_IMAGEIDENTIFIER */ { capwap_imageidentifier_element_create, capwap_imageidentifier_element_validate, capwap_imageidentifier_element_parsing, capwap_imageidentifier_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_LOCATION */ { capwap_location_element_create, capwap_location_element_validate, capwap_location_element_parsing, capwap_location_element_free }, - /* CAPWAP_ELEMENT_MAXIMUMLENGTH */ { capwap_maximumlength_element_create, capwap_maximumlength_element_validate, capwap_maximumlength_element_parsing, capwap_maximumlength_element_free }, - /* CAPWAP_ELEMENT_LOCALIPV4 */ { capwap_localipv4_element_create, capwap_localipv4_element_validate, capwap_localipv4_element_parsing, capwap_localipv4_element_free }, - /* CAPWAP_ELEMENT_RADIOADMSTATE */ { capwap_radioadmstate_element_create, capwap_radioadmstate_element_validate, capwap_radioadmstate_element_parsing, capwap_radioadmstate_element_free }, - /* CAPWAP_ELEMENT_RADIOOPRSTATE */ { capwap_radiooprstate_element_create, capwap_radiooprstate_element_validate, capwap_radiooprstate_element_parsing, capwap_radiooprstate_element_free }, - /* CAPWAP_ELEMENT_RESULTCODE */ { capwap_resultcode_element_create, capwap_resultcode_element_validate, capwap_resultcode_element_parsing, capwap_resultcode_element_free }, - /* CAPWAP_ELEMENT_RETURNEDMESSAGE */ { capwap_returnedmessage_element_create, capwap_returnedmessage_element_validate, capwap_returnedmessage_element_parsing, capwap_returnedmessage_element_free }, - /* CAPWAP_ELEMENT_SESSIONID */ { capwap_sessionid_element_create, capwap_sessionid_element_validate, capwap_sessionid_element_parsing, capwap_sessionid_element_free }, - /* CAPWAP_ELEMENT_STATISTICSTIMER */ { capwap_statisticstimer_element_create, capwap_statisticstimer_element_validate, capwap_statisticstimer_element_parsing, capwap_statisticstimer_element_free }, - /* CAPWAP_ELEMENT_VENDORPAYLOAD */ { capwap_vendorpayload_element_create, capwap_vendorpayload_element_validate, capwap_vendorpayload_element_parsing, capwap_vendorpayload_element_free }, - /* CAPWAP_ELEMENT_WTPBOARDDATA */ { capwap_wtpboarddata_element_create, capwap_wtpboarddata_element_validate, capwap_wtpboarddata_element_parsing, capwap_wtpboarddata_element_free }, - /* CAPWAP_ELEMENT_WTPDESCRIPTOR */ { capwap_wtpdescriptor_element_create, capwap_wtpdescriptor_element_validate, capwap_wtpdescriptor_element_parsing, capwap_wtpdescriptor_element_free }, - /* CAPWAP_ELEMENT_WTPFALLBACK */ { capwap_wtpfallback_element_create, capwap_wtpfallback_element_validate, capwap_wtpfallback_element_parsing, capwap_wtpfallback_element_free }, - /* CAPWAP_ELEMENT_WTPFRAMETUNNELMODE */ { capwap_wtpframetunnelmode_element_create, capwap_wtpframetunnelmode_element_validate, capwap_wtpframetunnelmode_element_parsing, capwap_wtpframetunnelmode_element_free }, - /* Reserved */ { NULL, NULL }, - /* Reserved */ { NULL, NULL }, - /* CAPWAP_ELEMENT_WTPMACTYPE */ { capwap_wtpmactype_element_create, capwap_wtpmactype_element_validate, capwap_wtpmactype_element_parsing, capwap_wtpmactype_element_free }, - /* CAPWAP_ELEMENT_WTPNAME */ { capwap_wtpname_element_create, capwap_wtpname_element_validate, capwap_wtpname_element_parsing, capwap_wtpname_element_free }, - /* Reserved */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_WTPREBOOTSTAT */ { capwap_wtprebootstat_element_create, capwap_wtprebootstat_element_validate, capwap_wtprebootstat_element_parsing, capwap_wtprebootstat_element_free }, - /* CAPWAP_ELEMENT_WTPSTATICIPADDRESS */ { capwap_wtpstaticipaddress_element_create, capwap_wtpstaticipaddress_element_validate, capwap_wtpstaticipaddress_element_parsing, capwap_wtpstaticipaddress_element_free }, - /* CAPWAP_ELEMENT_LOCALIPV6 */ { capwap_localipv6_element_create, capwap_localipv6_element_validate, capwap_localipv6_element_parsing, capwap_localipv6_element_free }, - /* CAPWAP_ELEMENT_TRANSPORT */ { capwap_transport_element_create, capwap_transport_element_validate, capwap_transport_element_parsing, capwap_transport_element_free }, - /* CAPWAP_ELEMENT_MTUDISCOVERY */ { capwap_mtudiscovery_element_create, capwap_mtudiscovery_element_validate, capwap_mtudiscovery_element_parsing, capwap_mtudiscovery_element_free }, - /* CAPWAP_ELEMENT_ECNSUPPORT */ { capwap_ecnsupport_element_create, capwap_ecnsupport_element_validate, capwap_ecnsupport_element_parsing, capwap_ecnsupport_element_free }, -}; +/* Helper create parsed message element */ +#define PARSING_MESSAGE_ELEMENT(data) \ + if (data) { return 1; } \ + data = read_ops->parsing_message_element((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops); \ + if (!data) { return 1; } -static struct capwap_message_elements_func ieee80211_message_elements[CAPWAP_80211_MESSAGE_ELEMENTS_COUNT] = { - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_80211_ANTENNA */ { capwap_80211_antenna_element_create, capwap_80211_antenna_element_validate, capwap_80211_antenna_element_parsing, capwap_80211_antenna_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL */ { capwap_80211_dscontrol_element_create, capwap_80211_dscontrol_element_validate, capwap_80211_dscontrol_element_parsing, capwap_80211_dscontrol_element_free }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_80211_MACOPERATION */ { capwap_80211_macoperation_element_create, capwap_80211_macoperation_element_validate, capwap_80211_macoperation_element_parsing, capwap_80211_macoperation_element_free }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY */ { capwap_80211_multidomaincapability_element_create, capwap_80211_multidomaincapability_element_validate, capwap_80211_multidomaincapability_element_parsing, capwap_80211_multidomaincapability_element_free }, - /* CAPWAP_ELEMENT_80211_OFDMCONTROL */ { capwap_80211_ofdmcontrol_element_create, capwap_80211_ofdmcontrol_element_validate, capwap_80211_ofdmcontrol_element_parsing, capwap_80211_ofdmcontrol_element_free }, - /* CAPWAP_ELEMENT_80211_RATESET */ { capwap_80211_rateset_element_create, capwap_80211_rateset_element_validate, capwap_80211_rateset_element_parsing, capwap_80211_rateset_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_80211_SUPPORTEDRATES */ { capwap_80211_supportedrates_element_create, capwap_80211_supportedrates_element_validate, capwap_80211_supportedrates_element_parsing, capwap_80211_supportedrates_element_free }, - /* CAPWAP_ELEMENT_80211_TXPOWER */ { capwap_80211_txpower_element_create, capwap_80211_txpower_element_validate, capwap_80211_txpower_element_parsing, capwap_80211_txpower_element_free }, - /* CAPWAP_ELEMENT_80211_TXPOWERLEVEL */ { capwap_80211_txpowerlevel_element_create, capwap_80211_txpowerlevel_element_validate, capwap_80211_txpowerlevel_element_parsing, capwap_80211_txpowerlevel_element_free }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* */ { NULL, NULL }, - /* CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION */ { capwap_80211_wtpradioinformation_element_create, capwap_80211_wtpradioinformation_element_validate, capwap_80211_wtpradioinformation_element_parsing, capwap_80211_wtpradioinformation_element_free }, +#define ARRAY_PARSING_MESSAGE_ELEMENT(data, type) \ + type msgelement; \ + if (!data) { data = capwap_array_create(sizeof(type), 0); } \ + msgelement = read_ops->parsing_message_element((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops); \ + if (!msgelement) { return 1; } \ + memcpy(capwap_array_get_item_pointer(data, data->count), &msgelement, sizeof(type)); + +/* Helper free parsed message element */ +#define FREE_PARSED_MESSAGE_ELEMENT(type, data) \ + if (data) { \ + capwap_get_message_element_ops(type)->free_parsed_message_element(data); \ + data = NULL; \ + } + +#define FREE_ARRAY_PARSED_MESSAGE_ELEMENT(type, data) \ + if (data) { \ + unsigned long i; \ + for (i = 0; i < data->count; i++) { \ + capwap_get_message_element_ops(type)->free_parsed_message_element(*(void**)capwap_array_get_item_pointer(data, i)); \ + } \ + capwap_array_free(data); \ + data = NULL; \ + } + +/* */ +static struct capwap_message_elements_ops* capwap_message_elements[CAPWAP_MESSAGE_ELEMENTS_COUNT] = { + /* CAPWAP_ELEMENT_ACDESCRIPTION */ &capwap_element_acdescriptor_ops, + /* CAPWAP_ELEMENT_ACIPV4LIST */ &capwap_element_acipv4list_ops, + /* CAPWAP_ELEMENT_ACIPV6LIST */ &capwap_element_acipv6list_ops, + /* CAPWAP_ELEMENT_ACNAME */ &capwap_element_acname_ops, + /* CAPWAP_ELEMENT_ACNAMEPRIORITY */ &capwap_element_acnamepriority_ops, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* Reserved */ NULL, + /* CAPWAP_ELEMENT_CONTROLIPV4 */ &capwap_element_controlipv4_ops, + /* CAPWAP_ELEMENT_CONTROLIPV6 */ &capwap_element_controlipv6_ops, + /* CAPWAP_ELEMENT_TIMERS */ &capwap_element_timers_ops, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD */ &capwap_element_decrypterrorreportperiod_ops, + /* */ NULL, + /* */ NULL, + /* Reserved */ NULL, + /* CAPWAP_ELEMENT_DISCOVERYTYPE */ &capwap_element_discoverytype_ops, + /* */ NULL, + /* */ NULL, + /* CAPWAP_ELEMENT_IDLETIMEOUT */ &capwap_element_idletimeout_ops, + /* */ NULL, + /* CAPWAP_ELEMENT_IMAGEIDENTIFIER */ &capwap_element_imageidentifier_ops, + /* */ NULL, + /* */ NULL, + /* CAPWAP_ELEMENT_LOCATION */ &capwap_element_location_ops, + /* CAPWAP_ELEMENT_MAXIMUMLENGTH */ &capwap_element_maximumlength_ops, + /* CAPWAP_ELEMENT_LOCALIPV4 */ &capwap_element_localipv4_ops, + /* CAPWAP_ELEMENT_RADIOADMSTATE */ &capwap_element_radioadmstate_ops, + /* CAPWAP_ELEMENT_RADIOOPRSTATE */ &capwap_element_radiooprstate_ops, + /* CAPWAP_ELEMENT_RESULTCODE */ &capwap_element_resultcode_ops, + /* CAPWAP_ELEMENT_RETURNEDMESSAGE */ &capwap_element_returnedmessage_ops, + /* CAPWAP_ELEMENT_SESSIONID */ &capwap_element_sessionid_ops, + /* CAPWAP_ELEMENT_STATISTICSTIMER */ &capwap_element_statisticstimer_ops, + /* CAPWAP_ELEMENT_VENDORPAYLOAD */ &capwap_element_vendorpayload_ops, + /* CAPWAP_ELEMENT_WTPBOARDDATA */ &capwap_element_wtpboarddata_ops, + /* CAPWAP_ELEMENT_WTPDESCRIPTOR */ &capwap_element_wtpdescriptor_ops, + /* CAPWAP_ELEMENT_WTPFALLBACK */ &capwap_element_wtpfallback_ops, + /* CAPWAP_ELEMENT_WTPFRAMETUNNELMODE */ &capwap_element_wtpframetunnelmode_ops, + /* Reserved */ NULL, + /* Reserved */ NULL, + /* CAPWAP_ELEMENT_WTPMACTYPE */ &capwap_element_wtpmactype_ops, + /* CAPWAP_ELEMENT_WTPNAME */ &capwap_element_wtpname_ops, + /* Reserved */ NULL, + /* */ NULL, + /* CAPWAP_ELEMENT_WTPREBOOTSTAT */ &capwap_element_wtprebootstat_ops, + /* CAPWAP_ELEMENT_WTPSTATICIPADDRESS */ &capwap_element_wtpstaticipaddress_ops, + /* CAPWAP_ELEMENT_LOCALIPV6 */ &capwap_element_localipv6_ops, + /* CAPWAP_ELEMENT_TRANSPORT */ &capwap_element_transport_ops, + /* CAPWAP_ELEMENT_MTUDISCOVERY */ &capwap_element_mtudiscovery_ops, + /* CAPWAP_ELEMENT_ECNSUPPORT */ &capwap_element_ecnsupport_ops }; /* */ -struct capwap_message_elements_func* capwap_get_message_element(unsigned long code) { +static struct capwap_message_elements_ops* capwap_80211_message_elements[CAPWAP_MESSAGE_ELEMENTS_COUNT] = { + /* */ NULL, + /* CAPWAP_ELEMENT_80211_ANTENNA */ &capwap_element_80211_antenna_ops, + /* */ NULL, + /* */ NULL, + /* CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL */ &capwap_element_80211_directsequencecontrol_ops, + /* */ NULL, + /* CAPWAP_ELEMENT_80211_MACOPERATION */ &capwap_element_80211_macoperation_ops, + /* */ NULL, + /* CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY */ &capwap_element_80211_multidomaincapability_ops, + /* CAPWAP_ELEMENT_80211_OFDMCONTROL */ &capwap_element_80211_ofdmcontrol_ops, + /* CAPWAP_ELEMENT_80211_RATESET */ &capwap_element_80211_rateset_ops, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* CAPWAP_ELEMENT_80211_SUPPORTEDRATES */ &capwap_element_80211_supportedrates_ops, + /* CAPWAP_ELEMENT_80211_TXPOWER */ &capwap_element_80211_txpower_ops, + /* CAPWAP_ELEMENT_80211_TXPOWERLEVEL */ &capwap_element_80211_txpowerlevel_ops, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* */ NULL, + /* CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION */ &capwap_element_80211_wtpradioinformation_ops +}; + +/* */ +struct capwap_message_elements_ops* capwap_get_message_element_ops(unsigned short code) { if ((code >= CAPWAP_MESSAGE_ELEMENTS_START) && (code <= CAPWAP_MESSAGE_ELEMENTS_STOP)) { - return &standard_message_elements[code - CAPWAP_MESSAGE_ELEMENTS_START]; + return capwap_message_elements[code - CAPWAP_MESSAGE_ELEMENTS_START]; } else if ((code >= CAPWAP_80211_MESSAGE_ELEMENTS_START) && (code <= CAPWAP_80211_MESSAGE_ELEMENTS_STOP)) { - return &ieee80211_message_elements[code - CAPWAP_80211_MESSAGE_ELEMENTS_START]; + return capwap_80211_message_elements[code - CAPWAP_80211_MESSAGE_ELEMENTS_START]; } return NULL; } /* */ -void capwap_init_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding) { - ASSERT(element != NULL); +int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, struct capwap_parsed_packet* packet) { + unsigned short binding; - memset(element, 0, sizeof(struct capwap_element_discovery_request)); - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - element->binding.ieee80211.wtpradioinformation = capwap_array_create(sizeof(struct capwap_80211_wtpradioinformation_element*), 0); + ASSERT(rxmngpacket != NULL); + ASSERT(packet != NULL); + + /* */ + memset(packet, 0, sizeof(struct capwap_parsed_packet)); + packet->rxmngpacket = rxmngpacket; + packet->connection = connection; + + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + + /* Position reader to capwap body */ + memcpy(&rxmngpacket->readpos, &rxmngpacket->readbodypos, sizeof(struct read_block_from_pos)); + + if (rxmngpacket->isctrlpacket) { + unsigned short bodylength = rxmngpacket->ctrlmsg.length; + while (bodylength > 0) { + uint16_t type; + uint16_t msglength; + struct capwap_message_elements_ops* read_ops; + + /* Get type and length */ + rxmngpacket->readerpacketallowed = sizeof(struct capwap_message_element); + if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &type) != sizeof(uint16_t)) { + /* TODO */ + return 1; + } + if (rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &msglength) != sizeof(uint16_t)) { + /* TODO */ + return 1; + } + + /* Check length */ + if (msglength > bodylength) { + /* TODO */ + return 1; + } + + /* */ + read_ops = capwap_get_message_element_ops(type); + + /* Allowed to parsing only the size of message element */ + rxmngpacket->readerpacketallowed = msglength; + if (IS_MESSAGE_ELEMENTS(type) && read_ops) { + /* Parsing standard message element */ + switch (type) { + case CAPWAP_ELEMENT_ACDESCRIPTION: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.acdescriptor); + break; + } + + case CAPWAP_ELEMENT_ACIPV4LIST: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.acipv4list); + break; + } + + case CAPWAP_ELEMENT_ACIPV6LIST: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.acipv6list); + break; + } + + case CAPWAP_ELEMENT_ACNAME: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.acname); + break; + } + + case CAPWAP_ELEMENT_ACNAMEPRIORITY: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.acnamepriority, struct capwap_acnamepriority_element*); + break; + } + + case CAPWAP_ELEMENT_CONTROLIPV4: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.controlipv4, struct capwap_controlipv4_element*); + break; + } + + case CAPWAP_ELEMENT_CONTROLIPV6: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.controlipv6, struct capwap_controlipv6_element*); + break; + } + + case CAPWAP_ELEMENT_TIMERS: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.timers); + break; + } + + case CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.decrypterrorreportperiod, struct capwap_decrypterrorreportperiod_element*); + break; + } + + case CAPWAP_ELEMENT_DISCOVERYTYPE: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.discoverytype); + break; + } + + case CAPWAP_ELEMENT_IDLETIMEOUT: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.idletimeout); + break; + } + + case CAPWAP_ELEMENT_IMAGEIDENTIFIER: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.imageidentifier); + break; + } + + case CAPWAP_ELEMENT_LOCATION: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.location); + break; + } + + case CAPWAP_ELEMENT_MAXIMUMLENGTH: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.maximumlength); + break; + } + + case CAPWAP_ELEMENT_LOCALIPV4: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.localipv4); + break; + } + + case CAPWAP_ELEMENT_RADIOADMSTATE: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.radioadmstate, struct capwap_radioadmstate_element*); + break; + } + + case CAPWAP_ELEMENT_RADIOOPRSTATE: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.radiooprstate, struct capwap_radiooprstate_element*); + break; + } + + case CAPWAP_ELEMENT_RESULTCODE: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.resultcode); + break; + } + + case CAPWAP_ELEMENT_RETURNEDMESSAGE: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.returnedmessage, struct capwap_returnedmessage_element*); + break; + } + + case CAPWAP_ELEMENT_SESSIONID: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.sessionid); + break; + } + + case CAPWAP_ELEMENT_STATISTICSTIMER: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.statisticstimer); + break; + } + + case CAPWAP_ELEMENT_VENDORPAYLOAD: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.vendorpayload); + break; + } + + case CAPWAP_ELEMENT_WTPBOARDDATA: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtpboarddata); + break; + } + + case CAPWAP_ELEMENT_WTPDESCRIPTOR: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtpdescriptor); + break; + } + + case CAPWAP_ELEMENT_WTPFALLBACK: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtpfallback); + break; + } + + case CAPWAP_ELEMENT_WTPFRAMETUNNELMODE: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtpframetunnel); + break; + } + + case CAPWAP_ELEMENT_WTPMACTYPE: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtpmactype); + break; + } + + case CAPWAP_ELEMENT_WTPNAME: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtpname); + break; + } + + case CAPWAP_ELEMENT_WTPREBOOTSTAT: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtprebootstat); + break; + } + + case CAPWAP_ELEMENT_WTPSTATICIPADDRESS: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.wtpstaticipaddress); + break; + } + + case CAPWAP_ELEMENT_LOCALIPV6: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.localipv6); + break; + } + + case CAPWAP_ELEMENT_TRANSPORT: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.transport); + break; + } + + case CAPWAP_ELEMENT_MTUDISCOVERY: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.mtudiscovery); + break; + } + + case CAPWAP_ELEMENT_ECNSUPPORT: { + PARSING_MESSAGE_ELEMENT(packet->messageelements.ecnsupport); + break; + } + + default: { + /* TODO */ + return 1; + } + } + } else if (IS_80211_MESSAGE_ELEMENTS(type) && read_ops) { + if (binding != CAPWAP_WIRELESS_BINDING_IEEE80211) { + /* TODO */ + return 1; + } + + /* Parsing ieee80211 message element */ + switch (type) { + case CAPWAP_ELEMENT_80211_ANTENNA: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.antenna, struct capwap_80211_antenna_element*); + break; + } + + case CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.directsequencecontrol, struct capwap_80211_directsequencecontrol_element*); + break; + } + + case CAPWAP_ELEMENT_80211_MACOPERATION: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.macoperation, struct capwap_80211_macoperation_element*); + break; + } + + case CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.multidomaincapability, struct capwap_80211_multidomaincapability_element*); + break; + } + + case CAPWAP_ELEMENT_80211_OFDMCONTROL: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.ofdmcontrol, struct capwap_80211_ofdmcontrol_element*); + break; + } + + case CAPWAP_ELEMENT_80211_RATESET: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.rateset, struct capwap_80211_rateset_element*); + break; + } + + case CAPWAP_ELEMENT_80211_SUPPORTEDRATES: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.supportedrates, struct capwap_80211_supportedrates_element*); + break; + } + + case CAPWAP_ELEMENT_80211_TXPOWER: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.txpower, struct capwap_80211_txpower_element*); + break; + } + + case CAPWAP_ELEMENT_80211_TXPOWERLEVEL: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.txpowerlevel, struct capwap_80211_txpowerlevel_element*); + break; + } + + case CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION: { + ARRAY_PARSING_MESSAGE_ELEMENT(packet->messageelements.ieee80211.wtpradioinformation, struct capwap_80211_wtpradioinformation_element*); + break; + } + + default: { + /* TODO */ + return 1; + } + } + } else { + /* TODO */ + return 1; + } + + /* Check if read all data of message element */ + if (rxmngpacket->readerpacketallowed) { + /* TODO */ + return 1; + } + + /* */ + bodylength -= (msglength + sizeof(struct capwap_message_element)); + } + } else if (IS_FLAG_K_HEADER(rxmngpacket->header)) { + uint16_t type; + uint16_t msglength; + struct capwap_message_elements_ops* read_ops; + unsigned short bodylength = rxmngpacket->datamsg.length; + + if (!bodylength) { + /* TODO */ + return 1; + } + + /* Get type and length */ + rxmngpacket->readerpacketallowed = sizeof(struct capwap_message_element); + rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &type); + rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &msglength); + + /* Check length */ + if ((msglength + sizeof(struct capwap_message_element)) != bodylength) { + /* TODO */ + return 1; + } + + /* Allowed to parsing only the size of message element */ + rxmngpacket->readerpacketallowed = msglength; + if (type != CAPWAP_ELEMENT_SESSIONID) { + /* TODO */ + return 1; + } + + /* Retrieve session id */ + read_ops = capwap_get_message_element_ops(CAPWAP_ELEMENT_SESSIONID); + packet->messageelements.sessionid = read_ops->parsing_message_element((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->read_ops); + if (!packet->messageelements.sessionid) { + /* TODO */ + return 1; + } } + + return 0; } /* */ -int capwap_parsing_element_discovery_request(struct capwap_element_discovery_request* element, struct capwap_list_item* item) { - ASSERT(element != NULL); +int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct capwap_array* returnedmessage) { + unsigned short binding; + + ASSERT(packet != NULL); + ASSERT(packet->rxmngpacket != NULL); + + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + + if (packet->rxmngpacket->isctrlpacket) { + switch (packet->rxmngpacket->ctrlmsg.type) { + case CAPWAP_DISCOVERY_REQUEST: { + if (packet->messageelements.discoverytype && + packet->messageelements.wtpboarddata && + packet->messageelements.wtpdescriptor && + packet->messageelements.wtpframetunnel && + packet->messageelements.wtpmactype) { + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (packet->messageelements.ieee80211.wtpradioinformation) { + return 0; + } + } else { + return 0; + } + } - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_DISCOVERYTYPE: { - element->discoverytype = (struct capwap_discoverytype_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPBOARDDATA: { - element->wtpboarddata = (struct capwap_wtpboarddata_element*)f->parsing(elementitem); break; } - case CAPWAP_ELEMENT_WTPDESCRIPTOR: { - element->wtpdescriptor = (struct capwap_wtpdescriptor_element*)f->parsing(elementitem); + case CAPWAP_DISCOVERY_RESPONSE: { + if (packet->messageelements.acdescriptor && + packet->messageelements.acname && + (packet->messageelements.controlipv4 || packet->messageelements.controlipv6)) { + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (packet->messageelements.ieee80211.wtpradioinformation) { + return 0; + } + } else { + return 0; + } + } + break; } - case CAPWAP_ELEMENT_WTPFRAMETUNNELMODE: { - element->wtpframetunnel = (struct capwap_wtpframetunnelmode_element*)f->parsing(elementitem); + case CAPWAP_JOIN_REQUEST: { + if (packet->messageelements.location && + packet->messageelements.wtpboarddata && + packet->messageelements.wtpdescriptor && + packet->messageelements.wtpname && + packet->messageelements.sessionid && + packet->messageelements.wtpframetunnel && + packet->messageelements.wtpmactype && + packet->messageelements.ecnsupport && + (packet->messageelements.localipv4 || packet->messageelements.localipv6)) { + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (packet->messageelements.ieee80211.wtpradioinformation) { + return 0; + } + } else { + return 0; + } + } + break; } - case CAPWAP_ELEMENT_WTPMACTYPE: { - element->wtpmactype = (struct capwap_wtpmactype_element*)f->parsing(elementitem); + case CAPWAP_JOIN_RESPONSE: { + if (packet->messageelements.resultcode && + packet->messageelements.acdescriptor && + packet->messageelements.acname && + packet->messageelements.ecnsupport && + (packet->messageelements.controlipv4 || packet->messageelements.controlipv6) && + (packet->messageelements.localipv4 || packet->messageelements.localipv6)) { + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (packet->messageelements.ieee80211.wtpradioinformation) { + return 0; + } + } else { + return 0; + } + } + break; } - - case CAPWAP_ELEMENT_MTUDISCOVERY: { - element->mtudiscovery = (struct capwap_mtudiscovery_element*)f->parsing(elementitem); + + case CAPWAP_CONFIGURATION_STATUS_REQUEST: { + if (packet->messageelements.acname && + packet->messageelements.radioadmstate && + packet->messageelements.statisticstimer && + packet->messageelements.wtprebootstat) { + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (packet->messageelements.ieee80211.wtpradioinformation) { + return 0; + } + } else { + return 0; + } + } + break; } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); + + case CAPWAP_CONFIGURATION_STATUS_RESPONSE: { + if (packet->messageelements.timers && + packet->messageelements.decrypterrorreportperiod && + packet->messageelements.idletimeout && + packet->messageelements.wtpfallback && + (packet->messageelements.acipv4list || packet->messageelements.acipv6list)) { + + return 0; + } + break; } - - case CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION: { - struct capwap_80211_wtpradioinformation_element** radio; - - radio = (struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, element->binding.ieee80211.wtpradioinformation->count); - *radio = (struct capwap_80211_wtpradioinformation_element*)f->parsing(elementitem); + + case CAPWAP_CONFIGURATION_UPDATE_REQUEST: { + if (packet->messageelements.acnamepriority || + //packet->messageelements.actimestamp || TODO + //packet->messageelements.addaclmac || TODO + packet->messageelements.timers || + packet->messageelements.decrypterrorreportperiod || + //packet->messageelements.delaclmac || TODO + packet->messageelements.idletimeout || + packet->messageelements.location || + packet->messageelements.radioadmstate || + packet->messageelements.statisticstimer || + packet->messageelements.wtpfallback || + packet->messageelements.wtpname || + packet->messageelements.wtpstaticipaddress || + packet->messageelements.imageidentifier || + packet->messageelements.vendorpayload) { + + return 0; + } + + break; + } + + case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: { + return 0; + } + + case CAPWAP_WTP_EVENT_REQUEST: { + if (packet->messageelements.decrypterrorreportperiod || + //packet->messageelements.duplicateipv4 || TODO + //packet->messageelements.duplicateipv6 || TODO + //packet->messageelements.wtpradiostat || TODO + packet->messageelements.wtprebootstat || + //packet->messageelements.deletestation || TODO + packet->messageelements.vendorpayload) { + + return 0; + } + + break; + } + + case CAPWAP_WTP_EVENT_RESPONSE: { + return 0; + } + + case CAPWAP_CHANGE_STATE_EVENT_REQUEST: { + if (packet->messageelements.radiooprstate && + packet->messageelements.resultcode) { + + return 0; + } + + break; + } + + case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: { + return 0; + } + + case CAPWAP_ECHO_REQUEST: { + return 0; + } + + case CAPWAP_ECHO_RESPONSE: { + return 0; + } + + case CAPWAP_IMAGE_DATA_REQUEST: { + return 0; + } + + case CAPWAP_IMAGE_DATA_RESPONSE: { + if (packet->messageelements.resultcode) { + return 0; + } + + break; + } + + case CAPWAP_RESET_REQUEST: { + if (packet->messageelements.imageidentifier) { + return 0; + } + + break; + } + + case CAPWAP_RESET_RESPONSE: { + return 0; + } + + case CAPWAP_PRIMARY_DISCOVERY_REQUEST: { + if (packet->messageelements.discoverytype && + packet->messageelements.wtpboarddata && + packet->messageelements.wtpdescriptor && + packet->messageelements.wtpframetunnel && + packet->messageelements.wtpmactype) { + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (packet->messageelements.ieee80211.wtpradioinformation) { + return 0; + } + } else { + return 0; + } + } + + break; + } + + case CAPWAP_PRIMARY_DISCOVERY_RESPONSE: { + if (packet->messageelements.acdescriptor && + packet->messageelements.acname && + (packet->messageelements.controlipv4 || packet->messageelements.controlipv6)) { + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + if (packet->messageelements.ieee80211.wtpradioinformation) { + return 0; + } + } else { + return 0; + } + } + + break; + } + + case CAPWAP_DATA_TRANSFER_REQUEST: { + /* TODO */ + break; + } + + case CAPWAP_DATA_TRANSFER_RESPONSE: { + if (packet->messageelements.resultcode) { + return 0; + } + + break; + } + + case CAPWAP_CLEAR_CONFIGURATION_REQUEST: { + return 0; + } + + case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: { + if (packet->messageelements.resultcode) { + return 0; + } + + break; + } + + case CAPWAP_STATION_CONFIGURATION_REQUEST: { + /* TODO */ + break; + } + + case CAPWAP_STATION_CONFIGURATION_RESPONSE: { + if (packet->messageelements.resultcode) { + return 0; + } + break; } } - - /* Next element */ - item = item->next; + } else if (IS_FLAG_K_HEADER(packet->rxmngpacket->header)) { + /* Keep alive data message require session id */ + if (packet->messageelements.sessionid) { + return 0; + } } return 1; } /* */ -void capwap_free_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding) { - unsigned long i; - struct capwap_message_elements_func* f; - - ASSERT(element != NULL); - - if (element->discoverytype) { - capwap_get_message_element(CAPWAP_ELEMENT_DISCOVERYTYPE)->free(element->discoverytype); - } - - if (element->wtpboarddata) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPBOARDDATA)->free(element->wtpboarddata); - } - - if (element->wtpdescriptor) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPDESCRIPTOR)->free(element->wtpdescriptor); - } - - if (element->wtpframetunnel) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE)->free(element->wtpframetunnel); - } - - if (element->wtpmactype) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPMACTYPE)->free(element->wtpmactype); - } - - if (element->mtudiscovery) { - capwap_get_message_element(CAPWAP_ELEMENT_MTUDISCOVERY)->free(element->mtudiscovery); - } - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (element->binding.ieee80211.wtpradioinformation->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); - - for (i = 0; i < element->binding.ieee80211.wtpradioinformation->count; i++) { - f->free(*(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, i)); - } - } - - capwap_array_free(element->binding.ieee80211.wtpradioinformation); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_discovery_request)); -} - -/* */ -void capwap_init_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_discovery_response)); - - element->controlipv4 = capwap_array_create(sizeof(struct capwap_controlipv4_element*), 0); - element->controlipv6 = capwap_array_create(sizeof(struct capwap_controlipv6_element*), 0); - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - element->binding.ieee80211.wtpradioinformation = capwap_array_create(sizeof(struct capwap_80211_wtpradioinformation_element*), 0); - } -} - -/* */ -int capwap_parsing_element_discovery_response(struct capwap_element_discovery_response* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_ACDESCRIPTION: { - element->acdescriptor = (struct capwap_acdescriptor_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACNAME: { - element->acname = (struct capwap_acname_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_CONTROLIPV4: { - struct capwap_controlipv4_element** controlipv4; - - controlipv4 = (struct capwap_controlipv4_element**)capwap_array_get_item_pointer(element->controlipv4, element->controlipv4->count); - *controlipv4 = (struct capwap_controlipv4_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_CONTROLIPV6: { - struct capwap_controlipv6_element** controlipv6; - - controlipv6 = (struct capwap_controlipv6_element**)capwap_array_get_item_pointer(element->controlipv6, element->controlipv6->count); - *controlipv6 = (struct capwap_controlipv6_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION: { - struct capwap_80211_wtpradioinformation_element** radio; - - radio = (struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, element->binding.ieee80211.wtpradioinformation->count); - *radio = (struct capwap_80211_wtpradioinformation_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding) { - unsigned long i; - struct capwap_message_elements_func* f; - - ASSERT(element != NULL); - - if (element->acdescriptor) { - capwap_get_message_element(CAPWAP_ELEMENT_ACDESCRIPTION)->free(element->acdescriptor); - } - - if (element->acname) { - capwap_get_message_element(CAPWAP_ELEMENT_ACNAME)->free(element->acname); - } - - if (element->controlipv4->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV4); - - for (i = 0; i < element->controlipv4->count; i++) { - f->free(*(struct capwap_controlipv4_element**)capwap_array_get_item_pointer(element->controlipv4, i)); - } - } - capwap_array_free(element->controlipv4); - - if (element->controlipv6->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV6); - - for (i = 0; i < element->controlipv6->count; i++) { - f->free(*(struct capwap_controlipv6_element**)capwap_array_get_item_pointer(element->controlipv6, i)); - } - } - capwap_array_free(element->controlipv6); - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (element->binding.ieee80211.wtpradioinformation->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); - - for (i = 0; i < element->binding.ieee80211.wtpradioinformation->count; i++) { - f->free(*(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, i)); - } - } - - capwap_array_free(element->binding.ieee80211.wtpradioinformation); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_discovery_response)); -} - -/* */ -void capwap_init_element_join_request(struct capwap_element_join_request* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_join_request)); - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - element->binding.ieee80211.wtpradioinformation = capwap_array_create(sizeof(struct capwap_80211_wtpradioinformation_element*), 0); - } -} - -/* */ -int capwap_parsing_element_join_request(struct capwap_element_join_request* element, struct capwap_list_item* item) { - ASSERT(element); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_LOCATION: { - element->locationdata = (struct capwap_location_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPBOARDDATA: { - element->wtpboarddata = (struct capwap_wtpboarddata_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPDESCRIPTOR: { - element->wtpdescriptor = (struct capwap_wtpdescriptor_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPNAME: { - element->wtpname = (struct capwap_wtpname_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_SESSIONID: { - element->sessionid = (struct capwap_sessionid_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPFRAMETUNNELMODE: { - element->wtpframetunnel = (struct capwap_wtpframetunnelmode_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPMACTYPE: { - element->wtpmactype = (struct capwap_wtpmactype_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ECNSUPPORT: { - element->ecnsupport = (struct capwap_ecnsupport_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_LOCALIPV4: { - element->localipv4 = (struct capwap_localipv4_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_LOCALIPV6: { - element->localipv6 = (struct capwap_localipv6_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_TRANSPORT: { - element->trasport = (struct capwap_transport_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_MAXIMUMLENGTH: { - element->maxiumlength = (struct capwap_maximumlength_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPREBOOTSTAT: { - element->wtprebootstat = (struct capwap_wtprebootstat_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION: { - struct capwap_80211_wtpradioinformation_element** radio; - - radio = (struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, element->binding.ieee80211.wtpradioinformation->count); - *radio = (struct capwap_80211_wtpradioinformation_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_join_request(struct capwap_element_join_request* element, unsigned short binding) { - unsigned long i; - struct capwap_message_elements_func* f; - - ASSERT(element != NULL); - - if (element->locationdata) { - capwap_get_message_element(CAPWAP_ELEMENT_LOCATION)->free(element->locationdata); - } - - if (element->wtpboarddata) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPBOARDDATA)->free(element->wtpboarddata); - } - - if (element->wtpdescriptor) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPDESCRIPTOR)->free(element->wtpdescriptor); - } - - if (element->wtpname) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPNAME)->free(element->wtpname); - } - - if (element->sessionid) { - capwap_get_message_element(CAPWAP_ELEMENT_SESSIONID)->free(element->sessionid); - } - - if (element->wtpframetunnel) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE)->free(element->wtpframetunnel); - } - - if (element->wtpmactype) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPMACTYPE)->free(element->wtpmactype); - } - - if (element->ecnsupport) { - capwap_get_message_element(CAPWAP_ELEMENT_ECNSUPPORT)->free(element->ecnsupport); - } - - if (element->localipv4) { - capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV4)->free(element->localipv4); - } - - if (element->localipv6) { - capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV6)->free(element->localipv6); - } - - if (element->trasport) { - capwap_get_message_element(CAPWAP_ELEMENT_TRANSPORT)->free(element->trasport); - } - - if (element->maxiumlength) { - capwap_get_message_element(CAPWAP_ELEMENT_MAXIMUMLENGTH)->free(element->maxiumlength); - } - - if (element->wtprebootstat) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPREBOOTSTAT)->free(element->wtprebootstat); - } - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (element->binding.ieee80211.wtpradioinformation->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); - - for (i = 0; i < element->binding.ieee80211.wtpradioinformation->count; i++) { - f->free(*(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, i)); - } - } - - capwap_array_free(element->binding.ieee80211.wtpradioinformation); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_join_request)); -} - -/* */ -void capwap_init_element_join_response(struct capwap_element_join_response* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_join_response)); - - element->returnedmessage = capwap_array_create(sizeof(struct capwap_returnedmessage_element*), 0); - element->controlipv4 = capwap_array_create(sizeof(struct capwap_controlipv4_element*), 0); - element->controlipv6 = capwap_array_create(sizeof(struct capwap_controlipv6_element*), 0); - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - element->binding.ieee80211.wtpradioinformation = capwap_array_create(sizeof(struct capwap_80211_wtpradioinformation_element*), 0); - } -} - -/* */ -int capwap_parsing_element_join_response(struct capwap_element_join_response* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_RESULTCODE: { - element->resultcode = (struct capwap_resultcode_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_RETURNEDMESSAGE: { - struct capwap_returnedmessage_element** returnedmessage; - - returnedmessage = (struct capwap_returnedmessage_element**)capwap_array_get_item_pointer(element->returnedmessage, element->returnedmessage->count); - *returnedmessage = (struct capwap_returnedmessage_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACDESCRIPTION: { - element->acdescriptor = (struct capwap_acdescriptor_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACNAME: { - element->acname = (struct capwap_acname_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ECNSUPPORT: { - element->ecnsupport = (struct capwap_ecnsupport_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_CONTROLIPV4: { - struct capwap_controlipv4_element** controlipv4; - - controlipv4 = (struct capwap_controlipv4_element**)capwap_array_get_item_pointer(element->controlipv4, element->controlipv4->count); - *controlipv4 = (struct capwap_controlipv4_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_CONTROLIPV6: { - struct capwap_controlipv6_element** controlipv6; - - controlipv6 = (struct capwap_controlipv6_element**)capwap_array_get_item_pointer(element->controlipv6, element->controlipv6->count); - *controlipv6 = (struct capwap_controlipv6_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_LOCALIPV4: { - element->localipv4 = (struct capwap_localipv4_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_LOCALIPV6: { - element->localipv6 = (struct capwap_localipv6_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACIPV4LIST: { - element->acipv4list = (capwap_acipv4list_element_array*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACIPV6LIST: { - element->acipv6list = (capwap_acipv6list_element_array*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_TRANSPORT: { - element->trasport = (struct capwap_transport_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_IMAGEIDENTIFIER: { - element->imageidentifier = (struct capwap_imageidentifier_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_MAXIMUMLENGTH: { - element->maxiumlength = (struct capwap_maximumlength_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION: { - struct capwap_80211_wtpradioinformation_element** radio; - - radio = (struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, element->binding.ieee80211.wtpradioinformation->count); - *radio = (struct capwap_80211_wtpradioinformation_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_join_response(struct capwap_element_join_response* element, unsigned short binding) { - unsigned long i; - struct capwap_message_elements_func* f; - - ASSERT(element != NULL); - - if (element->resultcode) { - capwap_get_message_element(CAPWAP_ELEMENT_RESULTCODE)->free(element->resultcode); - } - - if (element->returnedmessage->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_RETURNEDMESSAGE); - - for (i = 0; i < element->returnedmessage->count; i++) { - f->free(*(struct capwap_returnedmessage_element**)capwap_array_get_item_pointer(element->returnedmessage, i)); - } - } - capwap_array_free(element->returnedmessage); - - if (element->acdescriptor) { - capwap_get_message_element(CAPWAP_ELEMENT_ACDESCRIPTION)->free(element->acdescriptor); - } - - if (element->acname) { - capwap_get_message_element(CAPWAP_ELEMENT_ACNAME)->free(element->acname); - } - - if (element->ecnsupport) { - capwap_get_message_element(CAPWAP_ELEMENT_ECNSUPPORT)->free(element->ecnsupport); - } - - if (element->controlipv4->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV4); - - for (i = 0; i < element->controlipv4->count; i++) { - f->free(*(struct capwap_controlipv4_element**)capwap_array_get_item_pointer(element->controlipv4, i)); - } - } - capwap_array_free(element->controlipv4); - - if (element->controlipv6->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV6); - - for (i = 0; i < element->controlipv6->count; i++) { - f->free(*(struct capwap_controlipv6_element**)capwap_array_get_item_pointer(element->controlipv6, i)); - } - } - capwap_array_free(element->controlipv6); - - if (element->localipv4) { - capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV4)->free(element->localipv4); - } - - if (element->localipv6) { - capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV6)->free(element->localipv6); - } - - if (element->acipv4list) { - capwap_get_message_element(CAPWAP_ELEMENT_ACIPV4LIST)->free(element->acipv4list); - } - - if (element->acipv6list) { - capwap_get_message_element(CAPWAP_ELEMENT_ACIPV6LIST)->free(element->acipv6list); - } - - if (element->trasport) { - capwap_get_message_element(CAPWAP_ELEMENT_TRANSPORT)->free(element->trasport); - } - - if (element->imageidentifier) { - capwap_get_message_element(CAPWAP_ELEMENT_IMAGEIDENTIFIER)->free(element->imageidentifier); - } - - if (element->maxiumlength) { - capwap_get_message_element(CAPWAP_ELEMENT_MAXIMUMLENGTH)->free(element->maxiumlength); - } - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (element->binding.ieee80211.wtpradioinformation->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); - - for (i = 0; i < element->binding.ieee80211.wtpradioinformation->count; i++) { - f->free(*(struct capwap_80211_wtpradioinformation_element**)capwap_array_get_item_pointer(element->binding.ieee80211.wtpradioinformation, i)); - } - } - - capwap_array_free(element->binding.ieee80211.wtpradioinformation); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_join_response)); -} - -/* */ -void capwap_init_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_configurationstatus_request)); - - element->radioadmstatus = capwap_array_create(sizeof(struct capwap_radioadmstate_element*), 0); - element->acnamepriority = capwap_array_create(sizeof(struct capwap_acnamepriority_element*), 0); -} - -/* */ -int capwap_parsing_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_ACNAME: { - element->acname = (struct capwap_acname_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_RADIOADMSTATE: { - struct capwap_radioadmstate_element** radioadmstate; - - radioadmstate = (struct capwap_radioadmstate_element**)capwap_array_get_item_pointer(element->radioadmstatus, element->radioadmstatus->count); - *radioadmstate = (struct capwap_radioadmstate_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_STATISTICSTIMER: { - element->statisticstimer = (struct capwap_statisticstimer_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPREBOOTSTAT: { - element->wtprebootstat = (struct capwap_wtprebootstat_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACNAMEPRIORITY: { - struct capwap_acnamepriority_element** acnamepriority; - - acnamepriority = (struct capwap_acnamepriority_element**)capwap_array_get_item_pointer(element->acnamepriority, element->acnamepriority->count); - *acnamepriority = (struct capwap_acnamepriority_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_TRANSPORT: { - element->trasport = (struct capwap_transport_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPSTATICIPADDRESS: { - element->wtpstaticipaddress = (struct capwap_wtpstaticipaddress_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } +void capwap_free_parsed_packet(struct capwap_parsed_packet* packet) { + ASSERT(packet != NULL); + + if (packet->rxmngpacket) { + unsigned short binding = GET_WBID_HEADER(packet->rxmngpacket->header); + + /* */ + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_ACDESCRIPTION, packet->messageelements.acdescriptor); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_ACIPV4LIST, packet->messageelements.acipv4list); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_ACIPV6LIST, packet->messageelements.acipv6list); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_ACNAME, packet->messageelements.acname); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_ACNAMEPRIORITY, packet->messageelements.acnamepriority); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_CONTROLIPV4, packet->messageelements.controlipv4); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_CONTROLIPV6, packet->messageelements.controlipv6); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_TIMERS, packet->messageelements.timers); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD, packet->messageelements.decrypterrorreportperiod); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_DISCOVERYTYPE, packet->messageelements.discoverytype); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_IDLETIMEOUT, packet->messageelements.idletimeout); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_IMAGEIDENTIFIER, packet->messageelements.imageidentifier); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_LOCATION, packet->messageelements.location); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_MAXIMUMLENGTH, packet->messageelements.maximumlength); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_LOCALIPV4, packet->messageelements.localipv4); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_RADIOADMSTATE, packet->messageelements.radioadmstate); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_RADIOOPRSTATE, packet->messageelements.radiooprstate); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_RESULTCODE, packet->messageelements.resultcode); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_RETURNEDMESSAGE, packet->messageelements.returnedmessage); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_SESSIONID, packet->messageelements.sessionid); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_STATISTICSTIMER, packet->messageelements.statisticstimer); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_VENDORPAYLOAD, packet->messageelements.vendorpayload); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPBOARDDATA, packet->messageelements.wtpboarddata); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPDESCRIPTOR, packet->messageelements.wtpdescriptor); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPFALLBACK, packet->messageelements.wtpfallback); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE, packet->messageelements.wtpframetunnel); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPMACTYPE, packet->messageelements.wtpmactype); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPNAME, packet->messageelements.wtpname); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPREBOOTSTAT, packet->messageelements.wtprebootstat); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_WTPSTATICIPADDRESS, packet->messageelements.wtpstaticipaddress); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_LOCALIPV6, packet->messageelements.localipv6); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_TRANSPORT, packet->messageelements.transport); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_MTUDISCOVERY, packet->messageelements.mtudiscovery); + FREE_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_ECNSUPPORT, packet->messageelements.ecnsupport); + + if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_ANTENNA, packet->messageelements.ieee80211.antenna); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL, packet->messageelements.ieee80211.directsequencecontrol); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_MACOPERATION, packet->messageelements.ieee80211.macoperation); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY, packet->messageelements.ieee80211.multidomaincapability); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_OFDMCONTROL, packet->messageelements.ieee80211.ofdmcontrol); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_RATESET, packet->messageelements.ieee80211.rateset); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_SUPPORTEDRATES, packet->messageelements.ieee80211.supportedrates); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_TXPOWER, packet->messageelements.ieee80211.txpower); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_TXPOWERLEVEL, packet->messageelements.ieee80211.txpowerlevel); + FREE_ARRAY_PARSED_MESSAGE_ELEMENT(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, packet->messageelements.ieee80211.wtpradioinformation); } - /* Next element */ - item = item->next; + /* */ + packet->rxmngpacket = NULL; } - - return 1; -} - -/* */ -void capwap_free_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding) { - unsigned long i; - struct capwap_message_elements_func* f; - - ASSERT(element != NULL); - - if (element->acname) { - capwap_get_message_element(CAPWAP_ELEMENT_ACNAME)->free(element->acname); - } - - if (element->radioadmstatus->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOADMSTATE); - - for (i = 0; i < element->radioadmstatus->count; i++) { - f->free(*(struct capwap_radioadmstate_element**)capwap_array_get_item_pointer(element->radioadmstatus, i)); - } - } - capwap_array_free(element->radioadmstatus); - - if (element->statisticstimer) { - capwap_get_message_element(CAPWAP_ELEMENT_STATISTICSTIMER)->free(element->statisticstimer); - } - - if (element->wtprebootstat) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPREBOOTSTAT)->free(element->wtprebootstat); - } - - if (element->acnamepriority->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_ACNAMEPRIORITY); - - for (i = 0; i < element->acnamepriority->count; i++) { - f->free(*(struct capwap_acnamepriority_element**)capwap_array_get_item_pointer(element->acnamepriority, i)); - } - } - capwap_array_free(element->acnamepriority); - - if (element->trasport) { - capwap_get_message_element(CAPWAP_ELEMENT_TRANSPORT)->free(element->trasport); - } - - if (element->wtpstaticipaddress) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPSTATICIPADDRESS)->free(element->wtpstaticipaddress); - } - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_configurationstatus_request)); -} - -/* */ -void capwap_init_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_configurationstatus_response)); - - element->decrypterrorresultperiod = capwap_array_create(sizeof(struct capwap_decrypterrorreport_element*), 0); - element->radiooprstatus = capwap_array_create(sizeof(struct capwap_radiooprstate_element*), 0); -} - -/* */ -int capwap_parsing_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_TIMERS: { - element->timers = (struct capwap_timers_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD: { - struct capwap_decrypterrorreport_element** decrypterrorresultperiod; - - decrypterrorresultperiod = (struct capwap_decrypterrorreport_element**)capwap_array_get_item_pointer(element->decrypterrorresultperiod, element->decrypterrorresultperiod->count); - *decrypterrorresultperiod = (struct capwap_decrypterrorreport_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_IDLETIMEOUT: { - element->idletimeout = (struct capwap_idletimeout_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPFALLBACK: { - element->wtpfallback = (struct capwap_wtpfallback_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACIPV4LIST: { - element->acipv4list = (capwap_acipv4list_element_array*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_ACIPV6LIST: { - element->acipv6list = (capwap_acipv6list_element_array*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_RADIOOPRSTATE: { - struct capwap_radiooprstate_element** radiooprstatus; - - radiooprstatus = (struct capwap_radiooprstate_element**)capwap_array_get_item_pointer(element->radiooprstatus, element->radiooprstatus->count); - *radiooprstatus = (struct capwap_radiooprstate_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_WTPSTATICIPADDRESS: { - element->wtpstaticipaddress = (struct capwap_wtpstaticipaddress_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding) { - unsigned long i; - struct capwap_message_elements_func* f; - - ASSERT(element != NULL); - - if (element->timers) { - capwap_get_message_element(CAPWAP_ELEMENT_TIMERS)->free(element->timers); - } - - if (element->decrypterrorresultperiod->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD); - - for (i = 0; i < element->decrypterrorresultperiod->count; i++) { - f->free(*(struct capwap_decrypterrorreport_element**)capwap_array_get_item_pointer(element->decrypterrorresultperiod, i)); - } - } - capwap_array_free(element->decrypterrorresultperiod); - - if (element->idletimeout) { - capwap_get_message_element(CAPWAP_ELEMENT_IDLETIMEOUT)->free(element->idletimeout); - } - - if (element->wtpfallback) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPFALLBACK)->free(element->wtpfallback); - } - - if (element->acipv4list) { - capwap_get_message_element(CAPWAP_ELEMENT_ACIPV4LIST)->free(element->acipv4list); - } - - if (element->acipv6list) { - capwap_get_message_element(CAPWAP_ELEMENT_ACIPV6LIST)->free(element->acipv6list); - } - - if (element->radiooprstatus->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOOPRSTATE); - - for (i = 0; i < element->radiooprstatus->count; i++) { - f->free(*(struct capwap_radiooprstate_element**)capwap_array_get_item_pointer(element->radiooprstatus, i)); - } - } - capwap_array_free(element->radiooprstatus); - - if (element->wtpstaticipaddress) { - capwap_get_message_element(CAPWAP_ELEMENT_WTPSTATICIPADDRESS)->free(element->wtpstaticipaddress); - } - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_configurationstatus_response)); -} - -/* */ -void capwap_init_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_changestateevent_request)); - - element->radiooprstatus = capwap_array_create(sizeof(struct capwap_radiooprstate_element*), 0); - element->returnedmessage = capwap_array_create(sizeof(struct capwap_returnedmessage_element*), 0); -} - -/* */ -int capwap_parsing_element_changestateevent_request(struct capwap_element_changestateevent_request* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_RADIOOPRSTATE: { - struct capwap_radiooprstate_element** radiooprstatus; - - radiooprstatus = (struct capwap_radiooprstate_element**)capwap_array_get_item_pointer(element->radiooprstatus, element->radiooprstatus->count); - *radiooprstatus = (struct capwap_radiooprstate_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_RESULTCODE: { - element->resultcode = (struct capwap_resultcode_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_RETURNEDMESSAGE: { - struct capwap_returnedmessage_element** returnedmessage; - - returnedmessage = (struct capwap_returnedmessage_element**)capwap_array_get_item_pointer(element->returnedmessage, element->returnedmessage->count); - *returnedmessage = (struct capwap_returnedmessage_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding) { - unsigned long i; - struct capwap_message_elements_func* f; - - ASSERT(element != NULL); - - if (element->radiooprstatus->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOOPRSTATE); - - for (i = 0; i < element->radiooprstatus->count; i++) { - f->free(*(struct capwap_radiooprstate_element**)capwap_array_get_item_pointer(element->radiooprstatus, i)); - } - } - capwap_array_free(element->radiooprstatus); - - if (element->resultcode) { - capwap_get_message_element(CAPWAP_ELEMENT_RESULTCODE)->free(element->resultcode); - } - - if (element->returnedmessage->count > 0) { - f = capwap_get_message_element(CAPWAP_ELEMENT_RETURNEDMESSAGE); - - for (i = 0; i < element->returnedmessage->count; i++) { - f->free(*(struct capwap_returnedmessage_element**)capwap_array_get_item_pointer(element->returnedmessage, i)); - } - } - capwap_array_free(element->returnedmessage); - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_changestateevent_request)); -} - -/* */ -void capwap_init_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_changestateevent_response)); -} - -/* */ -int capwap_parsing_element_changestateevent_response(struct capwap_element_changestateevent_response* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding) { - ASSERT(element != NULL); - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_changestateevent_response)); -} - -/* */ -void capwap_init_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_echo_request)); -} - -/* */ -int capwap_parsing_element_echo_request(struct capwap_element_echo_request* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding) { - ASSERT(element != NULL); - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_echo_request)); -} - -/* */ -void capwap_init_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_echo_response)); -} - -/* */ -int capwap_parsing_element_echo_response(struct capwap_element_echo_response* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding) { - ASSERT(element != NULL); - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_echo_response)); -} - -/* */ -void capwap_init_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_reset_request)); -} - -/* */ -int capwap_parsing_element_reset_request(struct capwap_element_reset_request* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_IMAGEIDENTIFIER: { - element->imageidentifier = (struct capwap_imageidentifier_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding) { - ASSERT(element != NULL); - - if (element->imageidentifier) { - capwap_get_message_element(CAPWAP_ELEMENT_IMAGEIDENTIFIER)->free(element->imageidentifier); - } - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_reset_request)); -} - -/* */ -void capwap_init_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding) { - ASSERT(element != NULL); - - memset(element, 0, sizeof(struct capwap_element_reset_response)); -} - -/* */ -int capwap_parsing_element_reset_response(struct capwap_element_reset_response* element, struct capwap_list_item* item) { - ASSERT(element != NULL); - - while (item != NULL) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_RESULTCODE: { - element->resultcode = (struct capwap_resultcode_element*)f->parsing(elementitem); - break; - } - - case CAPWAP_ELEMENT_VENDORPAYLOAD: { - element->vendorpayload = (struct capwap_vendorpayload_element*)f->parsing(elementitem); - break; - } - } - - /* Next element */ - item = item->next; - } - - return 1; -} - -/* */ -void capwap_free_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding) { - ASSERT(element != NULL); - - if (element->resultcode) { - capwap_get_message_element(CAPWAP_ELEMENT_RESULTCODE)->free(element->resultcode); - } - - if (element->vendorpayload) { - capwap_get_message_element(CAPWAP_ELEMENT_VENDORPAYLOAD)->free(element->vendorpayload); - } - - /* Clean */ - memset(element, 0, sizeof(struct capwap_element_reset_response)); + + /* */ + packet->connection = NULL; } diff --git a/src/common/capwap_element.h b/src/common/capwap_element.h index 40bf21b..14f109b 100644 --- a/src/common/capwap_element.h +++ b/src/common/capwap_element.h @@ -1,6 +1,7 @@ #ifndef __CAPWAP_ELEMENT_HEADER__ #define __CAPWAP_ELEMENT_HEADER__ +#include "capwap_rfc.h" #include "capwap_array.h" #include "capwap_list.h" @@ -16,26 +17,33 @@ #define CAPWAP_80211_MESSAGE_ELEMENTS_COUNT ((CAPWAP_80211_MESSAGE_ELEMENTS_STOP - CAPWAP_80211_MESSAGE_ELEMENTS_START) + 1) #define IS_80211_MESSAGE_ELEMENTS(x) (((x >= CAPWAP_80211_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_80211_MESSAGE_ELEMENTS_STOP)) ? 1 : 0) -/* Message element */ -struct capwap_message_element { - unsigned short type; - unsigned short length; - char data[0]; -} __attribute__((__packed__)); - -typedef struct capwap_message_element*(*capwap_create_message_element)(void* data, unsigned long length); -typedef int(*capwap_validate_message_element)(struct capwap_message_element* element); -typedef void*(*capwap_parsing_message_element)(struct capwap_message_element* element); -typedef void(*capwap_free_message_element)(void*); - -struct capwap_message_elements_func { - capwap_create_message_element create; - capwap_validate_message_element check; - capwap_parsing_message_element parsing; - capwap_free_message_element free; +/* */ +typedef void* capwap_message_elements_handle; +struct capwap_write_message_elements_ops { + int (*write_u8)(capwap_message_elements_handle handle, uint8_t data); + int (*write_u16)(capwap_message_elements_handle handle, uint16_t data); + int (*write_u32)(capwap_message_elements_handle handle, uint32_t data); + int (*write_block)(capwap_message_elements_handle handle, uint8_t* data, unsigned short length); }; -struct capwap_message_elements_func* capwap_get_message_element(unsigned long code); +struct capwap_read_message_elements_ops { + unsigned short (*read_ready)(capwap_message_elements_handle handle); + int (*read_u8)(capwap_message_elements_handle handle, uint8_t* data); + int (*read_u16)(capwap_message_elements_handle handle, uint16_t* data); + int (*read_u32)(capwap_message_elements_handle handle, uint32_t* data); + int (*read_block)(capwap_message_elements_handle handle, uint8_t* data, unsigned short length); +}; + +struct capwap_message_elements_ops { + /* Build message element */ + void (*create_message_element)(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func); + + /* Parsing message element */ + void* (*parsing_message_element)(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func); + void (*free_parsed_message_element)(void*); +}; + +struct capwap_message_elements_ops* capwap_get_message_element_ops(unsigned short code); /*********************************************************************************************************************/ /* Standard message elements */ @@ -106,192 +114,66 @@ struct capwap_message_elements_func* capwap_get_message_element(unsigned long co #include "capwap_element_80211_wtpradioinformation.h" /* 01048 */ /*********************************************************************************************************************/ -struct capwap_element_discovery_request { - struct capwap_discoverytype_element* discoverytype; - struct capwap_wtpboarddata_element* wtpboarddata; - struct capwap_wtpdescriptor_element* wtpdescriptor; - struct capwap_wtpframetunnelmode_element* wtpframetunnel; - struct capwap_wtpmactype_element* wtpmactype; - struct capwap_mtudiscovery_element* mtudiscovery; - struct capwap_vendorpayload_element* vendorpayload; - - union { - struct { - struct capwap_array* wtpradioinformation; - } ieee80211; - } binding; -}; - -void capwap_init_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding); -int capwap_parsing_element_discovery_request(struct capwap_element_discovery_request* element, struct capwap_list_item* item); -void capwap_free_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding); - -/* */ -struct capwap_element_discovery_response { +struct capwap_message_elements { struct capwap_acdescriptor_element* acdescriptor; + struct capwap_acipv4list_element* acipv4list; + struct capwap_acipv6list_element* acipv6list; struct capwap_acname_element* acname; - struct capwap_array* controlipv4; - struct capwap_array* controlipv6; - struct capwap_vendorpayload_element* vendorpayload; - - union { - struct { - struct capwap_array* wtpradioinformation; - } ieee80211; - } binding; -}; - -void capwap_init_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding); -int capwap_parsing_element_discovery_response(struct capwap_element_discovery_response* element, struct capwap_list_item* item); -void capwap_free_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding); - -/* */ -struct capwap_element_join_request { - struct capwap_location_element* locationdata; - struct capwap_wtpboarddata_element* wtpboarddata; - struct capwap_wtpdescriptor_element* wtpdescriptor; - struct capwap_wtpname_element* wtpname; - struct capwap_sessionid_element* sessionid; - struct capwap_wtpframetunnelmode_element* wtpframetunnel; - struct capwap_wtpmactype_element* wtpmactype; - struct capwap_ecnsupport_element* ecnsupport; - struct capwap_localipv4_element* localipv4; - struct capwap_localipv6_element* localipv6; - struct capwap_transport_element* trasport; - struct capwap_maximumlength_element* maxiumlength; - struct capwap_wtprebootstat_element* wtprebootstat; - struct capwap_vendorpayload_element* vendorpayload; - - union { - struct { - struct capwap_array* wtpradioinformation; - } ieee80211; - } binding; -}; - -void capwap_init_element_join_request(struct capwap_element_join_request* element, unsigned short binding); -int capwap_parsing_element_join_request(struct capwap_element_join_request* element, struct capwap_list_item* item); -void capwap_free_element_join_request(struct capwap_element_join_request* element, unsigned short binding); - -/* */ -struct capwap_element_join_response { - struct capwap_resultcode_element* resultcode; - struct capwap_array* returnedmessage; - struct capwap_acdescriptor_element* acdescriptor; - struct capwap_acname_element* acname; - struct capwap_ecnsupport_element* ecnsupport; - struct capwap_array* controlipv4; - struct capwap_array* controlipv6; - struct capwap_localipv4_element* localipv4; - struct capwap_localipv6_element* localipv6; - capwap_acipv4list_element_array* acipv4list; - capwap_acipv6list_element_array* acipv6list; - struct capwap_transport_element* trasport; - struct capwap_imageidentifier_element* imageidentifier; - struct capwap_maximumlength_element* maxiumlength; - struct capwap_vendorpayload_element* vendorpayload; - - union { - struct { - struct capwap_array* wtpradioinformation; - } ieee80211; - } binding; -}; - -void capwap_init_element_join_response(struct capwap_element_join_response* element, unsigned short binding); -int capwap_parsing_element_join_response(struct capwap_element_join_response* element, struct capwap_list_item* item); -void capwap_free_element_join_response(struct capwap_element_join_response* element, unsigned short binding); - -/* */ -struct capwap_element_configurationstatus_request { - struct capwap_acname_element* acname; - struct capwap_array* radioadmstatus; - struct capwap_statisticstimer_element* statisticstimer; - struct capwap_wtprebootstat_element* wtprebootstat; struct capwap_array* acnamepriority; - struct capwap_transport_element* trasport; - struct capwap_wtpstaticipaddress_element* wtpstaticipaddress; - struct capwap_vendorpayload_element* vendorpayload; -}; - -void capwap_init_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding); -int capwap_parsing_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, struct capwap_list_item* item); -void capwap_free_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding); - -/* */ -struct capwap_element_configurationstatus_response { + struct capwap_array* controlipv4; + struct capwap_array* controlipv6; struct capwap_timers_element* timers; - struct capwap_array* decrypterrorresultperiod; + struct capwap_array* decrypterrorreportperiod; + struct capwap_discoverytype_element* discoverytype; struct capwap_idletimeout_element* idletimeout; - struct capwap_wtpfallback_element* wtpfallback; - capwap_acipv4list_element_array* acipv4list; - capwap_acipv6list_element_array* acipv6list; - struct capwap_array* radiooprstatus; - struct capwap_wtpstaticipaddress_element* wtpstaticipaddress; - struct capwap_vendorpayload_element* vendorpayload; -}; - -void capwap_init_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding); -int capwap_parsing_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, struct capwap_list_item* item); -void capwap_free_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding); - -/* */ -struct capwap_element_changestateevent_request { - struct capwap_array* radiooprstatus; + struct capwap_imageidentifier_element* imageidentifier; + struct capwap_location_element* location; + struct capwap_maximumlength_element* maximumlength; + struct capwap_localipv4_element* localipv4; + struct capwap_array* radioadmstate; + struct capwap_array* radiooprstate; struct capwap_resultcode_element* resultcode; struct capwap_array* returnedmessage; + struct capwap_sessionid_element* sessionid; + struct capwap_statisticstimer_element* statisticstimer; struct capwap_vendorpayload_element* vendorpayload; + struct capwap_wtpboarddata_element* wtpboarddata; + struct capwap_wtpdescriptor_element* wtpdescriptor; + struct capwap_wtpfallback_element* wtpfallback; + struct capwap_wtpframetunnelmode_element* wtpframetunnel; + struct capwap_wtpmactype_element* wtpmactype; + struct capwap_wtpname_element* wtpname; + struct capwap_wtprebootstat_element* wtprebootstat; + struct capwap_wtpstaticipaddress_element* wtpstaticipaddress; + struct capwap_localipv6_element* localipv6; + struct capwap_transport_element* transport; + struct capwap_mtudiscovery_element* mtudiscovery; + struct capwap_ecnsupport_element* ecnsupport; + + union { + struct { + struct capwap_array* antenna; + struct capwap_array* directsequencecontrol; + struct capwap_array* macoperation; + struct capwap_array* multidomaincapability; + struct capwap_array* ofdmcontrol; + struct capwap_array* rateset; + struct capwap_array* supportedrates; + struct capwap_array* txpower; + struct capwap_array* txpowerlevel; + struct capwap_array* wtpradioinformation; + } ieee80211; + }; }; -void capwap_init_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding); -int capwap_parsing_element_changestateevent_request(struct capwap_element_changestateevent_request* element, struct capwap_list_item* item); -void capwap_free_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding); - -/* */ -struct capwap_element_changestateevent_response { - struct capwap_vendorpayload_element* vendorpayload; +struct capwap_parsed_packet { + struct capwap_packet_rxmng* rxmngpacket; + struct capwap_connection* connection; + struct capwap_message_elements messageelements; }; -void capwap_init_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding); -int capwap_parsing_element_changestateevent_response(struct capwap_element_changestateevent_response* element, struct capwap_list_item* item); -void capwap_free_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding); - -/* */ -struct capwap_element_echo_request { - struct capwap_vendorpayload_element* vendorpayload; -}; - -void capwap_init_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding); -int capwap_parsing_element_echo_request(struct capwap_element_echo_request* element, struct capwap_list_item* item); -void capwap_free_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding); - -/* */ -struct capwap_element_echo_response { - struct capwap_vendorpayload_element* vendorpayload; -}; - -void capwap_init_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding); -int capwap_parsing_element_echo_response(struct capwap_element_echo_response* element, struct capwap_list_item* item); -void capwap_free_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding); - -/* */ -struct capwap_element_reset_request { - struct capwap_imageidentifier_element* imageidentifier; - struct capwap_vendorpayload_element* vendorpayload; -}; - -void capwap_init_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding); -int capwap_parsing_element_reset_request(struct capwap_element_reset_request* element, struct capwap_list_item* item); -void capwap_free_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding); - -/* */ -struct capwap_element_reset_response { - struct capwap_resultcode_element* resultcode; - struct capwap_vendorpayload_element* vendorpayload; -}; - -void capwap_init_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding); -int capwap_parsing_element_reset_response(struct capwap_element_reset_response* element, struct capwap_list_item* item); -void capwap_free_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding); +int capwap_parsing_packet(struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, struct capwap_parsed_packet* packet); +int capwap_validate_parsed_packet(struct capwap_parsed_packet* packet, struct capwap_array* returnedmessage); +void capwap_free_parsed_packet(struct capwap_parsed_packet* packet); #endif /* __CAPWAP_ELEMENT_HEADER__ */ diff --git a/src/common/capwap_element_80211_antenna.c b/src/common/capwap_element_80211_antenna.c index d6bf385..977b6c5 100644 --- a/src/common/capwap_element_80211_antenna.c +++ b/src/common/capwap_element_80211_antenna.c @@ -17,98 +17,74 @@ Length: >= 5 ********************************************************************/ -struct capwap_80211_antenna_raw_element { - unsigned char radioid; - unsigned char diversity; - unsigned char combiner; - unsigned char antennacount; - unsigned char antennaselections[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_antenna_element_create(void* data, unsigned long datalength) { - int i; - unsigned short antennalength; - struct capwap_message_element* element; - struct capwap_80211_antenna_raw_element* dataraw; - struct capwap_80211_antenna_element* dataelement = (struct capwap_80211_antenna_element*)data; +static void capwap_80211_antenna_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_antenna_element* element = (struct capwap_80211_antenna_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_antenna_element)); - /* Alloc block of memory */ - antennalength = dataelement->antennacount * sizeof(unsigned char); - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_antenna_raw_element) + antennalength); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_antenna_raw_element) + antennalength); - element->type = htons(CAPWAP_ELEMENT_80211_ANTENNA); - element->length = htons(sizeof(struct capwap_80211_antenna_raw_element) + antennalength); - dataraw = (struct capwap_80211_antenna_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->diversity = dataelement->diversity; - dataraw->combiner = dataelement->combiner; - dataraw->antennacount = dataelement->antennacount; - for (i = 0; i < dataelement->antennacount; i++) { - dataraw->antennaselections[i] = dataelement->antennaselections[i]; - } - - return element; + func->write_u8(handle, element->radioid); + func->write_u8(handle, element->diversity); + func->write_u8(handle, element->combiner); + func->write_u8(handle, element->antennacount); + func->write_block(handle, element->antennaselections, element->antennacount); } /* */ -int capwap_80211_antenna_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_antenna_element_parsing(struct capwap_message_element* element) { - int i; - unsigned short antennalength; +static void* capwap_80211_antenna_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_80211_antenna_element* data; - struct capwap_80211_antenna_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_ANTENNA); - antennalength = ntohs(element->length); - if (antennalength < 5) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length < 5) { + capwap_logging_debug("Invalid IEEE 802.11 Antenna element"); return NULL; } - antennalength -= sizeof(struct capwap_80211_antenna_raw_element); - if (antennalength > CAPWAP_ANTENNASELECTIONS_MAXLENGTH) { + length -= 4; + if (length > CAPWAP_ANTENNASELECTIONS_MAXLENGTH) { + capwap_logging_debug("Invalid IEEE 802.11 Antenna element"); return NULL; } - dataraw = (struct capwap_80211_antenna_raw_element*)element->data; - /* */ data = (struct capwap_80211_antenna_element*)capwap_alloc(sizeof(struct capwap_80211_antenna_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->diversity = dataraw->diversity; - data->combiner = dataraw->combiner; - data->antennacount = dataraw->antennacount; - for (i = 0; i < dataraw->antennacount; i++) { - data->antennaselections[i] = dataraw->antennaselections[i]; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_antenna_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, &data->diversity); + func->read_u8(handle, &data->combiner); + func->read_u8(handle, &data->antennacount); + + /* Check */ + if (data->antennacount != length) { + capwap_logging_debug("Invalid IEEE 802.11 Antenna element"); + capwap_free(data); + return NULL; } + func->read_block(handle, data->antennaselections, length); + return data; } /* */ -void capwap_80211_antenna_element_free(void* data) { +static void capwap_80211_antenna_element_free(void* data) { ASSERT(data != NULL); - + capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_antenna_ops = { + .create_message_element = capwap_80211_antenna_element_create, + .parsing_message_element = capwap_80211_antenna_element_parsing, + .free_parsed_message_element = capwap_80211_antenna_element_free +}; diff --git a/src/common/capwap_element_80211_antenna.h b/src/common/capwap_element_80211_antenna.h index 98031ab..89fa5ff 100644 --- a/src/common/capwap_element_80211_antenna.h +++ b/src/common/capwap_element_80211_antenna.h @@ -3,16 +3,6 @@ #define CAPWAP_ELEMENT_80211_ANTENNA 1025 -#define CAPWAP_ANTENNASELECTIONS_MAXLENGTH 255 - -struct capwap_80211_antenna_element { - unsigned char radioid; - unsigned char diversity; - unsigned char combiner; - unsigned char antennacount; - unsigned char antennaselections[CAPWAP_ANTENNASELECTIONS_MAXLENGTH]; -}; - #define CAPWAP_ANTENNA_DIVERSITY_DISABLE 0 #define CAPWAP_ANTENNA_DIVERSITY_ENABLE 1 @@ -24,15 +14,16 @@ struct capwap_80211_antenna_element { #define CAPWAP_ANTENNA_INTERNAL 1 #define CAPWAP_ANTENNA_EXTERNAL 2 -struct capwap_message_element* capwap_80211_antenna_element_create(void* data, unsigned long length); -int capwap_80211_antenna_element_validate(struct capwap_message_element* element); -void* capwap_80211_antenna_element_parsing(struct capwap_message_element* element); -void capwap_80211_antenna_element_free(void* data); +#define CAPWAP_ANTENNASELECTIONS_MAXLENGTH 255 + +struct capwap_80211_antenna_element { + uint8_t radioid; + uint8_t diversity; + uint8_t combiner; + uint8_t antennacount; + uint8_t antennaselections[CAPWAP_ANTENNASELECTIONS_MAXLENGTH]; +}; + +extern struct capwap_message_elements_ops capwap_element_80211_antenna_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_ANTENNA_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_ANTENNA); \ - f->create(x, sizeof(struct capwap_80211_antenna_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_ANTENNA_HEADER__ */ diff --git a/src/common/capwap_element_80211_directsequencecontrol.c b/src/common/capwap_element_80211_directsequencecontrol.c index 6316915..bdd3b4c 100644 --- a/src/common/capwap_element_80211_directsequencecontrol.c +++ b/src/common/capwap_element_80211_directsequencecontrol.c @@ -17,79 +17,59 @@ Length: 8 ********************************************************************/ -struct capwap_80211_directsequencecontrol_raw_element { - unsigned char radioid; - unsigned char reserved; - unsigned char currentchannel; - unsigned char currentcca; - unsigned long enerydetectthreshold; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_dscontrol_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_80211_directsequencecontrol_raw_element* dataraw; - struct capwap_80211_directsequencecontrol_element* dataelement = (struct capwap_80211_directsequencecontrol_element*)data; +static void capwap_80211_directsequencecontrol_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_directsequencecontrol_element* element = (struct capwap_80211_directsequencecontrol_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_directsequencecontrol_element)); - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_directsequencecontrol_raw_element)); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_directsequencecontrol_raw_element)); - element->type = htons(CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL); - element->length = htons(sizeof(struct capwap_80211_directsequencecontrol_raw_element)); - dataraw = (struct capwap_80211_directsequencecontrol_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->currentchannel = dataelement->currentchannel; - dataraw->currentcca = dataelement->currentcca; - dataraw->enerydetectthreshold = htonl(dataelement->enerydetectthreshold); - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u8(handle, 0); + func->write_u8(handle, element->currentchannel); + func->write_u8(handle, element->currentcca); + func->write_u32(handle, element->enerydetectthreshold); } /* */ -int capwap_80211_dscontrol_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_dscontrol_element_parsing(struct capwap_message_element* element) { +static void* capwap_80211_directsequencecontrol_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_80211_directsequencecontrol_element* data; - struct capwap_80211_directsequencecontrol_raw_element* dataraw; - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL); + ASSERT(handle != NULL); + ASSERT(func != NULL); - if (ntohs(element->length) != 8) { + if (func->read_ready(handle) != 8) { + capwap_logging_debug("Invalid IEEE 802.11 Direct Sequence Control element"); return NULL; } - dataraw = (struct capwap_80211_directsequencecontrol_raw_element*)element->data; - /* */ data = (struct capwap_80211_directsequencecontrol_element*)capwap_alloc(sizeof(struct capwap_80211_directsequencecontrol_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->currentchannel = dataraw->currentchannel; - data->currentcca = dataraw->currentcca; - data->enerydetectthreshold = ntohl(dataraw->enerydetectthreshold); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_directsequencecontrol_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, NULL); + func->read_u8(handle, &data->currentchannel); + func->read_u8(handle, &data->currentcca); + func->read_u32(handle, &data->enerydetectthreshold); + return data; } /* */ -void capwap_80211_dscontrol_element_free(void* data) { +static void capwap_80211_directsequencecontrol_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_directsequencecontrol_ops = { + .create_message_element = capwap_80211_directsequencecontrol_element_create, + .parsing_message_element = capwap_80211_directsequencecontrol_element_parsing, + .free_parsed_message_element = capwap_80211_directsequencecontrol_element_free +}; diff --git a/src/common/capwap_element_80211_directsequencecontrol.h b/src/common/capwap_element_80211_directsequencecontrol.h index db99ddf..e87f64e 100644 --- a/src/common/capwap_element_80211_directsequencecontrol.h +++ b/src/common/capwap_element_80211_directsequencecontrol.h @@ -3,28 +3,19 @@ #define CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL 1028 -struct capwap_80211_directsequencecontrol_element { - unsigned char radioid; - unsigned char currentchannel; - unsigned char currentcca; - unsigned long enerydetectthreshold; -}; - #define CAPWAP_DSCONTROL_CCA_EDONLY 1 #define CAPWAP_DSCONTROL_CCA_CSONLY 2 #define CAPWAP_DSCONTROL_CCA_EDANDCS 4 #define CAPWAP_DSCONTROL_CCA_CSWITHTIME 8 #define CAPWAP_DSCONTROL_CCA_HRCSANDED 16 -struct capwap_message_element* capwap_80211_dscontrol_element_create(void* data, unsigned long length); -int capwap_80211_dscontrol_element_validate(struct capwap_message_element* element); -void* capwap_80211_dscontrol_element_parsing(struct capwap_message_element* element); -void capwap_80211_dscontrol_element_free(void* data); +struct capwap_80211_directsequencecontrol_element { + uint8_t radioid; + uint8_t currentchannel; + uint8_t currentcca; + uint32_t enerydetectthreshold; +}; + +extern struct capwap_message_elements_ops capwap_element_80211_directsequencecontrol_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_DIRECTSEQUENCECONTROL_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL); \ - f->create(x, sizeof(struct capwap_80211_directsequencecontrol_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_DIRECTSEQUENCECONTROL_HEADER__ */ diff --git a/src/common/capwap_element_80211_macoperation.c b/src/common/capwap_element_80211_macoperation.c index ceca243..5a2454b 100644 --- a/src/common/capwap_element_80211_macoperation.c +++ b/src/common/capwap_element_80211_macoperation.c @@ -21,88 +21,65 @@ Length: 16 ********************************************************************/ -struct capwap_80211_macoperation_raw_element { - unsigned char radioid; - unsigned char reserved; - unsigned short rtsthreshold; - unsigned char shortretry; - unsigned char longretry; - unsigned short fragthreshold; - unsigned long txmsdulifetime; - unsigned long rxmsdulifetime; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_macoperation_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_80211_macoperation_raw_element* dataraw; - struct capwap_80211_macoperation_element* dataelement = (struct capwap_80211_macoperation_element*)data; +static void capwap_80211_macoperation_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_macoperation_element* element = (struct capwap_80211_macoperation_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_macoperation_element)); - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_macoperation_raw_element)); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_macoperation_raw_element)); - element->type = htons(CAPWAP_ELEMENT_80211_MACOPERATION); - element->length = htons(sizeof(struct capwap_80211_macoperation_raw_element)); - dataraw = (struct capwap_80211_macoperation_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->rtsthreshold = htons(dataelement->rtsthreshold); - dataraw->shortretry = dataelement->shortretry; - dataraw->longretry = dataelement->longretry; - dataraw->fragthreshold = htons(dataelement->fragthreshold); - dataraw->txmsdulifetime = htonl(dataelement->txmsdulifetime); - dataraw->rxmsdulifetime = htonl(dataelement->rxmsdulifetime); - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u8(handle, 0); + func->write_u16(handle, element->rtsthreshold); + func->write_u8(handle, element->shortretry); + func->write_u8(handle, element->longretry); + func->write_u16(handle, element->fragthreshold); + func->write_u32(handle, element->txmsdulifetime); + func->write_u32(handle, element->rxmsdulifetime); } /* */ -int capwap_80211_macoperation_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_macoperation_element_parsing(struct capwap_message_element* element) { +static void* capwap_80211_macoperation_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_80211_macoperation_element* data; - struct capwap_80211_macoperation_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_MACOPERATION); - - if (ntohs(element->length) != 16) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 16) { + capwap_logging_debug("Invalid IEEE 802.11 MAC Operation element"); return NULL; } - dataraw = (struct capwap_80211_macoperation_raw_element*)element->data; - /* */ data = (struct capwap_80211_macoperation_element*)capwap_alloc(sizeof(struct capwap_80211_macoperation_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->rtsthreshold = ntohs(dataraw->rtsthreshold); - data->shortretry = dataraw->shortretry; - data->longretry = dataraw->longretry; - data->fragthreshold = ntohs(dataraw->fragthreshold); - data->txmsdulifetime = ntohl(dataraw->txmsdulifetime); - data->rxmsdulifetime = ntohl(dataraw->rxmsdulifetime); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_macoperation_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, NULL); + func->read_u16(handle, &data->rtsthreshold); + func->read_u8(handle, &data->shortretry); + func->read_u8(handle, &data->longretry); + func->read_u16(handle, &data->fragthreshold); + func->read_u32(handle, &data->txmsdulifetime); + func->read_u32(handle, &data->rxmsdulifetime); + return data; } /* */ -void capwap_80211_macoperation_element_free(void* data) { +static void capwap_80211_macoperation_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_macoperation_ops = { + .create_message_element = capwap_80211_macoperation_element_create, + .parsing_message_element = capwap_80211_macoperation_element_parsing, + .free_parsed_message_element = capwap_80211_macoperation_element_free +}; diff --git a/src/common/capwap_element_80211_macoperation.h b/src/common/capwap_element_80211_macoperation.h index cf9656a..535b640 100644 --- a/src/common/capwap_element_80211_macoperation.h +++ b/src/common/capwap_element_80211_macoperation.h @@ -4,24 +4,15 @@ #define CAPWAP_ELEMENT_80211_MACOPERATION 1030 struct capwap_80211_macoperation_element { - unsigned char radioid; - unsigned short rtsthreshold; - unsigned char shortretry; - unsigned char longretry; - unsigned short fragthreshold; - unsigned long txmsdulifetime; - unsigned long rxmsdulifetime; + uint8_t radioid; + uint16_t rtsthreshold; + uint8_t shortretry; + uint8_t longretry; + uint16_t fragthreshold; + uint32_t txmsdulifetime; + uint32_t rxmsdulifetime; }; -struct capwap_message_element* capwap_80211_macoperation_element_create(void* data, unsigned long length); -int capwap_80211_macoperation_element_validate(struct capwap_message_element* element); -void* capwap_80211_macoperation_element_parsing(struct capwap_message_element* element); -void capwap_80211_macoperation_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_80211_macoperation_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_MACOPERATION_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_MACOPERATION); \ - f->create(x, sizeof(struct capwap_80211_macoperation_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_MACOPERATION_HEADER__ */ diff --git a/src/common/capwap_element_80211_multidomaincapability.c b/src/common/capwap_element_80211_multidomaincapability.c index 3073ab2..6fd3b63 100644 --- a/src/common/capwap_element_80211_multidomaincapability.c +++ b/src/common/capwap_element_80211_multidomaincapability.c @@ -17,79 +17,59 @@ Length: 8 ********************************************************************/ -struct capwap_80211_multidomaincapability_raw_element { - unsigned char radioid; - unsigned char reserved; - unsigned short firstchannel; - unsigned short numberchannels; - unsigned short maxtxpowerlevel; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_multidomaincapability_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_80211_multidomaincapability_raw_element* dataraw; - struct capwap_80211_multidomaincapability_element* dataelement = (struct capwap_80211_multidomaincapability_element*)data; +static void capwap_80211_multidomaincapability_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_multidomaincapability_element* element = (struct capwap_80211_multidomaincapability_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_multidomaincapability_element)); - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_multidomaincapability_raw_element)); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_multidomaincapability_raw_element)); - element->type = htons(CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY); - element->length = htons(sizeof(struct capwap_80211_multidomaincapability_raw_element)); - dataraw = (struct capwap_80211_multidomaincapability_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->firstchannel = htons(dataelement->firstchannel); - dataraw->numberchannels = htons(dataelement->numberchannels); - dataraw->maxtxpowerlevel = htons(dataelement->maxtxpowerlevel); - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u8(handle, 0); + func->write_u16(handle, element->firstchannel); + func->write_u16(handle, element->numberchannels); + func->write_u16(handle, element->maxtxpowerlevel); } /* */ -int capwap_80211_multidomaincapability_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_multidomaincapability_element_parsing(struct capwap_message_element* element) { +static void* capwap_80211_multidomaincapability_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_80211_multidomaincapability_element* data; - struct capwap_80211_multidomaincapability_raw_element* dataraw; - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY); + ASSERT(handle != NULL); + ASSERT(func != NULL); - if (ntohs(element->length) != 8) { + if (func->read_ready(handle) != 8) { + capwap_logging_debug("Invalid IEEE 802.11 Multi-Domain Capability element"); return NULL; } - dataraw = (struct capwap_80211_multidomaincapability_raw_element*)element->data; - /* */ data = (struct capwap_80211_multidomaincapability_element*)capwap_alloc(sizeof(struct capwap_80211_multidomaincapability_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->firstchannel = ntohs(dataraw->firstchannel); - data->numberchannels = htons(dataraw->numberchannels); - data->maxtxpowerlevel = htons(dataraw->maxtxpowerlevel); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_multidomaincapability_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, NULL); + func->read_u16(handle, &data->firstchannel); + func->read_u16(handle, &data->numberchannels); + func->read_u16(handle, &data->maxtxpowerlevel); + return data; } /* */ -void capwap_80211_multidomaincapability_element_free(void* data) { +static void capwap_80211_multidomaincapability_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_multidomaincapability_ops = { + .create_message_element = capwap_80211_multidomaincapability_element_create, + .parsing_message_element = capwap_80211_multidomaincapability_element_parsing, + .free_parsed_message_element = capwap_80211_multidomaincapability_element_free +}; diff --git a/src/common/capwap_element_80211_multidomaincapability.h b/src/common/capwap_element_80211_multidomaincapability.h index af446a1..a84e99c 100644 --- a/src/common/capwap_element_80211_multidomaincapability.h +++ b/src/common/capwap_element_80211_multidomaincapability.h @@ -4,21 +4,12 @@ #define CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY 1032 struct capwap_80211_multidomaincapability_element { - unsigned char radioid; - unsigned short firstchannel; - unsigned short numberchannels; - unsigned short maxtxpowerlevel; + uint8_t radioid; + uint16_t firstchannel; + uint16_t numberchannels; + uint16_t maxtxpowerlevel; }; -struct capwap_message_element* capwap_80211_multidomaincapability_element_create(void* data, unsigned long length); -int capwap_80211_multidomaincapability_element_validate(struct capwap_message_element* element); -void* capwap_80211_multidomaincapability_element_parsing(struct capwap_message_element* element); -void capwap_80211_multidomaincapability_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_80211_multidomaincapability_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_MULTIDOMAINCAPABILITY_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY); \ - f->create(x, sizeof(struct capwap_80211_multidomaincapability_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_MULTIDOMAINCAPABILITY_HEADER__ */ diff --git a/src/common/capwap_element_80211_ofdmcontrol.c b/src/common/capwap_element_80211_ofdmcontrol.c index 015acb1..39253c0 100644 --- a/src/common/capwap_element_80211_ofdmcontrol.c +++ b/src/common/capwap_element_80211_ofdmcontrol.c @@ -17,79 +17,59 @@ Length: 8 ********************************************************************/ -struct capwap_80211_ofdmcontrol_raw_element { - unsigned char radioid; - unsigned char reserved; - unsigned char currentchannel; - unsigned char bandsupport; - unsigned long tithreshold; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_ofdmcontrol_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_80211_ofdmcontrol_raw_element* dataraw; - struct capwap_80211_ofdmcontrol_element* dataelement = (struct capwap_80211_ofdmcontrol_element*)data; +static void capwap_80211_ofdmcontrol_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_ofdmcontrol_element* element = (struct capwap_80211_ofdmcontrol_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_ofdmcontrol_element)); - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_ofdmcontrol_raw_element)); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_ofdmcontrol_raw_element)); - element->type = htons(CAPWAP_ELEMENT_80211_OFDMCONTROL); - element->length = htons(sizeof(struct capwap_80211_ofdmcontrol_raw_element)); - dataraw = (struct capwap_80211_ofdmcontrol_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->currentchannel = dataelement->currentchannel; - dataraw->bandsupport = dataelement->bandsupport; - dataraw->tithreshold = htonl(dataelement->tithreshold); - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u8(handle, 0); + func->write_u8(handle, element->currentchannel); + func->write_u8(handle, element->bandsupport); + func->write_u32(handle, element->tithreshold); } /* */ -int capwap_80211_ofdmcontrol_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_ofdmcontrol_element_parsing(struct capwap_message_element* element) { +static void* capwap_80211_ofdmcontrol_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_80211_ofdmcontrol_element* data; - struct capwap_80211_ofdmcontrol_raw_element* dataraw; - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_OFDMCONTROL); + ASSERT(handle != NULL); + ASSERT(func != NULL); - if (ntohs(element->length) != 8) { + if (func->read_ready(handle) != 8) { + capwap_logging_debug("Invalid IEEE 802.11 OFDM Control element"); return NULL; } - dataraw = (struct capwap_80211_ofdmcontrol_raw_element*)element->data; - /* */ data = (struct capwap_80211_ofdmcontrol_element*)capwap_alloc(sizeof(struct capwap_80211_ofdmcontrol_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->currentchannel = ntohs(dataraw->currentchannel); - data->bandsupport = ntohs(dataraw->bandsupport); - data->tithreshold = ntohl(dataraw->tithreshold); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_ofdmcontrol_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, NULL); + func->read_u8(handle, &data->currentchannel); + func->read_u8(handle, &data->bandsupport); + func->read_u32(handle, &data->tithreshold); + return data; } /* */ -void capwap_80211_ofdmcontrol_element_free(void* data) { +static void capwap_80211_ofdmcontrol_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_ofdmcontrol_ops = { + .create_message_element = capwap_80211_ofdmcontrol_element_create, + .parsing_message_element = capwap_80211_ofdmcontrol_element_parsing, + .free_parsed_message_element = capwap_80211_ofdmcontrol_element_free +}; diff --git a/src/common/capwap_element_80211_ofdmcontrol.h b/src/common/capwap_element_80211_ofdmcontrol.h index 3ceafab..eec1de2 100644 --- a/src/common/capwap_element_80211_ofdmcontrol.h +++ b/src/common/capwap_element_80211_ofdmcontrol.h @@ -3,13 +3,6 @@ #define CAPWAP_ELEMENT_80211_OFDMCONTROL 1033 -struct capwap_80211_ofdmcontrol_element { - unsigned char radioid; - unsigned char currentchannel; - unsigned char bandsupport; - unsigned long tithreshold; -}; - #define CAPWAP_OFDMCONTROL_BAND_515_525 0x01 #define CAPWAP_OFDMCONTROL_BAND_525_535 0x02 #define CAPWAP_OFDMCONTROL_BAND_5725_5825 0x04 @@ -18,15 +11,13 @@ struct capwap_80211_ofdmcontrol_element { #define CAPWAP_OFDMCONTROL_BAND_503_5091 0x20 #define CAPWAP_OFDMCONTROL_BAND_494_499 0x40 -struct capwap_message_element* capwap_80211_ofdmcontrol_element_create(void* data, unsigned long length); -int capwap_80211_ofdmcontrol_element_validate(struct capwap_message_element* element); -void* capwap_80211_ofdmcontrol_element_parsing(struct capwap_message_element* element); -void capwap_80211_ofdmcontrol_element_free(void* data); +struct capwap_80211_ofdmcontrol_element { + uint8_t radioid; + uint8_t currentchannel; + uint8_t bandsupport; + uint32_t tithreshold; +}; + +extern struct capwap_message_elements_ops capwap_element_80211_ofdmcontrol_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_OFDMCONTROL_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_OFDMCONTROL); \ - f->create(x, sizeof(struct capwap_80211_ofdmcontrol_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_OFDMCONTROL_HEADER__ */ diff --git a/src/common/capwap_element_80211_rateset.c b/src/common/capwap_element_80211_rateset.c index 5eabc7b..b78f489 100644 --- a/src/common/capwap_element_80211_rateset.c +++ b/src/common/capwap_element_80211_rateset.c @@ -15,90 +15,61 @@ Length: >= 3 ********************************************************************/ -struct capwap_80211_rateset_raw_element { - unsigned char radioid; - unsigned char rateset[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_rateset_element_create(void* data, unsigned long datalength) { - int i; - unsigned short ratesetlength; - struct capwap_message_element* element; - struct capwap_80211_rateset_raw_element* dataraw; - struct capwap_80211_rateset_element* dataelement = (struct capwap_80211_rateset_element*)data; +static void capwap_80211_rateset_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_rateset_element* element = (struct capwap_80211_rateset_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_rateset_element)); - /* Alloc block of memory */ - ratesetlength = dataelement->ratesetcount * sizeof(unsigned char); - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_rateset_raw_element) + ratesetlength); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_rateset_raw_element) + ratesetlength); - element->type = htons(CAPWAP_ELEMENT_80211_RATESET); - element->length = htons(sizeof(struct capwap_80211_rateset_raw_element) + ratesetlength); - dataraw = (struct capwap_80211_rateset_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - for (i = 0; i < dataelement->ratesetcount; i++) { - dataraw->rateset[i] = dataelement->rateset[i]; - } - - return element; + func->write_u8(handle, element->radioid); + func->write_block(handle, element->rateset, element->ratesetcount); } /* */ -int capwap_80211_rateset_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_rateset_element_parsing(struct capwap_message_element* element) { - int i; - unsigned short ratesetlength; +static void* capwap_80211_rateset_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_80211_rateset_element* data; - struct capwap_80211_rateset_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_RATESET); - ratesetlength = ntohs(element->length); - if (ratesetlength < 3) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length < 3) { + capwap_logging_debug("Invalid IEEE 802.11 Rate Set element"); return NULL; } - ratesetlength -= sizeof(struct capwap_80211_rateset_raw_element); - if (ratesetlength > CAPWAP_SUPPORTEDRATES_MAXLENGTH) { + length -= 1; + if (length > CAPWAP_RATESET_MAXLENGTH) { + capwap_logging_debug("Invalid IEEE 802.11 Rate Set element"); return NULL; } - dataraw = (struct capwap_80211_rateset_raw_element*)element->data; - /* */ data = (struct capwap_80211_rateset_element*)capwap_alloc(sizeof(struct capwap_80211_rateset_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->ratesetcount = ratesetlength; - for (i = 0; i < ratesetlength; i++) { - data->rateset[i] = dataraw->rateset[i]; - } + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_rateset_element)); + func->read_u8(handle, &data->radioid); + data->ratesetcount = length; + func->read_block(handle, data->rateset, length); return data; } /* */ -void capwap_80211_rateset_element_free(void* data) { +static void capwap_80211_rateset_element_free(void* data) { ASSERT(data != NULL); - + capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_rateset_ops = { + .create_message_element = capwap_80211_rateset_element_create, + .parsing_message_element = capwap_80211_rateset_element_parsing, + .free_parsed_message_element = capwap_80211_rateset_element_free +}; diff --git a/src/common/capwap_element_80211_rateset.h b/src/common/capwap_element_80211_rateset.h index bfd4d75..4648ff6 100644 --- a/src/common/capwap_element_80211_rateset.h +++ b/src/common/capwap_element_80211_rateset.h @@ -7,20 +7,11 @@ #define CAPWAP_RATESET_MAXLENGTH 8 struct capwap_80211_rateset_element { - unsigned char radioid; - unsigned char ratesetcount; - unsigned char rateset[CAPWAP_RATESET_MAXLENGTH]; + uint8_t radioid; + uint8_t ratesetcount; + uint8_t rateset[CAPWAP_RATESET_MAXLENGTH]; }; -struct capwap_message_element* capwap_80211_rateset_element_create(void* data, unsigned long length); -int capwap_80211_rateset_element_validate(struct capwap_message_element* element); -void* capwap_80211_rateset_element_parsing(struct capwap_message_element* element); -void capwap_80211_rateset_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_80211_rateset_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_RATESET_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_RATESET); \ - f->create(x, sizeof(struct capwap_80211_rateset_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_RATESET_HEADER__ */ diff --git a/src/common/capwap_element_80211_supportedrates.c b/src/common/capwap_element_80211_supportedrates.c index 7be22d3..4fb31c2 100644 --- a/src/common/capwap_element_80211_supportedrates.c +++ b/src/common/capwap_element_80211_supportedrates.c @@ -15,90 +15,61 @@ Length: >= 3 ********************************************************************/ -struct capwap_80211_supportedrates_raw_element { - unsigned char radioid; - unsigned char supportedrates[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_supportedrates_element_create(void* data, unsigned long datalength) { - int i; - unsigned short supportedrateslength; - struct capwap_message_element* element; - struct capwap_80211_supportedrates_raw_element* dataraw; - struct capwap_80211_supportedrates_element* dataelement = (struct capwap_80211_supportedrates_element*)data; +static void capwap_80211_supportedrates_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_supportedrates_element* element = (struct capwap_80211_supportedrates_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_supportedrates_element)); - /* Alloc block of memory */ - supportedrateslength = dataelement->supportedratescount * sizeof(unsigned char); - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_supportedrates_raw_element) + supportedrateslength); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_supportedrates_raw_element) + supportedrateslength); - element->type = htons(CAPWAP_ELEMENT_80211_SUPPORTEDRATES); - element->length = htons(sizeof(struct capwap_80211_supportedrates_raw_element) + supportedrateslength); - dataraw = (struct capwap_80211_supportedrates_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - for (i = 0; i < dataelement->supportedratescount; i++) { - dataraw->supportedrates[i] = dataelement->supportedrates[i]; - } - - return element; + func->write_u8(handle, element->radioid); + func->write_block(handle, element->supportedrates, element->supportedratescount); } /* */ -int capwap_80211_supportedrates_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_supportedrates_element_parsing(struct capwap_message_element* element) { - int i; - unsigned short supportedrateslength; +static void* capwap_80211_supportedrates_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_80211_supportedrates_element* data; - struct capwap_80211_supportedrates_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_SUPPORTEDRATES); - supportedrateslength = ntohs(element->length); - if (supportedrateslength < 3) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length < 3) { + capwap_logging_debug("Invalid IEEE 802.11 Supported Rates element"); return NULL; } - supportedrateslength -= sizeof(struct capwap_80211_supportedrates_raw_element); - if (supportedrateslength > CAPWAP_SUPPORTEDRATES_MAXLENGTH) { + length -= 1; + if (length > CAPWAP_RATESET_MAXLENGTH) { + capwap_logging_debug("Invalid IEEE 802.11 Supported Rates element"); return NULL; } - dataraw = (struct capwap_80211_supportedrates_raw_element*)element->data; - /* */ data = (struct capwap_80211_supportedrates_element*)capwap_alloc(sizeof(struct capwap_80211_supportedrates_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->supportedratescount = supportedrateslength; - for (i = 0; i < supportedrateslength; i++) { - data->supportedrates[i] = dataraw->supportedrates[i]; - } + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_supportedrates_element)); + func->read_u8(handle, &data->radioid); + data->supportedratescount = length; + func->read_block(handle, data->supportedrates, length); return data; } /* */ -void capwap_80211_supportedrates_element_free(void* data) { +static void capwap_80211_supportedrates_element_free(void* data) { ASSERT(data != NULL); - + capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_supportedrates_ops = { + .create_message_element = capwap_80211_supportedrates_element_create, + .parsing_message_element = capwap_80211_supportedrates_element_parsing, + .free_parsed_message_element = capwap_80211_supportedrates_element_free +}; diff --git a/src/common/capwap_element_80211_supportedrates.h b/src/common/capwap_element_80211_supportedrates.h index 75bb8cd..c507a60 100644 --- a/src/common/capwap_element_80211_supportedrates.h +++ b/src/common/capwap_element_80211_supportedrates.h @@ -7,20 +7,11 @@ #define CAPWAP_SUPPORTEDRATES_MAXLENGTH 8 struct capwap_80211_supportedrates_element { - unsigned char radioid; - unsigned char supportedratescount; - unsigned char supportedrates[CAPWAP_SUPPORTEDRATES_MAXLENGTH]; + uint8_t radioid; + uint8_t supportedratescount; + uint8_t supportedrates[CAPWAP_SUPPORTEDRATES_MAXLENGTH]; }; -struct capwap_message_element* capwap_80211_supportedrates_element_create(void* data, unsigned long length); -int capwap_80211_supportedrates_element_validate(struct capwap_message_element* element); -void* capwap_80211_supportedrates_element_parsing(struct capwap_message_element* element); -void capwap_80211_supportedrates_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_80211_supportedrates_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_SUPPORTEDRATES_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_SUPPORTEDRATES); \ - f->create(x, sizeof(struct capwap_80211_supportedrates_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_SUPPORTEDRATES_HEADER__ */ diff --git a/src/common/capwap_element_80211_txpower.c b/src/common/capwap_element_80211_txpower.c index 8b4fd18..8b83b2e 100644 --- a/src/common/capwap_element_80211_txpower.c +++ b/src/common/capwap_element_80211_txpower.c @@ -15,72 +15,55 @@ Length: 4 ********************************************************************/ -struct capwap_80211_txpower_raw_element { - unsigned char radioid; - unsigned short currenttxpower; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_txpower_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_80211_txpower_raw_element* dataraw; - struct capwap_80211_txpower_element* dataelement = (struct capwap_80211_txpower_element*)data; - +static void capwap_80211_txpower_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_txpower_element* element = (struct capwap_80211_txpower_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_txpower_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_txpower_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_txpower_raw_element)); - element->type = htons(CAPWAP_ELEMENT_80211_TXPOWER); - element->length = htons(sizeof(struct capwap_80211_txpower_raw_element)); - dataraw = (struct capwap_80211_txpower_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->currenttxpower = htons(dataelement->currenttxpower); - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u8(handle, 0); + func->write_u16(handle, element->currenttxpower); } /* */ -int capwap_80211_txpower_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_txpower_element_parsing(struct capwap_message_element* element) { +static void* capwap_80211_txpower_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_80211_txpower_element* data; - struct capwap_80211_txpower_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_TXPOWER); - - if (ntohs(element->length) != 4) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 4) { + capwap_logging_debug("Invalid IEEE 802.11 Tx Power element"); return NULL; } - dataraw = (struct capwap_80211_txpower_raw_element*)element->data; - /* */ data = (struct capwap_80211_txpower_element*)capwap_alloc(sizeof(struct capwap_80211_txpower_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->currenttxpower = ntohs(dataraw->currenttxpower); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_txpower_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, NULL); + func->read_u16(handle, &data->currenttxpower); + return data; } /* */ -void capwap_80211_txpower_element_free(void* data) { +static void capwap_80211_txpower_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_txpower_ops = { + .create_message_element = capwap_80211_txpower_element_create, + .parsing_message_element = capwap_80211_txpower_element_parsing, + .free_parsed_message_element = capwap_80211_txpower_element_free +}; diff --git a/src/common/capwap_element_80211_txpower.h b/src/common/capwap_element_80211_txpower.h index e3f8526..8cc70d7 100644 --- a/src/common/capwap_element_80211_txpower.h +++ b/src/common/capwap_element_80211_txpower.h @@ -4,19 +4,10 @@ #define CAPWAP_ELEMENT_80211_TXPOWER 1041 struct capwap_80211_txpower_element { - unsigned char radioid; - unsigned short currenttxpower; + uint8_t radioid; + uint16_t currenttxpower; }; -struct capwap_message_element* capwap_80211_txpower_element_create(void* data, unsigned long length); -int capwap_80211_txpower_element_validate(struct capwap_message_element* element); -void* capwap_80211_txpower_element_parsing(struct capwap_message_element* element); -void capwap_80211_txpower_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_80211_txpower_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_TXPOWER_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_TXPOWER); \ - f->create(x, sizeof(struct capwap_80211_txpower_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_TXPOWER_HEADER__ */ diff --git a/src/common/capwap_element_80211_txpowerlevel.c b/src/common/capwap_element_80211_txpowerlevel.c index 95d447b..3b95a71 100644 --- a/src/common/capwap_element_80211_txpowerlevel.c +++ b/src/common/capwap_element_80211_txpowerlevel.c @@ -15,73 +15,38 @@ Length: >= 4 ********************************************************************/ -struct capwap_80211_txpowerlevel_raw_element { - unsigned char radioid; - unsigned char numlevels; - unsigned short powerlevel[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_txpowerlevel_element_create(void* data, unsigned long datalength) { +static void capwap_80211_txpowerlevel_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { int i; - unsigned short txpowerlength; - struct capwap_message_element* element; - struct capwap_80211_txpowerlevel_raw_element* dataraw; - struct capwap_80211_txpowerlevel_element* dataelement = (struct capwap_80211_txpowerlevel_element*)data; + struct capwap_80211_txpowerlevel_element* element = (struct capwap_80211_txpowerlevel_element*)data; ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_txpowerlevel_element)); - /* Alloc block of memory */ - txpowerlength = dataelement->numlevels * sizeof(unsigned char); - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_txpowerlevel_raw_element) + txpowerlength); - if (!element) { - capwap_outofmemory(); + func->write_u8(handle, element->radioid); + func->write_u8(handle, element->numlevels); + for (i = 0; i < element->numlevels; i++) { + func->write_u16(handle, element->powerlevel[i]); } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_txpowerlevel_raw_element) + txpowerlength); - element->type = htons(CAPWAP_ELEMENT_80211_TXPOWERLEVEL); - element->length = htons(sizeof(struct capwap_80211_txpowerlevel_raw_element) + txpowerlength); - dataraw = (struct capwap_80211_txpowerlevel_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->numlevels = dataelement->numlevels; - for (i = 0; i < dataelement->numlevels; i++) { - dataraw->powerlevel[i] = htons(dataelement->powerlevel[i]); - } - - return element; } /* */ -int capwap_80211_txpowerlevel_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_txpowerlevel_element_parsing(struct capwap_message_element* element) { +static void* capwap_80211_txpowerlevel_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { int i; - unsigned short txpowerlength; + unsigned short length; struct capwap_80211_txpowerlevel_element* data; - struct capwap_80211_txpowerlevel_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_TXPOWERLEVEL); - txpowerlength = ntohs(element->length); - if (txpowerlength < 4) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length < 4) { + capwap_logging_debug("Invalid IEEE 802.11 Tx Power Level element"); return NULL; } - txpowerlength -= sizeof(struct capwap_80211_txpowerlevel_raw_element); - if (txpowerlength > (CAPWAP_TXPOWERLEVEL_MAXLENGTH * sizeof(unsigned short))) { - return NULL; - } - - dataraw = (struct capwap_80211_txpowerlevel_raw_element*)element->data; - if ((dataraw->numlevels < 1) || (dataraw->numlevels > CAPWAP_TXPOWERLEVEL_MAXLENGTH)) { + length -= 2; + if ((length % sizeof(uint16_t)) || ((length / sizeof(uint16_t)) > CAPWAP_TXPOWERLEVEL_MAXLENGTH)) { + capwap_logging_debug("Invalid IEEE 802.11 Tx Power Level element"); return NULL; } @@ -91,19 +56,35 @@ void* capwap_80211_txpowerlevel_element_parsing(struct capwap_message_element* e capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->numlevels = dataraw->numlevels; - for (i = 0; i < dataraw->numlevels; i++) { - data->powerlevel[i] = dataraw->powerlevel[i]; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_txpowerlevel_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, &data->numlevels); + + /* Check */ + if ((data->numlevels * sizeof(uint16_t)) != length) { + capwap_logging_debug("Invalid IEEE 802.11 Tx Power Level element"); + capwap_free(data); + return NULL; + } + + for (i = 0; i < data->numlevels; i++) { + func->read_u16(handle, &data->powerlevel[i]); } return data; } /* */ -void capwap_80211_txpowerlevel_element_free(void* data) { +static void capwap_80211_txpowerlevel_element_free(void* data) { ASSERT(data != NULL); - + capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_txpowerlevel_ops = { + .create_message_element = capwap_80211_txpowerlevel_element_create, + .parsing_message_element = capwap_80211_txpowerlevel_element_parsing, + .free_parsed_message_element = capwap_80211_txpowerlevel_element_free +}; diff --git a/src/common/capwap_element_80211_txpowerlevel.h b/src/common/capwap_element_80211_txpowerlevel.h index 3ee39e3..ad96759 100644 --- a/src/common/capwap_element_80211_txpowerlevel.h +++ b/src/common/capwap_element_80211_txpowerlevel.h @@ -6,20 +6,11 @@ #define CAPWAP_TXPOWERLEVEL_MAXLENGTH 8 struct capwap_80211_txpowerlevel_element { - unsigned char radioid; - unsigned char numlevels; - unsigned short powerlevel[CAPWAP_TXPOWERLEVEL_MAXLENGTH]; + uint8_t radioid; + uint8_t numlevels; + uint16_t powerlevel[CAPWAP_TXPOWERLEVEL_MAXLENGTH]; }; -struct capwap_message_element* capwap_80211_txpowerlevel_element_create(void* data, unsigned long length); -int capwap_80211_txpowerlevel_element_validate(struct capwap_message_element* element); -void* capwap_80211_txpowerlevel_element_parsing(struct capwap_message_element* element); -void capwap_80211_txpowerlevel_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_80211_txpowerlevel_ops; -/* Helper */ -#define CAPWAP_CREATE_80211_TXPOWERLEVEL_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_TXPOWERLEVEL); \ - f->create(x, sizeof(struct capwap_80211_txpowerlevel_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_TXPOWERLEVEL_HEADER__ */ diff --git a/src/common/capwap_element_80211_wtpradioinformation.c b/src/common/capwap_element_80211_wtpradioinformation.c index 4ad3e72..1ab4266 100644 --- a/src/common/capwap_element_80211_wtpradioinformation.c +++ b/src/common/capwap_element_80211_wtpradioinformation.c @@ -17,72 +17,53 @@ Length: 5 ********************************************************************/ -struct capwap_80211_wtpradioinformation_raw_element { - unsigned char radioid; - unsigned long radiotype; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_80211_wtpradioinformation_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_80211_wtpradioinformation_raw_element* dataraw; - struct capwap_80211_wtpradioinformation_element* dataelement = (struct capwap_80211_wtpradioinformation_element*)data; - +static void capwap_80211_wtpradioinformation_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_80211_wtpradioinformation_element* element = (struct capwap_80211_wtpradioinformation_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_80211_wtpradioinformation_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_wtpradioinformation_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_wtpradioinformation_raw_element)); - element->type = htons(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); - element->length = htons(sizeof(struct capwap_80211_wtpradioinformation_raw_element)); - dataraw = (struct capwap_80211_wtpradioinformation_raw_element*)element->data; - - dataraw->radioid = dataelement->radioid; - dataraw->radiotype = htonl(dataelement->radiotype); - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u32(handle, element->radiotype); } /* */ -int capwap_80211_wtpradioinformation_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_80211_wtpradioinformation_element_parsing(struct capwap_message_element* element) { +static void* capwap_80211_wtpradioinformation_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_80211_wtpradioinformation_element* data; - struct capwap_80211_wtpradioinformation_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); - - if (ntohs(element->length) != 5) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 5) { + capwap_logging_debug("Invalid IEEE 802.11 WTP Radio Information element"); return NULL; } - dataraw = (struct capwap_80211_wtpradioinformation_raw_element*)element->data; - /* */ data = (struct capwap_80211_wtpradioinformation_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioinformation_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->radioid = dataraw->radioid; - data->radiotype = ntohl(dataraw->radiotype); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_80211_wtpradioinformation_element)); + func->read_u8(handle, &data->radioid); + func->read_u32(handle, &data->radiotype); + return data; } /* */ -void capwap_80211_wtpradioinformation_element_free(void* data) { +static void capwap_80211_wtpradioinformation_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_80211_wtpradioinformation_ops = { + .create_message_element = capwap_80211_wtpradioinformation_element_create, + .parsing_message_element = capwap_80211_wtpradioinformation_element_parsing, + .free_parsed_message_element = capwap_80211_wtpradioinformation_element_free +}; diff --git a/src/common/capwap_element_80211_wtpradioinformation.h b/src/common/capwap_element_80211_wtpradioinformation.h index 3e07023..0d877ba 100644 --- a/src/common/capwap_element_80211_wtpradioinformation.h +++ b/src/common/capwap_element_80211_wtpradioinformation.h @@ -3,25 +3,16 @@ #define CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION 1048 +#define CAPWAP_RADIO_TYPE_80211B 0x01 +#define CAPWAP_RADIO_TYPE_80211A 0x02 +#define CAPWAP_RADIO_TYPE_80211G 0x04 +#define CAPWAP_RADIO_TYPE_80211N 0x08 + struct capwap_80211_wtpradioinformation_element { - unsigned char radioid; - unsigned long radiotype; + uint8_t radioid; + uint32_t radiotype; }; -#define CAPWAP_RADIO_TYPE_80211N 0x08 -#define CAPWAP_RADIO_TYPE_80211G 0x04 -#define CAPWAP_RADIO_TYPE_80211A 0x02 -#define CAPWAP_RADIO_TYPE_80211B 0x01 +extern struct capwap_message_elements_ops capwap_element_80211_wtpradioinformation_ops; -struct capwap_message_element* capwap_80211_wtpradioinformation_element_create(void* data, unsigned long length); -int capwap_80211_wtpradioinformation_element_validate(struct capwap_message_element* element); -void* capwap_80211_wtpradioinformation_element_parsing(struct capwap_message_element* element); -void capwap_80211_wtpradioinformation_element_free(void* data); - -/* Helper */ -#define CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION); \ - f->create(x, sizeof(struct capwap_80211_wtpradioinformation_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__ */ diff --git a/src/common/capwap_element_acdescriptor.c b/src/common/capwap_element_acdescriptor.c index 649cd74..c9ba0f1 100644 --- a/src/common/capwap_element_acdescriptor.c +++ b/src/common/capwap_element_acdescriptor.c @@ -15,7 +15,7 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | AC Information Sub-Element... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - + 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -31,109 +31,53 @@ Length: >= 12 ********************************************************************/ -struct capwap_acdescriptor_raw_element { - unsigned short stations; - unsigned short limit; - unsigned short activewtp; - unsigned short maxwtp; - unsigned char security; - unsigned char rmacfield; - unsigned char reserved; - unsigned char dtlspolicy; - char data[0]; -} __attribute__((__packed__)); - -struct capwap_acdescriptor_raw_desc_subelement { - unsigned long vendor; - unsigned short type; - unsigned short length; - char data[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_acdescriptor_element_create(void* data, unsigned long datalength) { - char* pos; - unsigned long i; - unsigned short length; - struct capwap_message_element* element; - struct capwap_acdescriptor_raw_element* dataraw; - struct capwap_acdescriptor_element* dataelement = (struct capwap_acdescriptor_element*)data; - +static void capwap_acdescriptor_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + int i; + struct capwap_acdescriptor_element* element = (struct capwap_acdescriptor_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_acdescriptor_element)); - ASSERT(dataelement->descsubelement != NULL); - - /* Calc length packet */ - length = sizeof(struct capwap_acdescriptor_raw_element); - for (i = 0; i < dataelement->descsubelement->count; i++) { - struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i); - length += sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desc->length; - } - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + length); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + length); - element->type = htons(CAPWAP_ELEMENT_ACDESCRIPTION); - element->length = htons(length); - - /* Descriptor */ - dataraw = (struct capwap_acdescriptor_raw_element*)element->data; - dataraw->stations = htons(dataelement->station); - dataraw->limit = htons(dataelement->stationlimit); - dataraw->activewtp = htons(dataelement->wtp); - dataraw->maxwtp = htons(dataelement->wtplimit); - dataraw->security = dataelement->security; - dataraw->rmacfield = dataelement->rmacfield; - dataraw->dtlspolicy = dataelement->dtlspolicy; - - /* Descriptor Sub-Element */ - pos = dataraw->data; - for (i = 0; i < dataelement->descsubelement->count; i++) { - struct capwap_acdescriptor_raw_desc_subelement* descraw = (struct capwap_acdescriptor_raw_desc_subelement*)pos; - struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i); - - descraw->vendor = htonl(desc->vendor); - descraw->type = htons(desc->type); - descraw->length = htons(desc->length); - memcpy(descraw->data, desc->data, desc->length); - - pos += sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desc->length; - } - - return element; -} - -/* */ -int capwap_acdescriptor_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_acdescriptor_element_parsing(struct capwap_message_element* element) { - unsigned char i; - long length; - char* pos; - struct capwap_acdescriptor_element* data; - struct capwap_acdescriptor_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACDESCRIPTION); - - length = (long)ntohs(element->length); - if (length < 12) { - capwap_logging_debug("Invalid AC Descriptor element"); - return NULL; - } /* */ - dataraw = (struct capwap_acdescriptor_raw_element*)element->data; - if ((dataraw->stations > dataraw->limit) || (dataraw->activewtp > dataraw->maxwtp)) { + func->write_u16(handle, element->stations); + func->write_u16(handle, element->stationlimit); + func->write_u16(handle, element->activewtp); + func->write_u16(handle, element->maxwtp); + func->write_u8(handle, element->security); + func->write_u8(handle, element->rmacfield); + func->write_u8(handle, 0); + func->write_u8(handle, element->dtlspolicy); + + /* */ + for (i = 0; i < element->descsubelement->count; i++) { + struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i); + + func->write_u32(handle, desc->vendor); + func->write_u16(handle, desc->type); + func->write_u16(handle, desc->length); + func->write_block(handle, desc->data, desc->length); + } +} + +/* */ +static void capwap_acdescriptor_element_free(void* data) { + struct capwap_acdescriptor_element* dataelement = (struct capwap_acdescriptor_element*)data; + + ASSERT(dataelement != NULL); + ASSERT(dataelement->descsubelement != NULL); + + capwap_array_free(dataelement->descsubelement); + capwap_free(dataelement); +} + +/* */ +static void* capwap_acdescriptor_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + struct capwap_acdescriptor_element* data; + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) < 12) { capwap_logging_debug("Invalid AC Descriptor element"); return NULL; } @@ -144,56 +88,56 @@ void* capwap_acdescriptor_element_parsing(struct capwap_message_element* element capwap_outofmemory(); } + memset(data, 0, sizeof(struct capwap_acdescriptor_element)); data->descsubelement = capwap_array_create(sizeof(struct capwap_acdescriptor_desc_subelement), 0); - + data->descsubelement->zeroed = 1; + + /* Retrieve data */ + func->read_u16(handle, &data->stations); + func->read_u16(handle, &data->stationlimit); + func->read_u16(handle, &data->activewtp); + func->read_u16(handle, &data->maxwtp); + + /* Check */ + if ((data->stations > data->stationlimit) || (data->activewtp > data->maxwtp)) { + capwap_logging_debug("Invalid AC Descriptor element"); + capwap_acdescriptor_element_free(data); + return NULL; + } + /* */ - data->station = htons(dataraw->stations); - data->stationlimit = htons(dataraw->limit); - data->wtp = htons(dataraw->activewtp); - data->wtplimit = htons(dataraw->maxwtp); - data->security = dataraw->security; - data->rmacfield = dataraw->rmacfield; - data->dtlspolicy = dataraw->dtlspolicy; - - pos = dataraw->data; - length -= sizeof(struct capwap_acdescriptor_raw_element); - + func->read_u8(handle, &data->security); + func->read_u8(handle, &data->rmacfield); + func->read_u8(handle, NULL); + func->read_u8(handle, &data->dtlspolicy); + /* Description Subelement */ - i = 0; - while (length > 0) { - struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, i); - struct capwap_acdescriptor_raw_desc_subelement* descraw = (struct capwap_acdescriptor_raw_desc_subelement*)pos; - unsigned short desclength = ntohs(descraw->length); - unsigned short descrawlength = sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desclength; - - if ((desclength > CAPWAP_ACDESC_SUBELEMENT_MAXDATA) || (length < descrawlength)) { + while (func->read_ready(handle) > 0) { + unsigned short length; + struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, data->descsubelement->count); + + /* */ + func->read_u32(handle, &desc->vendor); + func->read_u16(handle, &desc->type); + func->read_u16(handle, &desc->length); + + /* Check buffer size */ + length = func->read_ready(handle); + if ((length > CAPWAP_ACDESC_SUBELEMENT_MAXDATA) || (length < desc->length)) { capwap_logging_debug("Invalid AC Descriptor element"); capwap_acdescriptor_element_free(data); return NULL; } - - /* */ - desc->vendor = ntohl(descraw->vendor); - desc->type = ntohs(descraw->type); - desc->length = desclength; - memcpy(desc->data, descraw->data, desclength); - /* */ - i++; - pos += descrawlength; - length -= descrawlength; + func->read_block(handle, desc->data, desc->length); } - + return data; } /* */ -void capwap_acdescriptor_element_free(void* data) { - struct capwap_acdescriptor_element* dataelement = (struct capwap_acdescriptor_element*)data; - - ASSERT(dataelement != NULL); - ASSERT(dataelement->descsubelement != NULL); - - capwap_array_free(dataelement->descsubelement); - capwap_free(dataelement); -} +struct capwap_message_elements_ops capwap_element_acdescriptor_ops = { + .create_message_element = capwap_acdescriptor_element_create, + .parsing_message_element = capwap_acdescriptor_element_parsing, + .free_parsed_message_element = capwap_acdescriptor_element_free +}; diff --git a/src/common/capwap_element_acdescriptor.h b/src/common/capwap_element_acdescriptor.h index cc7fb55..04136ba 100644 --- a/src/common/capwap_element_acdescriptor.h +++ b/src/common/capwap_element_acdescriptor.h @@ -13,13 +13,13 @@ #define CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED 0x02 struct capwap_acdescriptor_element { - unsigned short station; - unsigned short stationlimit; - unsigned short wtp; - unsigned short wtplimit; - unsigned char security; - unsigned char rmacfield; - unsigned char dtlspolicy; + uint16_t stations; + uint16_t stationlimit; + uint16_t activewtp; + uint16_t maxwtp; + uint8_t security; + uint8_t rmacfield; + uint8_t dtlspolicy; struct capwap_array* descsubelement; }; @@ -28,21 +28,12 @@ struct capwap_acdescriptor_element { #define CAPWAP_ACDESC_SUBELEMENT_MAXDATA 1024 struct capwap_acdescriptor_desc_subelement { - unsigned long vendor; - unsigned short type; - unsigned short length; - char data[CAPWAP_ACDESC_SUBELEMENT_MAXDATA]; + uint32_t vendor; + uint16_t type; + uint16_t length; + uint8_t data[CAPWAP_ACDESC_SUBELEMENT_MAXDATA]; }; -struct capwap_message_element* capwap_acdescriptor_element_create(void* data, unsigned long length); -int capwap_acdescriptor_element_validate(struct capwap_message_element* element); -void* capwap_acdescriptor_element_parsing(struct capwap_message_element* element); -void capwap_acdescriptor_element_free(void* data); - -/* Helper */ -#define CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACDESCRIPTION); \ - f->create(x, sizeof(struct capwap_acdescriptor_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_acdescriptor_ops; #endif /* __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__ */ diff --git a/src/common/capwap_element_acipv4list.c b/src/common/capwap_element_acipv4list.c index f4ae181..2c2e3be 100644 --- a/src/common/capwap_element_acipv4list.c +++ b/src/common/capwap_element_acipv4list.c @@ -10,94 +10,68 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 2 for AC IPv4 List + Length: >= 4 ********************************************************************/ -struct capwap_acipv4list_raw_element { - unsigned long address; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_acipv4list_element_create(void* data, unsigned long datalength) { - int i; - int items; - unsigned short sizeitems; - struct capwap_message_element* element; - capwap_acipv4list_element_array* dataarray = (capwap_acipv4list_element_array*)data; - struct capwap_acipv4list_raw_element* dataraw; - +static void capwap_acipv4list_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + unsigned long i; + struct capwap_acipv4list_element* element = (struct capwap_acipv4list_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(capwap_acipv4list_element_array)); - - items = min(dataarray->count, CAPWAP_ACIPV4LIST_MAX_ELEMENTS); - - /* Alloc block of memory */ - sizeitems = sizeof(struct capwap_acipv4list_raw_element) * items; - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeitems); - if (!element) { - capwap_outofmemory(); + + /* */ + for (i = 0; i < element->addresses->count; i++) { + func->write_block(handle, (uint8_t*)capwap_array_get_item_pointer(element->addresses, i), sizeof(struct in_addr)); } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeitems); - element->type = htons(CAPWAP_ELEMENT_ACIPV4LIST); - element->length = htons(sizeitems); - - dataraw = (struct capwap_acipv4list_raw_element*)element->data; - for (i = 0; i < items; i++) { - struct capwap_acipv4list_element* dataelement = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(dataarray, i); - dataraw->address = dataelement->address.s_addr; - - /* Next raw item */ - dataraw++; - } - - return element; } /* */ -int capwap_acipv4list_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} +static void* capwap_acipv4list_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + uint16_t length; + struct capwap_acipv4list_element* data; -/* */ -void* capwap_acipv4list_element_parsing(struct capwap_message_element* element) { - int i; - int items; - unsigned short length; - capwap_acipv4list_element_array* data; - struct capwap_acipv4list_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACIPV4LIST); - - length = ntohs(element->length); - if ((length > 0) && ((length % sizeof(struct capwap_acipv4list_raw_element)) != 0)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if ((length >= 4) && (length <= CAPWAP_ACIPV4LIST_MAX_ELEMENTS * 4) && (length % 4)) { + capwap_logging_debug("Invalid AC IPv4 List element"); return NULL; } /* */ - items = length / sizeof(struct capwap_acipv4list_raw_element); - data = (capwap_acipv4list_element_array*)capwap_array_create(sizeof(struct capwap_acipv4list_element), items); + data = (struct capwap_acipv4list_element*)capwap_alloc(sizeof(struct capwap_acipv4list_element)); + if (!data) { + capwap_outofmemory(); + } - /* */ - dataraw = (struct capwap_acipv4list_raw_element*)element->data; - for (i = 0; i < items; i++) { - struct capwap_acipv4list_element* dataelement = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(data, i); - dataelement->address.s_addr = dataraw->address; - - /* Next raw item */ - dataraw++; + /* Retrieve data */ + data->addresses = capwap_array_create(sizeof(struct in_addr), 0); + while (length > 0) { + struct in_addr* address = (struct in_addr*)capwap_array_get_item_pointer(data->addresses, data->addresses->count); + func->read_block(handle, (uint8_t*)address, sizeof(struct in_addr)); + length -= 4; } return data; } /* */ -void capwap_acipv4list_element_free(void* data) { +static void capwap_acipv4list_element_free(void* data) { + struct capwap_acipv4list_element* element = (struct capwap_acipv4list_element*)data; + ASSERT(data != NULL); - capwap_array_free((capwap_acipv4list_element_array*)data); + capwap_array_free(element->addresses); + capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_acipv4list_ops = { + .create_message_element = capwap_acipv4list_element_create, + .parsing_message_element = capwap_acipv4list_element_parsing, + .free_parsed_message_element = capwap_acipv4list_element_free +}; diff --git a/src/common/capwap_element_acipv4list.h b/src/common/capwap_element_acipv4list.h index 911f659..d73e043 100644 --- a/src/common/capwap_element_acipv4list.h +++ b/src/common/capwap_element_acipv4list.h @@ -5,21 +5,10 @@ #define CAPWAP_ACIPV4LIST_MAX_ELEMENTS 1024 -typedef struct capwap_array capwap_acipv4list_element_array; struct capwap_acipv4list_element { - struct in_addr address; + struct capwap_array* addresses; }; -struct capwap_message_element* capwap_acipv4list_element_create(void* data, unsigned long datalength); -int capwap_acipv4list_element_validate(struct capwap_message_element* element); -void* capwap_acipv4list_element_parsing(struct capwap_message_element* element); -void capwap_acipv4list_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_ACIPV4LIST_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACIPV4LIST); \ - f->create(x, sizeof(capwap_acipv4list_element_array)); \ - }) +extern struct capwap_message_elements_ops capwap_element_acipv4list_ops; #endif /* __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__ */ diff --git a/src/common/capwap_element_acipv6list.c b/src/common/capwap_element_acipv6list.c index f4ebed2..5037619 100644 --- a/src/common/capwap_element_acipv6list.c +++ b/src/common/capwap_element_acipv6list.c @@ -16,94 +16,68 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 3 for AC IPV6 List + Length: >= 16 ********************************************************************/ -struct capwap_acipv6list_raw_element { - unsigned long address[4]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_acipv6list_element_create(void* data, unsigned long datalength) { - int i; - int items; - unsigned short sizeitems; - struct capwap_message_element* element; - capwap_acipv6list_element_array* dataarray = (capwap_acipv6list_element_array*)data; - struct capwap_acipv6list_raw_element* dataraw; - +static void capwap_acipv6list_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + unsigned long i; + struct capwap_acipv6list_element* element = (struct capwap_acipv6list_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(capwap_acipv6list_element_array)); - - items = min(dataarray->count, CAPWAP_ACIPV6LIST_MAX_ELEMENTS); - - /* Alloc block of memory */ - sizeitems = sizeof(struct capwap_acipv6list_raw_element) * items; - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeitems); - if (!element) { - capwap_outofmemory(); + + /* */ + for (i = 0; i < element->addresses->count; i++) { + func->write_block(handle, (uint8_t*)capwap_array_get_item_pointer(element->addresses, i), sizeof(struct in6_addr)); } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeitems); - element->type = htons(CAPWAP_ELEMENT_ACIPV6LIST); - element->length = htons(sizeitems); - - dataraw = (struct capwap_acipv6list_raw_element*)element->data; - for (i = 0; i < items; i++) { - struct capwap_acipv6list_element* dataelement = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(dataarray, i); - memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4); - - /* Next raw item */ - dataraw++; - } - - return element; } /* */ -int capwap_acipv6list_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} +static void* capwap_acipv6list_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + uint16_t length; + struct capwap_acipv6list_element* data; -/* */ -void* capwap_acipv6list_element_parsing(struct capwap_message_element* element) { - int i; - int items; - unsigned short length; - capwap_acipv6list_element_array* data; - struct capwap_acipv6list_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACIPV6LIST); - - length = ntohs(element->length); - if ((length > 0) && ((length % sizeof(struct capwap_acipv6list_raw_element)) != 0)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if ((length >= 16) && (length <= CAPWAP_ACIPV4LIST_MAX_ELEMENTS * 16) && (length % 16)) { + capwap_logging_debug("Invalid AC IPv6 List element"); return NULL; } /* */ - items = length / sizeof(struct capwap_acipv6list_raw_element); - data = (capwap_acipv6list_element_array*)capwap_array_create(sizeof(struct capwap_acipv6list_element), items); + data = (struct capwap_acipv6list_element*)capwap_alloc(sizeof(struct capwap_acipv6list_element)); + if (!data) { + capwap_outofmemory(); + } - /* */ - dataraw = (struct capwap_acipv6list_raw_element*)element->data; - for (i = 0; i < items; i++) { - struct capwap_acipv6list_element* dataelement = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(data, i); - memcpy(dataelement->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4); - - /* Next raw item */ - dataraw++; + /* Retrieve data */ + data->addresses = capwap_array_create(sizeof(struct in6_addr), 0); + while (length > 0) { + struct in6_addr* address = (struct in6_addr*)capwap_array_get_item_pointer(data->addresses, data->addresses->count); + func->read_block(handle, (uint8_t*)address, sizeof(struct in6_addr)); + length -= 16; } return data; } /* */ -void capwap_acipv6list_element_free(void* data) { +static void capwap_acipv6list_element_free(void* data) { + struct capwap_acipv6list_element* element = (struct capwap_acipv6list_element*)data; + ASSERT(data != NULL); - capwap_array_free((capwap_acipv6list_element_array*)data); + capwap_array_free(element->addresses); + capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_acipv6list_ops = { + .create_message_element = capwap_acipv6list_element_create, + .parsing_message_element = capwap_acipv6list_element_parsing, + .free_parsed_message_element = capwap_acipv6list_element_free +}; diff --git a/src/common/capwap_element_acipv6list.h b/src/common/capwap_element_acipv6list.h index 55f8aa6..e5af618 100644 --- a/src/common/capwap_element_acipv6list.h +++ b/src/common/capwap_element_acipv6list.h @@ -5,21 +5,10 @@ #define CAPWAP_ACIPV6LIST_MAX_ELEMENTS 1024 -typedef struct capwap_array capwap_acipv6list_element_array; struct capwap_acipv6list_element { - struct in6_addr address; + struct capwap_array* addresses; }; -struct capwap_message_element* capwap_acipv6list_element_create(void* data, unsigned long datalength); -int capwap_acipv6list_element_validate(struct capwap_message_element* element); -void* capwap_acipv6list_element_parsing(struct capwap_message_element* element); -void capwap_acipv6list_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_ACIPV6LIST_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACIPV6LIST); \ - f->create(x, sizeof(capwap_acipv6list_element_array)); \ - }) +extern struct capwap_message_elements_ops capwap_element_acipv6list_ops; #endif /* __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__ */ diff --git a/src/common/capwap_element_acname.c b/src/common/capwap_element_acname.c index be21527..64469d1 100644 --- a/src/common/capwap_element_acname.c +++ b/src/common/capwap_element_acname.c @@ -10,77 +10,57 @@ +-+-+-+-+-+-+-+-+ Type: 4 for AC Name + Length: >= 1 ********************************************************************/ -struct capwap_acname_raw_element { - char name[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_acname_element_create(void* data, unsigned long datalength) { - unsigned short namelength; - struct capwap_message_element* element; - struct capwap_acname_raw_element* dataraw; - struct capwap_acname_element* dataelement = (struct capwap_acname_element*)data; - +static void capwap_acname_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_acname_element* element = (struct capwap_acname_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_acname_element)); - - /* Alloc block of memory */ - namelength = strlen(dataelement->name); - element = capwap_alloc(sizeof(struct capwap_message_element) + namelength); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + namelength); - element->type = htons(CAPWAP_ELEMENT_ACNAME); - element->length = htons(namelength); - - dataraw = (struct capwap_acname_raw_element*)element->data; - memcpy(&dataraw->name[0], &dataelement->name[0], namelength); - return element; + func->write_block(handle, element->name, strlen((char*)element->name)); } /* */ -int capwap_acname_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_acname_element_parsing(struct capwap_message_element* element) { - unsigned short namelength; +static void* capwap_acname_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_acname_element* data; - struct capwap_acname_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACNAME); - namelength = ntohs(element->length); - if (!namelength || (namelength > CAPWAP_ACNAME_MAXLENGTH)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if ((length < 1) || (length > CAPWAP_ACNAME_MAXLENGTH)) { + capwap_logging_debug("Invalid AC Name element"); return NULL; } /* */ - dataraw = (struct capwap_acname_raw_element*)element->data; data = (struct capwap_acname_element*)capwap_alloc(sizeof(struct capwap_acname_element)); if (!data) { capwap_outofmemory(); } - /* */ - memcpy(&data->name[0], &dataraw->name[0], namelength); - data->name[namelength] = 0; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_acname_element)); + func->read_block(handle, data->name, length); + return data; } /* */ -void capwap_acname_element_free(void* data) { +static void capwap_acname_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_acname_ops = { + .create_message_element = capwap_acname_element_create, + .parsing_message_element = capwap_acname_element_parsing, + .free_parsed_message_element = capwap_acname_element_free +}; diff --git a/src/common/capwap_element_acname.h b/src/common/capwap_element_acname.h index 8bc73ee..a9641b7 100644 --- a/src/common/capwap_element_acname.h +++ b/src/common/capwap_element_acname.h @@ -6,19 +6,9 @@ #define CAPWAP_ACNAME_MAXLENGTH 512 struct capwap_acname_element { - char name[CAPWAP_ACNAME_MAXLENGTH + 1]; + uint8_t name[CAPWAP_ACNAME_MAXLENGTH + 1]; }; -struct capwap_message_element* capwap_acname_element_create(void* data, unsigned long datalength); -int capwap_acname_element_validate(struct capwap_message_element* element); -void* capwap_acname_element_parsing(struct capwap_message_element* element); -void capwap_acname_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_ACNAME_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACNAME); \ - f->create(x, sizeof(struct capwap_acname_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_acname_ops; #endif /* __CAPWAP_ELEMENT_ACNAME_HEADER__ */ diff --git a/src/common/capwap_element_acnamepriority.c b/src/common/capwap_element_acnamepriority.c index bd6cc5d..08da2fd 100644 --- a/src/common/capwap_element_acnamepriority.c +++ b/src/common/capwap_element_acnamepriority.c @@ -10,82 +10,59 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 5 for AC Name with Priority + Length: >= 2 ********************************************************************/ -struct capwap_acnamepriority_raw_element { - unsigned char priority; - char name[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_acnamepriority_element_create(void* data, unsigned long datalength) { - unsigned short namelength; - struct capwap_message_element* element; - struct capwap_acnamepriority_raw_element* dataraw; - struct capwap_acnamepriority_element* dataelement = (struct capwap_acnamepriority_element*)data; - +static void capwap_acnamepriority_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_acnamepriority_element* element = (struct capwap_acnamepriority_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_acnamepriority_element)); - - /* Alloc block of memory */ - namelength = strlen(dataelement->name); - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_acnamepriority_raw_element) + namelength); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_acnamepriority_raw_element) + namelength); - element->type = htons(CAPWAP_ELEMENT_ACNAMEPRIORITY); - element->length = htons(sizeof(struct capwap_acnamepriority_raw_element) + namelength); - - dataraw = (struct capwap_acnamepriority_raw_element*)element->data; - dataraw->priority = dataelement->priority; - memcpy(&dataraw->name[0], &dataelement->name[0], namelength); - - return element; + func->write_u8(handle, element->priority); + func->write_block(handle, element->name, strlen((char*)element->name)); } /* */ -int capwap_acnamepriority_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_acnamepriority_element_parsing(struct capwap_message_element* element) { - unsigned short namelength; +static void* capwap_acnamepriority_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_acnamepriority_element* data; - struct capwap_acnamepriority_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACNAMEPRIORITY); - namelength = ntohs(element->length) - sizeof(struct capwap_acnamepriority_raw_element); - if (!namelength || (namelength > CAPWAP_ACNAMEPRIORITY_MAXLENGTH)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle) - 1; + if ((length < 1) || (length > CAPWAP_ACNAMEPRIORITY_MAXLENGTH)) { + capwap_logging_debug("Invalid AC Name Priority element"); return NULL; } /* */ - dataraw = (struct capwap_acnamepriority_raw_element*)element->data; data = (struct capwap_acnamepriority_element*)capwap_alloc(sizeof(struct capwap_acnamepriority_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->priority = dataraw->priority; - memcpy(&data->name[0], &dataraw->name[0], namelength); - data->name[namelength] = 0; - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_acnamepriority_element)); + func->read_u8(handle, &data->priority); + func->read_block(handle, data->name, length); + return data; } /* */ -void capwap_acnamepriority_element_free(void* data) { +static void capwap_acnamepriority_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_acnamepriority_ops = { + .create_message_element = capwap_acnamepriority_element_create, + .parsing_message_element = capwap_acnamepriority_element_parsing, + .free_parsed_message_element = capwap_acnamepriority_element_free +}; diff --git a/src/common/capwap_element_acnamepriority.h b/src/common/capwap_element_acnamepriority.h index cb34158..5b508e2 100644 --- a/src/common/capwap_element_acnamepriority.h +++ b/src/common/capwap_element_acnamepriority.h @@ -6,20 +6,10 @@ #define CAPWAP_ACNAMEPRIORITY_MAXLENGTH 512 struct capwap_acnamepriority_element { - unsigned char priority; - char name[CAPWAP_ACNAMEPRIORITY_MAXLENGTH + 1]; + uint8_t priority; + uint8_t name[CAPWAP_ACNAMEPRIORITY_MAXLENGTH + 1]; }; -struct capwap_message_element* capwap_acnamepriority_element_create(void* data, unsigned long datalength); -int capwap_acnamepriority_element_validate(struct capwap_message_element* element); -void* capwap_acnamepriority_element_parsing(struct capwap_message_element* element); -void capwap_acnamepriority_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_ACNAMEPRIORITY_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACNAMEPRIORITY); \ - f->create(x, sizeof(struct capwap_acnamepriority_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_acnamepriority_ops; #endif /* __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__ */ diff --git a/src/common/capwap_element_controlipv4.c b/src/common/capwap_element_controlipv4.c index d72cfb9..ea0260f 100644 --- a/src/common/capwap_element_controlipv4.c +++ b/src/common/capwap_element_controlipv4.c @@ -12,57 +12,31 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 10 for CAPWAP Control IPv4 Address + Length: 6 ********************************************************************/ -struct capwap_controlipv4_raw_element { - unsigned long address; - unsigned short wtpcount; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_controlipv4_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_controlipv4_element* dataelement = (struct capwap_controlipv4_element*)data; - struct capwap_controlipv4_raw_element* dataraw; - +static void capwap_controlipv4_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_controlipv4_element* element = (struct capwap_controlipv4_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_controlipv4_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv4_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv4_raw_element)); - element->type = htons(CAPWAP_ELEMENT_CONTROLIPV4); - element->length = htons(sizeof(struct capwap_controlipv4_raw_element)); - - dataraw = (struct capwap_controlipv4_raw_element*)element->data; - dataraw->address = dataelement->address.s_addr; - dataraw->wtpcount = htons(dataelement->wtpcount); - - return element; + /* */ + func->write_block(handle, (uint8_t*)&element->address, sizeof(struct in_addr)); + func->write_u16(handle, element->wtpcount); } /* */ -int capwap_controlipv4_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_controlipv4_element_parsing(struct capwap_message_element* element) { +static void* capwap_controlipv4_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_controlipv4_element* data; - struct capwap_controlipv4_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_CONTROLIPV4); - - if (ntohs(element->length) != sizeof(struct capwap_controlipv4_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 6) { + capwap_logging_debug("Invalid Control IPv4 Address element"); return NULL; } @@ -72,17 +46,24 @@ void* capwap_controlipv4_element_parsing(struct capwap_message_element* element) capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_controlipv4_raw_element*)element->data; - data->address.s_addr = dataraw->address; - data->wtpcount = ntohs(dataraw->wtpcount); - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_controlipv4_element)); + func->read_block(handle, (uint8_t*)&data->address, sizeof(struct in_addr)); + func->read_u16(handle, &data->wtpcount); + return data; } /* */ -void capwap_controlipv4_element_free(void* data) { +static void capwap_controlipv4_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_controlipv4_ops = { + .create_message_element = capwap_controlipv4_element_create, + .parsing_message_element = capwap_controlipv4_element_parsing, + .free_parsed_message_element = capwap_controlipv4_element_free +}; diff --git a/src/common/capwap_element_controlipv4.h b/src/common/capwap_element_controlipv4.h index fbb7ebb..f08c2f3 100644 --- a/src/common/capwap_element_controlipv4.h +++ b/src/common/capwap_element_controlipv4.h @@ -5,19 +5,9 @@ struct capwap_controlipv4_element { struct in_addr address; - unsigned short wtpcount; + uint16_t wtpcount; }; -struct capwap_message_element* capwap_controlipv4_element_create(void* data, unsigned long datalength); -int capwap_controlipv4_element_validate(struct capwap_message_element* element); -void* capwap_controlipv4_element_parsing(struct capwap_message_element* element); -void capwap_controlipv4_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_CONTROLIPV4_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV4); \ - f->create(x, sizeof(struct capwap_controlipv4_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_controlipv4_ops; #endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */ diff --git a/src/common/capwap_element_controlipv6.c b/src/common/capwap_element_controlipv6.c index 6211bc2..95cf892 100644 --- a/src/common/capwap_element_controlipv6.c +++ b/src/common/capwap_element_controlipv6.c @@ -18,57 +18,31 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 11 for CAPWAP Control IPv6 Address + Length: 18 ********************************************************************/ -struct capwap_controlipv6_raw_element { - unsigned long address[4]; - unsigned short wtpcount; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_controlipv6_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_controlipv6_element* dataelement = (struct capwap_controlipv6_element*)data; - struct capwap_controlipv6_raw_element* dataraw; - +static void capwap_controlipv6_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_controlipv6_element* element = (struct capwap_controlipv6_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_controlipv6_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv6_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv6_raw_element)); - element->type = htons(CAPWAP_ELEMENT_CONTROLIPV6); - element->length = htons(sizeof(struct capwap_controlipv6_raw_element)); - - dataraw = (struct capwap_controlipv6_raw_element*)element->data; - memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4); - dataraw->wtpcount = htons(dataelement->wtpcount); - - return element; + /* */ + func->write_block(handle, (uint8_t*)&element->address, sizeof(struct in6_addr)); + func->write_u16(handle, element->wtpcount); } /* */ -int capwap_controlipv6_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_controlipv6_element_parsing(struct capwap_message_element* element) { +static void* capwap_controlipv6_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_controlipv6_element* data; - struct capwap_controlipv6_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_CONTROLIPV6); - - if (ntohs(element->length) != sizeof(struct capwap_controlipv6_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 18) { + capwap_logging_debug("Invalid Control IPv6 Address element"); return NULL; } @@ -78,17 +52,24 @@ void* capwap_controlipv6_element_parsing(struct capwap_message_element* element) capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_controlipv6_raw_element*)element->data; - memcpy(data->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4); - data->wtpcount = ntohs(dataraw->wtpcount); - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_controlipv6_element)); + func->read_block(handle, (uint8_t*)&data->address, sizeof(struct in6_addr)); + func->read_u16(handle, &data->wtpcount); + return data; } /* */ -void capwap_controlipv6_element_free(void* data) { +static void capwap_controlipv6_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_controlipv6_ops = { + .create_message_element = capwap_controlipv6_element_create, + .parsing_message_element = capwap_controlipv6_element_parsing, + .free_parsed_message_element = capwap_controlipv6_element_free +}; diff --git a/src/common/capwap_element_controlipv6.h b/src/common/capwap_element_controlipv6.h index 2963eb6..f19213f 100644 --- a/src/common/capwap_element_controlipv6.h +++ b/src/common/capwap_element_controlipv6.h @@ -8,16 +8,6 @@ struct capwap_controlipv6_element { unsigned short wtpcount; }; -struct capwap_message_element* capwap_controlipv6_element_create(void* data, unsigned long datalength); -int capwap_controlipv6_element_validate(struct capwap_message_element* element); -void* capwap_controlipv6_element_parsing(struct capwap_message_element* element); -void capwap_controlipv6_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_CONTROLIPV6_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV6); \ - f->create(x, sizeof(struct capwap_controlipv6_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_controlipv6_ops; #endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */ diff --git a/src/common/capwap_element_decrypterrorreportperiod.c b/src/common/capwap_element_decrypterrorreportperiod.c index e729ce0..fd0e8b7 100644 --- a/src/common/capwap_element_decrypterrorreportperiod.c +++ b/src/common/capwap_element_decrypterrorreportperiod.c @@ -10,57 +10,31 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 16 for Decryption Error Report Period + Length: 3 ********************************************************************/ -struct capwap_decrypterrorreportperiod_raw_element { - unsigned char radioid; - unsigned short interval; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_decrypterrorreportperiod_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_decrypterrorreportperiod_element* dataelement = (struct capwap_decrypterrorreportperiod_element*)data; - struct capwap_decrypterrorreportperiod_raw_element* dataraw; - +static void capwap_decrypterrorreportperiod_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_decrypterrorreportperiod_element* element = (struct capwap_decrypterrorreportperiod_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_decrypterrorreportperiod_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_decrypterrorreportperiod_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_decrypterrorreportperiod_raw_element)); - element->type = htons(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD); - element->length = htons(sizeof(struct capwap_decrypterrorreportperiod_raw_element)); - - dataraw = (struct capwap_decrypterrorreportperiod_raw_element*)element->data; - dataraw->radioid = dataelement->radioid; - dataraw->interval = htons(dataelement->interval); - - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u16(handle, element->interval); } /* */ -int capwap_decrypterrorreportperiod_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_decrypterrorreportperiod_element_parsing(struct capwap_message_element* element) { +static void* capwap_decrypterrorreportperiod_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_decrypterrorreportperiod_element* data; - struct capwap_decrypterrorreportperiod_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD); - - if (ntohs(element->length) != sizeof(struct capwap_decrypterrorreportperiod_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 3) { + capwap_logging_debug("Invalid Decryption Error Report Period element"); return NULL; } @@ -70,17 +44,24 @@ void* capwap_decrypterrorreportperiod_element_parsing(struct capwap_message_elem capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_decrypterrorreportperiod_raw_element*)element->data; - data->radioid = dataraw->radioid; - data->interval = ntohs(dataraw->interval); - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_decrypterrorreportperiod_element)); + func->read_u8(handle, &data->radioid); + func->read_u16(handle, &data->interval); + return data; } /* */ -void capwap_decrypterrorreportperiod_element_free(void* data) { +static void capwap_decrypterrorreportperiod_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_decrypterrorreportperiod_ops = { + .create_message_element = capwap_decrypterrorreportperiod_element_create, + .parsing_message_element = capwap_decrypterrorreportperiod_element_parsing, + .free_parsed_message_element = capwap_decrypterrorreportperiod_element_free +}; diff --git a/src/common/capwap_element_decrypterrorreportperiod.h b/src/common/capwap_element_decrypterrorreportperiod.h index e479175..4668657 100644 --- a/src/common/capwap_element_decrypterrorreportperiod.h +++ b/src/common/capwap_element_decrypterrorreportperiod.h @@ -4,19 +4,10 @@ #define CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD 16 struct capwap_decrypterrorreportperiod_element { - unsigned char radioid; - unsigned short interval; + uint8_t radioid; + uint16_t interval; }; -struct capwap_message_element* capwap_decrypterrorreportperiod_element_create(void* data, unsigned long length); -int capwap_decrypterrorreportperiod_element_validate(struct capwap_message_element* element); -void* capwap_decrypterrorreportperiod_element_parsing(struct capwap_message_element* element); -void capwap_decrypterrorreportperiod_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_decrypterrorreportperiod_ops; -/* Helper */ -#define CAPWAP_CREATE_DECRYPTERRORREPORTPERIOD_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD); \ - f->create(x, sizeof(struct capwap_decrypterrorreportperiod_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_HEADER__ */ diff --git a/src/common/capwap_element_discoverytype.c b/src/common/capwap_element_discoverytype.c index b684c90..1869490 100644 --- a/src/common/capwap_element_discoverytype.c +++ b/src/common/capwap_element_discoverytype.c @@ -10,49 +10,30 @@ +-+-+-+-+-+-+-+-+ Type: 20 for Discovery Type + Length: 1 ********************************************************************/ -struct capwap_discoverytype_raw_element { - unsigned char type; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_discoverytype_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_discoverytype_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_discoverytype_element* element = (struct capwap_discoverytype_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_discoverytype_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_discoverytype_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_discoverytype_raw_element)); - element->type = htons(CAPWAP_ELEMENT_DISCOVERYTYPE); - element->length = htons(sizeof(struct capwap_discoverytype_raw_element)); - ((struct capwap_discoverytype_raw_element*)element->data)->type = ((struct capwap_discoverytype_element*)data)->type; - return element; + /* */ + func->write_u8(handle, element->type); } /* */ -int capwap_discoverytype_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_discoverytype_element_parsing(struct capwap_message_element* element) { +static void* capwap_discoverytype_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_discoverytype_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_DISCOVERYTYPE); - - if (ntohs(element->length) != sizeof(struct capwap_discoverytype_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 1) { + capwap_logging_debug("Invalid Discovery Type element"); return NULL; } @@ -62,14 +43,23 @@ void* capwap_discoverytype_element_parsing(struct capwap_message_element* elemen capwap_outofmemory(); } - /* */ - data->type = ((struct capwap_discoverytype_raw_element*)element->data)->type; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_discoverytype_element)); + func->read_u8(handle, &data->type); + return data; } /* */ -void capwap_discoverytype_element_free(void* data) { +static void capwap_discoverytype_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_discoverytype_ops = { + .create_message_element = capwap_discoverytype_element_create, + .parsing_message_element = capwap_discoverytype_element_parsing, + .free_parsed_message_element = capwap_discoverytype_element_free +}; diff --git a/src/common/capwap_element_discoverytype.h b/src/common/capwap_element_discoverytype.h index c404b42..dd6fabb 100644 --- a/src/common/capwap_element_discoverytype.h +++ b/src/common/capwap_element_discoverytype.h @@ -10,19 +10,9 @@ #define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_ACREFERRAL 4 struct capwap_discoverytype_element { - unsigned char type; + uint8_t type; }; -struct capwap_message_element* capwap_discoverytype_element_create(void* data, unsigned long datalength); -int capwap_discoverytype_element_validate(struct capwap_message_element* element); -void* capwap_discoverytype_element_parsing(struct capwap_message_element* element); -void capwap_discoverytype_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_DISCOVERYTYPE_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_DISCOVERYTYPE); \ - f->create(x, sizeof(struct capwap_discoverytype_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_discoverytype_ops; #endif /* __CAPWAP_ELEMENT_DISCOVERYTYPE_HEADER__ */ diff --git a/src/common/capwap_element_ecnsupport.c b/src/common/capwap_element_ecnsupport.c index 5b86816..8886634 100644 --- a/src/common/capwap_element_ecnsupport.c +++ b/src/common/capwap_element_ecnsupport.c @@ -10,51 +10,30 @@ +-+-+-+-+-+-+-+-+ Type: 53 for ECN Support + Length: 1 ********************************************************************/ -struct capwap_ecnsupport_raw_element { - char flag; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_ecnsupport_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_ecnsupport_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_ecnsupport_element* element = (struct capwap_ecnsupport_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_ecnsupport_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_ecnsupport_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_ecnsupport_raw_element)); - element->type = htons(CAPWAP_ELEMENT_ECNSUPPORT); - element->length = htons(sizeof(struct capwap_ecnsupport_raw_element)); - - ((struct capwap_ecnsupport_raw_element*)element->data)->flag = ((struct capwap_ecnsupport_element*)data)->flag; - - return element; + /* */ + func->write_u8(handle, element->flag); } /* */ -int capwap_ecnsupport_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_ecnsupport_element_parsing(struct capwap_message_element* element) { +static void* capwap_ecnsupport_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_ecnsupport_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ECNSUPPORT); - - if (ntohs(element->length) != sizeof(struct capwap_ecnsupport_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 1) { + capwap_logging_debug("Invalid ECN Support element"); return NULL; } @@ -64,14 +43,23 @@ void* capwap_ecnsupport_element_parsing(struct capwap_message_element* element) capwap_outofmemory(); } - /* */ - data->flag = ((struct capwap_ecnsupport_raw_element*)element->data)->flag; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_ecnsupport_element)); + func->read_u8(handle, &data->flag); + return data; } /* */ -void capwap_ecnsupport_element_free(void* data) { +static void capwap_ecnsupport_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_ecnsupport_ops = { + .create_message_element = capwap_ecnsupport_element_create, + .parsing_message_element = capwap_ecnsupport_element_parsing, + .free_parsed_message_element = capwap_ecnsupport_element_free +}; diff --git a/src/common/capwap_element_ecnsupport.h b/src/common/capwap_element_ecnsupport.h index bc4ff79..edad005 100644 --- a/src/common/capwap_element_ecnsupport.h +++ b/src/common/capwap_element_ecnsupport.h @@ -3,22 +3,13 @@ #define CAPWAP_ELEMENT_ECNSUPPORT 53 -struct capwap_ecnsupport_element { - char flag; -}; - #define CAPWAP_LIMITED_ECN_SUPPORT 0 #define CAPWAP_FULL_ECN_SUPPORT 1 -struct capwap_message_element* capwap_ecnsupport_element_create(void* data, unsigned long length); -int capwap_ecnsupport_element_validate(struct capwap_message_element* element); -void* capwap_ecnsupport_element_parsing(struct capwap_message_element* element); -void capwap_ecnsupport_element_free(void* data); +struct capwap_ecnsupport_element { + uint8_t flag; +}; + +extern struct capwap_message_elements_ops capwap_element_ecnsupport_ops; -/* Helper */ -#define CAPWAP_CREATE_ECNSUPPORT_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ECNSUPPORT); \ - f->create(x, sizeof(struct capwap_ecnsupport_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_ECNSUPPORT_HEADER__ */ diff --git a/src/common/capwap_element_idletimeout.c b/src/common/capwap_element_idletimeout.c index ee4e30b..33270f8 100644 --- a/src/common/capwap_element_idletimeout.c +++ b/src/common/capwap_element_idletimeout.c @@ -14,47 +14,25 @@ Length: 4 ********************************************************************/ -struct capwap_idletimeout_raw_element { - unsigned long timeout; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_idletimeout_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_idletimeout_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_idletimeout_element* element = (struct capwap_idletimeout_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_idletimeout_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_idletimeout_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_idletimeout_raw_element)); - element->type = htons(CAPWAP_ELEMENT_IDLETIMEOUT); - element->length = htons(sizeof(struct capwap_idletimeout_raw_element)); - - ((struct capwap_idletimeout_raw_element*)element->data)->timeout = htonl(((struct capwap_idletimeout_element*)data)->timeout); - - return element; + /* */ + func->write_u32(handle, element->timeout); } /* */ -int capwap_idletimeout_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_idletimeout_element_parsing(struct capwap_message_element* element) { +static void* capwap_idletimeout_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_idletimeout_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_IDLETIMEOUT); - - if (ntohs(element->length) != sizeof(struct capwap_idletimeout_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 4) { + capwap_logging_debug("Invalid Idle Timeout element"); return NULL; } @@ -64,14 +42,23 @@ void* capwap_idletimeout_element_parsing(struct capwap_message_element* element) capwap_outofmemory(); } - /* */ - data->timeout = ntohl(((struct capwap_idletimeout_raw_element*)element->data)->timeout); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_idletimeout_element)); + func->read_u32(handle, &data->timeout); + return data; } /* */ -void capwap_idletimeout_element_free(void* data) { +static void capwap_idletimeout_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_idletimeout_ops = { + .create_message_element = capwap_idletimeout_element_create, + .parsing_message_element = capwap_idletimeout_element_parsing, + .free_parsed_message_element = capwap_idletimeout_element_free +}; diff --git a/src/common/capwap_element_idletimeout.h b/src/common/capwap_element_idletimeout.h index e640954..c1759c2 100644 --- a/src/common/capwap_element_idletimeout.h +++ b/src/common/capwap_element_idletimeout.h @@ -4,18 +4,9 @@ #define CAPWAP_ELEMENT_IDLETIMEOUT 23 struct capwap_idletimeout_element { - unsigned long timeout; + uint32_t timeout; }; -struct capwap_message_element* capwap_idletimeout_element_create(void* data, unsigned long length); -int capwap_idletimeout_element_validate(struct capwap_message_element* element); -void* capwap_idletimeout_element_parsing(struct capwap_message_element* element); -void capwap_idletimeout_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_idletimeout_ops; -/* Helper */ -#define CAPWAP_CREATE_IDLETIMEOUT_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_IDLETIMEOUT); \ - f->create(x, sizeof(struct capwap_idletimeout_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_IDLETIMEOUT_HEADER__ */ diff --git a/src/common/capwap_element_imageidentifier.c b/src/common/capwap_element_imageidentifier.c index 89d48c6..fd48646 100644 --- a/src/common/capwap_element_imageidentifier.c +++ b/src/common/capwap_element_imageidentifier.c @@ -12,82 +12,65 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 25 for Image Identifier + Length: >= 5 ********************************************************************/ -struct capwap_imageidentifier_raw_element { - unsigned long vendor; - char name[0]; -} __attribute__((__packed__)); +/* */ +static void capwap_imageidentifier_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_imageidentifier_element* element = (struct capwap_imageidentifier_element*)data; + + ASSERT(data != NULL); + + func->write_u32(handle, element->vendor); + func->write_block(handle, element->name, strlen((char*)element->name)); +} /* */ -struct capwap_message_element* capwap_imageidentifier_element_create(void* data, unsigned long datalength) { - unsigned short namelength; - struct capwap_message_element* element; - struct capwap_imageidentifier_raw_element* dataraw; - struct capwap_imageidentifier_element* dataelement = (struct capwap_imageidentifier_element*)data; - - ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_imageidentifier_element)); - - /* Alloc block of memory */ - namelength = strlen(dataelement->name); - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_imageidentifier_raw_element) + namelength); - if (!element) { - capwap_outofmemory(); +static void* capwap_imageidentifier_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; + struct capwap_imageidentifier_element* data; + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length < 5) { + capwap_logging_debug("Invalid Image Indentifier element"); + return NULL; } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_imageidentifier_raw_element) + namelength); - element->type = htons(CAPWAP_ELEMENT_IMAGEIDENTIFIER); - element->length = htons(sizeof(struct capwap_imageidentifier_raw_element) + namelength); - - dataraw = (struct capwap_imageidentifier_raw_element*)element->data; - dataraw->vendor = htonl(dataelement->vendor); - memcpy(&dataraw->name[0], &dataelement->name[0], namelength); - - return element; -} - -/* */ -int capwap_imageidentifier_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_imageidentifier_element_parsing(struct capwap_message_element* element) { - unsigned short namelength; - struct capwap_imageidentifier_element* data; - struct capwap_imageidentifier_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_IMAGEIDENTIFIER); - - namelength = ntohs(element->length) - sizeof(struct capwap_imageidentifier_raw_element); - if (!namelength || (namelength > CAPWAP_IMAGEIDENTIFIER_MAXLENGTH)) { + length -= 4; + if (length > CAPWAP_IMAGEIDENTIFIER_MAXLENGTH) { + capwap_logging_debug("Invalid AC Name element"); return NULL; } /* */ - dataraw = (struct capwap_imageidentifier_raw_element*)element->data; data = (struct capwap_imageidentifier_element*)capwap_alloc(sizeof(struct capwap_imageidentifier_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->vendor = ntohl(dataraw->vendor); - memcpy(&data->name[0], &dataraw->name[0], namelength); - data->name[namelength] = 0; - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_imageidentifier_element)); + func->read_u32(handle, &data->vendor); + func->read_block(handle, data->name, length); + return data; } /* */ -void capwap_imageidentifier_element_free(void* data) { +static void capwap_imageidentifier_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_imageidentifier_ops = { + .create_message_element = capwap_imageidentifier_element_create, + .parsing_message_element = capwap_imageidentifier_element_parsing, + .free_parsed_message_element = capwap_imageidentifier_element_free +}; diff --git a/src/common/capwap_element_imageidentifier.h b/src/common/capwap_element_imageidentifier.h index c0d8e4d..b62455c 100644 --- a/src/common/capwap_element_imageidentifier.h +++ b/src/common/capwap_element_imageidentifier.h @@ -6,20 +6,10 @@ #define CAPWAP_IMAGEIDENTIFIER_MAXLENGTH 1024 struct capwap_imageidentifier_element { - unsigned long vendor; - char name[CAPWAP_IMAGEIDENTIFIER_MAXLENGTH + 1]; + uint32_t vendor; + uint8_t name[CAPWAP_IMAGEIDENTIFIER_MAXLENGTH + 1]; }; -struct capwap_message_element* capwap_imageidentifier_element_create(void* data, unsigned long datalength); -int capwap_imageidentifier_element_validate(struct capwap_message_element* element); -void* capwap_imageidentifier_element_parsing(struct capwap_message_element* element); -void capwap_imageidentifier_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_IMAGEIDENTIFIER); \ - f->create(x, sizeof(struct capwap_imageidentifier_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_imageidentifier_ops; #endif /* __CAPWAP_ELEMENT_IMAGEIDENTIFIER_HEADER__ */ diff --git a/src/common/capwap_element_localipv4.c b/src/common/capwap_element_localipv4.c index 53f9231..f04acb7 100644 --- a/src/common/capwap_element_localipv4.c +++ b/src/common/capwap_element_localipv4.c @@ -10,55 +10,30 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 30 for CAPWAP Local IPv4 Address + Length: 4 ********************************************************************/ -struct capwap_localipv4_raw_element { - unsigned long address; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_localipv4_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_localipv4_element* dataelement = (struct capwap_localipv4_element*)data; - struct capwap_localipv4_raw_element* dataraw; - +static void capwap_localipv4_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_localipv4_element* element = (struct capwap_localipv4_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_localipv4_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv4_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv4_raw_element)); - element->type = htons(CAPWAP_ELEMENT_LOCALIPV4); - element->length = htons(sizeof(struct capwap_localipv4_raw_element)); - - dataraw = (struct capwap_localipv4_raw_element*)element->data; - dataraw->address = dataelement->address.s_addr; - - return element; + /* */ + func->write_block(handle, (uint8_t*)&element->address, sizeof(struct in_addr)); } /* */ -int capwap_localipv4_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_localipv4_element_parsing(struct capwap_message_element* element) { +static void* capwap_localipv4_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_localipv4_element* data; - struct capwap_localipv4_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCALIPV4); - - if (ntohs(element->length) != sizeof(struct capwap_localipv4_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 4) { + capwap_logging_debug("Invalid Local IPv4 Address element"); return NULL; } @@ -68,16 +43,23 @@ void* capwap_localipv4_element_parsing(struct capwap_message_element* element) { capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_localipv4_raw_element*)element->data; - data->address.s_addr = dataraw->address; - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_localipv4_element)); + func->read_block(handle, (uint8_t*)&data->address, sizeof(struct in_addr)); + return data; } /* */ -void capwap_localipv4_element_free(void* data) { +static void capwap_localipv4_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_localipv4_ops = { + .create_message_element = capwap_localipv4_element_create, + .parsing_message_element = capwap_localipv4_element_parsing, + .free_parsed_message_element = capwap_localipv4_element_free +}; diff --git a/src/common/capwap_element_localipv4.h b/src/common/capwap_element_localipv4.h index ac0c17f..3b86912 100644 --- a/src/common/capwap_element_localipv4.h +++ b/src/common/capwap_element_localipv4.h @@ -7,16 +7,6 @@ struct capwap_localipv4_element { struct in_addr address; }; -struct capwap_message_element* capwap_localipv4_element_create(void* data, unsigned long datalength); -int capwap_localipv4_element_validate(struct capwap_message_element* element); -void* capwap_localipv4_element_parsing(struct capwap_message_element* element); -void capwap_localipv4_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_LOCALIPV4_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV4); \ - f->create(x, sizeof(struct capwap_localipv4_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_localipv4_ops; #endif /* __CAPWAP_ELEMENT_LOCALIPV4_HEADER__ */ diff --git a/src/common/capwap_element_localipv6.c b/src/common/capwap_element_localipv6.c index dbeaf96..2c29e9c 100644 --- a/src/common/capwap_element_localipv6.c +++ b/src/common/capwap_element_localipv6.c @@ -20,51 +20,25 @@ Length: 16 ********************************************************************/ -struct capwap_localipv6_raw_element { - unsigned long address[4]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_localipv6_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_localipv6_element* dataelement = (struct capwap_localipv6_element*)data; - struct capwap_localipv6_raw_element* dataraw; - +static void capwap_localipv6_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_localipv6_element* element = (struct capwap_localipv6_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_localipv6_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv6_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv6_raw_element)); - element->type = htons(CAPWAP_ELEMENT_LOCALIPV6); - element->length = htons(sizeof(struct capwap_localipv6_raw_element)); - - dataraw = (struct capwap_localipv6_raw_element*)element->data; - memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4); - - return element; + /* */ + func->write_block(handle, (uint8_t*)&element->address, sizeof(struct in6_addr)); } /* */ -int capwap_localipv6_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_localipv6_element_parsing(struct capwap_message_element* element) { +static void* capwap_localipv6_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_localipv6_element* data; - struct capwap_localipv6_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCALIPV6); - - if (ntohs(element->length) != sizeof(struct capwap_localipv6_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 16) { + capwap_logging_debug("Invalid Local IPv6 Address element"); return NULL; } @@ -74,16 +48,23 @@ void* capwap_localipv6_element_parsing(struct capwap_message_element* element) { capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_localipv6_raw_element*)element->data; - memcpy(data->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4); - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_localipv6_element)); + func->read_block(handle, (uint8_t*)&data->address, sizeof(struct in6_addr)); + return data; } /* */ -void capwap_localipv6_element_free(void* data) { +static void capwap_localipv6_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_localipv6_ops = { + .create_message_element = capwap_localipv6_element_create, + .parsing_message_element = capwap_localipv6_element_parsing, + .free_parsed_message_element = capwap_localipv6_element_free +}; diff --git a/src/common/capwap_element_localipv6.h b/src/common/capwap_element_localipv6.h index 561c02c..c40f44c 100644 --- a/src/common/capwap_element_localipv6.h +++ b/src/common/capwap_element_localipv6.h @@ -7,16 +7,6 @@ struct capwap_localipv6_element { struct in6_addr address; }; -struct capwap_message_element* capwap_localipv6_element_create(void* data, unsigned long datalength); -int capwap_localipv6_element_validate(struct capwap_message_element* element); -void* capwap_localipv6_element_parsing(struct capwap_message_element* element); -void capwap_localipv6_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_LOCALIPV6_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV6); \ - f->create(x, sizeof(struct capwap_localipv6_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_localipv6_ops; #endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */ diff --git a/src/common/capwap_element_location.c b/src/common/capwap_element_location.c index 77c911a..baaae48 100644 --- a/src/common/capwap_element_location.c +++ b/src/common/capwap_element_location.c @@ -10,77 +10,57 @@ +-+-+-+-+-+-+-+-+ Type: 28 for Location Data + Length: >= 1 ********************************************************************/ -struct capwap_location_raw_element { - char value[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_location_element_create(void* data, unsigned long datalength) { - unsigned short namelength; - struct capwap_message_element* element; - struct capwap_location_raw_element* dataraw; - struct capwap_location_element* dataelement = (struct capwap_location_element*)data; - +static void capwap_location_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_location_element* element = (struct capwap_location_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_location_element)); - - /* Alloc block of memory */ - namelength = strlen(dataelement->value); - element = capwap_alloc(sizeof(struct capwap_message_element) + namelength); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + namelength); - element->type = htons(CAPWAP_ELEMENT_LOCATION); - element->length = htons(namelength); - - dataraw = (struct capwap_location_raw_element*)element->data; - memcpy(&dataraw->value[0], &dataelement->value[0], namelength); - return element; + func->write_block(handle, element->value, strlen((char*)element->value)); } /* */ -int capwap_location_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_location_element_parsing(struct capwap_message_element* element) { - unsigned short namelength; +static void* capwap_location_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_location_element* data; - struct capwap_location_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCATION); - namelength = ntohs(element->length); - if (!namelength || (namelength > CAPWAP_LOCATION_MAXLENGTH)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if ((length < 1) || (length > CAPWAP_ACNAME_MAXLENGTH)) { + capwap_logging_debug("Invalid AC Name element"); return NULL; } /* */ - dataraw = (struct capwap_location_raw_element*)element->data; data = (struct capwap_location_element*)capwap_alloc(sizeof(struct capwap_location_element)); if (!data) { capwap_outofmemory(); } - /* */ - memcpy(&data->value[0], &dataraw->value[0], namelength); - data->value[namelength] = 0; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_location_element)); + func->read_block(handle, data->value, length); + return data; } /* */ -void capwap_location_element_free(void* data) { +static void capwap_location_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_location_ops = { + .create_message_element = capwap_location_element_create, + .parsing_message_element = capwap_location_element_parsing, + .free_parsed_message_element = capwap_location_element_free +}; diff --git a/src/common/capwap_element_location.h b/src/common/capwap_element_location.h index 28bb516..08c093f 100644 --- a/src/common/capwap_element_location.h +++ b/src/common/capwap_element_location.h @@ -6,19 +6,9 @@ #define CAPWAP_LOCATION_MAXLENGTH 1024 struct capwap_location_element { - char value[CAPWAP_LOCATION_MAXLENGTH + 1]; + uint8_t value[CAPWAP_LOCATION_MAXLENGTH + 1]; }; -struct capwap_message_element* capwap_location_element_create(void* data, unsigned long datalength); -int capwap_location_element_validate(struct capwap_message_element* element); -void* capwap_location_element_parsing(struct capwap_message_element* element); -void capwap_location_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_LOCATION_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCATION); \ - f->create(x, sizeof(struct capwap_location_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_location_ops; #endif /* __CAPWAP_ELEMENT_LOCATION_HEADER__ */ diff --git a/src/common/capwap_element_maximumlength.c b/src/common/capwap_element_maximumlength.c index 499aed2..f2be408 100644 --- a/src/common/capwap_element_maximumlength.c +++ b/src/common/capwap_element_maximumlength.c @@ -10,51 +10,30 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 29 for Maximum Message Length + Length: 2 ********************************************************************/ -struct capwap_maximumlength_raw_element { - unsigned short length; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_maximumlength_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_maximumlength_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_maximumlength_element* element = (struct capwap_maximumlength_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_maximumlength_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_maximumlength_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_maximumlength_raw_element)); - element->type = htons(CAPWAP_ELEMENT_MAXIMUMLENGTH); - element->length = htons(sizeof(struct capwap_maximumlength_raw_element)); - - ((struct capwap_maximumlength_raw_element*)element->data)->length = htons(((struct capwap_maximumlength_element*)data)->length); - - return element; + /* */ + func->write_u16(handle, element->length); } /* */ -int capwap_maximumlength_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_maximumlength_element_parsing(struct capwap_message_element* element) { +static void* capwap_maximumlength_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_maximumlength_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_MAXIMUMLENGTH); - - if (ntohs(element->length) != sizeof(struct capwap_maximumlength_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 2) { + capwap_logging_debug("Invalid Maxium Message Length element"); return NULL; } @@ -64,14 +43,23 @@ void* capwap_maximumlength_element_parsing(struct capwap_message_element* elemen capwap_outofmemory(); } - /* */ - data->length = ntohs(((struct capwap_maximumlength_raw_element*)element->data)->length); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_maximumlength_element)); + func->read_u16(handle, &data->length); + return data; } /* */ -void capwap_maximumlength_element_free(void* data) { +static void capwap_maximumlength_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_maximumlength_ops = { + .create_message_element = capwap_maximumlength_element_create, + .parsing_message_element = capwap_maximumlength_element_parsing, + .free_parsed_message_element = capwap_maximumlength_element_free +}; diff --git a/src/common/capwap_element_maximumlength.h b/src/common/capwap_element_maximumlength.h index 6d0f84b..0387ebd 100644 --- a/src/common/capwap_element_maximumlength.h +++ b/src/common/capwap_element_maximumlength.h @@ -4,18 +4,9 @@ #define CAPWAP_ELEMENT_MAXIMUMLENGTH 29 struct capwap_maximumlength_element { - unsigned short length; + uint16_t length; }; -struct capwap_message_element* capwap_maximumlength_element_create(void* data, unsigned long length); -int capwap_maximumlength_element_validate(struct capwap_message_element* element); -void* capwap_maximumlength_element_parsing(struct capwap_message_element* element); -void capwap_maximumlength_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_maximumlength_ops; -/* Helper */ -#define CAPWAP_CREATE_MAXIMUMLENGTH_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_MAXIMUMLENGTH); \ - f->create(x, sizeof(struct capwap_maximumlength_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_MAXIMUMLENGTH_HEADER__ */ diff --git a/src/common/capwap_element_mtudiscovery.c b/src/common/capwap_element_mtudiscovery.c index 712eeba..cfaeb6f 100644 --- a/src/common/capwap_element_mtudiscovery.c +++ b/src/common/capwap_element_mtudiscovery.c @@ -10,63 +10,66 @@ +-+-+-+-+-+-+-+- Type: 52 for MTU Discovery Padding + Length: variable ********************************************************************/ /* */ -struct capwap_message_element* capwap_mtudiscovery_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_mtudiscovery_element* dataelement = (struct capwap_mtudiscovery_element*)data; - +static void capwap_mtudiscovery_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + uint16_t length; + struct capwap_mtudiscovery_element* element = (struct capwap_mtudiscovery_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_mtudiscovery_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + dataelement->length); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element)); - element->type = htons(CAPWAP_ELEMENT_MTUDISCOVERY); - element->length = htons(dataelement->length); - - if (dataelement->length > 0) { - memset(element->data, 0xff, dataelement->length); + /* */ + length = element->length; + while (length > 0) { + func->write_u8(handle, 0xff); + length--; } - - return element; } /* */ -int capwap_mtudiscovery_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_mtudiscovery_element_parsing(struct capwap_message_element* element) { +static void* capwap_mtudiscovery_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + uint16_t length; struct capwap_mtudiscovery_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_MTUDISCOVERY); - + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length > 0) { + capwap_logging_debug("Invalid MTU Discovery Padding element"); + return NULL; + } + /* */ data = (struct capwap_mtudiscovery_element*)capwap_alloc(sizeof(struct capwap_mtudiscovery_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->length = ntohs(element->length); + /* Retrieve data */ + data->length = length; + while (length > 0) { + func->read_u8(handle, NULL); + length--; + } + return data; } /* */ -void capwap_mtudiscovery_element_free(void* data) { +static void capwap_mtudiscovery_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_mtudiscovery_ops = { + .create_message_element = capwap_mtudiscovery_element_create, + .parsing_message_element = capwap_mtudiscovery_element_parsing, + .free_parsed_message_element = capwap_mtudiscovery_element_free +}; diff --git a/src/common/capwap_element_mtudiscovery.h b/src/common/capwap_element_mtudiscovery.h index 706e7e5..878b9a5 100644 --- a/src/common/capwap_element_mtudiscovery.h +++ b/src/common/capwap_element_mtudiscovery.h @@ -4,18 +4,9 @@ #define CAPWAP_ELEMENT_MTUDISCOVERY 52 struct capwap_mtudiscovery_element { - unsigned short length; + uint16_t length; }; -struct capwap_message_element* capwap_mtudiscovery_element_create(void* data, unsigned long length); -int capwap_mtudiscovery_element_validate(struct capwap_message_element* element); -void* capwap_mtudiscovery_element_parsing(struct capwap_message_element* element); -void capwap_mtudiscovery_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_mtudiscovery_ops; -/* Helper */ -#define CAPWAP_CREATE_MTUDISCOVERY_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_MTUDISCOVERY); \ - f->create(x, sizeof(struct capwap_mtudiscovery_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_MTUDISCOVERY_HEADER__ */ diff --git a/src/common/capwap_element_radioadmstate.c b/src/common/capwap_element_radioadmstate.c index dee558d..4635c8d 100644 --- a/src/common/capwap_element_radioadmstate.c +++ b/src/common/capwap_element_radioadmstate.c @@ -10,57 +10,31 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 31 for Radio Administrative State + Length: 2 ********************************************************************/ -struct capwap_radioadmstate_raw_element { - unsigned char radioid; - unsigned char state; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_radioadmstate_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_radioadmstate_element* dataelement = (struct capwap_radioadmstate_element*)data; - struct capwap_radioadmstate_raw_element* dataraw; - +static void capwap_radioadmstate_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_radioadmstate_element* element = (struct capwap_radioadmstate_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_radioadmstate_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_radioadmstate_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_radioadmstate_raw_element)); - element->type = htons(CAPWAP_ELEMENT_RADIOADMSTATE); - element->length = htons(sizeof(struct capwap_radioadmstate_raw_element)); - - dataraw = (struct capwap_radioadmstate_raw_element*)element->data; - dataraw->radioid = dataelement->radioid; - dataraw->state = dataelement->state; - - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u8(handle, element->state); } /* */ -int capwap_radioadmstate_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_radioadmstate_element_parsing(struct capwap_message_element* element) { +static void* capwap_radioadmstate_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_radioadmstate_element* data; - struct capwap_radioadmstate_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RADIOADMSTATE); - - if (ntohs(element->length) != sizeof(struct capwap_radioadmstate_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 2) { + capwap_logging_debug("Invalid Radio Administrative State element"); return NULL; } @@ -70,17 +44,24 @@ void* capwap_radioadmstate_element_parsing(struct capwap_message_element* elemen capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_radioadmstate_raw_element*)element->data; - data->radioid = dataraw->radioid; - data->state = dataraw->state; - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_radioadmstate_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, &data->state); + return data; } /* */ -void capwap_radioadmstate_element_free(void* data) { +static void capwap_radioadmstate_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_radioadmstate_ops = { + .create_message_element = capwap_radioadmstate_element_create, + .parsing_message_element = capwap_radioadmstate_element_parsing, + .free_parsed_message_element = capwap_radioadmstate_element_free +}; diff --git a/src/common/capwap_element_radioadmstate.h b/src/common/capwap_element_radioadmstate.h index a361e80..458efaa 100644 --- a/src/common/capwap_element_radioadmstate.h +++ b/src/common/capwap_element_radioadmstate.h @@ -3,23 +3,14 @@ #define CAPWAP_ELEMENT_RADIOADMSTATE 31 -struct capwap_radioadmstate_element { - unsigned char radioid; - unsigned char state; -}; - #define CAPWAP_RADIO_ADMIN_STATE_ENABLED 1 #define CAPWAP_RADIO_ADMIN_STATE_DISABLED 2 -struct capwap_message_element* capwap_radioadmstate_element_create(void* data, unsigned long length); -int capwap_radioadmstate_element_validate(struct capwap_message_element* element); -void* capwap_radioadmstate_element_parsing(struct capwap_message_element* element); -void capwap_radioadmstate_element_free(void* data); +struct capwap_radioadmstate_element { + uint8_t radioid; + uint8_t state; +}; + +extern struct capwap_message_elements_ops capwap_element_radioadmstate_ops; -/* Helper */ -#define CAPWAP_CREATE_RADIOADMSTATE_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOADMSTATE); \ - f->create(x, sizeof(struct capwap_radioadmstate_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_RADIOADMSTATE_HEADER__ */ diff --git a/src/common/capwap_element_radiooprstate.c b/src/common/capwap_element_radiooprstate.c index a7ceab6..294ece1 100644 --- a/src/common/capwap_element_radiooprstate.c +++ b/src/common/capwap_element_radiooprstate.c @@ -10,59 +10,32 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 32 for Radio Operational State + Length: 3 ********************************************************************/ -struct capwap_radiooprstate_raw_element { - unsigned char radioid; - unsigned char state; - unsigned char cause; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_radiooprstate_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_radiooprstate_element* dataelement = (struct capwap_radiooprstate_element*)data; - struct capwap_radiooprstate_raw_element* dataraw; - +static void capwap_radiooprstate_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_radiooprstate_element* element = (struct capwap_radiooprstate_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_radiooprstate_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_radiooprstate_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_radiooprstate_raw_element)); - element->type = htons(CAPWAP_ELEMENT_RADIOOPRSTATE); - element->length = htons(sizeof(struct capwap_radiooprstate_raw_element)); - - dataraw = (struct capwap_radiooprstate_raw_element*)element->data; - dataraw->radioid = dataelement->radioid; - dataraw->state = dataelement->state; - dataraw->cause = dataelement->cause; - - return element; + /* */ + func->write_u8(handle, element->radioid); + func->write_u8(handle, element->state); + func->write_u8(handle, element->cause); } /* */ -int capwap_radiooprstate_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_radiooprstate_element_parsing(struct capwap_message_element* element) { +static void* capwap_radiooprstate_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_radiooprstate_element* data; - struct capwap_radiooprstate_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RADIOOPRSTATE); - - if (ntohs(element->length) != sizeof(struct capwap_radiooprstate_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 3) { + capwap_logging_debug("Invalid Radio Operational State element"); return NULL; } @@ -72,18 +45,25 @@ void* capwap_radiooprstate_element_parsing(struct capwap_message_element* elemen capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_radiooprstate_raw_element*)element->data; - data->radioid = dataraw->radioid; - data->state = dataraw->state; - data->cause = dataraw->cause; - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_radiooprstate_element)); + func->read_u8(handle, &data->radioid); + func->read_u8(handle, &data->state); + func->read_u8(handle, &data->cause); + return data; } /* */ -void capwap_radiooprstate_element_free(void* data) { +static void capwap_radiooprstate_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_radiooprstate_ops = { + .create_message_element = capwap_radiooprstate_element_create, + .parsing_message_element = capwap_radiooprstate_element_parsing, + .free_parsed_message_element = capwap_radiooprstate_element_free +}; diff --git a/src/common/capwap_element_radiooprstate.h b/src/common/capwap_element_radiooprstate.h index 7cea6b0..d4e75d9 100644 --- a/src/common/capwap_element_radiooprstate.h +++ b/src/common/capwap_element_radiooprstate.h @@ -3,12 +3,6 @@ #define CAPWAP_ELEMENT_RADIOOPRSTATE 32 -struct capwap_radiooprstate_element { - unsigned char radioid; - unsigned char state; - unsigned char cause; -}; - #define CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED 1 #define CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED 2 @@ -17,15 +11,12 @@ struct capwap_radiooprstate_element { #define CAPWAP_RADIO_OPERATIONAL_CAUSE_SOFTWAREFAILURE 2 #define CAPWAP_RADIO_OPERATIONAL_CAUSE_ADMINSET 3 -struct capwap_message_element* capwap_radiooprstate_element_create(void* data, unsigned long length); -int capwap_radiooprstate_element_validate(struct capwap_message_element* element); -void* capwap_radiooprstate_element_parsing(struct capwap_message_element* element); -void capwap_radiooprstate_element_free(void* data); +struct capwap_radiooprstate_element { + unsigned char radioid; + unsigned char state; + unsigned char cause; +}; + +extern struct capwap_message_elements_ops capwap_element_radiooprstate_ops; -/* Helper */ -#define CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOOPRSTATE); \ - f->create(x, sizeof(struct capwap_radiooprstate_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_RADIOOPRSTATE_HEADER__ */ diff --git a/src/common/capwap_element_resultcode.c b/src/common/capwap_element_resultcode.c index 614ed6b..67f1e5f 100644 --- a/src/common/capwap_element_resultcode.c +++ b/src/common/capwap_element_resultcode.c @@ -10,51 +10,30 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 33 for Result Code + Length: 4 ********************************************************************/ -struct capwap_resultcode_raw_element { - unsigned long code; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_resultcode_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_resultcode_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_resultcode_element* element = (struct capwap_resultcode_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_resultcode_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_resultcode_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_resultcode_raw_element)); - element->type = htons(CAPWAP_ELEMENT_RESULTCODE); - element->length = htons(sizeof(struct capwap_resultcode_raw_element)); - - ((struct capwap_resultcode_raw_element*)element->data)->code = htonl(((struct capwap_resultcode_element*)data)->code); - - return element; + /* */ + func->write_u32(handle, element->code); } /* */ -int capwap_resultcode_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_resultcode_element_parsing(struct capwap_message_element* element) { +static void* capwap_resultcode_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_resultcode_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RESULTCODE); - - if (ntohs(element->length) != sizeof(struct capwap_resultcode_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 4) { + capwap_logging_debug("Invalid Result Code element"); return NULL; } @@ -64,14 +43,23 @@ void* capwap_resultcode_element_parsing(struct capwap_message_element* element) capwap_outofmemory(); } - /* */ - data->code = ntohl(((struct capwap_resultcode_raw_element*)element->data)->code); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_resultcode_element)); + func->read_u32(handle, &data->code); + return data; } /* */ -void capwap_resultcode_element_free(void* data) { +static void capwap_resultcode_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_resultcode_ops = { + .create_message_element = capwap_resultcode_element_create, + .parsing_message_element = capwap_resultcode_element_parsing, + .free_parsed_message_element = capwap_resultcode_element_free +}; diff --git a/src/common/capwap_element_resultcode.h b/src/common/capwap_element_resultcode.h index 13c022b..45c5ceb 100644 --- a/src/common/capwap_element_resultcode.h +++ b/src/common/capwap_element_resultcode.h @@ -28,18 +28,9 @@ #define CAPWAP_RESULTCODE_DATA_TRANSFER_ERROR 22 struct capwap_resultcode_element { - unsigned long code; + uint32_t code; }; -struct capwap_message_element* capwap_resultcode_element_create(void* data, unsigned long length); -int capwap_resultcode_element_validate(struct capwap_message_element* element); -void* capwap_resultcode_element_parsing(struct capwap_message_element* element); -void capwap_resultcode_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_resultcode_ops; -/* Helper */ -#define CAPWAP_CREATE_RESULTCODE_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RESULTCODE); \ - f->create(x, sizeof(struct capwap_resultcode_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_RESULTCODE_HEADER__ */ diff --git a/src/common/capwap_element_returnedmessage.c b/src/common/capwap_element_returnedmessage.c index 90053e3..6397a02 100644 --- a/src/common/capwap_element_returnedmessage.c +++ b/src/common/capwap_element_returnedmessage.c @@ -10,84 +10,67 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 34 for Returned Message Element + Length: >= 6 ********************************************************************/ -struct capwap_returnedmessage_raw_element { - unsigned char reason; - unsigned char length; - char message[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_returnedmessage_element_create(void* data, unsigned long datalength) { - unsigned short length; - struct capwap_message_element* element; - struct capwap_returnedmessage_raw_element* dataraw; - struct capwap_returnedmessage_element* dataelement = (struct capwap_returnedmessage_element*)data; - +static void capwap_returnedmessage_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_returnedmessage_element* element = (struct capwap_returnedmessage_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_returnedmessage_element)); - - /* Alloc block of memory */ - length = sizeof(struct capwap_returnedmessage_raw_element) + dataelement->length; - element = capwap_alloc(sizeof(struct capwap_message_element) + length); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element)); - element->type = htons(CAPWAP_ELEMENT_RETURNEDMESSAGE); - element->length = htons(length); - - dataraw = (struct capwap_returnedmessage_raw_element*)element->data; - dataraw->reason = dataelement->reason; - dataraw->length = dataelement->length; - memcpy(&dataraw->message[0], &dataelement->message[0], dataelement->length); - - return element; + func->write_u8(handle, element->reason); + func->write_u8(handle, element->length); + func->write_block(handle, element->message, element->length); } /* */ -int capwap_returnedmessage_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_returnedmessage_element_parsing(struct capwap_message_element* element) { +static void* capwap_returnedmessage_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { unsigned short length; struct capwap_returnedmessage_element* data; - struct capwap_returnedmessage_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RETURNEDMESSAGE); - length = ntohs(element->length) - sizeof(struct capwap_returnedmessage_raw_element); - if (length > CAPWAP_RETURNED_MESSAGE_MAX_LENGTH) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length < 6) { + capwap_logging_debug("Invalid Returned Message element"); return NULL; } - + + length -= 2; + if (length > CAPWAP_RETURNED_MESSAGE_MAX_LENGTH) { + capwap_logging_debug("Invalid Returned Message element"); + return NULL; + } + /* */ - dataraw = (struct capwap_returnedmessage_raw_element*)element->data; data = (struct capwap_returnedmessage_element*)capwap_alloc(sizeof(struct capwap_returnedmessage_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->reason = dataraw->reason; - data->length = dataraw->length; - memcpy(&data->message[0], &dataraw->message[0], dataraw->length); - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_returnedmessage_element)); + func->read_u8(handle, &data->reason); + func->read_u8(handle, &data->length); + func->read_block(handle, data->message, data->length); + return data; } /* */ -void capwap_returnedmessage_element_free(void* data) { +static void capwap_returnedmessage_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_returnedmessage_ops = { + .create_message_element = capwap_returnedmessage_element_create, + .parsing_message_element = capwap_returnedmessage_element_parsing, + .free_parsed_message_element = capwap_returnedmessage_element_free +}; diff --git a/src/common/capwap_element_returnedmessage.h b/src/common/capwap_element_returnedmessage.h index a127729..47157fa 100644 --- a/src/common/capwap_element_returnedmessage.h +++ b/src/common/capwap_element_returnedmessage.h @@ -11,20 +11,11 @@ #define CAPWAP_RETURNED_MESSAGE_MAX_LENGTH 255 struct capwap_returnedmessage_element { - unsigned char reason; - unsigned char length; - char message[CAPWAP_RETURNED_MESSAGE_MAX_LENGTH]; + uint8_t reason; + uint8_t length; + uint8_t message[CAPWAP_RETURNED_MESSAGE_MAX_LENGTH]; }; -struct capwap_message_element* capwap_returnedmessage_element_create(void* data, unsigned long length); -int capwap_returnedmessage_element_validate(struct capwap_message_element* element); -void* capwap_returnedmessage_element_parsing(struct capwap_message_element* element); -void capwap_returnedmessage_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_returnedmessage_ops; -/* Helper */ -#define CAPWAP_CREATE_RETURNEDMESSAGE_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RETURNEDMESSAGE); \ - f->create(x, sizeof(struct capwap_returnedmessage_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_RETURNEDMESSAGE_HEADER__ */ diff --git a/src/common/capwap_element_sessionid.c b/src/common/capwap_element_sessionid.c index 12e54ee..83fba9a 100644 --- a/src/common/capwap_element_sessionid.c +++ b/src/common/capwap_element_sessionid.c @@ -21,72 +21,6 @@ Length: 16 ********************************************************************/ -struct capwap_sessionid_raw_element { - unsigned char id[16]; -} __attribute__((__packed__)); - -/* */ -struct capwap_message_element* capwap_sessionid_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_sessionid_raw_element* dataraw; - struct capwap_sessionid_element* dataelement = (struct capwap_sessionid_element*)data; - - ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_sessionid_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_sessionid_element)); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_sessionid_element)); - element->type = htons(CAPWAP_ELEMENT_SESSIONID); - element->length = htons(sizeof(struct capwap_sessionid_element)); - - dataraw = (struct capwap_sessionid_raw_element*)element->data; - memcpy(&dataraw->id[0], &dataelement->id[0], sizeof(unsigned char) * 16); - return element; -} - -/* */ -int capwap_sessionid_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_sessionid_element_parsing(struct capwap_message_element* element) { - struct capwap_sessionid_element* data; - struct capwap_sessionid_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_SESSIONID); - - if (ntohs(element->length) != sizeof(struct capwap_sessionid_raw_element)) { - return NULL; - } - - /* */ - dataraw = (struct capwap_sessionid_raw_element*)element->data; - data = (struct capwap_sessionid_element*)capwap_alloc(sizeof(struct capwap_sessionid_element)); - if (!data) { - capwap_outofmemory(); - } - - /* */ - memcpy(&data->id[0], &dataraw->id[0], sizeof(unsigned char) * 16); - return data; -} - -/* */ -void capwap_sessionid_element_free(void* data) { - ASSERT(data != NULL); - - capwap_free(data); -} - /* */ void capwap_sessionid_generate(struct capwap_sessionid_element* session) { int i; @@ -113,3 +47,51 @@ void capwap_sessionid_printf(struct capwap_sessionid_element* session, char* str *pos = 0; } + +/* */ +static void capwap_sessionid_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_sessionid_element* element = (struct capwap_sessionid_element*)data; + + ASSERT(data != NULL); + + func->write_block(handle, element->id, 16); +} + +/* */ +static void* capwap_sessionid_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + struct capwap_sessionid_element* data; + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 16) { + capwap_logging_debug("Invalid Session ID element"); + return NULL; + } + + /* */ + data = (struct capwap_sessionid_element*)capwap_alloc(sizeof(struct capwap_sessionid_element)); + if (!data) { + capwap_outofmemory(); + } + + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_sessionid_element)); + func->read_block(handle, data->id, 16); + + return data; +} + +/* */ +static void capwap_sessionid_element_free(void* data) { + ASSERT(data != NULL); + + capwap_free(data); +} + +/* */ +struct capwap_message_elements_ops capwap_element_sessionid_ops = { + .create_message_element = capwap_sessionid_element_create, + .parsing_message_element = capwap_sessionid_element_parsing, + .free_parsed_message_element = capwap_sessionid_element_free +}; diff --git a/src/common/capwap_element_sessionid.h b/src/common/capwap_element_sessionid.h index d982e57..cc439ad 100644 --- a/src/common/capwap_element_sessionid.h +++ b/src/common/capwap_element_sessionid.h @@ -4,21 +4,13 @@ #define CAPWAP_ELEMENT_SESSIONID 35 struct capwap_sessionid_element { - unsigned char id[16]; + uint8_t id[16]; }; -struct capwap_message_element* capwap_sessionid_element_create(void* data, unsigned long datalength); -int capwap_sessionid_element_validate(struct capwap_message_element* element); -void* capwap_sessionid_element_parsing(struct capwap_message_element* element); -void capwap_sessionid_element_free(void* data); - +/* */ void capwap_sessionid_generate(struct capwap_sessionid_element* session); void capwap_sessionid_printf(struct capwap_sessionid_element* session, char* string); -/* Helper */ -#define CAPWAP_CREATE_SESSIONID_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_SESSIONID); \ - f->create(x, sizeof(struct capwap_sessionid_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_sessionid_ops; #endif /* __CAPWAP_ELEMENT_SESSIONID_HEADER__ */ diff --git a/src/common/capwap_element_statisticstimer.c b/src/common/capwap_element_statisticstimer.c index ee11a3b..422f28f 100644 --- a/src/common/capwap_element_statisticstimer.c +++ b/src/common/capwap_element_statisticstimer.c @@ -10,51 +10,30 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 36 for Statistics Timer + Length: 2 ********************************************************************/ -struct capwap_statisticstimer_raw_element { - unsigned short timer; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_statisticstimer_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_statisticstimer_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_statisticstimer_element* element = (struct capwap_statisticstimer_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_statisticstimer_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_statisticstimer_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_statisticstimer_raw_element)); - element->type = htons(CAPWAP_ELEMENT_STATISTICSTIMER); - element->length = htons(sizeof(struct capwap_statisticstimer_raw_element)); - - ((struct capwap_statisticstimer_raw_element*)element->data)->timer = htons(((struct capwap_statisticstimer_element*)data)->timer); - - return element; + /* */ + func->write_u16(handle, element->timer); } /* */ -int capwap_statisticstimer_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_statisticstimer_element_parsing(struct capwap_message_element* element) { +static void* capwap_statisticstimer_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_statisticstimer_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_STATISTICSTIMER); - - if (ntohs(element->length) != sizeof(struct capwap_statisticstimer_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 2) { + capwap_logging_debug("Invalid Statistics Timer element"); return NULL; } @@ -64,14 +43,23 @@ void* capwap_statisticstimer_element_parsing(struct capwap_message_element* elem capwap_outofmemory(); } - /* */ - data->timer = ntohs(((struct capwap_statisticstimer_raw_element*)element->data)->timer); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_statisticstimer_element)); + func->read_u16(handle, &data->timer); + return data; } /* */ -void capwap_statisticstimer_element_free(void* data) { +static void capwap_statisticstimer_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_statisticstimer_ops = { + .create_message_element = capwap_statisticstimer_element_create, + .parsing_message_element = capwap_statisticstimer_element_parsing, + .free_parsed_message_element = capwap_statisticstimer_element_free +}; diff --git a/src/common/capwap_element_statisticstimer.h b/src/common/capwap_element_statisticstimer.h index c4ceac6..3e92e74 100644 --- a/src/common/capwap_element_statisticstimer.h +++ b/src/common/capwap_element_statisticstimer.h @@ -4,18 +4,9 @@ #define CAPWAP_ELEMENT_STATISTICSTIMER 36 struct capwap_statisticstimer_element { - unsigned short timer; + uint16_t timer; }; -struct capwap_message_element* capwap_statisticstimer_element_create(void* data, unsigned long length); -int capwap_statisticstimer_element_validate(struct capwap_message_element* element); -void* capwap_statisticstimer_element_parsing(struct capwap_message_element* element); -void capwap_statisticstimer_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_statisticstimer_ops; -/* Helper */ -#define CAPWAP_CREATE_STATISTICSTIMER_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_STATISTICSTIMER); \ - f->create(x, sizeof(struct capwap_statisticstimer_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_STATISTICSTIMER_HEADER__ */ diff --git a/src/common/capwap_element_timers.c b/src/common/capwap_element_timers.c index 46ca9bb..c0c3a2f 100644 --- a/src/common/capwap_element_timers.c +++ b/src/common/capwap_element_timers.c @@ -10,57 +10,31 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 12 for CAPWAP Timers + Length: 2 ********************************************************************/ -struct capwap_timers_raw_element { - unsigned char discovery; - unsigned char echorequest; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_timers_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_timers_element* dataelement = (struct capwap_timers_element*)data; - struct capwap_timers_raw_element* dataraw; - +static void capwap_timers_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_timers_element* element = (struct capwap_timers_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_timers_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_timers_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_timers_raw_element)); - element->type = htons(CAPWAP_ELEMENT_TIMERS); - element->length = htons(sizeof(struct capwap_timers_raw_element)); - - dataraw = (struct capwap_timers_raw_element*)element->data; - dataraw->discovery = dataelement->discovery; - dataraw->echorequest = dataelement->echorequest; - - return element; + /* */ + func->write_u8(handle, element->discovery); + func->write_u8(handle, element->echorequest); } /* */ -int capwap_timers_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_timers_element_parsing(struct capwap_message_element* element) { +static void* capwap_timers_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_timers_element* data; - struct capwap_timers_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_TIMERS); - - if (ntohs(element->length) != sizeof(struct capwap_timers_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 2) { + capwap_logging_debug("Invalid Timers element"); return NULL; } @@ -70,17 +44,24 @@ void* capwap_timers_element_parsing(struct capwap_message_element* element) { capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_timers_raw_element*)element->data; - data->discovery = dataraw->discovery; - data->echorequest = dataraw->echorequest; - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_timers_element)); + func->read_u8(handle, &data->discovery); + func->read_u8(handle, &data->echorequest); + return data; } /* */ -void capwap_timers_element_free(void* data) { +static void capwap_timers_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_timers_ops = { + .create_message_element = capwap_timers_element_create, + .parsing_message_element = capwap_timers_element_parsing, + .free_parsed_message_element = capwap_timers_element_free +}; diff --git a/src/common/capwap_element_timers.h b/src/common/capwap_element_timers.h index 22700e7..19e5458 100644 --- a/src/common/capwap_element_timers.h +++ b/src/common/capwap_element_timers.h @@ -4,19 +4,10 @@ #define CAPWAP_ELEMENT_TIMERS 12 struct capwap_timers_element { - unsigned char discovery; - unsigned char echorequest; + uint8_t discovery; + uint8_t echorequest; }; -struct capwap_message_element* capwap_timers_element_create(void* data, unsigned long length); -int capwap_timers_element_validate(struct capwap_message_element* element); -void* capwap_timers_element_parsing(struct capwap_message_element* element); -void capwap_timers_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_timers_ops; -/* Helper */ -#define CAPWAP_CREATE_TIMERS_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_TIMERS); \ - f->create(x, sizeof(struct capwap_timers_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_TIMERS_HEADER__ */ diff --git a/src/common/capwap_element_transport.c b/src/common/capwap_element_transport.c index d03eb21..7ee2174 100644 --- a/src/common/capwap_element_transport.c +++ b/src/common/capwap_element_transport.c @@ -10,51 +10,30 @@ +-+-+-+-+-+-+-+-+ Type: 51 for CAPWAP Transport Protocol + Length: 1 ********************************************************************/ -struct capwap_transport_raw_element { - char type; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_transport_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_transport_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_transport_element* element = (struct capwap_transport_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_transport_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_transport_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_transport_raw_element)); - element->type = htons(CAPWAP_ELEMENT_TRANSPORT); - element->length = htons(sizeof(struct capwap_transport_raw_element)); - - ((struct capwap_transport_raw_element*)element->data)->type = ((struct capwap_transport_element*)data)->type; - - return element; + /* */ + func->write_u8(handle, element->type); } /* */ -int capwap_transport_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_transport_element_parsing(struct capwap_message_element* element) { +static void* capwap_transport_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_transport_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_TRANSPORT); - - if (ntohs(element->length) != sizeof(struct capwap_transport_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 1) { + capwap_logging_debug("Invalid Transport Protocol element"); return NULL; } @@ -64,14 +43,23 @@ void* capwap_transport_element_parsing(struct capwap_message_element* element) { capwap_outofmemory(); } - /* */ - data->type = ((struct capwap_transport_raw_element*)element->data)->type; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_transport_element)); + func->read_u8(handle, &data->type); + return data; } /* */ -void capwap_transport_element_free(void* data) { +static void capwap_transport_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_transport_ops = { + .create_message_element = capwap_transport_element_create, + .parsing_message_element = capwap_transport_element_parsing, + .free_parsed_message_element = capwap_transport_element_free +}; diff --git a/src/common/capwap_element_transport.h b/src/common/capwap_element_transport.h index 924f7b5..c99e89e 100644 --- a/src/common/capwap_element_transport.h +++ b/src/common/capwap_element_transport.h @@ -3,22 +3,13 @@ #define CAPWAP_ELEMENT_TRANSPORT 51 -struct capwap_transport_element { - char type; -}; - #define CAPWAP_UDPLITE_TRANSPORT 1 #define CAPWAP_UDP_TRANSPORT 2 -struct capwap_message_element* capwap_transport_element_create(void* data, unsigned long length); -int capwap_transport_element_validate(struct capwap_message_element* element); -void* capwap_transport_element_parsing(struct capwap_message_element* element); -void capwap_transport_element_free(void* data); +struct capwap_transport_element { + uint8_t type; +}; + +extern struct capwap_message_elements_ops capwap_element_transport_ops; -/* Helper */ -#define CAPWAP_CREATE_TRANSPORT_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_TRANSPORT); \ - f->create(x, sizeof(struct capwap_transport_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_TRANSPORT_HEADER__ */ diff --git a/src/common/capwap_element_vendorpayload.c b/src/common/capwap_element_vendorpayload.c index c875817..034dc6b 100644 --- a/src/common/capwap_element_vendorpayload.c +++ b/src/common/capwap_element_vendorpayload.c @@ -12,88 +12,67 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 37 for Vendor Specific Payload + Length: >= 7 ********************************************************************/ -struct capwap_vendorpayload_raw_element { - unsigned long vendorid; - unsigned short elementid; - char data[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_vendorpayload_element_create(void* data, unsigned long datalength) { - unsigned short elementlength; - struct capwap_message_element* element; - struct capwap_vendorpayload_raw_element* dataraw; - struct capwap_vendorpayload_element* dataelement = (struct capwap_vendorpayload_element*)data; - +static void capwap_vendorpayload_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_vendorpayload_element* element = (struct capwap_vendorpayload_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_vendorpayload_element)); - - /* */ - if (!dataelement->datalength || (dataelement->datalength > CAPWAP_VENDORPAYLOAD_MAXLENGTH)) { - return NULL; - } - - /* Alloc block of memory */ - elementlength = sizeof(struct capwap_vendorpayload_raw_element) + dataelement->datalength; - element = capwap_alloc(sizeof(struct capwap_message_element) + elementlength); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + elementlength); - element->type = htons(CAPWAP_ELEMENT_VENDORPAYLOAD); - element->length = htons(elementlength); - - dataraw = (struct capwap_vendorpayload_raw_element*)element->data; - dataraw->vendorid = htonl(dataelement->vendorid); - dataraw->elementid = htons(dataelement->elementid); - memcpy(&dataraw->data[0], &dataelement->data[0], dataelement->datalength); - return element; + func->write_u32(handle, element->vendorid); + func->write_u16(handle, element->elementid); + func->write_block(handle, element->data, element->datalength); } /* */ -int capwap_vendorpayload_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_vendorpayload_element_parsing(struct capwap_message_element* element) { - unsigned short elementlength; +static void* capwap_vendorpayload_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_vendorpayload_element* data; - struct capwap_vendorpayload_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_VENDORPAYLOAD); - elementlength = ntohs(element->length); - if (elementlength > sizeof(struct capwap_vendorpayload_raw_element)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if (length < 7) { + capwap_logging_debug("Invalid Vendor Specific Payload element"); + return NULL; + } + + length -= 6; + if (length > CAPWAP_VENDORPAYLOAD_MAXLENGTH) { + capwap_logging_debug("Invalid Vendor Specific Payload element"); return NULL; } /* */ - dataraw = (struct capwap_vendorpayload_raw_element*)element->data; data = (struct capwap_vendorpayload_element*)capwap_alloc(sizeof(struct capwap_vendorpayload_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->vendorid = ntohl(dataraw->vendorid); - data->elementid = ntohs(dataraw->elementid); - data->datalength = elementlength - sizeof(struct capwap_vendorpayload_element); - memcpy(&data->data[0], &dataraw->data[0], data->datalength); + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_vendorpayload_element)); + func->read_u32(handle, &data->vendorid); + func->read_u16(handle, &data->elementid); + func->read_block(handle, data->data, length); + return data; } /* */ -void capwap_vendorpayload_element_free(void* data) { +static void capwap_vendorpayload_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_vendorpayload_ops = { + .create_message_element = capwap_vendorpayload_element_create, + .parsing_message_element = capwap_vendorpayload_element_parsing, + .free_parsed_message_element = capwap_vendorpayload_element_free +}; diff --git a/src/common/capwap_element_vendorpayload.h b/src/common/capwap_element_vendorpayload.h index e664aa0..9dc390f 100644 --- a/src/common/capwap_element_vendorpayload.h +++ b/src/common/capwap_element_vendorpayload.h @@ -6,22 +6,12 @@ #define CAPWAP_VENDORPAYLOAD_MAXLENGTH 2048 struct capwap_vendorpayload_element { - unsigned long vendorid; - unsigned short elementid; - unsigned short datalength; - char data[CAPWAP_VENDORPAYLOAD_MAXLENGTH]; + uint32_t vendorid; + uint16_t elementid; + uint16_t datalength; + uint8_t data[CAPWAP_VENDORPAYLOAD_MAXLENGTH]; }; -struct capwap_message_element* capwap_vendorpayload_element_create(void* data, unsigned long datalength); -int capwap_vendorpayload_element_validate(struct capwap_message_element* element); -void* capwap_vendorpayload_element_parsing(struct capwap_message_element* element); -void capwap_vendorpayload_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_VENDORPAYLOAD_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_VENDORPAYLOAD_MAXLENGTH); \ - f->create(x, sizeof(struct capwap_vendorpayload_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_vendorpayload_ops; #endif /* __CAPWAP_ELEMENT_VENDORPAYLOAD_HEADER__ */ diff --git a/src/common/capwap_element_wtpboarddata.c b/src/common/capwap_element_wtpboarddata.c index 63f7a56..f8f5a41 100644 --- a/src/common/capwap_element_wtpboarddata.c +++ b/src/common/capwap_element_wtpboarddata.c @@ -21,141 +21,93 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 38 for WTP Board Data + Length: >=14 ********************************************************************/ -struct capwap_wtpboarddata_raw_element { - unsigned long vendor; - char data[0]; -} __attribute__((__packed__)); - -struct capwap_wtpboarddata_raw_board_subelement { - unsigned short type; - unsigned short length; - char data[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtpboarddata_element_create(void* data, unsigned long datalength) { - char* pos; - unsigned long i; - unsigned short length; - struct capwap_message_element* element; - struct capwap_wtpboarddata_raw_element* dataraw; - struct capwap_wtpboarddata_element* dataelement = (struct capwap_wtpboarddata_element*)data; - +static void capwap_wtpboarddata_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + int i; + struct capwap_wtpboarddata_element* element = (struct capwap_wtpboarddata_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_wtpboarddata_element)); - ASSERT(dataelement->boardsubelement != NULL); - - /* Calc length packet */ - length = sizeof(struct capwap_wtpboarddata_raw_element); - for (i = 0; i < dataelement->boardsubelement->count; i++) { - struct capwap_wtpboarddata_board_subelement* board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(dataelement->boardsubelement, i); - length += sizeof(struct capwap_wtpboarddata_raw_board_subelement) + board->length; - } - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + length); - if (!element) { - capwap_outofmemory(); - } - - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + length); - element->type = htons(CAPWAP_ELEMENT_WTPBOARDDATA); - element->length = htons(length); - /* */ - dataraw = (struct capwap_wtpboarddata_raw_element*)element->data; - dataraw->vendor = htonl(dataelement->vendor); - pos = dataraw->data; - - /* Board Sub-Element */ - for (i = 0; i < dataelement->boardsubelement->count; i++) { - struct capwap_wtpboarddata_raw_board_subelement* boardraw = (struct capwap_wtpboarddata_raw_board_subelement*)pos; - struct capwap_wtpboarddata_board_subelement* board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(dataelement->boardsubelement, i); - - boardraw->type = htons(board->type); - boardraw->length = htons(board->length); - memcpy(boardraw->data, board->data, board->length); - - pos += sizeof(struct capwap_wtpboarddata_raw_board_subelement) + board->length; + func->write_u32(handle, element->vendor); + + /* */ + for (i = 0; i < element->boardsubelement->count; i++) { + struct capwap_wtpboarddata_board_subelement* desc = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(element->boardsubelement, i); + + func->write_u16(handle, desc->type); + func->write_u16(handle, desc->length); + func->write_block(handle, desc->data, desc->length); } - - return element; } /* */ -int capwap_wtpboarddata_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; +static void capwap_wtpboarddata_element_free(void* data) { + struct capwap_wtpboarddata_element* dataelement = (struct capwap_wtpboarddata_element*)data; + + ASSERT(dataelement != NULL); + ASSERT(dataelement->boardsubelement != NULL); + + capwap_array_free(dataelement->boardsubelement); + capwap_free(dataelement); } /* */ -void* capwap_wtpboarddata_element_parsing(struct capwap_message_element* element) { - long i; - char* pos; - long length; +static void* capwap_wtpboarddata_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_wtpboarddata_element* data; - struct capwap_wtpboarddata_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPBOARDDATA); - - length = (long)ntohs(element->length); - if (length < 14) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) < 14) { capwap_logging_debug("Invalid WTP Board Data element"); return NULL; } /* */ - dataraw = (struct capwap_wtpboarddata_raw_element*)element->data; data = (struct capwap_wtpboarddata_element*)capwap_alloc(sizeof(struct capwap_wtpboarddata_element)); - data->boardsubelement = capwap_array_create(sizeof(struct capwap_wtpboarddata_board_subelement), 0); - - /* */ - data->vendor = ntohl(dataraw->vendor); - - pos = dataraw->data; - length -= sizeof(struct capwap_wtpboarddata_raw_element); + if (!data) { + capwap_outofmemory(); + } - /* Board Subelement */ - i = 0; - while (length > 0) { - struct capwap_wtpboarddata_board_subelement* board = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(data->boardsubelement, i); - struct capwap_wtpboarddata_raw_board_subelement* boardraw = (struct capwap_wtpboarddata_raw_board_subelement*)pos; - unsigned short boardlength = ntohs(boardraw->length); - unsigned short boardrawlength = sizeof(struct capwap_wtpboarddata_raw_board_subelement) + boardlength; - - if ((boardlength > CAPWAP_BOARD_SUBELEMENT_MAXDATA) || (length < boardrawlength)) { + memset(data, 0, sizeof(struct capwap_wtpboarddata_element)); + data->boardsubelement = capwap_array_create(sizeof(struct capwap_wtpboarddata_board_subelement), 0); + data->boardsubelement->zeroed = 1; + + /* Retrieve data */ + func->read_u32(handle, &data->vendor); + + /* WTP Board Data Subelement */ + while (func->read_ready(handle) > 0) { + unsigned short length; + struct capwap_wtpboarddata_board_subelement* desc = (struct capwap_wtpboarddata_board_subelement*)capwap_array_get_item_pointer(data->boardsubelement, data->boardsubelement->count); + + /* */ + func->read_u16(handle, &desc->type); + func->read_u16(handle, &desc->length); + + /* Check buffer size */ + length = func->read_ready(handle); + if ((length > CAPWAP_BOARD_SUBELEMENT_MAXDATA) || (length < desc->length)) { capwap_logging_debug("Invalid WTP Board Data element"); capwap_wtpboarddata_element_free(data); return NULL; } - - /* */ - board->type = ntohs(boardraw->type); - board->length = boardlength; - memcpy(board->data, boardraw->data, boardlength); - /* */ - i++; - pos += boardrawlength; - length -= boardrawlength; + func->read_block(handle, desc->data, desc->length); } - + return data; } /* */ -void capwap_wtpboarddata_element_free(void* data) { - struct capwap_wtpboarddata_element* dataelement = (struct capwap_wtpboarddata_element*)data; - - ASSERT(dataelement != NULL); - ASSERT(dataelement->boardsubelement != NULL); - - capwap_array_free(dataelement->boardsubelement); - capwap_free(dataelement); -} +struct capwap_message_elements_ops capwap_element_wtpboarddata_ops = { + .create_message_element = capwap_wtpboarddata_element_create, + .parsing_message_element = capwap_wtpboarddata_element_parsing, + .free_parsed_message_element = capwap_wtpboarddata_element_free +}; diff --git a/src/common/capwap_element_wtpboarddata.h b/src/common/capwap_element_wtpboarddata.h index 250c9a2..fad326a 100644 --- a/src/common/capwap_element_wtpboarddata.h +++ b/src/common/capwap_element_wtpboarddata.h @@ -4,7 +4,7 @@ #define CAPWAP_ELEMENT_WTPBOARDDATA 38 struct capwap_wtpboarddata_element { - unsigned long vendor; + uint32_t vendor; struct capwap_array* boardsubelement; }; @@ -16,20 +16,11 @@ struct capwap_wtpboarddata_element { #define CAPWAP_BOARD_SUBELEMENT_MAXDATA 1024 struct capwap_wtpboarddata_board_subelement { - unsigned short type; - unsigned short length; - char data[CAPWAP_BOARD_SUBELEMENT_MAXDATA]; + uint16_t type; + uint16_t length; + uint8_t data[CAPWAP_BOARD_SUBELEMENT_MAXDATA]; }; -struct capwap_message_element* capwap_wtpboarddata_element_create(void* data, unsigned long datalength); -int capwap_wtpboarddata_element_validate(struct capwap_message_element* element); -void* capwap_wtpboarddata_element_parsing(struct capwap_message_element* element); -void capwap_wtpboarddata_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_wtpboarddata_ops; -/* Helper */ -#define CAPWAP_CREATE_WTPBOARDDATA_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPBOARDDATA); \ - f->create(x, sizeof(struct capwap_wtpboarddata_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_WTPBOARDDATA_HEADER__ */ diff --git a/src/common/capwap_element_wtpdescriptor.c b/src/common/capwap_element_wtpdescriptor.c index 4d3a393..730f3de 100644 --- a/src/common/capwap_element_wtpdescriptor.c +++ b/src/common/capwap_element_wtpdescriptor.c @@ -29,128 +29,65 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 39 for WTP Descriptor + Length: >= 33 ********************************************************************/ -struct capwap_wtpdescriptor_raw_element { - unsigned char maxradios; - unsigned char radiosinuse; - unsigned char encryptcount; - char data[0]; -} __attribute__((__packed__)); - -struct capwap_wtpdescriptor_raw_encrypt_subelement { -#ifdef CAPWAP_BIG_ENDIAN - unsigned char reserved : 3; - unsigned char wbid : 5; -#else - unsigned char wbid : 5; - unsigned char reserved : 3; -#endif - unsigned short capabilities; -} __attribute__((__packed__)); - -struct capwap_wtpdescriptor_raw_desc_subelement { - unsigned long vendor; - unsigned short type; - unsigned short length; - char data[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtpdescriptor_element_create(void* data, unsigned long datalength) { - char* pos; - unsigned long i; - unsigned short length; - struct capwap_message_element* element; - struct capwap_wtpdescriptor_raw_element* dataraw; - struct capwap_wtpdescriptor_element* dataelement = (struct capwap_wtpdescriptor_element*)data; - +static void capwap_wtpdescriptor_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + int i; + struct capwap_wtpdescriptor_element* element = (struct capwap_wtpdescriptor_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_wtpdescriptor_element)); - ASSERT(dataelement->encryptsubelement != NULL); - ASSERT(dataelement->descsubelement != NULL); - - /* Calc length packet */ - length = sizeof(struct capwap_wtpdescriptor_raw_element); - length += dataelement->encryptsubelement->count * sizeof(struct capwap_wtpdescriptor_raw_encrypt_subelement); - for (i = 0; i < dataelement->descsubelement->count; i++) { - struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i); - length += sizeof(struct capwap_wtpdescriptor_raw_desc_subelement) + desc->length; - } - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + length); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + length); - element->type = htons(CAPWAP_ELEMENT_WTPDESCRIPTOR); - element->length = htons(length); + /* */ + func->write_u8(handle, element->maxradios); + func->write_u8(handle, element->radiosinuse); + func->write_u8(handle, element->encryptsubelement->count); - /* Descriptor */ - dataraw = (struct capwap_wtpdescriptor_raw_element*)element->data; - dataraw->maxradios = dataelement->maxradios; - dataraw->radiosinuse = dataelement->radiosinuse; - dataraw->encryptcount = (unsigned char)dataelement->encryptsubelement->count; - pos = dataraw->data; + /* */ + for (i = 0; i < element->encryptsubelement->count; i++) { + struct capwap_wtpdescriptor_encrypt_subelement* desc = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(element->encryptsubelement, i); - /* Encryption Sub-Element */ - for (i = 0; i < dataelement->encryptsubelement->count; i++) { - struct capwap_wtpdescriptor_raw_encrypt_subelement* encryptraw = (struct capwap_wtpdescriptor_raw_encrypt_subelement*)pos; - struct capwap_wtpdescriptor_encrypt_subelement* encrypt = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(dataelement->encryptsubelement, i); - - encryptraw->wbid = encrypt->wbid; - encryptraw->capabilities = htons(encrypt->capabilities); - - pos += sizeof(struct capwap_wtpdescriptor_raw_encrypt_subelement); - } - - /* Descriptor Sub-Element */ - for (i = 0; i < dataelement->descsubelement->count; i++) { - struct capwap_wtpdescriptor_raw_desc_subelement* descraw = (struct capwap_wtpdescriptor_raw_desc_subelement*)pos; - struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i); - - descraw->vendor = htonl(desc->vendor); - descraw->type = htons(desc->type); - descraw->length = htons(desc->length); - memcpy(descraw->data, desc->data, desc->length); - - pos += sizeof(struct capwap_wtpdescriptor_raw_desc_subelement) + desc->length; - } - - return element; -} - -/* */ -int capwap_wtpdescriptor_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_wtpdescriptor_element_parsing(struct capwap_message_element* element) { - unsigned char i; - long length; - char* pos; - struct capwap_wtpdescriptor_element* data; - struct capwap_wtpdescriptor_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPDESCRIPTOR); - - length = (long)ntohs(element->length); - if (length < 33) { - capwap_logging_debug("Invalid WTP Descriptor element"); - return NULL; + func->write_u8(handle, desc->wbid & 0x1f); + func->write_u16(handle, desc->capabilities); } /* */ - dataraw = (struct capwap_wtpdescriptor_raw_element*)element->data; - if ((dataraw->radiosinuse > dataraw->maxradios) || (dataraw->encryptcount == 0)) { + for (i = 0; i < element->descsubelement->count; i++) { + struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(element->descsubelement, i); + + func->write_u32(handle, desc->vendor); + func->write_u16(handle, desc->type); + func->write_u16(handle, desc->length); + func->write_block(handle, desc->data, desc->length); + } +} + +/* */ +static void capwap_wtpdescriptor_element_free(void* data) { + struct capwap_wtpdescriptor_element* dataelement = (struct capwap_wtpdescriptor_element*)data; + + ASSERT(dataelement != NULL); + ASSERT(dataelement->encryptsubelement != NULL); + ASSERT(dataelement->descsubelement != NULL); + + capwap_array_free(dataelement->encryptsubelement); + capwap_array_free(dataelement->descsubelement); + capwap_free(dataelement); +} + +/* */ +static void* capwap_wtpdescriptor_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + uint8_t i; + uint8_t encryptlength; + struct capwap_wtpdescriptor_element* data; + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) < 33) { capwap_logging_debug("Invalid WTP Descriptor element"); return NULL; } @@ -161,81 +98,76 @@ void* capwap_wtpdescriptor_element_parsing(struct capwap_message_element* elemen capwap_outofmemory(); } + memset(data, 0, sizeof(struct capwap_wtpdescriptor_element)); data->encryptsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_encrypt_subelement), 0); + data->encryptsubelement->zeroed = 1; data->descsubelement = capwap_array_create(sizeof(struct capwap_wtpdescriptor_desc_subelement), 0); - - /* */ - data->maxradios = dataraw->maxradios; - data->radiosinuse = dataraw->radiosinuse; - capwap_array_resize(data->encryptsubelement, dataraw->encryptcount); - - pos = dataraw->data; - length -= sizeof(struct capwap_wtpdescriptor_raw_element); - - /* Encrypt Subelement */ - for (i = 0; i < dataraw->encryptcount; i++) { - struct capwap_wtpdescriptor_encrypt_subelement* encrypt = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(data->encryptsubelement, i); - struct capwap_wtpdescriptor_raw_encrypt_subelement* encryptraw = (struct capwap_wtpdescriptor_raw_encrypt_subelement*)pos; - - if (length < sizeof(struct capwap_wtpdescriptor_raw_element)) { - capwap_logging_debug("Invalid WTP Descriptor element"); - capwap_wtpdescriptor_element_free(data); - return NULL; - } + data->descsubelement->zeroed = 1; - /* */ - encrypt->wbid = encryptraw->wbid; - encrypt->capabilities = ntohs(encryptraw->capabilities); + /* Retrieve data */ + func->read_u8(handle, &data->maxradios); + func->read_u8(handle, &data->radiosinuse); + func->read_u8(handle, &encryptlength); - /* */ - pos += sizeof(struct capwap_wtpdescriptor_raw_encrypt_subelement); - length -= sizeof(struct capwap_wtpdescriptor_raw_element); - } - - if (length < 0) { + /* Check */ + if (!encryptlength) { capwap_logging_debug("Invalid WTP Descriptor element"); capwap_wtpdescriptor_element_free(data); return NULL; } - /* Description Subelement */ - i = 0; - while (length > 0) { - struct capwap_wtpdescriptor_desc_subelement* desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, i); - struct capwap_wtpdescriptor_raw_desc_subelement* descraw = (struct capwap_wtpdescriptor_raw_desc_subelement*)pos; - unsigned short desclength = ntohs(descraw->length); - unsigned short descrawlength = sizeof(struct capwap_wtpdescriptor_raw_desc_subelement) + desclength; - - if ((desclength > CAPWAP_WTPDESC_SUBELEMENT_MAXDATA) || (length < descrawlength)) { + /* Encryption Subelement */ + for (i = 0; i < encryptlength; i++) { + struct capwap_wtpdescriptor_encrypt_subelement* desc; + + /* Check */ + if (func->read_ready(handle) < 3) { capwap_logging_debug("Invalid WTP Descriptor element"); capwap_wtpdescriptor_element_free(data); return NULL; } - - /* */ - desc->vendor = ntohl(descraw->vendor); - desc->type = ntohs(descraw->type); - desc->length = desclength; - memcpy(desc->data, descraw->data, desclength); /* */ - i++; - pos += descrawlength; - length -= descrawlength; + desc = (struct capwap_wtpdescriptor_encrypt_subelement*)capwap_array_get_item_pointer(data->encryptsubelement, data->encryptsubelement->count); + func->read_u8(handle, &desc->wbid); + func->read_u16(handle, &desc->capabilities); } - + + /* WTP Description Subelement */ + while (func->read_ready(handle) > 0) { + unsigned short length; + struct capwap_wtpdescriptor_desc_subelement* desc; + + /* Check */ + if (func->read_ready(handle) < 8) { + capwap_logging_debug("Invalid WTP Descriptor element"); + capwap_wtpdescriptor_element_free(data); + return NULL; + } + + /* */ + desc = (struct capwap_wtpdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, data->descsubelement->count); + func->read_u32(handle, &desc->vendor); + func->read_u16(handle, &desc->type); + func->read_u16(handle, &desc->length); + + /* Check buffer size */ + length = func->read_ready(handle); + if ((length > CAPWAP_WTPDESC_SUBELEMENT_MAXDATA) || (length < desc->length)) { + capwap_logging_debug("Invalid WTP Descriptor element"); + capwap_wtpdescriptor_element_free(data); + return NULL; + } + + func->read_block(handle, desc->data, desc->length); + } + return data; } /* */ -void capwap_wtpdescriptor_element_free(void* data) { - struct capwap_wtpdescriptor_element* dataelement = (struct capwap_wtpdescriptor_element*)data; - - ASSERT(dataelement != NULL); - ASSERT(dataelement->encryptsubelement != NULL); - ASSERT(dataelement->descsubelement != NULL); - - capwap_array_free(dataelement->encryptsubelement); - capwap_array_free(dataelement->descsubelement); - capwap_free(dataelement); -} +struct capwap_message_elements_ops capwap_element_wtpdescriptor_ops = { + .create_message_element = capwap_wtpdescriptor_element_create, + .parsing_message_element = capwap_wtpdescriptor_element_parsing, + .free_parsed_message_element = capwap_wtpdescriptor_element_free +}; diff --git a/src/common/capwap_element_wtpdescriptor.h b/src/common/capwap_element_wtpdescriptor.h index a9ebf86..ae7cd61 100644 --- a/src/common/capwap_element_wtpdescriptor.h +++ b/src/common/capwap_element_wtpdescriptor.h @@ -4,15 +4,15 @@ #define CAPWAP_ELEMENT_WTPDESCRIPTOR 39 struct capwap_wtpdescriptor_element { - unsigned char maxradios; - unsigned char radiosinuse; + uint8_t maxradios; + uint8_t radiosinuse; struct capwap_array* encryptsubelement; struct capwap_array* descsubelement; }; struct capwap_wtpdescriptor_encrypt_subelement { - unsigned char wbid; - unsigned short capabilities; + uint8_t wbid; + uint16_t capabilities; }; #define CAPWAP_WTPDESC_SUBELEMENT_HARDWAREVERSION 0 @@ -22,21 +22,12 @@ struct capwap_wtpdescriptor_encrypt_subelement { #define CAPWAP_WTPDESC_SUBELEMENT_MAXDATA 1024 struct capwap_wtpdescriptor_desc_subelement { - unsigned long vendor; - unsigned short type; - unsigned short length; - char data[CAPWAP_WTPDESC_SUBELEMENT_MAXDATA]; + uint32_t vendor; + uint16_t type; + uint16_t length; + uint8_t data[CAPWAP_WTPDESC_SUBELEMENT_MAXDATA]; }; -struct capwap_message_element* capwap_wtpdescriptor_element_create(void* data, unsigned long datalength); -int capwap_wtpdescriptor_element_validate(struct capwap_message_element* element); -void* capwap_wtpdescriptor_element_parsing(struct capwap_message_element* element); -void capwap_wtpdescriptor_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_wtpdescriptor_ops; -/* Helper */ -#define CAPWAP_CREATE_WTPDESCRIPTOR_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPDESCRIPTOR); \ - f->create(x, sizeof(struct capwap_wtpdescriptor_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_WTPDESCRIPTOR_HEADER__ */ diff --git a/src/common/capwap_element_wtpfallback.c b/src/common/capwap_element_wtpfallback.c index d77d9e9..2e7e90d 100644 --- a/src/common/capwap_element_wtpfallback.c +++ b/src/common/capwap_element_wtpfallback.c @@ -10,51 +10,30 @@ +-+-+-+-+-+-+-+-+ Type: 40 for WTP Fallback + Length: 1 ********************************************************************/ -struct capwap_wtpfallback_raw_element { - char mode; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtpfallback_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_wtpfallback_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_wtpfallback_element* element = (struct capwap_wtpfallback_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_wtpfallback_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpfallback_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpfallback_raw_element)); - element->type = htons(CAPWAP_ELEMENT_WTPFALLBACK); - element->length = htons(sizeof(struct capwap_wtpfallback_raw_element)); - - ((struct capwap_wtpfallback_raw_element*)element->data)->mode = ((struct capwap_wtpfallback_element*)data)->mode; - - return element; + /* */ + func->write_u8(handle, element->mode); } /* */ -int capwap_wtpfallback_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_wtpfallback_element_parsing(struct capwap_message_element* element) { +static void* capwap_wtpfallback_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_wtpfallback_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPFALLBACK); - - if (ntohs(element->length) != sizeof(struct capwap_wtpfallback_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 1) { + capwap_logging_debug("Invalid WTP Fallback element"); return NULL; } @@ -64,14 +43,23 @@ void* capwap_wtpfallback_element_parsing(struct capwap_message_element* element) capwap_outofmemory(); } - /* */ - data->mode = ((struct capwap_wtpfallback_raw_element*)element->data)->mode; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_wtpfallback_element)); + func->read_u8(handle, &data->mode); + return data; } /* */ -void capwap_wtpfallback_element_free(void* data) { +static void capwap_wtpfallback_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_wtpfallback_ops = { + .create_message_element = capwap_wtpfallback_element_create, + .parsing_message_element = capwap_wtpfallback_element_parsing, + .free_parsed_message_element = capwap_wtpfallback_element_free +}; diff --git a/src/common/capwap_element_wtpfallback.h b/src/common/capwap_element_wtpfallback.h index 2beebf2..2b931d0 100644 --- a/src/common/capwap_element_wtpfallback.h +++ b/src/common/capwap_element_wtpfallback.h @@ -3,22 +3,13 @@ #define CAPWAP_ELEMENT_WTPFALLBACK 40 -struct capwap_wtpfallback_element { - char mode; -}; - #define CAPWAP_WTP_FALLBACK_ENABLED 1 #define CAPWAP_WTP_FALLBACK_DISABLED 2 -struct capwap_message_element* capwap_wtpfallback_element_create(void* data, unsigned long length); -int capwap_wtpfallback_element_validate(struct capwap_message_element* element); -void* capwap_wtpfallback_element_parsing(struct capwap_message_element* element); -void capwap_wtpfallback_element_free(void* data); +struct capwap_wtpfallback_element { + uint8_t mode; +}; + +extern struct capwap_message_elements_ops capwap_element_wtpfallback_ops; -/* Helper */ -#define CAPWAP_CREATE_WTPFALLBACK_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPFALLBACK); \ - f->create(x, sizeof(struct capwap_ecnsupport_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_WTPFALLBACK_HEADER__ */ diff --git a/src/common/capwap_element_wtpframetunnelmode.c b/src/common/capwap_element_wtpframetunnelmode.c index e70613f..2f0f889 100644 --- a/src/common/capwap_element_wtpframetunnelmode.c +++ b/src/common/capwap_element_wtpframetunnelmode.c @@ -10,72 +10,56 @@ +-+-+-+-+-+-+-+-+ Type: 41 for WTP Frame Tunnel Mode + Length: 1 ********************************************************************/ -struct capwap_wtpframetunnelmode_raw_element { - unsigned char mode; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtpframetunnelmode_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_wtpframetunnelmode_raw_element* dataraw; - struct capwap_wtpframetunnelmode_element* dataelement = (struct capwap_wtpframetunnelmode_element*)data; - +static void capwap_wtpframetunnelmode_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_wtpframetunnelmode_element* element = (struct capwap_wtpframetunnelmode_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_wtpframetunnelmode_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpframetunnelmode_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpframetunnelmode_raw_element)); - element->type = htons(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE); - element->length = htons(sizeof(struct capwap_wtpframetunnelmode_raw_element)); - - dataraw = (struct capwap_wtpframetunnelmode_raw_element*)element->data; - dataraw->mode = dataelement->mode & CAPWAP_WTP_FRAME_TUNNEL_MODE_MASK; - return element; + /* */ + func->write_u8(handle, element->mode & CAPWAP_WTP_FRAME_TUNNEL_MODE_MASK); } /* */ -int capwap_wtpframetunnelmode_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_wtpframetunnelmode_element_parsing(struct capwap_message_element* element) { +static void* capwap_wtpframetunnelmode_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_wtpframetunnelmode_element* data; - struct capwap_wtpframetunnelmode_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPFRAMETUNNELMODE); - - if (ntohs(element->length) != 1) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 1) { + capwap_logging_debug("Invalid WTP Frame Tunnel Mode element"); return NULL; } /* */ - dataraw = (struct capwap_wtpframetunnelmode_raw_element*)element->data; data = (struct capwap_wtpframetunnelmode_element*)capwap_alloc(sizeof(struct capwap_wtpframetunnelmode_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->mode = dataraw->mode & CAPWAP_WTP_FRAME_TUNNEL_MODE_MASK; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_wtpframetunnelmode_element)); + func->read_u8(handle, &data->mode); + return data; } /* */ -void capwap_wtpframetunnelmode_element_free(void* data) { +static void capwap_wtpframetunnelmode_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_wtpframetunnelmode_ops = { + .create_message_element = capwap_wtpframetunnelmode_element_create, + .parsing_message_element = capwap_wtpframetunnelmode_element_parsing, + .free_parsed_message_element = capwap_wtpframetunnelmode_element_free +}; diff --git a/src/common/capwap_element_wtpframetunnelmode.h b/src/common/capwap_element_wtpframetunnelmode.h index c0cf0d0..d02e622 100644 --- a/src/common/capwap_element_wtpframetunnelmode.h +++ b/src/common/capwap_element_wtpframetunnelmode.h @@ -3,24 +3,15 @@ #define CAPWAP_ELEMENT_WTPFRAMETUNNELMODE 41 -struct capwap_wtpframetunnelmode_element { - unsigned char mode; -}; - #define CAPWAP_WTP_FRAME_TUNNEL_MODE_MASK 0x0e #define CAPWAP_WTP_NATIVE_FRAME_TUNNEL 0x08 #define CAPWAP_WTP_8023_FRAME_TUNNEL 0x04 #define CAPWAP_WTP_LOCAL_BRIDGING 0x02 -struct capwap_message_element* capwap_wtpframetunnelmode_element_create(void* data, unsigned long datalength); -int capwap_wtpframetunnelmode_element_validate(struct capwap_message_element* element); -void* capwap_wtpframetunnelmode_element_parsing(struct capwap_message_element* element); -void capwap_wtpframetunnelmode_element_free(void* data); +struct capwap_wtpframetunnelmode_element { + uint8_t mode; +}; -/* Helper */ -#define CAPWAP_CREATE_WTPFRAMETUNNELMODE_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPFRAMETUNNELMODE); \ - f->create(x, sizeof(struct capwap_wtpframetunnelmode_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_wtpframetunnelmode_ops; #endif /* __CAPWAP_ELEMENT_WTPFRAMETUNNELMODE_HEADER__ */ diff --git a/src/common/capwap_element_wtpmactype.c b/src/common/capwap_element_wtpmactype.c index 7b1a99f..145673d 100644 --- a/src/common/capwap_element_wtpmactype.c +++ b/src/common/capwap_element_wtpmactype.c @@ -10,51 +10,30 @@ +-+-+-+-+-+-+-+-+ Type: 44 for WTP MAC Type + Length: 1 ********************************************************************/ -struct capwap_wtpmactype_raw_element { - char type; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtpmactype_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - +static void capwap_wtpmactype_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_wtpmactype_element* element = (struct capwap_wtpmactype_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_wtpmactype_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpmactype_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpmactype_raw_element)); - element->type = htons(CAPWAP_ELEMENT_WTPMACTYPE); - element->length = htons(sizeof(struct capwap_wtpmactype_raw_element)); - - ((struct capwap_wtpmactype_raw_element*)element->data)->type = ((struct capwap_wtpmactype_element*)data)->type; - - return element; + /* */ + func->write_u8(handle, element->type); } /* */ -int capwap_wtpmactype_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_wtpmactype_element_parsing(struct capwap_message_element* element) { +static void* capwap_wtpmactype_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_wtpmactype_element* data; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPMACTYPE); - - if (ntohs(element->length) != sizeof(struct capwap_wtpmactype_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 1) { + capwap_logging_debug("Invalid ECN Support element"); return NULL; } @@ -64,14 +43,23 @@ void* capwap_wtpmactype_element_parsing(struct capwap_message_element* element) capwap_outofmemory(); } - /* */ - data->type = ((struct capwap_wtpmactype_raw_element*)element->data)->type; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_wtpmactype_element)); + func->read_u8(handle, &data->type); + return data; } /* */ -void capwap_wtpmactype_element_free(void* data) { +static void capwap_wtpmactype_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_wtpmactype_ops = { + .create_message_element = capwap_wtpmactype_element_create, + .parsing_message_element = capwap_wtpmactype_element_parsing, + .free_parsed_message_element = capwap_wtpmactype_element_free +}; diff --git a/src/common/capwap_element_wtpmactype.h b/src/common/capwap_element_wtpmactype.h index 870aa50..47c51c2 100644 --- a/src/common/capwap_element_wtpmactype.h +++ b/src/common/capwap_element_wtpmactype.h @@ -3,22 +3,13 @@ #define CAPWAP_ELEMENT_WTPMACTYPE 44 -struct capwap_wtpmactype_element { - char type; -}; - #define CAPWAP_LOCALMAC 0 #define CAPWAP_SPLITMAC 1 -struct capwap_message_element* capwap_wtpmactype_element_create(void* data, unsigned long length); -int capwap_wtpmactype_element_validate(struct capwap_message_element* element); -void* capwap_wtpmactype_element_parsing(struct capwap_message_element* element); -void capwap_wtpmactype_element_free(void* data); +struct capwap_wtpmactype_element { + uint8_t type; +}; + +extern struct capwap_message_elements_ops capwap_element_wtpmactype_ops; -/* Helper */ -#define CAPWAP_CREATE_WTPMACTYPE_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPMACTYPE); \ - f->create(x, sizeof(struct capwap_wtpmactype_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_WTPMACTYPE_HEADER__ */ diff --git a/src/common/capwap_element_wtpname.c b/src/common/capwap_element_wtpname.c index acc4382..e229ac1 100644 --- a/src/common/capwap_element_wtpname.c +++ b/src/common/capwap_element_wtpname.c @@ -10,77 +10,57 @@ +-+-+-+-+-+-+-+-+ Type: 45 for WTP Name + Length: >= 1 ********************************************************************/ -struct capwap_wtpname_raw_element { - char name[0]; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtpname_element_create(void* data, unsigned long datalength) { - unsigned short namelength; - struct capwap_message_element* element; - struct capwap_wtpname_raw_element* dataraw; - struct capwap_wtpname_element* dataelement = (struct capwap_wtpname_element*)data; - +static void capwap_wtpname_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_wtpname_element* element = (struct capwap_wtpname_element*)data; + ASSERT(data != NULL); - ASSERT(datalength >= sizeof(struct capwap_wtpname_element)); - - /* Alloc block of memory */ - namelength = strlen(dataelement->name); - element = capwap_alloc(sizeof(struct capwap_message_element) + namelength); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + namelength); - element->type = htons(CAPWAP_ELEMENT_WTPNAME); - element->length = htons(namelength); - - dataraw = (struct capwap_wtpname_raw_element*)element->data; - memcpy(&dataraw->name[0], &dataelement->name[0], namelength); - return element; + func->write_block(handle, element->name, strlen((char*)element->name)); } /* */ -int capwap_wtpname_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_wtpname_element_parsing(struct capwap_message_element* element) { - unsigned short namelength; +static void* capwap_wtpname_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { + unsigned short length; struct capwap_wtpname_element* data; - struct capwap_wtpname_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPNAME); - namelength = ntohs(element->length); - if (!namelength || (namelength > CAPWAP_WTPNAME_MAXLENGTH)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + length = func->read_ready(handle); + if ((length < 1) || (length > CAPWAP_WTPNAME_MAXLENGTH)) { + capwap_logging_debug("Invalid WTP Name element"); return NULL; } /* */ - dataraw = (struct capwap_wtpname_raw_element*)element->data; data = (struct capwap_wtpname_element*)capwap_alloc(sizeof(struct capwap_wtpname_element)); if (!data) { capwap_outofmemory(); } - /* */ - memcpy(&data->name[0], &dataraw->name[0], namelength); - data->name[namelength] = 0; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_wtpname_element)); + func->read_block(handle, data->name, length); + return data; } /* */ -void capwap_wtpname_element_free(void* data) { +static void capwap_wtpname_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_wtpname_ops = { + .create_message_element = capwap_wtpname_element_create, + .parsing_message_element = capwap_wtpname_element_parsing, + .free_parsed_message_element = capwap_wtpname_element_free +}; diff --git a/src/common/capwap_element_wtpname.h b/src/common/capwap_element_wtpname.h index de52f39..34c82b8 100644 --- a/src/common/capwap_element_wtpname.h +++ b/src/common/capwap_element_wtpname.h @@ -6,19 +6,9 @@ #define CAPWAP_WTPNAME_MAXLENGTH 512 struct capwap_wtpname_element { - char name[CAPWAP_WTPNAME_MAXLENGTH + 1]; + uint8_t name[CAPWAP_WTPNAME_MAXLENGTH + 1]; }; -struct capwap_message_element* capwap_wtpname_element_create(void* data, unsigned long datalength); -int capwap_wtpname_element_validate(struct capwap_message_element* element); -void* capwap_wtpname_element_parsing(struct capwap_message_element* element); -void capwap_wtpname_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_WTPNAME_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPNAME); \ - f->create(x, sizeof(struct capwap_wtpname_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_wtpname_ops; #endif /* __CAPWAP_ELEMENT_WTPNAME_HEADER__ */ diff --git a/src/common/capwap_element_wtprebootstat.c b/src/common/capwap_element_wtprebootstat.c index d688304..835de79 100644 --- a/src/common/capwap_element_wtprebootstat.c +++ b/src/common/capwap_element_wtprebootstat.c @@ -16,94 +16,70 @@ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Type: 48 for WTP Reboot Statistics + Length: 15 ********************************************************************/ -struct capwap_wtprebootstat_raw_element { - unsigned short rebootcount; - unsigned short acinitiatedcount; - unsigned short linkfailurecount; - unsigned short swfailurecount; - unsigned short hwfailurecount; - unsigned short otherfailurecount; - unsigned short unknownfailurecount; - unsigned char lastfailuretype; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtprebootstat_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_wtprebootstat_raw_element* dataraw; - struct capwap_wtprebootstat_element* dataelement = (struct capwap_wtprebootstat_element*)data; - +static void capwap_wtprebootstat_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_wtprebootstat_element* element = (struct capwap_wtprebootstat_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_wtprebootstat_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtprebootstat_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtprebootstat_raw_element)); - element->type = htons(CAPWAP_ELEMENT_WTPREBOOTSTAT); - element->length = htons(sizeof(struct capwap_wtprebootstat_raw_element)); - - dataraw = (struct capwap_wtprebootstat_raw_element*)element->data; - dataraw->rebootcount = htons(dataelement->rebootcount); - dataraw->acinitiatedcount = htons(dataelement->acinitiatedcount); - dataraw->linkfailurecount = htons(dataelement->linkfailurecount); - dataraw->swfailurecount = htons(dataelement->swfailurecount); - dataraw->hwfailurecount = htons(dataelement->hwfailurecount); - dataraw->otherfailurecount = htons(dataelement->otherfailurecount); - dataraw->unknownfailurecount = htons(dataelement->unknownfailurecount); - dataraw->lastfailuretype = dataelement->lastfailuretype; - - return element; + /* */ + func->write_u16(handle, element->rebootcount); + func->write_u16(handle, element->acinitiatedcount); + func->write_u16(handle, element->linkfailurecount); + func->write_u16(handle, element->swfailurecount); + func->write_u16(handle, element->hwfailurecount); + func->write_u16(handle, element->otherfailurecount); + func->write_u16(handle, element->unknownfailurecount); + func->write_u8(handle, element->lastfailuretype); } /* */ -int capwap_wtprebootstat_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_wtprebootstat_element_parsing(struct capwap_message_element* element) { +static void* capwap_wtprebootstat_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_wtprebootstat_element* data; - struct capwap_wtprebootstat_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPREBOOTSTAT); - if (ntohs(element->length) != sizeof(struct capwap_wtprebootstat_raw_element)) { + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 15) { + capwap_logging_debug("Invalid WTP Reboot Statistics element"); return NULL; } /* */ - dataraw = (struct capwap_wtprebootstat_raw_element*)element->data; data = (struct capwap_wtprebootstat_element*)capwap_alloc(sizeof(struct capwap_wtprebootstat_element)); if (!data) { capwap_outofmemory(); } - /* */ - data->rebootcount = ntohs(dataraw->rebootcount); - data->acinitiatedcount = ntohs(dataraw->acinitiatedcount); - data->linkfailurecount = ntohs(dataraw->linkfailurecount); - data->swfailurecount = ntohs(dataraw->swfailurecount); - data->hwfailurecount = ntohs(dataraw->hwfailurecount); - data->otherfailurecount = ntohs(dataraw->otherfailurecount); - data->unknownfailurecount = ntohs(dataraw->unknownfailurecount); - data->lastfailuretype = dataraw->lastfailuretype; + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_wtprebootstat_element)); + func->read_u16(handle, &data->rebootcount); + func->read_u16(handle, &data->acinitiatedcount); + func->read_u16(handle, &data->linkfailurecount); + func->read_u16(handle, &data->swfailurecount); + func->read_u16(handle, &data->hwfailurecount); + func->read_u16(handle, &data->otherfailurecount); + func->read_u16(handle, &data->unknownfailurecount); + func->read_u8(handle, &data->lastfailuretype); + return data; } /* */ -void capwap_wtprebootstat_element_free(void* data) { +static void capwap_wtprebootstat_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_wtprebootstat_ops = { + .create_message_element = capwap_wtprebootstat_element_create, + .parsing_message_element = capwap_wtprebootstat_element_parsing, + .free_parsed_message_element = capwap_wtprebootstat_element_free +}; diff --git a/src/common/capwap_element_wtprebootstat.h b/src/common/capwap_element_wtprebootstat.h index 38d5ab4..9a352a7 100644 --- a/src/common/capwap_element_wtprebootstat.h +++ b/src/common/capwap_element_wtprebootstat.h @@ -15,26 +15,16 @@ #define CAPWAP_LAST_FAILURE_UNKNOWN 255 struct capwap_wtprebootstat_element { - unsigned short rebootcount; - unsigned short acinitiatedcount; - unsigned short linkfailurecount; - unsigned short swfailurecount; - unsigned short hwfailurecount; - unsigned short otherfailurecount; - unsigned short unknownfailurecount; - unsigned char lastfailuretype; + uint16_t rebootcount; + uint16_t acinitiatedcount; + uint16_t linkfailurecount; + uint16_t swfailurecount; + uint16_t hwfailurecount; + uint16_t otherfailurecount; + uint16_t unknownfailurecount; + uint8_t lastfailuretype; }; -struct capwap_message_element* capwap_wtprebootstat_element_create(void* data, unsigned long datalength); -int capwap_wtprebootstat_element_validate(struct capwap_message_element* element); -void* capwap_wtprebootstat_element_parsing(struct capwap_message_element* element); -void capwap_wtprebootstat_element_free(void* data); - - -/* Helper */ -#define CAPWAP_CREATE_WTPREBOOTSTAT_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPREBOOTSTAT); \ - f->create(x, sizeof(struct capwap_wtprebootstat_element)); \ - }) +extern struct capwap_message_elements_ops capwap_element_wtprebootstat_ops; #endif /* __CAPWAP_ELEMENT_WTPREBOOTSTAT_HEADER__ */ diff --git a/src/common/capwap_element_wtpstaticipaddress.c b/src/common/capwap_element_wtpstaticipaddress.c index 4ca4956..8c2ddce 100644 --- a/src/common/capwap_element_wtpstaticipaddress.c +++ b/src/common/capwap_element_wtpstaticipaddress.c @@ -16,61 +16,33 @@ +-+-+-+-+-+-+-+-+ Type: 49 for WTP Static IP Address Information + Length: 13 ********************************************************************/ -struct capwap_wtpstaticipaddress_raw_element { - unsigned long address; - unsigned long netmask; - unsigned long gateway; - unsigned char staticip; -} __attribute__((__packed__)); - /* */ -struct capwap_message_element* capwap_wtpstaticipaddress_element_create(void* data, unsigned long datalength) { - struct capwap_message_element* element; - struct capwap_wtpstaticipaddress_element* dataelement = (struct capwap_wtpstaticipaddress_element*)data; - struct capwap_wtpstaticipaddress_raw_element* dataraw; - +static void capwap_wtpstaticipaddress_element_create(void* data, capwap_message_elements_handle handle, struct capwap_write_message_elements_ops* func) { + struct capwap_wtpstaticipaddress_element* element = (struct capwap_wtpstaticipaddress_element*)data; + ASSERT(data != NULL); - ASSERT(datalength == sizeof(struct capwap_wtpstaticipaddress_element)); - - /* Alloc block of memory */ - element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpstaticipaddress_raw_element)); - if (!element) { - capwap_outofmemory(); - } - /* Create message element */ - memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_wtpstaticipaddress_raw_element)); - element->type = htons(CAPWAP_ELEMENT_WTPSTATICIPADDRESS); - element->length = htons(sizeof(struct capwap_wtpstaticipaddress_raw_element)); - - dataraw = (struct capwap_wtpstaticipaddress_raw_element*)element->data; - dataraw->address = dataelement->address.s_addr; - dataraw->netmask = dataelement->netmask.s_addr; - dataraw->gateway = dataelement->gateway.s_addr; - dataraw->staticip = dataelement->staticip; - - return element; + /* */ + func->write_block(handle, (uint8_t*)&element->address, sizeof(struct in_addr)); + func->write_block(handle, (uint8_t*)&element->netmask, sizeof(struct in_addr)); + func->write_block(handle, (uint8_t*)&element->gateway, sizeof(struct in_addr)); + func->write_u8(handle, element->staticip); } /* */ -int capwap_wtpstaticipaddress_element_validate(struct capwap_message_element* element) { - /* TODO */ - return 1; -} - -/* */ -void* capwap_wtpstaticipaddress_element_parsing(struct capwap_message_element* element) { +static void* capwap_wtpstaticipaddress_element_parsing(capwap_message_elements_handle handle, struct capwap_read_message_elements_ops* func) { struct capwap_wtpstaticipaddress_element* data; - struct capwap_wtpstaticipaddress_raw_element* dataraw; - - ASSERT(element); - ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_WTPSTATICIPADDRESS); - - if (ntohs(element->length) != sizeof(struct capwap_wtpstaticipaddress_raw_element)) { + + ASSERT(handle != NULL); + ASSERT(func != NULL); + + if (func->read_ready(handle) != 13) { + capwap_logging_debug("Invalid WTP Static IP Address Information element"); return NULL; } @@ -80,19 +52,26 @@ void* capwap_wtpstaticipaddress_element_parsing(struct capwap_message_element* e capwap_outofmemory(); } - /* */ - dataraw = (struct capwap_wtpstaticipaddress_raw_element*)element->data; - data->address.s_addr = dataraw->address; - data->netmask.s_addr = dataraw->netmask; - data->gateway.s_addr = dataraw->gateway; - data->staticip = dataraw->staticip; - + /* Retrieve data */ + memset(data, 0, sizeof(struct capwap_wtpstaticipaddress_element)); + func->read_block(handle, (uint8_t*)&data->address, sizeof(struct in_addr)); + func->read_block(handle, (uint8_t*)&data->netmask, sizeof(struct in_addr)); + func->read_block(handle, (uint8_t*)&data->gateway, sizeof(struct in_addr)); + func->read_u8(handle, &data->staticip); + return data; } /* */ -void capwap_wtpstaticipaddress_element_free(void* data) { +static void capwap_wtpstaticipaddress_element_free(void* data) { ASSERT(data != NULL); capwap_free(data); } + +/* */ +struct capwap_message_elements_ops capwap_element_wtpstaticipaddress_ops = { + .create_message_element = capwap_wtpstaticipaddress_element_create, + .parsing_message_element = capwap_wtpstaticipaddress_element_parsing, + .free_parsed_message_element = capwap_wtpstaticipaddress_element_free +}; diff --git a/src/common/capwap_element_wtpstaticipaddress.h b/src/common/capwap_element_wtpstaticipaddress.h index 05a622d..a6f667d 100644 --- a/src/common/capwap_element_wtpstaticipaddress.h +++ b/src/common/capwap_element_wtpstaticipaddress.h @@ -7,18 +7,9 @@ struct capwap_wtpstaticipaddress_element { struct in_addr address; struct in_addr netmask; struct in_addr gateway; - unsigned char staticip; + uint8_t staticip; }; -struct capwap_message_element* capwap_wtpstaticipaddress_element_create(void* data, unsigned long length); -int capwap_wtpstaticipaddress_element_validate(struct capwap_message_element* element); -void* capwap_wtpstaticipaddress_element_parsing(struct capwap_message_element* element); -void capwap_wtpstaticipaddress_element_free(void* data); +extern struct capwap_message_elements_ops capwap_element_wtpstaticipaddress_ops; -/* Helper */ -#define CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT(x) ({ \ - struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_WTPSTATICIPADDRESS); \ - f->create(x, sizeof(struct capwap_wtpstaticipaddress_element)); \ - }) - #endif /* __CAPWAP_ELEMENT_WTPSTATICIPADDRESS_HEADER__ */ diff --git a/src/common/capwap_network.c b/src/common/capwap_network.c index 8e23e30..efb4e41 100644 --- a/src/common/capwap_network.c +++ b/src/common/capwap_network.c @@ -1,6 +1,8 @@ #include "capwap.h" +#include "capwap_list.h" #include "capwap_array.h" #include "capwap_network.h" +#include "capwap_protocol.h" #include #include #include @@ -628,7 +630,7 @@ int capwap_sendto(int sock, void* buffer, int size, struct sockaddr_storage* sen cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); pkt = (struct in_pktinfo*)CMSG_DATA(cmsg); - memset(pkt, 0, sizeof(struct in_pktinfo)); + memset(pkt, 0, sizeof(struct in_pktinfo)); memcpy(&pkt->ipi_spec_dst, &addr->sin_addr, sizeof(struct in_addr)); #elif defined IP_RECVDSTADDR struct in_addr* in; @@ -646,7 +648,7 @@ int capwap_sendto(int sock, void* buffer, int size, struct sockaddr_storage* sen #else #error "No method of getting the destination ip address supported" #endif - } else if (sendfromaddr->ss_family == AF_INET6) { + } else if (sendfromaddr->ss_family == AF_INET6) { struct in6_pktinfo* pkt; struct sockaddr_in6* addr = (struct sockaddr_in6*)sendfromaddr; @@ -661,16 +663,41 @@ int capwap_sendto(int sock, void* buffer, int size, struct sockaddr_storage* sen pkt = (struct in6_pktinfo*)CMSG_DATA(cmsg); memset(pkt, 0, sizeof(struct in6_pktinfo)); memcpy(&pkt->ipi6_addr, &addr->sin6_addr, sizeof(struct in6_addr)); - } + } do { - result = sendmsg(sock, &msgh, 0); + result = sendmsg(sock, &msgh, 0); } while ((result < 0) && ((errno == EAGAIN) || (errno == EINTR))); } return ((result > 0) ? size : 0); } +/* */ +int capwap_sendto_fragmentpacket(int sock, struct capwap_list* fragmentlist, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr) { + struct capwap_list_item* item; + + ASSERT(sock >= 0); + ASSERT(fragmentlist != NULL); + ASSERT(sendtoaddr != NULL); + + item = fragmentlist->first; + while (item) { + struct capwap_fragment_packet_item* fragmentpacket = (struct capwap_fragment_packet_item*)item->item; + ASSERT(fragmentpacket != NULL); + ASSERT(fragmentpacket->offset > 0); + + if (!capwap_sendto(sock, fragmentpacket->buffer, fragmentpacket->offset, sendfromaddr, sendtoaddr)) { + return 0; + } + + /* */ + item = item->next; + } + + return 1; +} + /* */ int capwap_ipv4_mapped_ipv6(struct sockaddr_storage* source, struct sockaddr_storage* dest) { ASSERT(source != NULL); @@ -1194,19 +1221,19 @@ void capwap_interface_list(struct capwap_network* net, struct capwap_list* list) /* */ for (ifcurrentpos = ifaddrlist; ifcurrentpos != NULL; ifcurrentpos = ifcurrentpos->ifa_next) { - struct capwap_list_item* item; - struct sockaddr_storage* addr; - - /* No loopback interface */ - if ((ifcurrentpos->ifa_flags & IFF_LOOPBACK) != 0) { - continue; - } - + struct capwap_list_item* item; + struct sockaddr_storage* addr; + + /* No loopback interface */ + if ((ifcurrentpos->ifa_flags & IFF_LOOPBACK) != 0) { + continue; + } + /* Only IPv4 and IPv6 */ if ((ifcurrentpos->ifa_addr == NULL) || ((ifcurrentpos->ifa_addr->sa_family != AF_INET) && (ifcurrentpos->ifa_addr->sa_family != AF_INET6))) { continue; } - + /* Filter family */ if ((net->sock_family != AF_UNSPEC) && (net->sock_family != ifcurrentpos->ifa_addr->sa_family)) { continue; diff --git a/src/common/capwap_network.h b/src/common/capwap_network.h index 01684f2..63900f8 100644 --- a/src/common/capwap_network.h +++ b/src/common/capwap_network.h @@ -60,6 +60,13 @@ struct capwap_socket { int isctrlsocket; }; +/* Network connection info */ +struct capwap_connection { + struct capwap_socket socket; + struct sockaddr_storage localaddr; + struct sockaddr_storage remoteaddr; +}; + void capwap_network_init(struct capwap_network* net); int capwap_network_set_pollfd(struct capwap_network* net, struct pollfd* fds, int fdscount); void capwap_interface_list(struct capwap_network* net, struct capwap_list* list); @@ -77,6 +84,7 @@ void capwap_close_sockets(struct capwap_network* net); int capwap_compare_ip(struct sockaddr_storage* addr1, struct sockaddr_storage* addr2); int capwap_sendto(int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr); +int capwap_sendto_fragmentpacket(int sock, struct capwap_list* fragmentlist, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr); int capwap_recvfrom(struct pollfd* fds, int fdscount, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, struct timeout_control* timeout); int capwap_ipv4_mapped_ipv6(struct sockaddr_storage* source, struct sockaddr_storage* dest); diff --git a/src/common/capwap_protocol.c b/src/common/capwap_protocol.c index e50aa64..bab78d9 100644 --- a/src/common/capwap_protocol.c +++ b/src/common/capwap_protocol.c @@ -6,10 +6,6 @@ #include "capwap_array.h" #include "md5.h" -/* */ -static struct capwap_fragment_sender* capwap_defragment_add_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr, struct capwap_header* header); -static struct capwap_list_item* capwap_defragment_create_packet(void* payload, int size, unsigned short offset); - /* Check valid packet */ int capwap_sanity_check(int isctrlsocket, int state, void* buffer, int buffersize, int dtlsctrlenable, int dtlsdataenable) { struct capwap_preamble* preamble; @@ -28,7 +24,7 @@ int capwap_sanity_check(int isctrlsocket, int state, void* buffer, int buffersiz if (state == CAPWAP_DISCOVERY_STATE) { return CAPWAP_WRONG_PACKET; } - + return CAPWAP_DTLS_PACKET; } else if ((preamble->type == CAPWAP_PREAMBLE_HEADER) && (buffersize >= sizeof(struct capwap_header))) { struct capwap_header* header = (struct capwap_header*)preamble; @@ -36,7 +32,7 @@ int capwap_sanity_check(int isctrlsocket, int state, void* buffer, int buffersiz if ((state != CAPWAP_DISCOVERY_STATE) && (state != CAPWAP_UNDEF_STATE)) { return CAPWAP_WRONG_PACKET; } - + return CAPWAP_PLAIN_PACKET; } } @@ -70,1095 +66,6 @@ int capwap_sanity_check(int isctrlsocket, int state, void* buffer, int buffersiz return CAPWAP_WRONG_PACKET; } -/* */ -int capwap_defragment_packets(struct sockaddr_storage* sendaddr, void* buffer, int buffersize, capwap_fragment_list* defraglist, struct capwap_packet* packet) { - struct capwap_header* header = (struct capwap_header*)buffer; - struct capwap_fragment_sender* defragsend; - int headersize; - - ASSERT(sendaddr != NULL); - ASSERT(buffer != NULL); - ASSERT(buffersize > sizeof(struct capwap_header)); - ASSERT(defraglist != NULL); - ASSERT(packet != NULL); - - headersize = GET_HLEN_HEADER(header) * 4; - defragsend = capwap_defragment_find_sender(defraglist, sendaddr); - - if (IS_FLAG_F_HEADER(header)) { - struct capwap_list_item* searchpacket; - struct capwap_fragment_packet* itempacket; - unsigned short fragid = GET_FRAGMENT_ID_HEADER(header); - unsigned short fragoffset = GET_FRAGMENT_OFFSET_HEADER(header); - char* payload = (char*)buffer + headersize; - int payloadsize = buffersize - headersize; - - /* Size of payload is multiple of 64bits */ - if ((payloadsize % 8) != 0) { - return CAPWAP_WRONG_FRAGMENT; - } - - if (!defragsend) { - /* Create new defragment item */ - defragsend = capwap_defragment_add_sender(defraglist, sendaddr, header); - if (!defragsend) { - return CAPWAP_WRONG_FRAGMENT; - } - } else if (fragid != defragsend->fragment_id) { - /* Wrong fragment id */ - capwap_defragment_remove_sender(defraglist, sendaddr); - return CAPWAP_WRONG_FRAGMENT; - } - - if (fragoffset == 0) { - /* Save header of the first packet of fragmentation */ - defragsend->header = (struct capwap_header*)capwap_clone(header, headersize); - } - - /* Defragment payload */ - searchpacket = defragsend->packetlist->last; - if (!searchpacket) { - struct capwap_list_item* packet = capwap_defragment_create_packet(payload, payloadsize, fragoffset); - capwap_itemlist_insert_before(defragsend->packetlist, NULL, packet); - } else { - while (searchpacket != NULL) { - itempacket = (struct capwap_fragment_packet*)searchpacket->item; - ASSERT(itempacket != NULL); - - if (itempacket->offset > fragoffset) { - if (!searchpacket->prev) { - struct capwap_list_item* packet = capwap_defragment_create_packet(payload, payloadsize, fragoffset); - capwap_itemlist_insert_before(defragsend->packetlist, searchpacket, packet); - break; - } - } else if (itempacket->offset < fragoffset) { - if (!defragsend->islastrecv || (searchpacket != defragsend->packetlist->last)) { - struct capwap_list_item* packet = capwap_defragment_create_packet(payload, payloadsize, fragoffset); - capwap_itemlist_insert_after(defragsend->packetlist, searchpacket, packet); - } - - break; - } else { - /* Duplicate packet */ - break; - } - - /* Prev fragment */ - searchpacket = searchpacket->prev; - } - } - - /* If last packet, mark end of fragmentation */ - if (!defragsend->islastrecv) { - defragsend->islastrecv = IS_FLAG_L_HEADER(header); - } - - /* Check if defragmentation is completed */ - if (defragsend->islastrecv) { - unsigned long checkoffset = 0; - - payloadsize = 0; - searchpacket = defragsend->packetlist->first; - while (searchpacket != NULL) { - itempacket = (struct capwap_fragment_packet*)searchpacket->item; - if (checkoffset != itempacket->offset) { - return CAPWAP_REQUEST_MORE_FRAGMENT; - } - - /* Next fragment */ - payloadsize += itempacket->size; - checkoffset += itempacket->size / 8; - searchpacket = searchpacket->next; - } - - /* Defragment complete */ - ASSERT(defragsend->header != NULL); - headersize = GET_HLEN_HEADER(defragsend->header) * 4; - packet->packetsize = headersize + payloadsize; - packet->header = (struct capwap_header*)capwap_alloc(packet->packetsize); - if (!packet->header) { - capwap_outofmemory(); - } - - /* Copy header and remove fragmention information */ - memcpy(packet->header, defragsend->header, headersize); - SET_FLAG_F_HEADER(packet->header, 0); - SET_FLAG_L_HEADER(packet->header, 0); - SET_FRAGMENT_ID_HEADER(packet->header, 0); - SET_FRAGMENT_OFFSET_HEADER(packet->header, 0); - - /* Copy payload */ - packet->payload = (char*)packet->header + headersize; - payload = packet->payload; - - searchpacket = defragsend->packetlist->first; - while (searchpacket != NULL) { - itempacket = (struct capwap_fragment_packet*)searchpacket->item; - memcpy(payload, itempacket->buffer, itempacket->size); - payload += itempacket->size; - - /* Next */ - searchpacket = searchpacket->next; - } - - capwap_defragment_remove_sender(defraglist, sendaddr); - return CAPWAP_RECEIVE_COMPLETE_PACKET; - } - - return CAPWAP_REQUEST_MORE_FRAGMENT; - } else { - /* Check if already received fragment packets */ - if (defragsend) { - /* Overlap fragment packet with complete packet */ - capwap_defragment_remove_sender(defraglist, sendaddr); - } else { - /* Copy buffer */ - packet->packetsize = buffersize; - packet->header = (struct capwap_header*)capwap_clone(buffer, packet->packetsize); - packet->payload = (void*)((char*)buffer + headersize); - - return CAPWAP_RECEIVE_COMPLETE_PACKET; - } - } - - return CAPWAP_WRONG_FRAGMENT; -} - -/* */ -capwap_fragment_list* capwap_defragment_init_list(void) { - return capwap_list_create(); -} - -/* */ -static void capwap_defragment_free_packetlist(struct capwap_list* packetlist) { - struct capwap_list_item* search; - - ASSERT(packetlist != NULL); - - search = packetlist->first; - while (search) { - struct capwap_fragment_packet* packet = (struct capwap_fragment_packet*)search->item; - ASSERT(packet->buffer != NULL); - - capwap_free(packet->buffer); - - /* Next */ - search = search->next; - } - - capwap_list_free(packetlist); -} - -/* */ -void capwap_defragment_flush_list(capwap_fragment_list* defraglist) { - struct capwap_fragment_sender* item; - - ASSERT(defraglist != NULL); - - while (defraglist->first) { - item = (struct capwap_fragment_sender*)defraglist->first->item; - ASSERT(item != NULL); - ASSERT(item->packetlist != NULL); - - capwap_defragment_free_packetlist(item->packetlist); - capwap_itemlist_free(capwap_itemlist_remove(defraglist, defraglist->first)); - } -} - -/* */ -void capwap_defragment_free_list(capwap_fragment_list* defraglist) { - ASSERT(defraglist != NULL); - - capwap_defragment_flush_list(defraglist); - capwap_list_free(defraglist); -} - -/* */ -struct capwap_fragment_sender* capwap_defragment_find_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr) { - struct capwap_fragment_sender* item; - struct capwap_list_item* search; - - ASSERT(defraglist != NULL); - ASSERT(sendaddr != NULL); - - search = defraglist->first; - while (search) { - item = (struct capwap_fragment_sender*)search->item; - ASSERT(item != NULL); - - if (!capwap_compare_ip(sendaddr, &item->sendaddr)) { - return item; - } - - search = search->next; - } - - return NULL; -} - -/* */ -static struct capwap_fragment_sender* capwap_defragment_add_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr, struct capwap_header* header) { - struct capwap_list_item* item; - struct capwap_fragment_sender* sender; - int headersize; - - ASSERT(defraglist != NULL); - ASSERT(sendaddr != NULL); - ASSERT(header != NULL); - - item = capwap_itemlist_create(sizeof(struct capwap_fragment_sender)); - sender = (struct capwap_fragment_sender*)item->item; - - memset(sender, 0, sizeof(struct capwap_fragment_sender)); - memcpy(&sender->sendaddr, sendaddr, sizeof(struct sockaddr_storage)); - sender->fragment_id = GET_FRAGMENT_ID_HEADER(header); - - headersize = GET_HLEN_HEADER(header) * 4; - sender->header = (struct capwap_header*)capwap_alloc(headersize); - if (!sender->header) { - capwap_outofmemory(); - } - - memcpy(sender->header, header, headersize); - sender->packetlist = capwap_list_create(); - - /* Add item to list */ - capwap_itemlist_insert_after(defraglist, NULL, item); - return sender; -} - -/* */ -int capwap_defragment_remove_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr) { - int found = 0; - struct capwap_fragment_sender* item; - struct capwap_list_item* search; - - ASSERT(defraglist != NULL); - ASSERT(sendaddr != NULL); - - search = defraglist->first; - while (search) { - item = (struct capwap_fragment_sender*)search->item; - ASSERT(item != NULL); - - if (!capwap_compare_ip(sendaddr, &item->sendaddr)) { - ASSERT(item->packetlist); - - found = 1; - capwap_defragment_free_packetlist(item->packetlist); - capwap_itemlist_free(capwap_itemlist_remove(defraglist, search)); - break; - } - - search = search->next; - } - - return found; -} - -/* */ -static struct capwap_list_item* capwap_defragment_create_packet(void* payload, int size, unsigned short offset) { - struct capwap_fragment_packet* packet; - struct capwap_list_item* item; - - ASSERT(payload != NULL); - ASSERT(size > 0); - - /* New fragment */ - item = capwap_itemlist_create(sizeof(struct capwap_fragment_packet)); - packet = (struct capwap_fragment_packet*)item->item; - - memset(packet, 0, sizeof(struct capwap_fragment_packet)); - packet->buffer = capwap_clone(payload, size); - packet->size = size; - packet->offset = offset; - - return item; -} - -/* */ -void capwap_free_packet(struct capwap_packet* packet) { - ASSERT(packet != NULL); - - if (packet->header) { - capwap_free(packet->header); - memset(packet, 0, sizeof(struct capwap_packet)); - } -} - -/* Creare tx packet */ -struct capwap_build_packet* capwap_tx_packet_create(unsigned short radioid, unsigned short binding) { - struct capwap_build_packet* packet; - struct capwap_header* header; - - packet = (struct capwap_build_packet*)capwap_alloc(sizeof(struct capwap_build_packet)); - if (!packet) { - capwap_outofmemory(); - } - - memset(packet, 0, sizeof(struct capwap_build_packet)); - header = &packet->header; - - /* Standard configuration */ - SET_VERSION_HEADER(header, CAPWAP_PROTOCOL_VERSION); - SET_TYPE_HEADER(header, CAPWAP_PREAMBLE_HEADER); - SET_HLEN_HEADER(header, sizeof(struct capwap_header) / 4); - SET_RID_HEADER(header, radioid); - SET_WBID_HEADER(header, binding); - - /* Message elements list */ - packet->elementslist = capwap_list_create(); - - return packet; -} - -/* Destroy tx packet */ -void capwap_build_packet_free(struct capwap_build_packet* buildpacket) { - ASSERT(buildpacket != NULL); - - /* */ - capwap_list_free(buildpacket->elementslist); - capwap_free(buildpacket); -} - -/* Add radio macaddress to packet */ -void capwap_build_packet_set_radio_macaddress(struct capwap_build_packet* buildpacket, int radiotype, char* macaddress) { - struct capwap_header* header; - - ASSERT(buildpacket != NULL); - - header = &buildpacket->header; - if (radiotype == CAPWAP_MACADDRESS_NONE) { - if (IS_FLAG_M_HEADER(header)) { - if (!IS_FLAG_W_HEADER(header)) { - SET_HLEN_HEADER(header, sizeof(struct capwap_header) / 4); - } else { - struct capwap_wireless_information* wireless = GET_WIRELESS_INFORMATION_STRUCT(header); - int lengthpadded = (((sizeof(struct capwap_wireless_information) + wireless->length) + 3) / 4); - - /* Move wireless information */ - memmove(((char*)header + sizeof(struct capwap_header)), wireless, lengthpadded * 4); - SET_HLEN_HEADER(header, (sizeof(struct capwap_header) / 4) + lengthpadded); - } - - SET_FLAG_M_HEADER(header, 0); - } - } else { - int i; - int radiosizepadded; - struct capwap_mac_address* radio; - int size = sizeof(struct capwap_header) / 4; - - ASSERT(macaddress != NULL); - ASSERT((radiotype == CAPWAP_MACADDRESS_EUI48) || (radiotype == CAPWAP_MACADDRESS_EUI64)); - - if (IS_FLAG_M_HEADER(header)) { - radio = GET_RADIO_MAC_ADDRESS_STRUCT(header); - - if (radio->length == radiotype) { - /* Rewrite mac address */ - memcpy(radio->address, macaddress, radiotype); - return; - } - - /* Remove old radio mac address */ - capwap_build_packet_set_radio_macaddress(buildpacket, CAPWAP_MACADDRESS_NONE, NULL); - } - - /* Radio mac address size*/ - radio = (struct capwap_mac_address*)((char*)header + sizeof(struct capwap_header)); - radiosizepadded = (((sizeof(struct capwap_mac_address) + radiotype) + 3) / 4); - size += radiosizepadded; - - /* Wireless information */ - if (IS_FLAG_W_HEADER(header)) { - struct capwap_wireless_information* wireless = GET_WIRELESS_INFORMATION_STRUCT(header); - int lengthpadded = (((sizeof(struct capwap_wireless_information) + wireless->length) + 3) / 4); - - memmove((char*)radio + radiosizepadded, wireless, lengthpadded * 4); - size += lengthpadded; - } - - radio->length = radiotype; - memcpy(radio->address, macaddress, radiotype); - for (i = (radiosizepadded * 4) - 2; i >= radiotype; i--) { - radio->address[i] = 0; - } - - SET_FLAG_M_HEADER(header, 1); - SET_HLEN_HEADER(header, size); - } -} - -/* Add Wireless Specific Information to packet */ -void capwap_build_packet_set_wireless_information(struct capwap_build_packet* buildpacket, void* buffer, unsigned char length) { - struct capwap_header* header; - int size; - - ASSERT(buildpacket != NULL); - - header = &buildpacket->header; - - /* Calculate size of header */ - size = sizeof(struct capwap_header) / 4; - if (IS_FLAG_M_HEADER(header)) { - struct capwap_mac_address* radio = GET_RADIO_MAC_ADDRESS_STRUCT(header); - size += ((sizeof(struct capwap_mac_address) + radio->length) + 3) / 4; - } - - /* Remove old wireless information */ - if (IS_FLAG_W_HEADER(header)) { - SET_HLEN_HEADER(header, size); - } - - /* Add new wireless information */ - if (length > 0) { - int i; - struct capwap_wireless_information* wireless; - int lengthpadded = (((sizeof(struct capwap_wireless_information) + length) + 3) / 4); - - ASSERT(buffer != NULL); - - wireless = GET_WIRELESS_INFORMATION_STRUCT(header); - wireless->length = length; - memcpy(wireless->data, buffer, length); - for (i = (lengthpadded * 4) - 2; i >= length; i--) { - wireless->data[i] = 0; - } - - /* Update size */ - size += lengthpadded; - SET_HLEN_HEADER(header, size); - } -} - -/* Set control message type */ -void capwap_build_packet_set_control_message_type(struct capwap_build_packet* buildpacket, unsigned long type, unsigned char seq) { - ASSERT(buildpacket != NULL); - - buildpacket->ctrlmsg.type = htonl(type); - buildpacket->ctrlmsg.seq = seq; - buildpacket->ctrlmsg.length = 0; - buildpacket->ctrlmsg.flags = 0; -} - -/* Add message element */ -void capwap_build_packet_add_message_element(struct capwap_build_packet* buildpacket, struct capwap_message_element* element) { - struct capwap_list_item* itemlist; - unsigned long length; - - ASSERT(buildpacket != NULL); - - if ((element == NULL) || (element->length == 0)) { - capwap_logging_debug("Warning, add null element to packet"); - return; - } - - /* Create item and add into last position of list*/ - length = ntohs(element->length) + sizeof(struct capwap_message_element); - itemlist = capwap_itemlist_create_with_item(element, length); - capwap_itemlist_insert_after(buildpacket->elementslist, NULL, itemlist); - - /* */ - if (buildpacket->isctrlmsg) { - buildpacket->ctrlmsg.length = htons(ntohs(buildpacket->ctrlmsg.length) + length); - } else { - buildpacket->datamsg.length = htons(ntohs(buildpacket->datamsg.length) + length); - } -} - -/* Generate fragment packets */ -int capwap_fragment_build_packet(struct capwap_build_packet* buildpacket, capwap_fragment_packet_array* packets, unsigned short mtu, unsigned short fragmentid) { - unsigned short i; - unsigned short reqpacket; - unsigned long length = 0; - unsigned short headerlength = 0; - struct capwap_header* header; - unsigned short fragmentposition = 0; - struct capwap_list_item* item = NULL; - unsigned long itempos = 0; - - ASSERT(buildpacket != NULL); - ASSERT(packets != NULL); - - /* Free array */ - capwap_fragment_free(packets); - if ((mtu > 0) && (mtu < CAPWAP_HEADER_MAX_SIZE)) { - /* Mtu must be greater than the maximum size of capwap header */ - capwap_logging_debug("The mtu is too small: %hu", mtu); - return -1; - } - - /* Get length raw packet */ - header = &buildpacket->header; - headerlength = GET_HLEN_HEADER(header) * 4; - if (buildpacket->isctrlmsg) { - length = sizeof(struct capwap_control_message) + ntohs(buildpacket->ctrlmsg.length); - } else if (IS_FLAG_K_HEADER(header)) { - length = sizeof(struct capwap_data_message) + ntohs(buildpacket->datamsg.length); - } - - /* Retrive number of request packet for send a capwap message */ - if (!mtu || ((headerlength + length) <= mtu)) { - reqpacket = 1; - } else { - unsigned long lengthpayload = length; - unsigned short mtupayload; - - /* Detect mtu payload */ - mtupayload = mtu - sizeof(struct capwap_header); - mtupayload -= mtupayload % 8; - - /* Calculate number of request packets without size of header */ - if (IS_FLAG_M_HEADER(header)) { - struct capwap_mac_address* radio = GET_RADIO_MAC_ADDRESS_STRUCT(header); - lengthpayload += ((sizeof(struct capwap_mac_address) + radio->length) + 3) / 4; - } - - if (IS_FLAG_W_HEADER(header)) { - struct capwap_wireless_information* wireless = GET_WIRELESS_INFORMATION_STRUCT(header); - lengthpayload += ((sizeof(struct capwap_wireless_information) + wireless->length) + 3) / 4; - } - - /* Request packet padded */ - reqpacket = (lengthpayload + (mtupayload - 1)) / mtupayload; - } - - /* Create packets */ - capwap_array_resize(packets, reqpacket); - for (i = 0; i < reqpacket; i++) { - long payloadsize = 0; - struct capwap_packet* packet = (struct capwap_packet*)capwap_array_get_item_pointer(packets, i); - memset(packet, 0, sizeof(struct capwap_packet)); - - if (reqpacket == 1) { - /* Build header */ - packet->packetsize = headerlength + length; - packet->header = (struct capwap_header*)capwap_alloc(packet->packetsize); - - memcpy(packet->header, &buildpacket->header, headerlength); - packet->payload = (void*)(((char*)packet->header) + headerlength); - payloadsize = length; - - /* Disable fragmentation */ - SET_FLAG_F_HEADER(packet->header, 0); - SET_FRAGMENT_ID_HEADER(packet->header, 0); - SET_FRAGMENT_OFFSET_HEADER(packet->header, 0); - SET_FLAG_L_HEADER(packet->header, 0); - } else { - unsigned short headerpos = ((i == 0) ? headerlength : sizeof(struct capwap_header)); - unsigned short mtupayload; - - /* Detect mtu payload */ - mtupayload = mtu - headerpos; - mtupayload -= mtupayload % 8; - - /* Build header */ - packet->packetsize = headerpos + mtupayload; - packet->header = (struct capwap_header*)capwap_alloc(packet->packetsize); - memcpy(packet->header, &buildpacket->header, headerpos); - packet->payload = (void*)(((char*)packet->header) + headerpos); - payloadsize = mtupayload; - - if (i > 0) { - /* Radio mac address and wireless information is sent only into first packet */ - SET_FLAG_M_HEADER(packet->header, 0); - SET_FLAG_W_HEADER(packet->header, 0); - SET_HLEN_HEADER(packet->header, sizeof(struct capwap_header) / 4); - } - - /* Use fragmentation */ - SET_FLAG_F_HEADER(packet->header, 1); - SET_FRAGMENT_ID_HEADER(packet->header, fragmentid); - SET_FRAGMENT_OFFSET_HEADER(packet->header, fragmentposition); - SET_FLAG_L_HEADER(packet->header, (((i + 1) == reqpacket) ? 1 : 0)); - } - - /* Build payload */ - if (length > 0) { - char* pos = (char*)packet->payload; - - /* Data/Control Message */ - if (i == 0) { - if (buildpacket->isctrlmsg) { - /* Control Message header can not fragment */ - if (payloadsize < sizeof(struct capwap_control_message)) { - capwap_logging_debug("Unable fragments packet, mtu is too small"); - capwap_fragment_free(packets); - return -1; - } - - memcpy(packet->payload, &buildpacket->ctrlmsg, sizeof(struct capwap_control_message)); - pos += sizeof(struct capwap_control_message); - payloadsize -= sizeof(struct capwap_control_message); - } else if (IS_FLAG_K_HEADER(header)) { - /* Data Message header can not fragment */ - if (payloadsize < sizeof(struct capwap_data_message)) { - capwap_logging_debug("Unable fragments packet, mtu is too small"); - capwap_fragment_free(packets); - return -1; - } - - memcpy(packet->payload, &buildpacket->datamsg, sizeof(struct capwap_data_message)); - pos += sizeof(struct capwap_data_message); - payloadsize -= sizeof(struct capwap_data_message); - } - - /* Configure message elements */ - item = buildpacket->elementslist->first; - itempos = 0; - } - - /* Add message elements */ - while ((item != NULL) && (payloadsize > 0)) { - unsigned short elementcopy; - unsigned short elementlength; - struct capwap_message_element* element = (struct capwap_message_element*)item->item; - - ASSERT(element != NULL); - - /* Copy message element */ - elementlength = sizeof(struct capwap_message_element) + ntohs(element->length); - elementcopy = min(elementlength - itempos, payloadsize); - memcpy(pos, &((char*)element)[itempos], elementcopy); - - pos += elementcopy; - itempos += elementcopy; - payloadsize -= elementcopy; - ASSERT(payloadsize >= 0); - - /* Next element */ - if (itempos == elementlength) { - item = item->next; - itempos = 0; - } - } - - if (((i + 1) == reqpacket) && (payloadsize > 0)) { - packet->packetsize -= payloadsize; - } else { - ASSERT(payloadsize == 0); - } - } - } - - /* Return 1 if fragment packet */ - return ((reqpacket > 1) ? 1 : 0); -} - -/* */ -void capwap_fragment_free(capwap_fragment_packet_array* packets) { - unsigned long i; - - ASSERT(packets != NULL); - - if (packets->count == 0) { - return; - } - - for (i = 0; i < packets->count; i++) { - capwap_free_packet((struct capwap_packet*)capwap_array_get_item_pointer(packets, i)); - } - - capwap_array_resize(packets, 0); -} - -/* */ -struct capwap_build_packet* capwap_rx_packet_create(void* buffer, int buffersize, int isctrlpacket) { - struct capwap_build_packet* buildpacket; - struct capwap_header* header; - char* pos = (char*)buffer; - int length; - int controlsize; - - ASSERT(buffer != NULL); - ASSERT(buffersize > 0); - - /* Header */ - header = (struct capwap_header*)buffer; - length = GET_HLEN_HEADER(header) * 4; - if (buffersize < length) { - return NULL; - } - - /* Build packet */ - buildpacket = (struct capwap_build_packet*)capwap_alloc(sizeof(struct capwap_build_packet)); - if (!buildpacket) { - capwap_outofmemory(); - } - - /* */ - memset(buildpacket, 0, sizeof(struct capwap_build_packet)); - buildpacket->isctrlmsg = (isctrlpacket ? 1 : 0); - - /* Header packet */ - memcpy(&buildpacket->header, pos, length); - pos += length; - buffersize -= length; - - if (buildpacket->isctrlmsg) { - if (buffersize < sizeof(struct capwap_control_message)) { - capwap_logging_debug("Invalid capwap packet, size of control message body is great of raw packet"); - capwap_free(buildpacket); - return NULL; - } - - /* Control message header */ - memcpy(&buildpacket->ctrlmsg, pos, sizeof(struct capwap_control_message)); - pos += sizeof(struct capwap_control_message); - buffersize -= sizeof(struct capwap_control_message); - - /* Check the packet size */ - controlsize = ntohs(buildpacket->ctrlmsg.length); - if (controlsize > buffersize) { - capwap_logging_debug("Invalid capwap packet, size of control message body is great of raw packet"); - capwap_free(buildpacket); - return NULL; - } - - /* Message elements list */ - buildpacket->elementslist = capwap_list_create(); - while (controlsize > 0) { - struct capwap_message_element* element = (struct capwap_message_element*)pos; - int elementsize = ntohs(element->length) + sizeof(struct capwap_message_element); - struct capwap_list_item* itemlist; - - /* Clone message element */ - itemlist = capwap_itemlist_create(elementsize); - memcpy(itemlist->item, pos, elementsize); - capwap_itemlist_insert_after(buildpacket->elementslist, NULL, itemlist); - - /* Next */ - pos += elementsize; - controlsize -= elementsize; - buffersize -= elementsize; - } - } else { - if (IS_FLAG_K_HEADER(&buildpacket->header)) { - if (buffersize < sizeof(struct capwap_data_message)) { - capwap_logging_debug("Invalid capwap packet, size of data message body is great of raw packet"); - capwap_free(buildpacket); - return NULL; - } - - /* Control message header */ - memcpy(&buildpacket->datamsg, pos, sizeof(struct capwap_data_message)); - pos += sizeof(struct capwap_data_message); - buffersize -= sizeof(struct capwap_data_message); - - /* Check the packet size */ - controlsize = ntohs(buildpacket->datamsg.length); - if (controlsize > buffersize) { - capwap_logging_debug("Invalid capwap packet, size of data message body is great of raw packet"); - capwap_free(buildpacket); - return NULL; - } - - /* Message elements list */ - buildpacket->elementslist = capwap_list_create(); - while (controlsize > 0) { - struct capwap_message_element* element = (struct capwap_message_element*)pos; - int elementsize = ntohs(element->length) + sizeof(struct capwap_message_element); - struct capwap_list_item* itemlist; - - /* Clone message element */ - itemlist = capwap_itemlist_create(elementsize); - memcpy(itemlist->item, pos, elementsize); - capwap_itemlist_insert_after(buildpacket->elementslist, NULL, itemlist); - - /* Next */ - pos += elementsize; - controlsize -= elementsize; - buffersize -= elementsize; - } - } else { - /* TODO */ - } - } - - return buildpacket; -} - -/* */ -unsigned long capwap_build_packet_validate(struct capwap_build_packet* buildpacket, capwap_unrecognized_element_array* reasonarray) { - unsigned short binding; - int ieee80211delta = CAPWAP_80211_MESSAGE_ELEMENTS_START - CAPWAP_MESSAGE_ELEMENTS_COUNT; - int elements[CAPWAP_MESSAGE_ELEMENTS_COUNT + CAPWAP_80211_MESSAGE_ELEMENTS_COUNT]; - struct capwap_list_item* item; - unsigned long result = CAPWAP_VALID_PACKET; - struct capwap_resultcode_element* resultcodeelement = NULL; - - ASSERT(buildpacket != NULL); - - /* Reset flags */ - memset(elements, 0, sizeof(elements)); - - /* Scan all elements */ - item = buildpacket->elementslist->first; - while (item != NULL) { - struct unrecognized_info info = { 0, 0 }; - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); \ - - if (f && f->check && f->parsing) { - if (f->check(elementitem)) { - if (IS_MESSAGE_ELEMENTS(type)) { - elements[type] = 1; - if (type == CAPWAP_ELEMENT_RESULTCODE) { - resultcodeelement = (struct capwap_resultcode_element*)f->parsing(elementitem); - } - } else if (IS_80211_MESSAGE_ELEMENTS(type)) { - elements[type - ieee80211delta] = 1; - } else { - /* Unknown message element */ - info.element = type; - info.reason = CAPWAP_REASON_UNKNOWN_MESSAGE_ELEMENT; - } - } else { - /* Invalid message element */ - info.element = type; - info.reason = CAPWAP_REASON_UNKNOWN_MESSAGE_ELEMENT_VALUE; - } - } else { - /* Unable parsing message element */ - info.element = type; - info.reason = CAPWAP_REASON_UNSUPPORTED_MESSAGE_ELEMENT; - } - - /* Copy error */ - if ((info.element != 0) && reasonarray) { - struct unrecognized_info* reasoninfo = capwap_array_get_item_pointer(reasonarray, reasonarray->count); - - memcpy(reasoninfo, &info, sizeof(struct unrecognized_info)); - result |= CAPWAP_UNRECOGNIZED_MSG_ELEMENT; - } - - /* Next item */ - item = item->next; - } - - /* Verify flags */ - binding = GET_WBID_HEADER(&buildpacket->header); - switch (ntohl(buildpacket->ctrlmsg.type)) { - case CAPWAP_DISCOVERY_REQUEST: { - if (elements[CAPWAP_ELEMENT_DISCOVERYTYPE] && - elements[CAPWAP_ELEMENT_WTPBOARDDATA] && - elements[CAPWAP_ELEMENT_WTPDESCRIPTOR] && - elements[CAPWAP_ELEMENT_WTPFRAMETUNNELMODE] && - elements[CAPWAP_ELEMENT_WTPMACTYPE]) { - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (!elements[CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION - ieee80211delta]) { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - } - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_DISCOVERY_RESPONSE: { - if (elements[CAPWAP_ELEMENT_ACDESCRIPTION] && - elements[CAPWAP_ELEMENT_ACNAME] && - (elements[CAPWAP_ELEMENT_CONTROLIPV4] || elements[CAPWAP_ELEMENT_CONTROLIPV6])) { - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (!elements[CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION - ieee80211delta]) { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - } - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_JOIN_REQUEST: { - if (elements[CAPWAP_ELEMENT_LOCATION] && - elements[CAPWAP_ELEMENT_WTPBOARDDATA] && - elements[CAPWAP_ELEMENT_WTPDESCRIPTOR] && - elements[CAPWAP_ELEMENT_WTPNAME] && - elements[CAPWAP_ELEMENT_SESSIONID] && - elements[CAPWAP_ELEMENT_WTPFRAMETUNNELMODE] && - elements[CAPWAP_ELEMENT_WTPMACTYPE] && - elements[CAPWAP_ELEMENT_ECNSUPPORT] && - (elements[CAPWAP_ELEMENT_LOCALIPV4] || elements[CAPWAP_ELEMENT_LOCALIPV6])) { - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (!elements[CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION - ieee80211delta]) { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - } - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_JOIN_RESPONSE: { - if (elements[CAPWAP_ELEMENT_RESULTCODE]) { - if ((resultcodeelement->code == CAPWAP_RESULTCODE_SUCCESS) || (resultcodeelement->code == CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED)) { - if (elements[CAPWAP_ELEMENT_ACDESCRIPTION] && - elements[CAPWAP_ELEMENT_ACNAME] && - elements[CAPWAP_ELEMENT_ECNSUPPORT] && - (elements[CAPWAP_ELEMENT_CONTROLIPV4] || elements[CAPWAP_ELEMENT_CONTROLIPV6]) && - (elements[CAPWAP_ELEMENT_LOCALIPV4] || elements[CAPWAP_ELEMENT_LOCALIPV6])) { - - if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - if (!elements[CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION - ieee80211delta]) { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - } - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - } else if (resultcodeelement->code == CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT) { - if (!elements[CAPWAP_ELEMENT_RETURNEDMESSAGE]) { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - } - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_CONFIGURATION_STATUS_REQUEST: { - if (elements[CAPWAP_ELEMENT_ACNAME] && - elements[CAPWAP_ELEMENT_RADIOADMSTATE] && - elements[CAPWAP_ELEMENT_STATISTICSTIMER] && - elements[CAPWAP_ELEMENT_WTPREBOOTSTAT]) { - /* TODO binding */ - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_CONFIGURATION_STATUS_RESPONSE: { - if (elements[CAPWAP_ELEMENT_TIMERS] && - elements[CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD] && - elements[CAPWAP_ELEMENT_IDLETIMEOUT] && - elements[CAPWAP_ELEMENT_WTPFALLBACK] && - (elements[CAPWAP_ELEMENT_ACIPV4LIST] || elements[CAPWAP_ELEMENT_ACIPV6LIST])) { - /* TODO binding */ - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_CONFIGURATION_UPDATE_REQUEST: { - break; - } - - case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: { - break; - } - - case CAPWAP_WTP_EVENT_REQUEST: { - break; - } - - case CAPWAP_WTP_EVENT_RESPONSE: { - break; - } - - case CAPWAP_CHANGE_STATE_EVENT_REQUEST: { - if (elements[CAPWAP_ELEMENT_RADIOOPRSTATE] && - elements[CAPWAP_ELEMENT_RESULTCODE]) { - /* TODO binding */ - } else { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - break; - } - - case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: { - /* TODO binding */ - break; - } - - case CAPWAP_ECHO_REQUEST: { - break; - } - - case CAPWAP_ECHO_RESPONSE: { - break; - } - - case CAPWAP_IMAGE_DATA_REQUEST: { - break; - } - - case CAPWAP_IMAGE_DATA_RESPONSE: { - break; - } - - case CAPWAP_RESET_REQUEST: { - if (!elements[CAPWAP_ELEMENT_IMAGEIDENTIFIER]) { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_RESET_RESPONSE: { - if (!elements[CAPWAP_ELEMENT_RESULTCODE]) { - result |= CAPWAP_MISSING_MANDATORY_MSG_ELEMENT; - } - - break; - } - - case CAPWAP_PRIMARY_DISCOVERY_REQUEST: { - break; - } - - case CAPWAP_PRIMARY_DISCOVERY_RESPONSE: { - break; - } - - case CAPWAP_DATA_TRANSFER_REQUEST: { - break; - } - - case CAPWAP_DATA_TRANSFER_RESPONSE: { - break; - } - - case CAPWAP_CLEAR_CONFIGURATION_REQUEST: { - break; - } - - case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: { - break; - } - - case CAPWAP_STATION_CONFIGURATION_REQUEST: { - break; - } - - case CAPWAP_STATION_CONFIGURATION_RESPONSE: { - break; - } - } - - if (resultcodeelement) { - capwap_get_message_element(CAPWAP_ELEMENT_RESULTCODE)->free(resultcodeelement); - } - - return result; -} - /* Detect if type is a request */ int capwap_is_request_type(unsigned long type) { if ((type == CAPWAP_DISCOVERY_REQUEST) || @@ -1183,145 +90,911 @@ int capwap_is_request_type(unsigned long type) { } /* Retrieve packet digest */ -void capwap_get_packet_digest(void* buffer, unsigned long length, unsigned char packetdigest[16]) { +void capwap_get_packet_digest(struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, unsigned char packetdigest[16]) { MD5_CTX mdContext; + struct capwap_list_item* item; + struct capwap_fragment_packet_item* packet; - ASSERT(buffer != NULL); - ASSERT(length > 0); - + ASSERT(rxmngpacket != NULL); + ASSERT(rxmngpacket->packetlength > 0); + ASSERT(connection != NULL); + MD5Init(&mdContext); - MD5Update(&mdContext, (unsigned char*)buffer, length); + + /* Address */ + if ((connection->localaddr.ss_family == AF_INET) && ((connection->remoteaddr.ss_family == AF_INET))) { + struct sockaddr_in* localaddr_in = (struct sockaddr_in*)&connection->localaddr; + struct sockaddr_in* remoteaddr_in = (struct sockaddr_in*)&connection->remoteaddr; + + MD5Update(&mdContext, (unsigned char*)&localaddr_in->sin_addr.s_addr, sizeof(unsigned long)); + MD5Update(&mdContext, (unsigned char*)&localaddr_in->sin_port, sizeof(unsigned short)); + MD5Update(&mdContext, (unsigned char*)&remoteaddr_in->sin_addr.s_addr, sizeof(unsigned long)); + MD5Update(&mdContext, (unsigned char*)&remoteaddr_in->sin_port, sizeof(unsigned short)); + } else if ((connection->localaddr.ss_family == AF_INET6) && ((connection->remoteaddr.ss_family == AF_INET6))) { + struct sockaddr_in6* localaddr_in6 = (struct sockaddr_in6*)&connection->localaddr; + struct sockaddr_in6* remoteaddr_in6 = (struct sockaddr_in6*)&connection->remoteaddr; + + MD5Update(&mdContext, (unsigned char*)&localaddr_in6->sin6_addr, sizeof(struct in6_addr)); + MD5Update(&mdContext, (unsigned char*)&localaddr_in6->sin6_port, sizeof(unsigned short)); + MD5Update(&mdContext, (unsigned char*)&remoteaddr_in6->sin6_addr, sizeof(struct in6_addr)); + MD5Update(&mdContext, (unsigned char*)&remoteaddr_in6->sin6_port, sizeof(unsigned short)); + } + + /* Packet */ + item = rxmngpacket->fragmentlist->first; + while (item) { + packet = (struct capwap_fragment_packet_item*)item->item; + MD5Update(&mdContext, (unsigned char*)packet->buffer, packet->offset); + item = item->next; + } + MD5Final(&mdContext); - + memcpy(&packetdigest[0], &mdContext.digest[0], sizeof(unsigned char) * 16); } /* Verify duplicate packet */ -int capwap_recv_retrasmitted_request(struct capwap_dtls* dtls, struct capwap_packet* packet, unsigned char lastseqnumber, unsigned char packetdigest[16], struct capwap_socket* sock, capwap_fragment_packet_array* txfragmentpacket, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr) { +int capwap_recv_retrasmitted_request(struct capwap_dtls* dtls, struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, unsigned char packetdigest[16], struct capwap_list* txfragmentpacket) { unsigned char recvpacketdigest[16]; - unsigned short lengthpayload; - - ASSERT(packet != NULL); - ASSERT(sock != NULL); - ASSERT(txfragmentpacket != NULL); - ASSERT(sendtoaddr != NULL); - lengthpayload = packet->packetsize - GET_HLEN_HEADER(packet->header) * 4; - if (lengthpayload >= sizeof(struct capwap_control_message)) { - struct capwap_control_message* ctrlmsg = (struct capwap_control_message*)packet->payload; - - /* Check if request */ - if (capwap_is_request_type(ntohl(ctrlmsg->type)) && (ctrlmsg->seq == lastseqnumber)) { - /* Check packet digest */ - capwap_get_packet_digest((void*)packet->header, packet->packetsize, recvpacketdigest); - if (!memcmp(&recvpacketdigest[0], &packetdigest[0], sizeof(unsigned char) * 16)) { - int i; - - /* Retransmit response */ - for (i = 0; i < txfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(dtls, sock->socket[sock->type], txpacket->header, txpacket->packetsize, sendfromaddr, sendtoaddr)) { - capwap_logging_debug("Warning: error to resend response packet"); - break; - } - } - - return 1; - } + ASSERT(rxmngpacket != NULL); + ASSERT(connection != NULL); + ASSERT(txfragmentpacket != NULL); + + /* Check packet digest */ + capwap_get_packet_digest(rxmngpacket, connection, recvpacketdigest); + if (!memcmp(&recvpacketdigest[0], &packetdigest[0], sizeof(unsigned char) * 16)) { + /* Retransmit response */ + if (!capwap_crypt_sendto_fragmentpacket(dtls, connection->socket.socket[connection->socket.type], txfragmentpacket, &connection->localaddr, &connection->remoteaddr)) { + capwap_logging_debug("Warning: error to resend response packet"); } + + return 1; } return 0; } /* Check valid message type */ -int capwap_check_message_type(struct capwap_dtls* dtls, struct capwap_packet* packet, unsigned short mtu) { +int capwap_check_message_type(struct capwap_packet_rxmng* rxmngpacket) { unsigned short lengthpayload; - ASSERT(packet != NULL); - ASSERT(mtu > 0); - - lengthpayload = packet->packetsize - GET_HLEN_HEADER(packet->header) * 4; - if (lengthpayload >= sizeof(struct capwap_control_message)) { - struct capwap_control_message* ctrlmsg = (struct capwap_control_message*)packet->payload; - unsigned long type = ntohl(ctrlmsg->type); - - if ((type >= CAPWAP_FIRST_MESSAGE_TYPE) && (type <= CAPWAP_LAST_MESSAGE_TYPE)) { - return 1; - } - - /* Unknown message type */ - if ((type % 2) != 0) { - int i; - struct capwap_build_packet* responsepacket; - struct capwap_resultcode_element resultcode = { CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST }; - capwap_fragment_packet_array* txfragmentpacket = NULL; - - /* Odd message type, response with "Unrecognized Request" */ - responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, GET_WBID_HEADER(packet->header)); - responsepacket->isctrlmsg = 1; - capwap_build_packet_set_control_message_type(responsepacket, type + 1, ctrlmsg->seq); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RESULTCODE_ELEMENT(&resultcode)); + ASSERT(rxmngpacket != NULL); - txfragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - if (capwap_fragment_build_packet(responsepacket, txfragmentpacket, mtu, 0) >= 0) { - for (i = 0; i < txfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(dtls, packet->socket.socket[packet->socket.type], txpacket->header, txpacket->packetsize, &packet->remoteaddr, &packet->remoteaddr)) { - break; - } - } + if (rxmngpacket->isctrlpacket && rxmngpacket->fragmentlist->first) { + struct capwap_fragment_packet_item* packet = (struct capwap_fragment_packet_item*)rxmngpacket->fragmentlist->first->item; + struct capwap_header* header = (struct capwap_header*)packet->buffer; + + lengthpayload = packet->offset - GET_HLEN_HEADER(header) * 4; + if (lengthpayload >= sizeof(struct capwap_control_message)) { + if ((rxmngpacket->ctrlmsg.type >= CAPWAP_FIRST_MESSAGE_TYPE) && (rxmngpacket->ctrlmsg.type <= CAPWAP_LAST_MESSAGE_TYPE)) { + return VALID_MESSAGE_TYPE; } - - /* Free memory */ - capwap_fragment_free(txfragmentpacket); - capwap_array_free(txfragmentpacket); - capwap_build_packet_free(responsepacket); - } - } - return 0; + /* Unknown message type */ + if ((rxmngpacket->ctrlmsg.type % 2) != 0) { + return INVALID_REQUEST_MESSAGE_TYPE; + } + } + } else if (!rxmngpacket->isctrlpacket && rxmngpacket->fragmentlist->first) { + return VALID_MESSAGE_TYPE; + } + + return INVALID_MESSAGE_TYPE; } -int capwap_get_sessionid_from_keepalive(struct capwap_build_packet* buildpacket, struct capwap_sessionid_element* session) { - int found = 0; +/* */ +void capwap_header_init(struct capwap_header_data* data, unsigned short radioid, unsigned short binding) { + struct capwap_header* header; - ASSERT(buildpacket != NULL); - ASSERT(session != NULL); + ASSERT(data != NULL); - /* Check is Data Packet KeepAlive */ - if (IS_FLAG_K_HEADER(&buildpacket->header) && !capwap_build_packet_validate(buildpacket, NULL)) { - struct capwap_list_item* item = buildpacket->elementslist->first; + /* */ + header = (struct capwap_header*)&data->headerbuffer[0]; + memset(header, 0, sizeof(struct capwap_header)); - while (!found && (item != NULL)) { - struct capwap_message_element* elementitem = (struct capwap_message_element*)item->item; - unsigned short type = ntohs(elementitem->type); - struct capwap_message_elements_func* f = capwap_get_message_element(type); - - ASSERT(f != NULL); - ASSERT(f->parsing != NULL); - - switch (type) { - case CAPWAP_ELEMENT_SESSIONID: { - struct capwap_sessionid_element* tempsession; - - tempsession = (struct capwap_sessionid_element*)f->parsing(elementitem); - memcpy(session, tempsession, sizeof(struct capwap_sessionid_element)); - f->free(tempsession); - - found = 1; - break; - } + /* Standard configuration */ + SET_VERSION_HEADER(header, CAPWAP_PROTOCOL_VERSION); + SET_TYPE_HEADER(header, CAPWAP_PREAMBLE_HEADER); + SET_HLEN_HEADER(header, sizeof(struct capwap_header) / 4); + SET_RID_HEADER(header, radioid); + SET_WBID_HEADER(header, binding); +} + +/* */ +void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, char* macaddress) { + struct capwap_header* header; + + ASSERT(data != NULL); + + header = (struct capwap_header*)&data->headerbuffer[0]; + if (radiotype == CAPWAP_MACADDRESS_NONE) { + if (IS_FLAG_M_HEADER(header)) { + if (!IS_FLAG_W_HEADER(header)) { + SET_HLEN_HEADER(header, sizeof(struct capwap_header) / 4); + } else { + struct capwap_wireless_information* wireless = GET_WIRELESS_INFORMATION_STRUCT(header); + int lengthpadded = (((sizeof(struct capwap_wireless_information) + wireless->length) + 3) / 4); + + /* Move wireless information */ + memmove(((char*)header + sizeof(struct capwap_header)), wireless, lengthpadded * 4); + SET_HLEN_HEADER(header, (sizeof(struct capwap_header) / 4) + lengthpadded); } + + SET_FLAG_M_HEADER(header, 0); + } + } else { + int i; + int radiosizepadded; + struct capwap_mac_address* radio; + int size = sizeof(struct capwap_header) / 4; + + ASSERT(macaddress != NULL); + ASSERT((radiotype == CAPWAP_MACADDRESS_EUI48) || (radiotype == CAPWAP_MACADDRESS_EUI64)); + + if (IS_FLAG_M_HEADER(header)) { + radio = GET_RADIO_MAC_ADDRESS_STRUCT(header); + + if (radio->length == radiotype) { + /* Rewrite mac address */ + memcpy(radio->address, macaddress, radiotype); + return; + } + + /* Remove old radio mac address */ + capwap_header_set_radio_macaddress(data, CAPWAP_MACADDRESS_NONE, NULL); + } + + /* Radio mac address size*/ + radio = (struct capwap_mac_address*)((char*)header + sizeof(struct capwap_header)); + radiosizepadded = (((sizeof(struct capwap_mac_address) + radiotype) + 3) / 4); + size += radiosizepadded; + + /* Wireless information */ + if (IS_FLAG_W_HEADER(header)) { + struct capwap_wireless_information* wireless = GET_WIRELESS_INFORMATION_STRUCT(header); + int lengthpadded = (((sizeof(struct capwap_wireless_information) + wireless->length) + 3) / 4); - /* Next element */ - item = item->next; + memmove((char*)radio + radiosizepadded, wireless, lengthpadded * 4); + size += lengthpadded; + } + + radio->length = radiotype; + memcpy(radio->address, macaddress, radiotype); + for (i = (radiosizepadded * 4) - 2; i >= radiotype; i--) { + radio->address[i] = 0; + } + + SET_FLAG_M_HEADER(header, 1); + SET_HLEN_HEADER(header, size); + } +} + +/* */ +void capwap_header_set_wireless_information(struct capwap_header_data* data, void* buffer, unsigned char length) { + int size; + struct capwap_header* header; + + ASSERT(data != NULL); + + header = (struct capwap_header*)&data->headerbuffer[0]; + + /* Calculate size of header */ + size = sizeof(struct capwap_header) / 4; + if (IS_FLAG_M_HEADER(header)) { + struct capwap_mac_address* radio = GET_RADIO_MAC_ADDRESS_STRUCT(header); + size += ((sizeof(struct capwap_mac_address) + radio->length) + 3) / 4; + } + + /* Remove old wireless information */ + if (IS_FLAG_W_HEADER(header)) { + SET_HLEN_HEADER(header, size); + } + + /* Add new wireless information */ + if (length > 0) { + int i; + struct capwap_wireless_information* wireless; + int lengthpadded = (((sizeof(struct capwap_wireless_information) + length) + 3) / 4); + + ASSERT(buffer != NULL); + + wireless = GET_WIRELESS_INFORMATION_STRUCT(header); + wireless->length = length; + memcpy(wireless->data, buffer, length); + for (i = (lengthpadded * 4) - 2; i >= length; i--) { + wireless->data[i] = 0; + } + + /* Update size */ + size += lengthpadded; + SET_HLEN_HEADER(header, size); + } +} + +/* */ +void capwap_header_set_keepalive_flag(struct capwap_header_data* data, int enable) { + struct capwap_header* header; + + ASSERT(data != NULL); + + header = (struct capwap_header*)&data->headerbuffer[0]; + SET_FLAG_K_HEADER(header, ((enable != 0) ? 1 : 0)); +} + +/* */ +static struct capwap_list_item* capwap_packet_txmng_create_fragment_item(struct capwap_packet_txmng* txmngpacket) { + struct capwap_list_item* item; + struct capwap_fragment_packet_item* packet; + + /* Create maxium size of packet */ + item = capwap_itemlist_create(sizeof(struct capwap_fragment_packet_item) + txmngpacket->mtu); + packet = (struct capwap_fragment_packet_item*)item->item; + + /* */ + memset(packet, 0, sizeof(sizeof(struct capwap_fragment_packet_item) + txmngpacket->mtu)); + packet->size = txmngpacket->mtu; + + /* Append to last position */ + capwap_itemlist_insert_after(txmngpacket->fragmentlist, NULL, item); + + return item; +} + +/* */ +static int capwap_fragment_write_block_from_pos(struct capwap_packet_txmng* txmngpacket, uint8_t* data, unsigned short length, struct write_block_from_pos* writepos) { + unsigned short packetpos; + struct capwap_list_item* item; + struct capwap_fragment_packet_item* fragmentpacket; + + ASSERT(txmngpacket != NULL); + ASSERT(data != NULL); + ASSERT(length > 0); + ASSERT(writepos != NULL); + + /* Get fragment packet */ + item = writepos->item; + packetpos = writepos->pos; + fragmentpacket = (struct capwap_fragment_packet_item*)item->item; + ASSERT(packetpos <= fragmentpacket->size); + + /* Write data into one o more fragment packet */ + while (length > 0) { + unsigned short available = min(length, (fragmentpacket->size - packetpos)); + + /* Check if require new fragment */ + if (!available) { + struct capwap_header* header; + + if (item->next) { + /* Next packet */ + item = item->next; + fragmentpacket = (struct capwap_fragment_packet_item*)item->item; + + /* Get capwap header size */ + header = (struct capwap_header*)fragmentpacket->buffer; + packetpos = GET_HLEN_HEADER(header); + } else { + /* Create new fragment packet */ + item = capwap_packet_txmng_create_fragment_item(txmngpacket); + fragmentpacket = (struct capwap_fragment_packet_item*)item->item; + + /* Copy capwap header without macaddress and wireless info */ + memcpy(fragmentpacket->buffer, txmngpacket->header, sizeof(struct capwap_header)); + fragmentpacket->offset += sizeof(struct capwap_header); + packetpos = fragmentpacket->offset; + + /* Normalize packet to multiple of 8 bytes */ + fragmentpacket->size -= (fragmentpacket->size - fragmentpacket->offset) % 8; + + /* Radio mac address and wireless information is sent only into first packet */ + header = (struct capwap_header*)fragmentpacket->buffer; + SET_FLAG_M_HEADER(header, 0); + SET_FLAG_W_HEADER(header, 0); + SET_HLEN_HEADER(header, sizeof(struct capwap_header) / 4); + } + + /* Recalculate space available */ + available = min(length, (fragmentpacket->size - packetpos)); + ASSERT(available > 0); + } + + /* Write data */ + memcpy(&fragmentpacket->buffer[packetpos], data, available); + length -= available; + txmngpacket->writerpacketsize += available; + + if ((available + packetpos) > fragmentpacket->offset) { + unsigned short oldoffset = fragmentpacket->offset; + + fragmentpacket->offset = available + packetpos; + if (txmngpacket->isctrlpacket) { + txmngpacket->ctrlmsg->length = htons(ntohs(txmngpacket->ctrlmsg->length) + (fragmentpacket->offset - oldoffset)); + } else { + txmngpacket->datamsg->length = htons(ntohs(txmngpacket->datamsg->length) + (fragmentpacket->offset - oldoffset)); + } } } - - return found; + + return length; +} + +/* */ +static int capwap_fragment_write_block(capwap_message_elements_handle handle, uint8_t* data, unsigned short length) { + struct capwap_packet_txmng* txmngpacket; + struct write_block_from_pos writepos; + + ASSERT(handle != NULL); + ASSERT(data != NULL); + ASSERT(length > 0); + + /* Get last fragment packet */ + txmngpacket = (struct capwap_packet_txmng*)handle; + + /* */ + writepos.item = txmngpacket->fragmentlist->last; + writepos.pos = ((struct capwap_fragment_packet_item*)writepos.item->item)->offset; + + return capwap_fragment_write_block_from_pos(txmngpacket, data, length, &writepos); +} + +/* */ +static int capwap_fragment_write_u8(capwap_message_elements_handle handle, uint8_t data) { + if (capwap_fragment_write_block(handle, &data, sizeof(uint8_t)) != sizeof(uint8_t)) { + return -1; + } + + return sizeof(uint8_t); +} + +/* */ +static int capwap_fragment_write_u16_from_pos(capwap_message_elements_handle handle, uint16_t data, struct write_block_from_pos* writepos) { + uint16_t temp = htons(data); + if (capwap_fragment_write_block_from_pos(handle, (uint8_t*)&temp, sizeof(uint16_t), writepos) != sizeof(uint16_t)) { + return -1; + } + + return sizeof(uint16_t); +} + +/* */ +static int capwap_fragment_write_u16(capwap_message_elements_handle handle, uint16_t data) { + uint16_t temp = htons(data); + if (capwap_fragment_write_block(handle, (uint8_t*)&temp, sizeof(uint16_t)) != sizeof(uint16_t)) { + return -1; + } + + return sizeof(uint16_t); +} + +/* */ +static int capwap_fragment_write_u32(capwap_message_elements_handle handle, uint32_t data) { + uint32_t temp = htonl(data); + if (capwap_fragment_write_block(handle, (uint8_t*)&temp, sizeof(uint32_t)) != sizeof(uint32_t)) { + return -1; + } + + return sizeof(uint32_t); +} + +/* */ +static struct capwap_packet_txmng* capwap_packet_txmng_create(struct capwap_header_data* data, unsigned short mtu) { + unsigned short headerlength; + struct capwap_packet_txmng* txmngpacket; + struct capwap_list_item* firstitem; + struct capwap_fragment_packet_item* fragmentpacket; + struct capwap_header* header; + + /* */ + txmngpacket = (struct capwap_packet_txmng*)capwap_alloc(sizeof(struct capwap_packet_txmng)); + if (!txmngpacket) { + capwap_outofmemory(); + } + + /* */ + memset(txmngpacket, 0, sizeof(struct capwap_packet_txmng)); + txmngpacket->mtu = mtu; + + /* Fragment bucket */ + txmngpacket->fragmentlist = capwap_list_create(); + + /* First packet */ + firstitem = capwap_packet_txmng_create_fragment_item(txmngpacket); + fragmentpacket = (struct capwap_fragment_packet_item*)firstitem->item; + + /* Get capwap header information */ + header = (struct capwap_header*)&data->headerbuffer[0]; + headerlength = GET_HLEN_HEADER(header) * 4; + + /* Normalize packet to multiple of 8 bytes */ + fragmentpacket->size -= (fragmentpacket->size - headerlength) % 8; + ASSERT(headerlength < fragmentpacket->size); + + /* Save capwap header */ + txmngpacket->header = (struct capwap_header*)fragmentpacket->buffer; + memcpy(txmngpacket->header, header, headerlength); + fragmentpacket->offset += headerlength; + + /* Configure basic IO write function */ + txmngpacket->write_ops.write_u8 = capwap_fragment_write_u8; + txmngpacket->write_ops.write_u16 = capwap_fragment_write_u16; + txmngpacket->write_ops.write_u32 = capwap_fragment_write_u32; + txmngpacket->write_ops.write_block = capwap_fragment_write_block; + + return txmngpacket; +} + +/* */ +struct capwap_packet_txmng* capwap_packet_txmng_create_ctrl_message(struct capwap_header_data* data, unsigned long type, unsigned char seq, unsigned short mtu) { + unsigned short length; + struct capwap_packet_txmng* txmngpacket; + struct capwap_fragment_packet_item* fragmentpacket; + + ASSERT(data != NULL); + ASSERT(mtu > 0); + + length = GET_HLEN_HEADER((struct capwap_header*)data->headerbuffer) * 4; + + /* Check MTU */ + if ((mtu > 0) && (mtu < (length + sizeof(struct capwap_control_message)))) { + capwap_logging_debug("The mtu is too small: %hu", mtu); + return NULL; + } + + /* Create management packets */ + txmngpacket = capwap_packet_txmng_create(data, mtu); + if (!txmngpacket) { + return NULL; + } + + /* Get single fragment */ + fragmentpacket = (struct capwap_fragment_packet_item*)txmngpacket->fragmentlist->last->item; + ASSERT((fragmentpacket->offset + sizeof(struct capwap_control_message)) < fragmentpacket->size); + + /* Create message */ + txmngpacket->isctrlpacket = 1; + + txmngpacket->ctrlmsg = (struct capwap_control_message*)&fragmentpacket->buffer[fragmentpacket->offset]; + txmngpacket->ctrlmsg->type = htonl(type); + txmngpacket->ctrlmsg->seq = seq; + txmngpacket->ctrlmsg->length = 0; + txmngpacket->ctrlmsg->flags = 0; + + /* Prepare for save capwap element */ + fragmentpacket->offset += sizeof(struct capwap_control_message); + + return txmngpacket; +} + +/* */ +struct capwap_packet_txmng* capwap_packet_txmng_create_data_message(struct capwap_header_data* data, unsigned short mtu) { + unsigned short length; + struct capwap_packet_txmng* txmngpacket; + struct capwap_fragment_packet_item* fragmentpacket; + + ASSERT(data != NULL); + ASSERT(mtu > 0); + + length = GET_HLEN_HEADER((struct capwap_header*)data->headerbuffer) * 4; + + /* Check MTU */ + if ((mtu > 0) && (mtu < (length + sizeof(struct capwap_data_message)))) { + capwap_logging_debug("The mtu is too small: %hu", mtu); + return NULL; + } + + /* Create management packets */ + txmngpacket = capwap_packet_txmng_create(data, mtu); + if (!txmngpacket) { + return NULL; + } + + /* Get single fragment */ + fragmentpacket = (struct capwap_fragment_packet_item*)txmngpacket->fragmentlist->last->item; + ASSERT((fragmentpacket->offset + sizeof(struct capwap_data_message)) < fragmentpacket->size); + + /* Create message */ + txmngpacket->isctrlpacket = 0; + + txmngpacket->datamsg = (struct capwap_data_message*)&fragmentpacket->buffer[fragmentpacket->offset]; + txmngpacket->datamsg->length = 0; + + /* Prepare for save frame */ + fragmentpacket->offset += sizeof(struct capwap_data_message); + + return txmngpacket; +} + +/* */ +void capwap_packet_txmng_add_message_element(struct capwap_packet_txmng* txmngpacket, unsigned short type, void* data) { + struct capwap_message_elements_ops* func; + struct write_block_from_pos writepos; + + ASSERT(txmngpacket != NULL); + + /* Retrieve message element function */ + func = capwap_get_message_element_ops(type); + ASSERT(func != NULL); + ASSERT(func->create_message_element != NULL); + + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Value ... | + +-+-+-+-+-+-+-+-+ + + Type and Length is add to this function, only custom create_message_element write Value message element + */ + + txmngpacket->write_ops.write_u16((capwap_message_elements_handle)txmngpacket, type); + + /* Length of message element is calculate after create_message_element function */ + writepos.item = txmngpacket->fragmentlist->last; + writepos.pos = ((struct capwap_fragment_packet_item*)writepos.item->item)->offset; + txmngpacket->write_ops.write_u16((capwap_message_elements_handle)txmngpacket, 0); + txmngpacket->writerpacketsize = 0; + + /* Build message element */ + func->create_message_element(data, (capwap_message_elements_handle)txmngpacket, &txmngpacket->write_ops); + + /* Write message element length */ + capwap_fragment_write_u16_from_pos((capwap_message_elements_handle)txmngpacket, txmngpacket->writerpacketsize, &writepos); +} + +/* */ +void capwap_packet_txmng_get_fragment_packets(struct capwap_packet_txmng* txmngpacket, struct capwap_list* fragmentlist, unsigned short fragmentid) { + unsigned short fragmentoffset = 0; + + ASSERT(txmngpacket != NULL); + ASSERT(fragmentlist != NULL); + + /* */ + while (txmngpacket->fragmentlist->first) { + struct capwap_list_item* item = capwap_itemlist_remove_head(txmngpacket->fragmentlist); + struct capwap_fragment_packet_item* fragmentpacket = (struct capwap_fragment_packet_item*)item->item; + struct capwap_header* header = (struct capwap_header*)fragmentpacket->buffer; + + /* Check if require fragment */ + if (!fragmentoffset && !txmngpacket->fragmentlist->first) { + SET_FLAG_F_HEADER(header, 0); + SET_FRAGMENT_ID_HEADER(header, 0); + SET_FRAGMENT_OFFSET_HEADER(header, 0); + SET_FLAG_L_HEADER(header, 0); + } else { + SET_FLAG_F_HEADER(header, 1); + SET_FRAGMENT_ID_HEADER(header, fragmentid); + SET_FRAGMENT_OFFSET_HEADER(header, fragmentoffset); + SET_FLAG_L_HEADER(header, (!txmngpacket->fragmentlist->first ? 1 : 0)); + + /* Update fragment offset */ + fragmentoffset += fragmentpacket->offset % 8; + } + + /* Transfer item to external list */ + capwap_itemlist_insert_after(fragmentlist, NULL, item); + } +} + +/* */ +void capwap_packet_txmng_free(struct capwap_packet_txmng* txmngpacket) { + if (txmngpacket) { + capwap_list_free(txmngpacket->fragmentlist); + capwap_free(txmngpacket); + } +} + +/* */ +unsigned short capwap_fragment_read_ready(capwap_message_elements_handle handle) { + struct capwap_packet_rxmng* rxmngpacket = (struct capwap_packet_rxmng*)handle; + + ASSERT(handle != NULL); + + return (rxmngpacket->readpos.item ? rxmngpacket->readerpacketallowed : 0); +} + +/* */ +static int capwap_fragment_read_block_from_pos(uint8_t* data, unsigned short length, struct read_block_from_pos* readpos, unsigned short lengthallowed) { + unsigned short readdataleft; + + ASSERT(length > 0); + ASSERT(readpos != NULL); + + readdataleft = (lengthallowed > 0 ? min(length, lengthallowed) : length); + length = readdataleft; + + while (readpos->item && readdataleft) { + struct capwap_fragment_packet_item* packet = (struct capwap_fragment_packet_item*)readpos->item->item; + unsigned short bufferlength = packet->size - readpos->pos; + unsigned short copylength = min(bufferlength, readdataleft); + + if (data) { + /* Copy data from capwap packet */ + memcpy(&data[length - readdataleft], &packet->buffer[readpos->pos], copylength); + } + + readdataleft -= copylength; + readpos->pos += copylength; + + /* Check buffer */ + if (readpos->pos == packet->size) { + /* Next packet */ + readpos->item = readpos->item->next; + if (!readpos->item) { + readpos->pos = 0; + if (readdataleft) { + capwap_logging_debug("Complete to read capwap packet but remain %hu byte to read", readdataleft); + } + } else { + struct capwap_header* header; + + /* Skip capwap header */ + packet = (struct capwap_fragment_packet_item*)readpos->item->item; + header = (struct capwap_header*)packet->buffer; + readpos->pos = GET_HLEN_HEADER(header) * 4; + } + } + } + + return (length - readdataleft); +} + +static int capwap_fragment_read_block(capwap_message_elements_handle handle, uint8_t* data, unsigned short length) { + unsigned short readlength; + struct capwap_packet_rxmng* rxmngpacket; + + ASSERT(handle != NULL); + + rxmngpacket = (struct capwap_packet_rxmng*)handle; + readlength = capwap_fragment_read_block_from_pos(data, length, &rxmngpacket->readpos, rxmngpacket->readerpacketallowed); + rxmngpacket->readerpacketallowed -= readlength; + + return readlength; +} + +/* */ +static int capwap_fragment_read_u8(capwap_message_elements_handle handle, uint8_t* data) { + if (capwap_fragment_read_block(handle, (uint8_t*)data, sizeof(uint8_t)) != sizeof(uint8_t)) { + return -1; + } + + return sizeof(uint8_t); +} + +/* */ +static int capwap_fragment_read_u16(capwap_message_elements_handle handle, uint16_t* data) { + uint16_t temp; + if (capwap_fragment_read_block(handle, (uint8_t*)&temp, sizeof(uint16_t)) != sizeof(uint16_t)) { + return -1; + } + + if (data) { + *data = ntohs(temp); + } + + return sizeof(uint16_t); +} + +/* */ +static int capwap_fragment_read_u32(capwap_message_elements_handle handle, uint32_t* data) { + uint32_t temp; + if (capwap_fragment_read_block(handle, (uint8_t*)&temp, sizeof(uint32_t)) != sizeof(uint32_t)) { + return -1; + } + + if (data) { + *data = ntohl(temp); + } + + return sizeof(uint32_t); +} + +/* */ +struct capwap_packet_rxmng* capwap_packet_rxmng_create_message(int isctrlpacket) { + struct capwap_packet_rxmng* rxmngpacket; + + /* */ + rxmngpacket = (struct capwap_packet_rxmng*)capwap_alloc(sizeof(struct capwap_packet_rxmng)); + if (!rxmngpacket) { + capwap_outofmemory(); + } + + /* */ + memset(rxmngpacket, 0, sizeof(struct capwap_packet_rxmng)); + rxmngpacket->isctrlpacket = isctrlpacket; + + /* Fragment bucket */ + rxmngpacket->fragmentlist = capwap_list_create(); + + return rxmngpacket; +} + +/* */ +static void capwap_packet_rxmng_complete(struct capwap_packet_rxmng* rxmngpacket) { + ASSERT(rxmngpacket->packetlength > 0); + + /* Configure basic IO read function */ + rxmngpacket->read_ops.read_ready = capwap_fragment_read_ready; + rxmngpacket->read_ops.read_u8 = capwap_fragment_read_u8; + rxmngpacket->read_ops.read_u16 = capwap_fragment_read_u16; + rxmngpacket->read_ops.read_u32 = capwap_fragment_read_u32; + rxmngpacket->read_ops.read_block = capwap_fragment_read_block; + + /* Set reader value */ + rxmngpacket->readpos.item = rxmngpacket->fragmentlist->first; + rxmngpacket->header = (struct capwap_header*)((struct capwap_fragment_packet_item*)rxmngpacket->fragmentlist->first->item)->buffer; + rxmngpacket->readpos.pos = GET_HLEN_HEADER(rxmngpacket->header) * 4; + + /* Read message type */ + if (rxmngpacket->isctrlpacket) { + rxmngpacket->readerpacketallowed = sizeof(struct capwap_control_message); + rxmngpacket->read_ops.read_u32((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->ctrlmsg.type); + rxmngpacket->read_ops.read_u8((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->ctrlmsg.seq); + rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->ctrlmsg.length); + rxmngpacket->read_ops.read_u8((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->ctrlmsg.flags); + } else { + rxmngpacket->readerpacketallowed = sizeof(struct capwap_data_message); + rxmngpacket->read_ops.read_u16((capwap_message_elements_handle)rxmngpacket, &rxmngpacket->datamsg.length); + } + + /* Position of capwap body */ + memcpy(&rxmngpacket->readbodypos, &rxmngpacket->readpos, sizeof(struct read_block_from_pos)); +} + +/* */ +static struct capwap_list_item* capwap_packet_rxmng_create_fragment_item(void* data, int length) { + struct capwap_list_item* item; + struct capwap_fragment_packet_item* packet; + + item = capwap_itemlist_create(sizeof(struct capwap_fragment_packet_item) + length); + packet = (struct capwap_fragment_packet_item*)item->item; + packet->size = length; + packet->offset = length; + memcpy(packet->buffer, data, length); + + return item; +} + +/* */ +int capwap_packet_rxmng_add_recv_packet(struct capwap_packet_rxmng* rxmngpacket, void* data, int length) { + struct capwap_header* header; + + ASSERT(rxmngpacket != NULL); + ASSERT(data != NULL); + ASSERT(length > 0); + + /* Parsing fragment capwap header */ + header = (struct capwap_header*)data; + if (IS_FLAG_F_HEADER(header)) { + struct capwap_list_item* itemsearch; + struct capwap_fragment_packet_item* packetsearch; + struct capwap_header* headersearch; + unsigned short fragid = GET_FRAGMENT_ID_HEADER(header); + unsigned short fragoffset = GET_FRAGMENT_OFFSET_HEADER(header); + unsigned short headersize = GET_HLEN_HEADER(header) * 4; + + /* Size of payload is multiple of 64bits */ + if (((length - headersize) % 8) != 0) { + capwap_logging_debug("Body capwap packet is not multiple of 64bit"); + return CAPWAP_WRONG_FRAGMENT; + } + + /* Check fragment id */ + if (rxmngpacket->fragmentlist->count > 0) { + itemsearch = rxmngpacket->fragmentlist->first; + packetsearch = (struct capwap_fragment_packet_item*)itemsearch->item; + headersearch = (struct capwap_header*)packetsearch->buffer; + + if (fragid != GET_FRAGMENT_ID_HEADER(headersearch)) { + capwap_logging_debug("Sent fragment packets with different fragment id"); + return CAPWAP_WRONG_FRAGMENT; + } + } + + /* Order fragment */ + if (!rxmngpacket->fragmentlist->count) { + capwap_itemlist_insert_before(rxmngpacket->fragmentlist, NULL, capwap_packet_rxmng_create_fragment_item(data, length)); + } else { + itemsearch = rxmngpacket->fragmentlist->first; + while (itemsearch) { + packetsearch = (struct capwap_fragment_packet_item*)itemsearch->item; + headersearch = (struct capwap_header*)packetsearch->buffer; + unsigned short fragoffsetsearch = GET_FRAGMENT_OFFSET_HEADER(headersearch); + + if (fragoffset < fragoffsetsearch) { + capwap_itemlist_insert_before(rxmngpacket->fragmentlist, itemsearch, capwap_packet_rxmng_create_fragment_item(data, length)); + break; + } else if ((fragoffset > fragoffsetsearch) && !itemsearch->next) { + capwap_itemlist_insert_after(rxmngpacket->fragmentlist, NULL, capwap_packet_rxmng_create_fragment_item(data, length)); + break; + } else { + /* Check duplicate packet */ + if (packetsearch->size != length) { + capwap_logging_debug("Duplicate fragment offset with different size"); + return CAPWAP_WRONG_FRAGMENT; + } + + if (memcmp(packetsearch->buffer, data, packetsearch->size)) { + capwap_logging_debug("Duplicate fragment offset with different packet"); + return CAPWAP_WRONG_FRAGMENT; + } + + /* Duplicate packet */ + break; + } + + /* Next fragment */ + itemsearch = itemsearch->next; + } + } + + /* Check complete only if receive last packet */ + ASSERT(rxmngpacket->fragmentlist->last != NULL); + packetsearch = (struct capwap_fragment_packet_item*)rxmngpacket->fragmentlist->last->item; + headersearch = (struct capwap_header*)packetsearch->buffer; + if (IS_FLAG_L_HEADER(header)) { + unsigned short sanityfragoffset = 0; + + /* Sanity check and complete */ + itemsearch = rxmngpacket->fragmentlist->first; + while (itemsearch) { + packetsearch = (struct capwap_fragment_packet_item*)itemsearch->item; + headersearch = (struct capwap_header*)packetsearch->buffer; + unsigned short fragoffsetsearch = GET_FRAGMENT_OFFSET_HEADER(headersearch); + unsigned short packetlength = packetsearch->size - GET_HLEN_HEADER(headersearch) * 4; + + /* Check fragment offset */ + if (sanityfragoffset < fragoffsetsearch) { + return CAPWAP_REQUEST_MORE_FRAGMENT; + } else if (sanityfragoffset > fragoffsetsearch) { + capwap_list_flush(rxmngpacket->fragmentlist); + capwap_logging_debug("Wrong fragment offset"); + return CAPWAP_WRONG_FRAGMENT; + } + + /* Update fragment offset */ + rxmngpacket->packetlength += packetlength; + sanityfragoffset += packetlength / 8; + + /* Next fragment */ + itemsearch = itemsearch->next; + } + + /* Packet complete */ + capwap_packet_rxmng_complete(rxmngpacket); + return CAPWAP_RECEIVE_COMPLETE_PACKET; + } + + return CAPWAP_REQUEST_MORE_FRAGMENT; + } else { + /* Check if already received fragment packets */ + if (rxmngpacket->fragmentlist->count > 0) { + /* Overlap fragment packet with complete packet */ + capwap_logging_debug("Overlap fragment packet with complete packet"); + return CAPWAP_WRONG_FRAGMENT; + } else { + struct capwap_header* header; + + /* */ + capwap_itemlist_insert_after(rxmngpacket->fragmentlist, NULL, capwap_packet_rxmng_create_fragment_item(data, length)); + header = (struct capwap_header*)data; + rxmngpacket->packetlength = length - GET_HLEN_HEADER(header) * 4; + + /* */ + capwap_packet_rxmng_complete(rxmngpacket); + return CAPWAP_RECEIVE_COMPLETE_PACKET; + } + } + + return CAPWAP_WRONG_FRAGMENT; +} + +/* */ +void capwap_packet_rxmng_free(struct capwap_packet_rxmng* rxmngpacket) { + if (rxmngpacket) { + capwap_list_free(rxmngpacket->fragmentlist); + capwap_free(rxmngpacket); + } } diff --git a/src/common/capwap_protocol.h b/src/common/capwap_protocol.h index bd19b5f..587912d 100644 --- a/src/common/capwap_protocol.h +++ b/src/common/capwap_protocol.h @@ -1,174 +1,17 @@ #ifndef __CAPWAP_PROTOCOL_HEADER__ #define __CAPWAP_PROTOCOL_HEADER__ +#include "capwap_rfc.h" #include "capwap_element.h" #include "capwap_network.h" #include "capwap_dtls.h" -#define CAPWAP_PROTOCOL_VERSION 0 +#define CAPWAP_RADIOID_NONE 0 -#define CAPWAP_MTU_DEFAULT 1400 -#define CAPWAP_DONT_FRAGMENT 0 +#define CAPWAP_WIRELESS_BINDING_NONE 0 +#define CAPWAP_WIRELESS_BINDING_IEEE80211 1 +#define CAPWAP_WIRELESS_BINDING_EPCGLOBAL 3 -/* Capwap preamble */ -#define CAPWAP_PREAMBLE_HEADER 0 -#define CAPWAP_PREAMBLE_DTLS_HEADER 1 - -struct capwap_preamble { -#ifdef CAPWAP_BIG_ENDIAN - unsigned char version : 4; - unsigned char type : 4; -#else - unsigned char type : 4; - unsigned char version : 4; -#endif -} __attribute__((__packed__)); - -/* Capwap DTLS header */ -struct capwap_dtls_header { - struct capwap_preamble preamble; - unsigned char reserved1; - unsigned char reserved2; - unsigned char reserved3; -} __attribute__((__packed__)); - -/* Capwap header: 8 (header) + 12 (radio mac) + 256 (wireless info) */ -#define CAPWAP_HEADER_MAX_SIZE 276 -struct capwap_header { - struct capwap_preamble preamble; -#ifdef CAPWAP_BIG_ENDIAN - unsigned short hlen : 5; - unsigned short rid : 5; - unsigned short wbid : 5; - unsigned short flag_t : 1; - unsigned char flag_f : 1; - unsigned char flag_l : 1; - unsigned char flag_w : 1; - unsigned char flag_m : 1; - unsigned char flag_k : 1; - unsigned char flag_res : 3; -#else - unsigned short _rid_hi : 3; - unsigned short hlen : 5; - unsigned short flag_t : 1; - unsigned short wbid : 5; - unsigned short _rid_lo : 2; - unsigned char flag_res : 3; - unsigned char flag_k : 1; - unsigned char flag_m : 1; - unsigned char flag_w : 1; - unsigned char flag_l : 1; - unsigned char flag_f : 1; -#endif - unsigned short frag_id; - unsigned short frag_off; /* Only first 13 bit */ -} __attribute__((__packed__)); - -#define FRAGMENT_OFFSET_MASK 0xfff8 - -/* Mac Address */ -struct capwap_mac_address { - unsigned char length; - char address[0]; -} __attribute__((__packed__)); - -/* Wireless Information */ -struct capwap_wireless_information { - unsigned char length; - char data[0]; -} __attribute__((__packed__)); - -/* Control Message Type */ -#define CAPWAP_FIRST_MESSAGE_TYPE 1 -#define CAPWAP_DISCOVERY_REQUEST 1 -#define CAPWAP_DISCOVERY_RESPONSE 2 -#define CAPWAP_JOIN_REQUEST 3 -#define CAPWAP_JOIN_RESPONSE 4 -#define CAPWAP_CONFIGURATION_STATUS_REQUEST 5 -#define CAPWAP_CONFIGURATION_STATUS_RESPONSE 6 -#define CAPWAP_CONFIGURATION_UPDATE_REQUEST 7 -#define CAPWAP_CONFIGURATION_UPDATE_RESPONSE 8 -#define CAPWAP_WTP_EVENT_REQUEST 9 -#define CAPWAP_WTP_EVENT_RESPONSE 10 -#define CAPWAP_CHANGE_STATE_EVENT_REQUEST 11 -#define CAPWAP_CHANGE_STATE_EVENT_RESPONSE 12 -#define CAPWAP_ECHO_REQUEST 13 -#define CAPWAP_ECHO_RESPONSE 14 -#define CAPWAP_IMAGE_DATA_REQUEST 15 -#define CAPWAP_IMAGE_DATA_RESPONSE 16 -#define CAPWAP_RESET_REQUEST 17 -#define CAPWAP_RESET_RESPONSE 18 -#define CAPWAP_PRIMARY_DISCOVERY_REQUEST 19 -#define CAPWAP_PRIMARY_DISCOVERY_RESPONSE 20 -#define CAPWAP_DATA_TRANSFER_REQUEST 21 -#define CAPWAP_DATA_TRANSFER_RESPONSE 22 -#define CAPWAP_CLEAR_CONFIGURATION_REQUEST 23 -#define CAPWAP_CLEAR_CONFIGURATION_RESPONSE 24 -#define CAPWAP_STATION_CONFIGURATION_REQUEST 25 -#define CAPWAP_STATION_CONFIGURATION_RESPONSE 26 -#define CAPWAP_LAST_MESSAGE_TYPE 26 - -/* Control Message */ -struct capwap_control_message { - unsigned long type; - unsigned char seq; - unsigned short length; - unsigned char flags; - char elements[0]; -} __attribute__((__packed__)); - -/* Data Message */ -struct capwap_data_message { - unsigned short length; - char elements[0]; -} __attribute__((__packed__)); - -/* Capwap dtls header helper */ -#define GET_DTLS_BODY(x) (void*)(((char*)(x)) + sizeof(struct capwap_dtls_header)) - -/* Capwap header helper */ -#define GET_VERSION_HEADER(x) ((x)->preamble.version) -#define SET_VERSION_HEADER(x, y) ((x)->preamble.version = (unsigned char)(y)) -#define GET_TYPE_HEADER(x) ((x)->preamble.type) -#define SET_TYPE_HEADER(x, y) ((x)->preamble.type = (unsigned char)(y)) - -#define GET_HLEN_HEADER(x) ((x)->hlen) -#define SET_HLEN_HEADER(x, y) ((x)->hlen = (unsigned short)(y)) -#ifdef CAPWAP_BIG_ENDIAN - #define GET_RID_HEADER(x) ((x)->rid) - #define SET_RID_HEADER(x, y) ((x)->rid = (unsigned short)(y)) -#else - #define GET_RID_HEADER(x) ((unsigned short)((x)->_rid_hi << 2 | (x)->_rid_lo)) - #define SET_RID_HEADER(x, y) ({ (x)->_rid_hi = (unsigned short)((y) >> 2); (x)->_rid_lo = (unsigned short)((y) & 0x0003); }) -#endif -#define GET_WBID_HEADER(x) ((x)->wbid) -#define SET_WBID_HEADER(x, y) ((x)->wbid = (unsigned short)(y)) - -#define IS_FLAG_T_HEADER(x) ((x)->flag_t) -#define SET_FLAG_T_HEADER(x, y) ((x)->flag_t = ((y) ? 1 : 0)) -#define IS_FLAG_F_HEADER(x) ((x)->flag_f) -#define SET_FLAG_F_HEADER(x, y) ((x)->flag_f = ((y) ? 1 : 0)) -#define IS_FLAG_L_HEADER(x) ((x)->flag_l) -#define SET_FLAG_L_HEADER(x, y) ((x)->flag_l = ((y) ? 1 : 0)) -#define IS_FLAG_W_HEADER(x) ((x)->flag_w) -#define SET_FLAG_W_HEADER(x, y) ((x)->flag_w = ((y) ? 1 : 0)) -#define IS_FLAG_M_HEADER(x) ((x)->flag_m) -#define SET_FLAG_M_HEADER(x, y) ((x)->flag_m = ((y) ? 1 : 0)) -#define IS_FLAG_K_HEADER(x) ((x)->flag_k) -#define SET_FLAG_K_HEADER(x, y) ((x)->flag_k = ((y) ? 1 : 0)) - -#define GET_FRAGMENT_ID_HEADER(x) (ntohs((x)->frag_id)) -#define SET_FRAGMENT_ID_HEADER(x, y) ((x)->frag_id = htons((unsigned short)(y))) -#define GET_FRAGMENT_OFFSET_HEADER(x) (ntohs((x)->frag_off) & FRAGMENT_OFFSET_MASK) -#define SET_FRAGMENT_OFFSET_HEADER(x, y) ((x)->frag_off &= ~FRAGMENT_OFFSET_MASK, (x)->frag_off |= htons((unsigned short)(y) & FRAGMENT_OFFSET_MASK)) - -#define GET_RADIO_MAC_ADDRESS_STRUCT(x) ((struct capwap_mac_address*)(((char*)(x)) + sizeof(struct capwap_header))) -#define GET_WIRELESS_INFORMATION_STRUCT(x) ((struct capwap_wireless_information*)(((char*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0))) -#define GET_PAYLOAD_HEADER(x) ((void*)(((char*)(x)) + GET_HLEN_HEADER(x) * 4)) - -#define IS_SEQUENCE_SMALLER(s1, s2) (((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0) - -/*********************************************************************************************************************/ /* Sanity check packet */ #define CAPWAP_WRONG_PACKET -1 #define CAPWAP_NONE_PACKET 0 @@ -176,81 +19,110 @@ struct capwap_data_message { #define CAPWAP_DTLS_PACKET 2 int capwap_sanity_check(int isctrlsocket, int state, void* buffer, int buffersize, int dtlsctrlenable, int dtlsdataenable); -/* Fragment packet */ -struct capwap_fragment_packet { - void* buffer; - int size; +/* Fragment management */ +struct capwap_fragment_packet_item { + unsigned short size; unsigned short offset; + char buffer[0]; }; -/* Fragment control list */ -struct capwap_fragment_sender { - struct sockaddr_storage sendaddr; - unsigned short fragment_id; - int islastrecv; - - /* Packet */ +/* Capwap header function */ +struct capwap_header_data { + char headerbuffer[CAPWAP_HEADER_MAX_SIZE]; +}; + +void capwap_header_init(struct capwap_header_data* data, unsigned short radioid, unsigned short binding); +void capwap_header_set_radio_macaddress(struct capwap_header_data* data, int radiotype, char* macaddress); +void capwap_header_set_wireless_information(struct capwap_header_data* data, void* buffer, unsigned char length); +void capwap_header_set_keepalive_flag(struct capwap_header_data* data, int enable); + +/* Management tx capwap packet */ +struct write_block_from_pos { + struct capwap_list_item* item; + unsigned short pos; +}; + +struct capwap_packet_txmng { + unsigned short mtu; + struct capwap_list* fragmentlist; + + /* Capwap header */ struct capwap_header* header; - struct capwap_list* packetlist; -}; -typedef struct capwap_list capwap_fragment_list; - -/* Packet */ -struct capwap_packet { - unsigned short packetsize; - struct capwap_header* header; - void* payload; - struct sockaddr_storage localaddr; - struct sockaddr_storage remoteaddr; - struct capwap_socket socket; -}; - -#define CAPWAP_WRONG_FRAGMENT -1 -#define CAPWAP_REQUEST_MORE_FRAGMENT 0 -#define CAPWAP_RECEIVE_COMPLETE_PACKET 1 -int capwap_defragment_packets(struct sockaddr_storage* sendaddr, void* buffer, int buffersize, capwap_fragment_list* defraglist, struct capwap_packet* packet); - -capwap_fragment_list* capwap_defragment_init_list(void); -void capwap_defragment_flush_list(capwap_fragment_list* defraglist); -void capwap_defragment_free_list(capwap_fragment_list* defraglist); - -int capwap_defragment_remove_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr); -struct capwap_fragment_sender* capwap_defragment_find_sender(capwap_fragment_list* defraglist, struct sockaddr_storage* sendaddr); - -void capwap_free_packet(struct capwap_packet* packet); - -/* Build tx packet */ -struct capwap_build_packet { + /* Capwap message */ + int isctrlpacket; union { - struct capwap_header header; - char headerbuffer[CAPWAP_HEADER_MAX_SIZE]; + struct capwap_control_message* ctrlmsg; + struct capwap_data_message* datamsg; }; - - /* Control Packet */ - int isctrlmsg; + + /* Write functions */ + struct capwap_write_message_elements_ops write_ops; + unsigned short writerpacketsize; +}; + +/* */ +struct capwap_packet_txmng* capwap_packet_txmng_create_ctrl_message(struct capwap_header_data* data, unsigned long type, unsigned char seq, unsigned short mtu); +struct capwap_packet_txmng* capwap_packet_txmng_create_data_message(struct capwap_header_data* data, unsigned short mtu); +void capwap_packet_txmng_add_message_element(struct capwap_packet_txmng* txmngpacket, unsigned short type, void* data); +void capwap_packet_txmng_get_fragment_packets(struct capwap_packet_txmng* txmngpacket, struct capwap_list* fragmentlist, unsigned short fragmentid); +void capwap_packet_txmng_free(struct capwap_packet_txmng* txmngpacket); + +/* Management rx capwap packet */ +struct read_block_from_pos { + struct capwap_list_item* item; + unsigned short pos; +}; + +struct capwap_packet_rxmng { + struct capwap_list* fragmentlist; + unsigned long packetlength; + + /* Capwap header */ + struct capwap_header* header; + + /* Capwap message */ + int isctrlpacket; union { struct capwap_control_message ctrlmsg; struct capwap_data_message datamsg; }; - - /* Message element */ - struct capwap_list* elementslist; + + /* Position of message elements or binding data */ + struct read_block_from_pos readbodypos; + + /* Read functions */ + struct capwap_read_message_elements_ops read_ops; + struct read_block_from_pos readpos; + unsigned short readerpacketallowed; + + struct capwap_list_item* readerfragmentitem; + unsigned short readerfragmentoffset; }; -#define CAPWAP_RADIOID_NONE 0 -#define CAPWAP_WIRELESS_BINDING_NONE 0 -#define CAPWAP_WIRELESS_BINDING_IEEE80211 1 -#define CAPWAP_WIRELESS_BINDING_EPCGLOBAL 3 +/* */ +#define CAPWAP_WRONG_FRAGMENT -1 +#define CAPWAP_REQUEST_MORE_FRAGMENT 0 +#define CAPWAP_RECEIVE_COMPLETE_PACKET 1 -struct capwap_build_packet* capwap_tx_packet_create(unsigned short radioid, unsigned short binding); -struct capwap_build_packet* capwap_rx_packet_create(void* buffer, int buffersize, int isctrlpacket); -void capwap_build_packet_free(struct capwap_build_packet* buildpacket); -void capwap_build_packet_set_radio_macaddress(struct capwap_build_packet* buildpacket, int radiotype, char* macaddress); -void capwap_build_packet_set_wireless_information(struct capwap_build_packet* buildpacket, void* buffer, unsigned char length); -void capwap_build_packet_set_control_message_type(struct capwap_build_packet* buildpacket, unsigned long type, unsigned char seq); -void capwap_build_packet_add_message_element(struct capwap_build_packet* buildpacket, struct capwap_message_element* element); +struct capwap_packet_rxmng* capwap_packet_rxmng_create_message(int isctrlpacket); +int capwap_packet_rxmng_add_recv_packet(struct capwap_packet_rxmng* rxmngpacket, void* data, int length); +void capwap_packet_rxmng_free(struct capwap_packet_rxmng* rxmngpacket); +/* */ +int capwap_is_request_type(unsigned long type); + +/* Check capwap message type */ +#define VALID_MESSAGE_TYPE 0 +#define INVALID_MESSAGE_TYPE 1 +#define INVALID_REQUEST_MESSAGE_TYPE 2 +int capwap_check_message_type(struct capwap_packet_rxmng* rxmngpacket); + +/* Retransmission function */ +void capwap_get_packet_digest(struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, unsigned char packetdigest[16]); +int capwap_recv_retrasmitted_request(struct capwap_dtls* dtls, struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection, unsigned char packetdigest[16], struct capwap_list* txfragmentpacket); + +/* TODO utile ? #define CAPWAP_VALID_PACKET 0x00000000 #define CAPWAP_MISSING_MANDATORY_MSG_ELEMENT 0x00000001 #define CAPWAP_UNRECOGNIZED_MSG_ELEMENT 0x00000002 @@ -259,20 +131,6 @@ struct unrecognized_info { unsigned short element; unsigned char reason; }; - -typedef struct capwap_array capwap_unrecognized_element_array; -unsigned long capwap_build_packet_validate(struct capwap_build_packet* buildpacket, capwap_unrecognized_element_array* reasonarray); - -typedef struct capwap_array capwap_fragment_packet_array; -int capwap_fragment_build_packet(struct capwap_build_packet* buildpacket, capwap_fragment_packet_array* packets, unsigned short mtu, unsigned short fragmentid); -void capwap_fragment_free(capwap_fragment_packet_array* packets); - -int capwap_is_request_type(unsigned long type); -void capwap_get_packet_digest(void* buffer, unsigned long length, unsigned char packetdigest[16]); -int capwap_recv_retrasmitted_request(struct capwap_dtls* dtls, struct capwap_packet* packet, unsigned char lastseqnumber, unsigned char packetdigest[16], struct capwap_socket* sock, capwap_fragment_packet_array* txfragmentpacket, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr); - -int capwap_check_message_type(struct capwap_dtls* dtls, struct capwap_packet* packet, unsigned short mtu); - -int capwap_get_sessionid_from_keepalive(struct capwap_build_packet* buildpacket, struct capwap_sessionid_element* session); +*/ #endif /* __CAPWAP_PROTOCOL_HEADER__ */ diff --git a/src/common/capwap_rfc.h b/src/common/capwap_rfc.h new file mode 100644 index 0000000..2724b7a --- /dev/null +++ b/src/common/capwap_rfc.h @@ -0,0 +1,180 @@ +#ifndef __CAPWAP_RFC_HEADER__ +#define __CAPWAP_RFC_HEADER__ + +#include + +#ifndef STRUCT_PACKED +#define STRUCT_PACKED __attribute__((__packed__)) +#endif + +#define CAPWAP_PROTOCOL_VERSION 0 + +#define CAPWAP_MTU_DEFAULT 1400 +#define CAPWAP_DONT_FRAGMENT 0 + +/* Capwap preamble */ +#define CAPWAP_PREAMBLE_HEADER 0 +#define CAPWAP_PREAMBLE_DTLS_HEADER 1 + +struct capwap_preamble { +#ifdef CAPWAP_BIG_ENDIAN + uint8_t version : 4; + uint8_t type : 4; +#else + uint8_t type : 4; + uint8_t version : 4; +#endif +} STRUCT_PACKED; + +/* Capwap DTLS header */ +struct capwap_dtls_header { + struct capwap_preamble preamble; + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; +} STRUCT_PACKED; + +/* Capwap header: 8 (header) + 12 (radio mac) + 256 (wireless info) */ +#define CAPWAP_HEADER_MAX_SIZE 276 +struct capwap_header { + struct capwap_preamble preamble; +#ifdef CAPWAP_BIG_ENDIAN + uint16_t hlen : 5; + uint16_t rid : 5; + uint16_t wbid : 5; + uint16_t flag_t : 1; + uint8_t flag_f : 1; + uint8_t flag_l : 1; + uint8_t flag_w : 1; + uint8_t flag_m : 1; + uint8_t flag_k : 1; + uint8_t flag_res : 3; +#else + uint16_t _rid_hi : 3; + uint16_t hlen : 5; + uint16_t flag_t : 1; + uint16_t wbid : 5; + uint16_t _rid_lo : 2; + uint8_t flag_res : 3; + uint8_t flag_k : 1; + uint8_t flag_m : 1; + uint8_t flag_w : 1; + uint8_t flag_l : 1; + uint8_t flag_f : 1; +#endif + uint16_t frag_id; + uint16_t frag_off; /* Only first 13 bit */ +} STRUCT_PACKED; + +#define FRAGMENT_OFFSET_MASK 0xfff8 + +/* Mac Address */ +struct capwap_mac_address { + uint8_t length; + int8_t address[0]; +} STRUCT_PACKED; + +/* Wireless Information */ +struct capwap_wireless_information { + uint8_t length; + int8_t data[0]; +} STRUCT_PACKED; + +/* Message element */ +struct capwap_message_element { + uint16_t type; + uint16_t length; + int8_t data[0]; +} STRUCT_PACKED; + +/* Control Message Type */ +#define CAPWAP_FIRST_MESSAGE_TYPE 1 +#define CAPWAP_DISCOVERY_REQUEST 1 +#define CAPWAP_DISCOVERY_RESPONSE 2 +#define CAPWAP_JOIN_REQUEST 3 +#define CAPWAP_JOIN_RESPONSE 4 +#define CAPWAP_CONFIGURATION_STATUS_REQUEST 5 +#define CAPWAP_CONFIGURATION_STATUS_RESPONSE 6 +#define CAPWAP_CONFIGURATION_UPDATE_REQUEST 7 +#define CAPWAP_CONFIGURATION_UPDATE_RESPONSE 8 +#define CAPWAP_WTP_EVENT_REQUEST 9 +#define CAPWAP_WTP_EVENT_RESPONSE 10 +#define CAPWAP_CHANGE_STATE_EVENT_REQUEST 11 +#define CAPWAP_CHANGE_STATE_EVENT_RESPONSE 12 +#define CAPWAP_ECHO_REQUEST 13 +#define CAPWAP_ECHO_RESPONSE 14 +#define CAPWAP_IMAGE_DATA_REQUEST 15 +#define CAPWAP_IMAGE_DATA_RESPONSE 16 +#define CAPWAP_RESET_REQUEST 17 +#define CAPWAP_RESET_RESPONSE 18 +#define CAPWAP_PRIMARY_DISCOVERY_REQUEST 19 +#define CAPWAP_PRIMARY_DISCOVERY_RESPONSE 20 +#define CAPWAP_DATA_TRANSFER_REQUEST 21 +#define CAPWAP_DATA_TRANSFER_RESPONSE 22 +#define CAPWAP_CLEAR_CONFIGURATION_REQUEST 23 +#define CAPWAP_CLEAR_CONFIGURATION_RESPONSE 24 +#define CAPWAP_STATION_CONFIGURATION_REQUEST 25 +#define CAPWAP_STATION_CONFIGURATION_RESPONSE 26 +#define CAPWAP_LAST_MESSAGE_TYPE 26 + +/* Control Message */ +struct capwap_control_message { + uint32_t type; + uint8_t seq; + uint16_t length; + uint8_t flags; + int8_t elements[0]; +} STRUCT_PACKED; + +/* Data Message */ +struct capwap_data_message { + uint16_t length; + int8_t elements[0]; +} STRUCT_PACKED; + +/* Capwap dtls header helper */ +#define GET_DTLS_BODY(x) (void*)(((int8_t*)(x)) + sizeof(struct capwap_dtls_header)) + +/* Capwap header helper */ +#define GET_VERSION_HEADER(x) ((x)->preamble.version) +#define SET_VERSION_HEADER(x, y) ((x)->preamble.version = (uint8_t)(y)) +#define GET_TYPE_HEADER(x) ((x)->preamble.type) +#define SET_TYPE_HEADER(x, y) ((x)->preamble.type = (uint8_t)(y)) + +#define GET_HLEN_HEADER(x) ((x)->hlen) +#define SET_HLEN_HEADER(x, y) ((x)->hlen = (uint16_t)(y)) +#ifdef CAPWAP_BIG_ENDIAN + #define GET_RID_HEADER(x) ((x)->rid) + #define SET_RID_HEADER(x, y) ((x)->rid = (uint16_t)(y)) +#else + #define GET_RID_HEADER(x) ((uint16_t)((x)->_rid_hi << 2 | (x)->_rid_lo)) + #define SET_RID_HEADER(x, y) ({ (x)->_rid_hi = (uint16_t)((y) >> 2); (x)->_rid_lo = (uint16_t)((y) & 0x0003); }) +#endif +#define GET_WBID_HEADER(x) ((x)->wbid) +#define SET_WBID_HEADER(x, y) ((x)->wbid = (uint16_t)(y)) + +#define IS_FLAG_T_HEADER(x) ((x)->flag_t) +#define SET_FLAG_T_HEADER(x, y) ((x)->flag_t = ((y) ? 1 : 0)) +#define IS_FLAG_F_HEADER(x) ((x)->flag_f) +#define SET_FLAG_F_HEADER(x, y) ((x)->flag_f = ((y) ? 1 : 0)) +#define IS_FLAG_L_HEADER(x) ((x)->flag_l) +#define SET_FLAG_L_HEADER(x, y) ((x)->flag_l = ((y) ? 1 : 0)) +#define IS_FLAG_W_HEADER(x) ((x)->flag_w) +#define SET_FLAG_W_HEADER(x, y) ((x)->flag_w = ((y) ? 1 : 0)) +#define IS_FLAG_M_HEADER(x) ((x)->flag_m) +#define SET_FLAG_M_HEADER(x, y) ((x)->flag_m = ((y) ? 1 : 0)) +#define IS_FLAG_K_HEADER(x) ((x)->flag_k) +#define SET_FLAG_K_HEADER(x, y) ((x)->flag_k = ((y) ? 1 : 0)) + +#define GET_FRAGMENT_ID_HEADER(x) (ntohs((x)->frag_id)) +#define SET_FRAGMENT_ID_HEADER(x, y) ((x)->frag_id = htons((uint16_t)(y))) +#define GET_FRAGMENT_OFFSET_HEADER(x) (ntohs((x)->frag_off) & FRAGMENT_OFFSET_MASK) +#define SET_FRAGMENT_OFFSET_HEADER(x, y) ((x)->frag_off &= ~FRAGMENT_OFFSET_MASK, (x)->frag_off |= htons((uint16_t)(y) & FRAGMENT_OFFSET_MASK)) + +#define GET_RADIO_MAC_ADDRESS_STRUCT(x) ((struct capwap_mac_address*)(((int8_t*)(x)) + sizeof(struct capwap_header))) +#define GET_WIRELESS_INFORMATION_STRUCT(x) ((struct capwap_wireless_information*)(((int8_t*)(x)) + sizeof(struct capwap_header) + (IS_FLAG_M_HEADER(x) ? (((GET_RADIO_MAC_ADDRESS_STRUCT(x)->length + sizeof(struct capwap_mac_address)) + 3) / 4) * 4 : 0))) +#define GET_PAYLOAD_HEADER(x) ((void*)(((int8_t*)(x)) + GET_HLEN_HEADER(x) * 4)) + +#define IS_SEQUENCE_SMALLER(s1, s2) (((((s1) < (s2)) && (((s2) - (s1)) < 128)) || (((s1) > (s2)) && (((s1) - (s2)) > 128))) ? 1 : 0) + +#endif /* __CAPWAP_RFC_HEADER__ */ diff --git a/src/wtp/wtp.c b/src/wtp/wtp.c index 2582109..0bc6d73 100644 --- a/src/wtp/wtp.c +++ b/src/wtp/wtp.c @@ -3,6 +3,7 @@ #include "capwap_protocol.h" #include "capwap_dfa.h" #include "capwap_array.h" +#include "capwap_list.h" #include "capwap_element.h" #include "capwap_dtls.h" #include "wtp_dfa.h" @@ -24,8 +25,8 @@ static int wtp_init(void) { memset(&g_wtp, 0, sizeof(struct wtp_t)); /* Standard name */ - strcpy(g_wtp.name.name, WTP_STANDARD_NAME); - strcpy(g_wtp.location.value, WTP_STANDARD_LOCATION); + strcpy((char*)g_wtp.name.name, WTP_STANDARD_NAME); + strcpy((char*)g_wtp.location.value, WTP_STANDARD_LOCATION); /* State machine */ g_wtp.dfa.state = CAPWAP_START_STATE; @@ -63,8 +64,8 @@ static int wtp_init(void) { /* Tx fragment packets */ g_wtp.mtu = CAPWAP_MTU_DEFAULT; - g_wtp.requestfragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - g_wtp.responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0); + g_wtp.requestfragmentpacket = capwap_list_create(); + g_wtp.responsefragmentpacket = capwap_list_create(); /* AC information */ g_wtp.discoverytype.type = CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_UNKNOWN; @@ -90,10 +91,8 @@ static void wtp_destroy(void) { capwap_array_free(g_wtp.boarddata.boardsubelement); /* Free fragments packet */ - capwap_fragment_free(g_wtp.requestfragmentpacket); - capwap_fragment_free(g_wtp.responsefragmentpacket); - capwap_array_free(g_wtp.requestfragmentpacket); - capwap_array_free(g_wtp.responsefragmentpacket); + capwap_list_free(g_wtp.requestfragmentpacket); + capwap_list_free(g_wtp.responsefragmentpacket); /* Free list AC */ capwap_array_free(g_wtp.acdiscoveryarray); @@ -222,7 +221,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) { return 0; } - strcpy(g_wtp.name.name, configString); + strcpy((char*)g_wtp.name.name, configString); } /* Set location of WTP */ @@ -232,7 +231,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) { return 0; } - strcpy(g_wtp.location.value, configString); + strcpy((char*)g_wtp.location.value, configString); } /* Set binding of WTP */ @@ -328,25 +327,25 @@ static int wtp_parsing_configuration_1_0(config_t* config) { if (!strcmp(configName, "model")) { element->type = CAPWAP_BOARD_SUBELEMENT_MODELNUMBER; element->length = lengthValue; - strcpy(element->data, configValue); + strcpy((char*)element->data, configValue); } else if (!strcmp(configName, "serial")) { element->type = CAPWAP_BOARD_SUBELEMENT_SERIALNUMBER; element->length = lengthValue; - strcpy(element->data, configValue); + strcpy((char*)element->data, configValue); } else if (!strcmp(configName, "id")) { element->type = CAPWAP_BOARD_SUBELEMENT_ID; element->length = lengthValue; - strcpy(element->data, configValue); + strcpy((char*)element->data, configValue); } else if (!strcmp(configName, "revision")) { element->type = CAPWAP_BOARD_SUBELEMENT_REVISION; element->length = lengthValue; - strcpy(element->data, configValue); + strcpy((char*)element->data, configValue); } else if (!strcmp(configName, "macaddress")) { const char* configType; if (config_setting_lookup_string(configElement, "type", &configType) == CONFIG_TRUE) { if (!strcmp(configType, "interface")) { element->type = CAPWAP_BOARD_SUBELEMENT_MACADDRESS; - element->length = capwap_get_macaddress_from_interface(configValue, element->data); + element->length = capwap_get_macaddress_from_interface(configValue, (char*)element->data); if (!element->length) { capwap_logging_error("Invalid configuration file, unable found macaddress of interface: '%s'", configValue); return 0; @@ -567,7 +566,7 @@ static int wtp_parsing_configuration_1_0(config_t* config) { desc->vendor = (unsigned long)configVendor; desc->type = type; desc->length = lengthValue; - strcpy(desc->data, configValue); + strcpy((char*)desc->data, configValue); } else { capwap_logging_error("Invalid configuration file, application.descriptor.info.value string length exceeded"); return 0; @@ -981,7 +980,7 @@ int main(int argc, char** argv) { wtp_dfa_change_state(CAPWAP_IDLE_STATE); /* Running WTP */ - result = wtp_dfa_execute(); + result = wtp_dfa_running(); /* Close socket */ capwap_close_sockets(&g_wtp.net); diff --git a/src/wtp/wtp.h b/src/wtp/wtp.h index 8b35997..53580c0 100644 --- a/src/wtp/wtp.h +++ b/src/wtp/wtp.h @@ -74,37 +74,40 @@ struct wtp_state { /* WTP */ struct wtp_t { int running; - + struct wtp_state dfa; struct capwap_network net; - + struct capwap_wtpname_element name; struct capwap_acname_element acname; struct capwap_location_element location; - + unsigned short binding; - struct capwap_discoverytype_element discoverytype; + struct capwap_discoverytype_element discoverytype; struct capwap_wtpframetunnelmode_element mactunnel; struct capwap_wtpmactype_element mactype; struct capwap_wtpboarddata_element boarddata; struct capwap_wtpdescriptor_element descriptor; - + struct capwap_sessionid_element sessionid; - + struct capwap_ecnsupport_element ecn; struct capwap_transport_element transport; struct capwap_statisticstimer_element statisticstimer; struct capwap_wtprebootstat_element rebootstat; - + + struct capwap_packet_rxmng* rxmngctrlpacket; + struct capwap_packet_rxmng* rxmngdatapacket; + unsigned char localseqnumber; unsigned char remoteseqnumber; unsigned short mtu; unsigned short fragmentid; - capwap_fragment_packet_array* requestfragmentpacket; - capwap_fragment_packet_array* responsefragmentpacket; + struct capwap_list* requestfragmentpacket; + struct capwap_list* responsefragmentpacket; unsigned char lastrecvpackethash[16]; - + /* */ int acdiscoveryrequest; unsigned long acpreferedselected; @@ -118,9 +121,9 @@ struct wtp_t { struct sockaddr_storage acdataaddress; struct capwap_socket acctrlsock; struct capwap_socket acdatasock; - + struct capwap_array* radios; - + /* Dtls */ int enabledtls; unsigned char dtlsdatapolicy; @@ -153,7 +156,9 @@ extern struct wtp_t g_wtp; /* */ int wtp_update_radio_in_use(); -/* build capwap element helper */ -void wtp_create_80211_wtpradioinformation_element(struct capwap_build_packet* buildpacket); +/* Build capwap element helper */ +void wtp_create_radioadmstate_element(struct capwap_packet_txmng* txmngpacket); +void wtp_create_radioopsstate_element(struct capwap_packet_txmng* txmngpacket); +void wtp_create_80211_wtpradioinformation_element(struct capwap_packet_txmng* txmngpacket); #endif /* __CAPWAP_WTP_HEADER__ */ diff --git a/src/wtp/wtp_dfa.c b/src/wtp/wtp_dfa.c index bd33fc1..e217b38 100644 --- a/src/wtp/wtp_dfa.c +++ b/src/wtp/wtp_dfa.c @@ -13,17 +13,333 @@ static void wtp_signal_handler(int signum) { } } +/* */ +static struct capwap_packet_rxmng* wtp_get_packet_rxmng(int isctrlmsg) { + struct capwap_packet_rxmng* rxmngpacket = NULL; + + if (isctrlmsg) { + if (!g_wtp.rxmngctrlpacket) { + g_wtp.rxmngctrlpacket = capwap_packet_rxmng_create_message(1); + } + + rxmngpacket = g_wtp.rxmngctrlpacket; + } else { + if (!g_wtp.rxmngdatapacket) { + g_wtp.rxmngdatapacket = capwap_packet_rxmng_create_message(0); + } + + rxmngpacket = g_wtp.rxmngdatapacket; + } + + return rxmngpacket; +} + +/* */ +static void wtp_free_packet_rxmng(int isctrlmsg) { + if (isctrlmsg && g_wtp.rxmngctrlpacket) { + capwap_packet_rxmng_free(g_wtp.rxmngctrlpacket); + g_wtp.rxmngctrlpacket = NULL; + } else if (!isctrlmsg && g_wtp.rxmngdatapacket) { + capwap_packet_rxmng_free(g_wtp.rxmngdatapacket); + g_wtp.rxmngdatapacket = NULL; + } +} + +/* */ +void wtp_send_invalid_request(struct capwap_packet_rxmng* rxmngpacket, struct capwap_connection* connection) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + struct capwap_list* responsefragmentpacket; + struct capwap_fragment_packet_item* packet; + struct capwap_header* header; + struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST }; + + ASSERT(rxmngpacket != NULL); + ASSERT(rxmngpacket->fragmentlist->first != NULL); + ASSERT(connection != NULL); + + /* */ + packet = (struct capwap_fragment_packet_item*)rxmngpacket->fragmentlist->first->item; + header = (struct capwap_header*)packet->buffer; + + /* Odd message type, response with "Unrecognized Request" */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, GET_WBID_HEADER(header)); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, rxmngpacket->ctrlmsg.type + 1, rxmngpacket->ctrlmsg.seq, g_wtp.mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); + + /* Unknown response complete, get fragment packets */ + responsefragmentpacket = capwap_list_create(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, responsefragmentpacket, g_wtp.fragmentid); + if (responsefragmentpacket->count > 1) { + g_wtp.fragmentid++; + } + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); + + /* Send unknown response */ + capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, connection->socket.socket[connection->socket.type], responsefragmentpacket, &connection->localaddr, &connection->remoteaddr); + + /* Don't buffering a packets sent */ + capwap_list_free(responsefragmentpacket); +} + +/* WTP Execute state */ +static int wtp_dfa_execute(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { + int action = WTP_DFA_NO_PACKET; + + switch (g_wtp.dfa.state) { + case CAPWAP_IDLE_STATE: { + action = 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); + 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); + 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); + break; + } + + case CAPWAP_DEAD_STATE: { + /* Never called with this state */ + ASSERT(0); + break; + } + + default: { + capwap_logging_debug("Unknown action event: %lu", g_wtp.dfa.state); + break; + } + } + + return action; +} + /* WTP state machine */ -int wtp_dfa_execute(void) { +int wtp_dfa_running(void) { + int res; int result = CAPWAP_SUCCESSFUL; int action = WTP_DFA_NO_PACKET; struct timeout_control timeout; - struct capwap_packet packet; - capwap_fragment_list* defraglist; - char buffer[CAPWAP_MAX_PACKET_SIZE]; + char bufferencrypt[CAPWAP_MAX_PACKET_SIZE]; + char bufferplain[CAPWAP_MAX_PACKET_SIZE]; + char* buffer; int buffersize; + struct capwap_socket socket; + struct capwap_connection connection; + struct capwap_parsed_packet packet; + int index; struct sockaddr_storage recvfromaddr; struct sockaddr_storage recvtoaddr; @@ -36,8 +352,7 @@ int wtp_dfa_execute(void) { capwap_init_timeout(&timeout); capwap_set_timeout(0, &timeout, CAPWAP_TIMER_CONTROL_CONNECTION); /* Start DFA with timeout */ - memset(&packet, 0, sizeof(struct capwap_packet)); - defraglist = capwap_defragment_init_list(); + memset(&packet, 0, sizeof(struct capwap_parsed_packet)); /* Configure poll struct */ fdscount = CAPWAP_MAX_SOCKETS * 2; @@ -59,6 +374,7 @@ int wtp_dfa_execute(void) { /* 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) { @@ -71,24 +387,25 @@ int wtp_dfa_execute(void) { continue; } else { int check; - + /* Check of packet */ - capwap_get_network_socket(&g_wtp.net, &packet.socket, fds[index].fd); - check = capwap_sanity_check(packet.socket.isctrlsocket, g_wtp.dfa.state, buffer, buffersize, g_wtp.ctrldtls.enable, g_wtp.datadtls.enable); + capwap_get_network_socket(&g_wtp.net, &socket, fds[index].fd); + 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 = (packet.socket.isctrlsocket ? &g_wtp.ctrldtls : &g_wtp.datadtls); - + struct capwap_dtls* dtls = (socket.isctrlsocket ? &g_wtp.ctrldtls : &g_wtp.datadtls); + if (dtls->enable) { int oldaction = dtls->action; - + /* Decrypt packet */ - buffersize = capwap_decrypt_packet(dtls, buffer, buffersize, NULL, CAPWAP_MAX_PACKET_SIZE); + 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 (packet.socket.isctrlsocket) { + 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); @@ -127,49 +444,88 @@ int wtp_dfa_execute(void) { /* */ if (check == CAPWAP_PLAIN_PACKET) { - /* If request, defragmentation packet */ - check = capwap_defragment_packets(&recvfromaddr, buffer, buffersize, defraglist, &packet); - if (check == CAPWAP_REQUEST_MORE_FRAGMENT) { - continue; - } else if (check != CAPWAP_RECEIVE_COMPLETE_PACKET) { - /* Discard fragments */ - capwap_defragment_remove_sender(defraglist, &recvfromaddr); - continue; - } - + 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)); } } - - /* Receive a complete packet */ - isrecvpacket = 1; - memcpy(&packet.localaddr, &recvtoaddr, sizeof(struct sockaddr_storage)); - memcpy(&packet.remoteaddr, &recvfromaddr, sizeof(struct sockaddr_storage)); + + /* */ + 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 (packet.socket.isctrlsocket) { - if (capwap_recv_retrasmitted_request(&g_wtp.ctrldtls, &packet, g_wtp.remoteseqnumber, g_wtp.lastrecvpackethash, &g_wtp.acctrlsock, g_wtp.responsefragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_free_packet(&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 */ - if (!capwap_check_message_type(&g_wtp.ctrldtls, &packet, g_wtp.mtu)) { - capwap_free_packet(&packet); + res = capwap_check_message_type(rxmngpacket); + if (res != VALID_MESSAGE_TYPE) { + if (res == INVALID_REQUEST_MESSAGE_TYPE) { + wtp_send_invalid_request(rxmngpacket, &connection); + } + + capwap_logging_debug("Invalid message type"); + wtp_free_packet_rxmng(socket.isctrlsocket); continue; } } + + /* Parsing packet */ + if (capwap_parsing_packet(rxmngpacket, &connection, &packet)) { + 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)) { + /* TODO gestione errore risposta */ + 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) { @@ -182,242 +538,12 @@ int wtp_dfa_execute(void) { } /* Execute state */ - switch (g_wtp.dfa.state) { - case CAPWAP_IDLE_STATE: { - action = wtp_dfa_state_idle((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_IDLE_TO_DISCOVERY_STATE: { - action = wtp_dfa_state_idle_to_discovery((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_IDLE_TO_DTLS_SETUP_STATE: { - action = wtp_dfa_state_idle_to_dtlssetup((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DISCOVERY_STATE: { - action = wtp_dfa_state_discovery((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DISCOVERY_TO_SULKING_STATE: { - action = wtp_dfa_state_discovery_to_sulking((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE: { - action = wtp_dfa_state_discovery_to_dtlssetup((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_SULKING_STATE: { - action = wtp_dfa_state_sulking((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_SULKING_TO_IDLE_STATE: { - action = wtp_dfa_state_sulking_to_idle((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DTLS_SETUP_STATE: { - action = wtp_dfa_state_dtlssetup((isrecvpacket ? &packet : NULL), &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((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_dtlsconnect_to_dtlsteardown((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DTLS_CONNECT_TO_JOIN_STATE: { - action = wtp_dfa_state_dtlsconnect_to_join((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_dtlsteardown((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE: { - action = wtp_dfa_state_dtlsteardown_to_idle((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE: { - action = wtp_dfa_state_dtlsteardown_to_sulking((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_JOIN_STATE: { - action = wtp_dfa_state_join((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_join_to_dtlsteardown((isrecvpacket ? &packet : NULL), &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((isrecvpacket ? &packet : NULL), &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((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_CONFIGURE_STATE: { - action = wtp_dfa_state_configure((isrecvpacket ? &packet : NULL), &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((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE: { - action = wtp_dfa_state_configure_to_datacheck((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_RESET_STATE: { - action = wtp_dfa_state_reset((isrecvpacket ? &packet : NULL), &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((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_datacheck_to_dtlsteardown((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_DATA_CHECK_TO_RUN_STATE: { - action = wtp_dfa_state_datacheck_to_run((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_RUN_STATE: { - action = wtp_dfa_state_run((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE: { - action = wtp_dfa_state_run_to_dtlsteardown((isrecvpacket ? &packet : NULL), &timeout); - break; - } - - case CAPWAP_RUN_TO_RESET_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } + action = wtp_dfa_execute((isrecvpacket ? &packet : NULL), &timeout); - case CAPWAP_DEAD_STATE: { - /* Never called with this state */ - ASSERT(0); - break; - } - - default: { - capwap_logging_debug("Unknown action event: %lu", g_wtp.dfa.state); - break; - } - } - /* Free memory */ + capwap_free_parsed_packet(&packet); if (isrecvpacket) { - capwap_free_packet(&packet); - } else { - capwap_defragment_flush_list(defraglist); + wtp_free_packet_rxmng(socket.isctrlsocket); } } @@ -434,8 +560,10 @@ int wtp_dfa_execute(void) { } /* Free memory */ - capwap_defragment_free_list(defraglist); + wtp_free_packet_rxmng(0); + wtp_free_packet_rxmng(1); capwap_free(fds); + return result; } @@ -449,11 +577,11 @@ void wtp_dfa_change_state(int state) { /* */ void wtp_free_reference_last_request(void) { - capwap_fragment_free(g_wtp.requestfragmentpacket); + capwap_list_flush(g_wtp.requestfragmentpacket); } /* */ void wtp_free_reference_last_response(void) { - capwap_fragment_free(g_wtp.responsefragmentpacket); + capwap_list_flush(g_wtp.responsefragmentpacket); memset(&g_wtp.lastrecvpackethash[0], 0, sizeof(g_wtp.lastrecvpackethash)); } diff --git a/src/wtp/wtp_dfa.h b/src/wtp/wtp_dfa.h index 73f5d29..201e78d 100644 --- a/src/wtp/wtp_dfa.h +++ b/src/wtp/wtp_dfa.h @@ -11,11 +11,10 @@ #define WTP_DFA_ACCEPT_PACKET 2 #define WTP_DFA_DROP_PACKET 3 -/* */ +/* */ /* TODO da rifare */ struct wtp_discovery_response { - struct sockaddr_storage acaddr; - struct capwap_build_packet* packet; - struct capwap_element_discovery_response discoveryresponse; + struct capwap_array* controlipv4; + struct capwap_array* controlipv6; }; void wtp_free_discovery_response_array(void); @@ -31,46 +30,46 @@ void wtp_free_reference_last_request(void); void wtp_free_reference_last_response(void); /* State machine */ -int wtp_dfa_execute(void); +int wtp_dfa_running(void); void wtp_dfa_change_state(int state); -int wtp_dfa_state_idle(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_idle_to_discovery(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_idle_to_dtlssetup(struct capwap_packet* packet, struct timeout_control* timeout); +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); -int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_discovery_to_sulking(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_discovery_to_dtlssetup(struct capwap_packet* packet, 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); -int wtp_dfa_state_sulking(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_sulking_to_idle(struct capwap_packet* packet, 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_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsconnect(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsconnect_to_dtlsteardown(struct capwap_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_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsteardown_to_sulking(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_dtlsteardown_to_idle(struct capwap_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_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_join(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_join_to_configure(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_join_to_dtlsteardown(struct capwap_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_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_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_configure_to_datacheck(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_configure_to_dtlsteardown(struct capwap_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_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_datacheck_to_run(struct capwap_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_datacheck_to_dtlsteardown(struct capwap_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_packet* packet, struct timeout_control* timeout); -int wtp_dfa_state_run_to_dtlsteardown(struct capwap_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_packet* packet, struct timeout_control* timeout); +int 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 b8535e8..cea8d73 100644 --- a/src/wtp/wtp_dfa_configure.c +++ b/src/wtp/wtp_dfa_configure.c @@ -6,61 +6,38 @@ #include "wtp_dfa.h" /* */ -static unsigned long wtp_configure_ac(struct capwap_element_configurationstatus_response* configureresponse) { +static unsigned long wtp_configure_ac(struct capwap_parsed_packet* packet) { /* TODO: gestione richiesta */ /* */ - g_wtp.dfa.rfcMaxDiscoveryInterval = configureresponse->timers->discovery; - g_wtp.dfa.rfcEchoInterval = configureresponse->timers->echorequest; + g_wtp.dfa.rfcMaxDiscoveryInterval = packet->messageelements.timers->discovery; + g_wtp.dfa.rfcEchoInterval = packet->messageelements.timers->echorequest; return CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE; } /* */ -int wtp_dfa_state_configure(struct capwap_packet* packet, struct timeout_control* timeout) { +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) { - if (!capwap_compare_ip(&g_wtp.acctrladdress, &packet->remoteaddr)) { - struct capwap_build_packet* buildpacket; + if (!capwap_compare_ip(&g_wtp.acctrladdress, &packet->connection->remoteaddr)) { + 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 packet */ - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - unsigned short binding; - - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if ((binding == g_wtp.binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CONFIGURATION_STATUS_RESPONSE) && ((g_wtp.localseqnumber - 1) == buildpacket->ctrlmsg.seq)) { - struct capwap_element_configurationstatus_response configureresponse; - - /* Valid packet, free request packet */ - wtp_free_reference_last_request(); - - /* Configuration status response info */ - capwap_init_element_configurationstatus_response(&configureresponse, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_configurationstatus_response(&configureresponse, buildpacket->elementslist->first)) { - wtp_dfa_change_state(wtp_configure_ac(&configureresponse)); - status = WTP_DFA_NO_PACKET; - } - - /* Free join response */ - capwap_free_element_configurationstatus_response(&configureresponse, binding); - } - } - - /* Free */ - capwap_build_packet_free(buildpacket); + /* Parsing response values */ + wtp_dfa_change_state(wtp_configure_ac(packet)); + status = WTP_DFA_NO_PACKET; } } } else { - int i; - /* No Configuration status response received */ g_wtp.dfa.rfcRetransmitCount++; if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { @@ -69,17 +46,11 @@ int wtp_dfa_state_configure(struct capwap_packet* packet, struct timeout_control wtp_dfa_change_state(CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE); status = WTP_DFA_NO_PACKET; } else { - /* Retransmit configuration request */ - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send configuration status request packet"); - break; - } + /* 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); } @@ -88,84 +59,44 @@ int wtp_dfa_state_configure(struct capwap_packet* packet, struct timeout_control return status; } -int wtp_dfa_state_configure_to_datacheck(struct capwap_packet* packet, struct timeout_control* timeout) { - unsigned long i; - int result = -1; +int wtp_dfa_state_configure_to_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; int status = WTP_DFA_NO_PACKET; - struct capwap_build_packet* buildpacket; - struct capwap_resultcode_element resultcode; - + struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_SUCCESS }; + ASSERT(timeout != NULL); ASSERT(packet == NULL); - - /* Build packet */ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, g_wtp.binding); - buildpacket->isctrlmsg = 1; - - /* Prepare change state event request */ - capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_CHANGE_STATE_EVENT_REQUEST, g_wtp.localseqnumber++); - - 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); - struct capwap_radiooprstate_element radiooprstate; - - radiooprstate.radioid = (unsigned char)(i + 1); - radiooprstate.state = ((radio->status == WTP_RADIO_ENABLED) ? CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED : CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED); - - if (radiooprstate.state == WTP_RADIO_ENABLED) { - radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_NORMAL; - } else if (radiooprstate.state == WTP_RADIO_DISABLED) { - radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_ADMINSET; - } else if (radiooprstate.state == WTP_RADIO_HWFAILURE) { - radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_RADIOFAILURE; - } else if (radiooprstate.state == WTP_RADIO_SWFAILURE) { - radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_SOFTWAREFAILURE; - } - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT(&radiooprstate)); - } - - resultcode.code = CAPWAP_RESULTCODE_SUCCESS; - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_RESULTCODE_ELEMENT(&resultcode)); + /* 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_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - /* Create change state event request packet */ - if (!capwap_build_packet_validate(buildpacket, NULL)) { - wtp_free_reference_last_request(); - result = capwap_fragment_build_packet(buildpacket, g_wtp.requestfragmentpacket, g_wtp.mtu, g_wtp.fragmentid); - if (result == 1) { - g_wtp.fragmentid++; - } - } else { - capwap_logging_debug("Warning: build invalid change state event request packet"); + /* 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++; } - capwap_build_packet_free(buildpacket); + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); - /* Send change state event request to AC */ - if (result >= 0) { - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send change state event request packet"); - result = -1; - break; - } - } - - if (result == -1) { - /* Error to send packets */ - wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); - } else { - 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; - } + /* 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); + status = WTP_DFA_ACCEPT_PACKET; } else { + /* Error to send packets */ + capwap_logging_debug("Warning: error to send change state event request packet"); + wtp_free_reference_last_request(); wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); } @@ -173,7 +104,7 @@ int wtp_dfa_state_configure_to_datacheck(struct capwap_packet* packet, struct ti } /* */ -int wtp_dfa_state_configure_to_dtlsteardown(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_configure_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(packet == NULL); ASSERT(timeout != NULL); diff --git a/src/wtp/wtp_dfa_datacheck.c b/src/wtp/wtp_dfa_datacheck.c index da6a19f..a232912 100644 --- a/src/wtp/wtp_dfa_datacheck.c +++ b/src/wtp/wtp_dfa_datacheck.c @@ -4,57 +4,48 @@ #include "wtp_dfa.h" /* */ -static unsigned long wtp_datacheck_ac(struct capwap_element_changestateevent_response* changestateresponse) { +static unsigned long wtp_datacheck_ac(struct capwap_parsed_packet* packet) { /* TODO: gestione richiesta */ return CAPWAP_DATA_CHECK_TO_RUN_STATE; } /* */ -int wtp_dfa_state_datacheck(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_datacheck(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { int status = WTP_DFA_ACCEPT_PACKET; - + ASSERT(timeout != NULL); if (packet) { - if (!capwap_compare_ip(&g_wtp.acctrladdress, &packet->remoteaddr)) { - struct capwap_build_packet* buildpacket; + if (!capwap_compare_ip(&g_wtp.acctrladdress, &packet->connection->remoteaddr)) { + unsigned short binding; - /* Parsing packet */ - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - unsigned short binding; - - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if ((binding == g_wtp.binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CHANGE_STATE_EVENT_RESPONSE) && ((g_wtp.localseqnumber - 1) == buildpacket->ctrlmsg.seq)) { - struct capwap_element_changestateevent_response changestateresponse; - - /* Valid packet, free request packet */ - wtp_free_reference_last_request(); - - /* Configuration status response info */ - capwap_init_element_changestateevent_response(&changestateresponse, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_changestateevent_response(&changestateresponse, buildpacket->elementslist->first)) { - wtp_dfa_change_state(wtp_datacheck_ac(&changestateresponse)); - status = WTP_DFA_NO_PACKET; + /* */ + 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++; + } } - - /* Free join response */ - capwap_free_element_changestateevent_response(&changestateresponse, binding); } } + } - /* Free */ - capwap_build_packet_free(buildpacket); + 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; } } } else { - int i; - /* No change state response received */ g_wtp.dfa.rfcRetransmitCount++; if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { @@ -64,16 +55,10 @@ int wtp_dfa_state_datacheck(struct capwap_packet* packet, struct timeout_control status = WTP_DFA_NO_PACKET; } else { /* Retransmit change state request */ - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send change state request packet"); - break; - } + 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"); } - + /* Update timeout */ capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } @@ -83,12 +68,12 @@ int wtp_dfa_state_datacheck(struct capwap_packet* packet, struct timeout_control } /* */ -int wtp_dfa_state_datacheck_to_run(struct capwap_packet* packet, struct timeout_control* timeout) { - int result; +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; - struct capwap_build_packet* buildpacket; - capwap_fragment_packet_array* txfragpacket; - + ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -112,52 +97,47 @@ int wtp_dfa_state_datacheck_to_run(struct capwap_packet* packet, struct timeout_ return WTP_DFA_NO_PACKET; } } - + /* Build packet */ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, CAPWAP_WIRELESS_BINDING_NONE); - buildpacket->isctrlmsg = 0; - - /* */ - SET_FLAG_K_HEADER(&buildpacket->header, 1); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_SESSIONID_ELEMENT(&g_wtp.sessionid)); + 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 */ - txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0); - if (!result) { - struct capwap_packet* txpacket; - - ASSERT(txfragpacket->count == 1); - - txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress)) { + /* 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"); - result = -1; + wtp_dfa_change_state(CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE); + status = WTP_DFA_NO_PACKET; } - } - - capwap_fragment_free(txfragpacket); - capwap_array_free(txfragpacket); - capwap_build_packet_free(buildpacket); - - /* Send Configuration Status request to AC */ - if (!result) { - 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 { + 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_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_datacheck_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(packet == NULL); ASSERT(timeout != NULL); diff --git a/src/wtp/wtp_dfa_discovery.c b/src/wtp/wtp_dfa_discovery.c index 6b8a407..73a2c84 100644 --- a/src/wtp/wtp_dfa_discovery.c +++ b/src/wtp/wtp_dfa_discovery.c @@ -8,50 +8,49 @@ /* */ void wtp_free_discovery_response_array(void) { int i; - + /* Free items */ 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); - - capwap_free_element_discovery_response(&response->discoveryresponse, GET_WBID_HEADER(&response->packet->header)); - capwap_build_packet_free(response->packet); + capwap_array_free(response->controlipv4); + capwap_array_free(response->controlipv6); } - + /* Remove all items */ capwap_array_resize(g_wtp.acdiscoveryresponse, 0); } /* */ -int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { int status = WTP_DFA_ACCEPT_PACKET; ASSERT(timeout != NULL); if (packet) { - struct capwap_build_packet* buildpacket; - - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (capwap_build_packet_validate(buildpacket, NULL)) { - capwap_build_packet_free(buildpacket); /* Invalid packet */ - } else { - unsigned short binding; - - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if ((binding != g_wtp.binding) || (ntohl(buildpacket->ctrlmsg.type) != CAPWAP_DISCOVERY_RESPONSE) || ((g_wtp.localseqnumber - 1) != buildpacket->ctrlmsg.seq)) { - capwap_build_packet_free(buildpacket); /* Invalid packet */ - } else { - struct wtp_discovery_response* response = (struct wtp_discovery_response*)capwap_array_get_item_pointer(g_wtp.acdiscoveryresponse, g_wtp.acdiscoveryresponse->count); + unsigned short binding; - /* Discovery response info */ - memcpy(&response->acaddr, &packet->remoteaddr, sizeof(struct sockaddr_storage)); - response->packet = buildpacket; - capwap_init_element_discovery_response(&response->discoveryresponse, binding); + /* */ + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + if (packet->rxmngpacket->isctrlpacket && (binding == g_wtp.binding) && (packet->rxmngpacket->ctrlmsg.type == CAPWAP_DISCOVERY_RESPONSE) && ((g_wtp.localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { + int i; + struct wtp_discovery_response* response = (struct wtp_discovery_response*)capwap_array_get_item_pointer(g_wtp.acdiscoveryresponse, g_wtp.acdiscoveryresponse->count); - /* Parsing elements list */ - capwap_parsing_element_discovery_response(&response->discoveryresponse, buildpacket->elementslist->first); - } + /* Create controlipv4 */ + response->controlipv4 = capwap_array_create(sizeof(struct capwap_controlipv4_element), 0); + for (i = 0; i < packet->messageelements.controlipv4->count; i++) { + struct capwap_controlipv4_element* src = *(struct capwap_controlipv4_element**)capwap_array_get_item_pointer(packet->messageelements.controlipv4, i); + struct capwap_controlipv4_element* dst = (struct capwap_controlipv4_element*)capwap_array_get_item_pointer(response->controlipv4, i); + + memcpy(dst, src, sizeof(struct capwap_controlipv4_element)); + } + + /* Create controlipv4 */ + response->controlipv6 = capwap_array_create(sizeof(struct capwap_controlipv6_element), 0); + for (i = 0; i < packet->messageelements.controlipv6->count; i++) { + struct capwap_controlipv6_element* src = *(struct capwap_controlipv6_element**)capwap_array_get_item_pointer(packet->messageelements.controlipv6, i); + struct capwap_controlipv6_element* dst = (struct capwap_controlipv6_element*)capwap_array_get_item_pointer(response->controlipv6, i); + + memcpy(dst, src, sizeof(struct capwap_controlipv6_element)); } } } else if (g_wtp.acdiscoveryresponse->count > 0) { @@ -72,19 +71,19 @@ int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control /* AC with IPv4 */ if ((g_wtp.net.sock_family == AF_UNSPEC) || (g_wtp.net.sock_family == AF_INET)) { - for (w = 0; w < response->discoveryresponse.controlipv4->count; w++) { - struct capwap_controlipv4_element* controlipv4 = *(struct capwap_controlipv4_element**)capwap_array_get_item_pointer(response->discoveryresponse.controlipv4, w); - + 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 */ 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)); @@ -93,7 +92,7 @@ int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control break; } } - + /* Check by number of WTP */ if (indexpreferred == -1) { if ((countwtp == -1) || (countwtp > controlipv4->wtpcount)) { @@ -108,19 +107,19 @@ int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control /* AC with IPv6 */ if ((g_wtp.net.sock_family == AF_UNSPEC) || (g_wtp.net.sock_family == AF_INET6)) { - for (w = 0; w < response->discoveryresponse.controlipv6->count; w++) { - struct capwap_controlipv6_element* controlipv6 = *(struct capwap_controlipv6_element**)capwap_array_get_item_pointer(response->discoveryresponse.controlipv6, w); - + 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 */ 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)); @@ -129,7 +128,7 @@ int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control break; } } - + /* Check by number of WTP */ if (indexpreferred == -1) { if ((countwtp == -1) || (countwtp > controlipv6->wtpcount)) { @@ -145,19 +144,16 @@ int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control /* 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 { - int result; - struct capwap_build_packet* buildpacket; - /* No Discovery response received */ g_wtp.dfa.rfcDiscoveryCount++; if (g_wtp.dfa.rfcDiscoveryCount >= g_wtp.dfa.rfcMaxDiscoveries) { @@ -165,73 +161,58 @@ int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control wtp_dfa_change_state(CAPWAP_DISCOVERY_TO_SULKING_STATE); status = WTP_DFA_NO_PACKET; } else { + int i; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + /* Update status radio */ g_wtp.descriptor.radiosinuse = wtp_update_radio_in_use(); /* Build packet */ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, g_wtp.binding); - buildpacket->isctrlmsg = 1; + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_DISCOVERY_REQUEST, g_wtp.localseqnumber++, g_wtp.mtu); - /* Prepare discovery request */ - capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_DISCOVERY_REQUEST, g_wtp.localseqnumber++); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_DISCOVERYTYPE_ELEMENT(&g_wtp.discoverytype)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPBOARDDATA_ELEMENT(&g_wtp.boarddata)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPDESCRIPTOR_ELEMENT(&g_wtp.descriptor)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPFRAMETUNNELMODE_ELEMENT(&g_wtp.mactunnel)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPMACTYPE_ELEMENT(&g_wtp.mactype)); + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_DISCOVERYTYPE, &g_wtp.discoverytype); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPBOARDDATA, &g_wtp.boarddata); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPDESCRIPTOR, &g_wtp.descriptor); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE, &g_wtp.mactunnel); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPMACTYPE, &g_wtp.mactype); if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - wtp_create_80211_wtpradioinformation_element(buildpacket); - } else { - capwap_logging_debug("Unknown capwap binding"); + wtp_create_80211_wtpradioinformation_element(txmngpacket); } /* CAPWAP_CREATE_MTUDISCOVERYPADDING_ELEMENT */ /* TODO */ /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - /* Create discovery request packet */ - if (!capwap_build_packet_validate(buildpacket, NULL)) { - wtp_free_reference_last_request(); - result = capwap_fragment_build_packet(buildpacket, g_wtp.requestfragmentpacket, g_wtp.mtu, g_wtp.fragmentid); - if (result == 1) { - g_wtp.fragmentid++; - } - } else { - result = -1; - capwap_logging_debug("Warning: build invalid discovery request packet"); + /* Discovery 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++; } - - capwap_build_packet_free(buildpacket); + + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); /* Send discovery request to AC */ - if (result >= 0) { - int i; - - /* Send broadcast packet to all socket */ - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - int j; - struct capwap_packet* packet = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - - ASSERT(packet != NULL); - - for (j = 0; j < g_wtp.acdiscoveryarray->count; j++) { - int sock; - struct sockaddr_storage* sendtoaddr = (struct sockaddr_storage*)capwap_array_get_item_pointer(g_wtp.acdiscoveryarray, j); - - sock = capwap_get_socket(&g_wtp.net, sendtoaddr->ss_family, IPPROTO_UDP, 1); - if (sock >= 0) { - if (!capwap_sendto(sock, packet->header, packet->packetsize, NULL, sendtoaddr)) { - capwap_logging_debug("Warning: error to send discovery request packet"); - break; - } - } + for (i = 0; i < g_wtp.acdiscoveryarray->count; i++) { + int sock; + struct sockaddr_storage* sendtoaddr = (struct sockaddr_storage*)capwap_array_get_item_pointer(g_wtp.acdiscoveryarray, i); + + sock = capwap_get_socket(&g_wtp.net, sendtoaddr->ss_family, IPPROTO_UDP, 1); + if (sock >= 0) { + if (!capwap_sendto_fragmentpacket(sock, g_wtp.requestfragmentpacket, NULL, sendtoaddr)) { + capwap_logging_debug("Warning: error to send discovery request packet"); + break; } } - - /* Don't buffering a packets sent */ - wtp_free_reference_last_request(); } - + + /* Don't buffering a packets sent */ + wtp_free_reference_last_request(); + /* Wait before send another Discovery Request */ capwap_set_timeout(g_wtp.dfa.rfcDiscoveryInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } @@ -241,7 +222,7 @@ int wtp_dfa_state_discovery(struct capwap_packet* packet, struct timeout_control } /* */ -int wtp_dfa_state_discovery_to_sulking(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_discovery_to_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -252,7 +233,7 @@ int wtp_dfa_state_discovery_to_sulking(struct capwap_packet* packet, struct time } /* */ -int wtp_dfa_state_discovery_to_dtlssetup(struct capwap_packet* packet, struct timeout_control* timeout) { +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); diff --git a/src/wtp/wtp_dfa_dtls.c b/src/wtp/wtp_dfa_dtls.c index ebc1545..408f97d 100644 --- a/src/wtp/wtp_dfa_dtls.c +++ b/src/wtp/wtp_dfa_dtls.c @@ -12,7 +12,7 @@ int wtp_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param } /* */ -int wtp_dfa_state_dtlssetup(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_dtlssetup(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { int status = WTP_DFA_ACCEPT_PACKET; ASSERT(timeout != NULL); @@ -36,7 +36,7 @@ int wtp_dfa_state_dtlssetup(struct capwap_packet* packet, struct timeout_control } /* */ -int wtp_dfa_state_dtlsconnect(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_dtlsconnect(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -45,7 +45,7 @@ int wtp_dfa_state_dtlsconnect(struct capwap_packet* packet, struct timeout_contr } /* */ -int wtp_dfa_state_dtlsconnect_to_dtlsteardown(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_dtlsconnect_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(packet == NULL); ASSERT(timeout != NULL); @@ -74,7 +74,7 @@ int wtp_teardown_connection(struct timeout_control* timeout) { } /* */ -int wtp_dfa_state_dtlsteardown(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -103,7 +103,7 @@ int wtp_dfa_state_dtlsteardown(struct capwap_packet* packet, struct timeout_cont } /* */ -int wtp_dfa_state_dtlsteardown_to_sulking(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_dtlsteardown_to_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -114,7 +114,7 @@ int wtp_dfa_state_dtlsteardown_to_sulking(struct capwap_packet* packet, struct t } /* */ -int wtp_dfa_state_dtlsteardown_to_idle(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_dtlsteardown_to_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); diff --git a/src/wtp/wtp_dfa_idle.c b/src/wtp/wtp_dfa_idle.c index cc35a4e..76cbec0 100644 --- a/src/wtp/wtp_dfa_idle.c +++ b/src/wtp/wtp_dfa_idle.c @@ -3,7 +3,7 @@ #include "wtp_dfa.h" /* */ -int wtp_dfa_state_idle(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -32,7 +32,7 @@ int wtp_dfa_state_idle(struct capwap_packet* packet, struct timeout_control* tim } /* Prepare to discovery AC */ -int wtp_dfa_state_idle_to_discovery(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_idle_to_discovery(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -50,7 +50,7 @@ int wtp_dfa_state_idle_to_discovery(struct capwap_packet* packet, struct timeout } /* Prepare to connect with AC */ -int wtp_dfa_state_idle_to_dtlssetup(struct capwap_packet* packet, struct timeout_control* timeout) { +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); diff --git a/src/wtp/wtp_dfa_imagedata.c b/src/wtp/wtp_dfa_imagedata.c index ccc7237..3d18ae3 100644 --- a/src/wtp/wtp_dfa_imagedata.c +++ b/src/wtp/wtp_dfa_imagedata.c @@ -3,7 +3,7 @@ #include "wtp_dfa.h" /* */ -int wtp_dfa_state_imagedata_to_dtlsteardown(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_imagedata_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(packet == NULL); ASSERT(timeout != NULL); diff --git a/src/wtp/wtp_dfa_join.c b/src/wtp/wtp_dfa_join.c index 5c91246..5b37bd6 100644 --- a/src/wtp/wtp_dfa_join.c +++ b/src/wtp/wtp_dfa_join.c @@ -6,31 +6,30 @@ #include "wtp_dfa.h" /* */ -static unsigned long wtp_join_ac(struct capwap_element_join_response* joinresponse) { +static unsigned long wtp_join_ac(struct capwap_parsed_packet* packet) { /* TODO: gestione richiesta CAPWAP_JOIN_TO_IMAGE_DATA_STATE <-> CAPWAP_JOIN_TO_CONFIGURE_STATE */ /* Check DTLS data policy */ - if (!(g_wtp.validdtlsdatapolicy & joinresponse->acdescriptor->dtlspolicy)) { + if (!(g_wtp.validdtlsdatapolicy & packet->messageelements.acdescriptor->dtlspolicy)) { return CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE; } /* AC name associated */ - strcpy(g_wtp.acname.name, joinresponse->acname->name); + strcpy((char*)g_wtp.acname.name, (char*)packet->messageelements.acname->name); /* DTLS data policy */ - g_wtp.dtlsdatapolicy = joinresponse->acdescriptor->dtlspolicy & g_wtp.validdtlsdatapolicy; + g_wtp.dtlsdatapolicy = packet->messageelements.acdescriptor->dtlspolicy & g_wtp.validdtlsdatapolicy; return CAPWAP_JOIN_TO_CONFIGURE_STATE; } /* */ -int wtp_dfa_state_dtlsconnect_to_join(struct capwap_packet* packet, struct timeout_control* timeout) { - int i; - int result = -1; +int wtp_dfa_state_dtlsconnect_to_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; int status = WTP_DFA_NO_PACKET; - struct capwap_build_packet* buildpacket; #ifdef DEBUG char sessionname[33]; @@ -54,81 +53,61 @@ int wtp_dfa_state_dtlsconnect_to_join(struct capwap_packet* packet, struct timeo #endif /* Build packet */ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, g_wtp.binding); - buildpacket->isctrlmsg = 1; - - /* Prepare join request */ - capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_JOIN_REQUEST, g_wtp.localseqnumber++); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_LOCATION_ELEMENT(&g_wtp.location)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPBOARDDATA_ELEMENT(&g_wtp.boarddata)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPDESCRIPTOR_ELEMENT(&g_wtp.descriptor)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPNAME_ELEMENT(&g_wtp.name)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_SESSIONID_ELEMENT(&g_wtp.sessionid)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPFRAMETUNNELMODE_ELEMENT(&g_wtp.mactunnel)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPMACTYPE_ELEMENT(&g_wtp.mactype)); + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_JOIN_REQUEST, g_wtp.localseqnumber++, g_wtp.mtu); + + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCATION, &g_wtp.location); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPBOARDDATA, &g_wtp.boarddata); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPDESCRIPTOR, &g_wtp.descriptor); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPNAME, &g_wtp.name); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_SESSIONID, &g_wtp.sessionid); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPFRAMETUNNELMODE, &g_wtp.mactunnel); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_WTPMACTYPE, &g_wtp.mactype); if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - wtp_create_80211_wtpradioinformation_element(buildpacket); - } else { - capwap_logging_debug("Unknown capwap binding"); + wtp_create_80211_wtpradioinformation_element(txmngpacket); } - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_ECNSUPPORT_ELEMENT(&g_wtp.ecn)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_ECNSUPPORT, &g_wtp.ecn); if (g_wtp.wtpctrladdress.ss_family == AF_INET) { struct capwap_localipv4_element addr; - + memcpy(&addr.address, &((struct sockaddr_in*)&g_wtp.wtpctrladdress)->sin_addr, sizeof(struct in_addr)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_LOCALIPV4_ELEMENT(&addr)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV4, &addr); } else if (g_wtp.wtpctrladdress.ss_family == AF_INET6) { struct capwap_localipv6_element addr; - + memcpy(&addr.address, &((struct sockaddr_in6*)&g_wtp.wtpctrladdress)->sin6_addr, sizeof(struct in6_addr)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_LOCALIPV6_ELEMENT(&addr)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_LOCALIPV6, &addr); } - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_TRANSPORT_ELEMENT(&g_wtp.transport)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &g_wtp.transport); /* CAPWAP_CREATE_MAXIMUMMESSAGELENGTH_ELEMENT */ /* TODO */ /* CAPWAP_CREATE_WTPREBOOTSTATISTICS_ELEMENT */ /* TODO */ /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - /* Create join request packet */ - if (!capwap_build_packet_validate(buildpacket, NULL)) { - wtp_free_reference_last_request(); - result = capwap_fragment_build_packet(buildpacket, g_wtp.requestfragmentpacket, g_wtp.mtu, g_wtp.fragmentid); - if (result == 1) { - g_wtp.fragmentid++; - } - } else { - capwap_logging_debug("Warning: build invalid join request packet"); + /* Join 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++; } - capwap_build_packet_free(buildpacket); + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); /* Send join request to AC */ - if (result >= 0) { - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send join request packet"); - result = -1; - break; - } - } - - if (result == -1) { - /* Error to send packets */ - wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE); - } else { - 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; - } + 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_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); } @@ -136,50 +115,27 @@ int wtp_dfa_state_dtlsconnect_to_join(struct capwap_packet* packet, struct timeo } /* */ -int wtp_dfa_state_join(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_join(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { int status = WTP_DFA_ACCEPT_PACKET; ASSERT(timeout != NULL); if (packet) { - if (!capwap_compare_ip(&g_wtp.acctrladdress, &packet->remoteaddr)) { - struct capwap_build_packet* buildpacket; + if (!capwap_compare_ip(&g_wtp.acctrladdress, &packet->connection->remoteaddr)) { + unsigned short binding; - /* Parsing packet */ - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - unsigned short binding; - - /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if ((binding == g_wtp.binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_JOIN_RESPONSE) && ((g_wtp.localseqnumber - 1) == buildpacket->ctrlmsg.seq)) { - struct capwap_element_join_response joinresponse; - - /* Valid packet, free request packet */ - wtp_free_reference_last_request(); - - /* Join response info */ - capwap_init_element_join_response(&joinresponse, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_join_response(&joinresponse, buildpacket->elementslist->first)) { - wtp_dfa_change_state(wtp_join_ac(&joinresponse)); - status = WTP_DFA_NO_PACKET; - } - - /* Free join response */ - capwap_free_element_join_response(&joinresponse, 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(); - /* Free */ - capwap_build_packet_free(buildpacket); + /* Parsing response values */ + wtp_dfa_change_state(wtp_join_ac(packet)); + status = WTP_DFA_NO_PACKET; } } } else { - int i; - /* No Join response received */ g_wtp.dfa.rfcRetransmitCount++; if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { @@ -188,17 +144,11 @@ int wtp_dfa_state_join(struct capwap_packet* packet, struct timeout_control* tim wtp_dfa_change_state(CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE); status = WTP_DFA_NO_PACKET; } else { - /* Retransmit join request */ - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send join request packet"); - break; - } + /* 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)) { + capwap_logging_debug("Warning: error to send join request packet"); } - + /* Update timeout */ capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } @@ -208,83 +158,53 @@ int wtp_dfa_state_join(struct capwap_packet* packet, struct timeout_control* tim } /* */ -int wtp_dfa_state_join_to_configure(struct capwap_packet* packet, struct timeout_control* timeout) { - unsigned long i; - int result = -1; +int wtp_dfa_state_join_to_configure(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; int status = WTP_DFA_NO_PACKET; - struct capwap_build_packet* buildpacket; - + ASSERT(timeout != NULL); ASSERT(packet == NULL); - + /* Build packet */ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, g_wtp.binding); - buildpacket->isctrlmsg = 1; - - /* Prepare Configuration Status request */ - capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_CONFIGURATION_STATUS_REQUEST, g_wtp.localseqnumber++); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_wtp.acname)); - - 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); - struct capwap_radioadmstate_element radioadmstate; - - radioadmstate.radioid = (unsigned char)(i + 1); - radioadmstate.state = ((radio->status == WTP_RADIO_DISABLED) ? CAPWAP_RADIO_ADMIN_STATE_DISABLED : CAPWAP_RADIO_ADMIN_STATE_ENABLED); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_RADIOADMSTATE_ELEMENT(&radioadmstate)); - } - - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_STATISTICSTIMER_ELEMENT(&g_wtp.statisticstimer)); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_WTPREBOOTSTAT_ELEMENT(&g_wtp.rebootstat)); - + 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_CREATE_ACNAMEPRIORITY_ELEMENT */ /* TODO */ - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_TRANSPORT_ELEMENT(&g_wtp.transport)); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_TRANSPORT, &g_wtp.transport); /* CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT */ /* TODO */ - /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ if (g_wtp.binding == CAPWAP_WIRELESS_BINDING_IEEE80211) { - wtp_create_80211_wtpradioinformation_element(buildpacket); - } else { - capwap_logging_debug("Unknown capwap binding"); + wtp_create_80211_wtpradioinformation_element(txmngpacket); } - /* Create Configuration Status request packet */ - if (!capwap_build_packet_validate(buildpacket, NULL)) { - wtp_free_reference_last_request(); - result = capwap_fragment_build_packet(buildpacket, g_wtp.requestfragmentpacket, g_wtp.mtu, g_wtp.fragmentid); - if (result == 1) { - g_wtp.fragmentid++; - } - } else { - capwap_logging_debug("Warning: build invalid configuretion status request packet"); + /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* 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++; } - capwap_build_packet_free(buildpacket); + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); /* Send Configuration Status request to AC */ - if (result >= 0) { - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send configuration status request packet"); - result = -1; - break; - } - } - - if (result == -1) { - /* Error to send packets */ - wtp_free_reference_last_request(); - wtp_dfa_change_state(CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE); - } else { - 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; - } + 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); } @@ -292,7 +212,7 @@ int wtp_dfa_state_join_to_configure(struct capwap_packet* packet, struct timeout } /* */ -int wtp_dfa_state_join_to_dtlsteardown(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_join_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(packet == NULL); ASSERT(timeout != NULL); diff --git a/src/wtp/wtp_dfa_reset.c b/src/wtp/wtp_dfa_reset.c index 0da283b..3a7eff5 100644 --- a/src/wtp/wtp_dfa_reset.c +++ b/src/wtp/wtp_dfa_reset.c @@ -3,7 +3,7 @@ #include "wtp_dfa.h" /* */ -int wtp_dfa_state_reset(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_reset(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(packet == NULL); ASSERT(timeout != NULL); diff --git a/src/wtp/wtp_dfa_run.c b/src/wtp/wtp_dfa_run.c index 567bbdf..162df19 100644 --- a/src/wtp/wtp_dfa_run.c +++ b/src/wtp/wtp_dfa_run.c @@ -5,237 +5,165 @@ /* */ static int send_echo_request() { - int i; int result = -1; - struct capwap_build_packet* buildpacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; /* Build packet */ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, g_wtp.binding); - buildpacket->isctrlmsg = 1; - - /* Prepare echo request */ - capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_ECHO_REQUEST, g_wtp.localseqnumber++); + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_ECHO_REQUEST, g_wtp.localseqnumber++, g_wtp.mtu); + + /* Add message element */ /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - /* Create echo request packet */ - if (!capwap_build_packet_validate(buildpacket, NULL)) { - wtp_free_reference_last_request(); - result = capwap_fragment_build_packet(buildpacket, g_wtp.requestfragmentpacket, g_wtp.mtu, g_wtp.fragmentid); - if (result == 1) { - g_wtp.fragmentid++; - } - } else { - capwap_logging_debug("Warning: build invalid echo request packet"); + /* Echo 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++; } - capwap_build_packet_free(buildpacket); + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); /* Send echo request to AC */ - if (result >= 0) { - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send echo request packet"); - result = -1; - break; - } - } - - if (result == -1) { - wtp_free_reference_last_request(); /* Error to send packets */ - } + 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)) { + result = 0; + } else { + /* Error to send packets */ + capwap_logging_debug("Warning: error to send echo request packet"); + wtp_free_reference_last_request(); } - + return result; } /* */ -static int receive_echo_response(struct capwap_build_packet* buildpacket) { - unsigned short binding; - struct capwap_element_echo_response echoresponse; - - ASSERT(buildpacket != NULL); +static int receive_echo_response(struct capwap_parsed_packet* packet) { + ASSERT(packet != NULL); /* Valid packet, free request packet */ wtp_free_reference_last_request(); - - /* Echo response info */ - binding = GET_WBID_HEADER(&buildpacket->header); - capwap_init_element_echo_response(&echoresponse, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_echo_response(&echoresponse, buildpacket->elementslist->first)) { - /* TODO */ - } - - /* Free join response */ - capwap_free_element_echo_response(&echoresponse, binding); return 0; } /* */ -static void receive_reset_request(struct capwap_build_packet* buildpacket, struct capwap_packet* packet) { - unsigned long i; +static void receive_reset_request(struct capwap_parsed_packet* packet) { unsigned short binding; - ASSERT(buildpacket != NULL); + ASSERT(packet != NULL); /* */ - binding = GET_WBID_HEADER(&buildpacket->header); - if ((binding == g_wtp.binding) && IS_SEQUENCE_SMALLER(g_wtp.remoteseqnumber, buildpacket->ctrlmsg.seq)) { - struct capwap_element_reset_request resetrequest; - - /* Reset request info*/ - capwap_init_element_reset_request(&resetrequest, binding); - - /* Parsing elements list */ - if (capwap_parsing_element_reset_request(&resetrequest, buildpacket->elementslist->first)) { - struct capwap_build_packet* responsepacket; - struct capwap_resultcode_element resultcode = { CAPWAP_RESULTCODE_SUCCESS }; + binding = GET_WBID_HEADER(packet->rxmngpacket->header); + if ((binding == g_wtp.binding) && IS_SEQUENCE_SMALLER(g_wtp.remoteseqnumber, packet->rxmngpacket->ctrlmsg.seq)) { + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; + struct capwap_resultcode_element resultcode = { .code = CAPWAP_RESULTCODE_SUCCESS }; - /* Create response */ - responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding); - responsepacket->isctrlmsg = 1; + /* Build packet */ + capwap_header_init(&capwapheader, CAPWAP_RADIOID_NONE, g_wtp.binding); + txmngpacket = capwap_packet_txmng_create_ctrl_message(&capwapheader, CAPWAP_RESET_RESPONSE, packet->rxmngpacket->ctrlmsg.seq, g_wtp.mtu); - /* Prepare echo response */ - capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_RESET_RESPONSE, buildpacket->ctrlmsg.seq); - capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RESULTCODE_ELEMENT(&resultcode)); - /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ + /* Add message element */ + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RESULTCODE, &resultcode); + /* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */ /* TODO */ - if (!capwap_build_packet_validate(responsepacket, NULL)) { - int result; + /* Reset response complete, get fragment packets */ + wtp_free_reference_last_response(); + capwap_packet_txmng_get_fragment_packets(txmngpacket, g_wtp.responsefragmentpacket, g_wtp.fragmentid); + if (g_wtp.responsefragmentpacket->count > 1) { + g_wtp.fragmentid++; + } - wtp_free_reference_last_response(); + /* Free packets manager */ + capwap_packet_txmng_free(txmngpacket); - /* Send reset response to AC */ - result = capwap_fragment_build_packet(responsepacket, g_wtp.responsefragmentpacket, g_wtp.mtu, g_wtp.fragmentid); - if (result >= 0) { - if (result == 1) { - g_wtp.fragmentid++; - } + /* Save remote sequence number */ + g_wtp.remoteseqnumber = packet->rxmngpacket->ctrlmsg.seq; + capwap_get_packet_digest(packet->rxmngpacket, packet->connection, g_wtp.lastrecvpackethash); - /* Save remote sequence number */ - g_wtp.remoteseqnumber = buildpacket->ctrlmsg.seq; - capwap_get_packet_digest((void*)packet->header, packet->packetsize, g_wtp.lastrecvpackethash); - - /* Send */ - for (i = 0; i < g_wtp.responsefragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.responsefragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - /* Response is already created and saved. When receive a re-request, DFA autoresponse */ - capwap_logging_debug("Warning: error to send reset response packet"); - break; - } - } - } - } - - /* Free memory */ - capwap_build_packet_free(responsepacket); - } - - /* Free */ - capwap_free_element_reset_request(&resetrequest, binding); + /* Send Reset response to AC */ + if (!capwap_crypt_sendto_fragmentpacket(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], g_wtp.responsefragmentpacket, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { + capwap_logging_debug("Warning: error to send reset response packet"); + } } } /* */ -int wtp_dfa_state_run(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_run(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { int status = WTP_DFA_ACCEPT_PACKET; ASSERT(timeout != NULL); if (packet) { - struct capwap_build_packet* buildpacket; - - buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket); - if (buildpacket) { - if (!capwap_build_packet_validate(buildpacket, NULL)) { - if (packet->socket.isctrlsocket) { - unsigned long typemsg = ntohl(buildpacket->ctrlmsg.type); - - if (capwap_is_request_type(typemsg) || ((g_wtp.localseqnumber - 1) == buildpacket->ctrlmsg.seq)) { - switch (typemsg) { - case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: { - /* TODO */ - break; - } - - case CAPWAP_CHANGE_STATE_EVENT_REQUEST: { - /* TODO */ - break; - } - - case CAPWAP_ECHO_RESPONSE: { - if (!receive_echo_response(buildpacket)) { - capwap_kill_timeout(timeout, CAPWAP_TIMER_CONTROL_CONNECTION); - capwap_set_timeout(g_wtp.dfa.rfcEchoInterval, timeout, CAPWAP_TIMER_CONTROL_ECHO); - } - - break; - } - - case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: { - /* TODO */ - break; - } - - case CAPWAP_WTP_EVENT_REQUEST: { - /* TODO */ - break; - } - - case CAPWAP_DATA_TRANSFER_REQUEST: { - /* TODO */ - break; - } - - case CAPWAP_DATA_TRANSFER_RESPONSE: { - /* TODO */ - break; - } - - case CAPWAP_RESET_REQUEST: { - receive_reset_request(buildpacket, packet); - wtp_dfa_change_state(CAPWAP_RESET_STATE); - status = WTP_DFA_NO_PACKET; - break; - } - } - } - } else { - if (IS_FLAG_K_HEADER(&buildpacket->header) && capwap_is_enable_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD)) { - struct capwap_sessionid_element sessionid; - - if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) { - if (!memcmp(&sessionid, &g_wtp.sessionid, sizeof(struct capwap_sessionid_element))) { - /* Receive Data Keep-Alive, wait for next packet */ - capwap_kill_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); - capwap_set_timeout(g_wtp.dfa.rfcDataChannelKeepAlive, timeout, CAPWAP_TIMER_DATA_KEEPALIVE); - } - } - } else { + if (packet->rxmngpacket->isctrlpacket) { + if (capwap_is_request_type(packet->rxmngpacket->ctrlmsg.type) || ((g_wtp.localseqnumber - 1) == packet->rxmngpacket->ctrlmsg.seq)) { + switch (packet->rxmngpacket->ctrlmsg.type) { + case CAPWAP_CONFIGURATION_UPDATE_RESPONSE: { /* TODO */ - - /* Update data keep-alive timeout */ - if (!capwap_is_enable_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD)) { - capwap_set_timeout(g_wtp.dfa.rfcDataChannelKeepAlive, timeout, CAPWAP_TIMER_DATA_KEEPALIVE); + break; + } + + case CAPWAP_CHANGE_STATE_EVENT_REQUEST: { + /* TODO */ + break; + } + + case CAPWAP_ECHO_RESPONSE: { + if (!receive_echo_response(packet)) { + capwap_kill_timeout(timeout, CAPWAP_TIMER_CONTROL_CONNECTION); + capwap_set_timeout(g_wtp.dfa.rfcEchoInterval, timeout, CAPWAP_TIMER_CONTROL_ECHO); } + + break; + } + + case CAPWAP_CLEAR_CONFIGURATION_RESPONSE: { + /* TODO */ + break; + } + + case CAPWAP_WTP_EVENT_REQUEST: { + /* TODO */ + break; + } + + case CAPWAP_DATA_TRANSFER_REQUEST: { + /* TODO */ + break; + } + + case CAPWAP_DATA_TRANSFER_RESPONSE: { + /* TODO */ + break; + } + + case CAPWAP_RESET_REQUEST: { + receive_reset_request(packet); + wtp_dfa_change_state(CAPWAP_RESET_STATE); + status = WTP_DFA_NO_PACKET; + break; } } } - - /* Free */ - capwap_build_packet_free(buildpacket); + } else { + if (IS_FLAG_K_HEADER(packet->rxmngpacket->header) && capwap_is_enable_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD)) { + if (!memcmp(packet->messageelements.sessionid, &g_wtp.sessionid, sizeof(struct capwap_sessionid_element))) { + /* Receive Data Keep-Alive, wait for next packet */ + capwap_kill_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); + capwap_set_timeout(g_wtp.dfa.rfcDataChannelKeepAlive, timeout, CAPWAP_TIMER_DATA_KEEPALIVE); + } + } else { + /* TODO */ + + /* Update data keep-alive timeout */ + if (!capwap_is_enable_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD)) { + capwap_set_timeout(g_wtp.dfa.rfcDataChannelKeepAlive, timeout, CAPWAP_TIMER_DATA_KEEPALIVE); + } + } } } else { if (capwap_is_timeout(timeout, CAPWAP_TIMER_CONTROL_CONNECTION)) { - int i; - /* No response received */ g_wtp.dfa.rfcRetransmitCount++; if (g_wtp.dfa.rfcRetransmitCount >= g_wtp.dfa.rfcMaxRetransmit) { @@ -245,16 +173,10 @@ int wtp_dfa_state_run(struct capwap_packet* packet, struct timeout_control* time status = WTP_DFA_NO_PACKET; } else { /* Retransmit request */ - for (i = 0; i < g_wtp.requestfragmentpacket->count; i++) { - struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(g_wtp.requestfragmentpacket, i); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.ctrldtls, g_wtp.acctrlsock.socket[g_wtp.acctrlsock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpctrladdress, &g_wtp.acctrladdress)) { - capwap_logging_debug("Warning: error to send request packet"); - break; - } + 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 request packet"); } - + /* Update timeout */ capwap_set_timeout(g_wtp.dfa.rfcRetransmitInterval, timeout, CAPWAP_TIMER_CONTROL_CONNECTION); } @@ -270,46 +192,41 @@ int wtp_dfa_state_run(struct capwap_packet* packet, struct timeout_control* time status = WTP_DFA_NO_PACKET; } } else if (capwap_is_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVE)) { - int result; - struct capwap_build_packet* buildpacket; - capwap_fragment_packet_array* txfragpacket; + struct capwap_list* txfragpacket; + struct capwap_header_data capwapheader; + struct capwap_packet_txmng* txmngpacket; - /* Build packet Data Keep-Alive*/ - buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, CAPWAP_WIRELESS_BINDING_NONE); - buildpacket->isctrlmsg = 0; - - /* */ - SET_FLAG_K_HEADER(&buildpacket->header, 1); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_SESSIONID_ELEMENT(&g_wtp.sessionid)); - - txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0); - result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0); - if (!result) { - struct capwap_packet* txpacket; - - ASSERT(txfragpacket->count == 1); - - txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0); - ASSERT(txpacket != NULL); - - if (!capwap_crypt_sendto(&g_wtp.datadtls, g_wtp.acdatasock.socket[g_wtp.acdatasock.type], txpacket->header, txpacket->packetsize, &g_wtp.wtpdataaddress, &g_wtp.acdataaddress)) { + /* 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_DATA_KEEPALIVE); + capwap_set_timeout(g_wtp.dfa.rfcDataChannelDeadInterval, timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); + } else { + /* Error to send packets */ capwap_logging_debug("Warning: error to send data channel keepalive packet"); - result = -1; + wtp_dfa_change_state(CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE); + status = WTP_DFA_NO_PACKET; } - } - - capwap_fragment_free(txfragpacket); - capwap_array_free(txfragpacket); - capwap_build_packet_free(buildpacket); - - /* Send Configuration Status request to AC */ - if (!result) { - capwap_kill_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVE); - capwap_set_timeout(g_wtp.dfa.rfcDataChannelDeadInterval, timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); } 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; } + + /* Free packets manager */ + capwap_list_free(txfragpacket); + capwap_packet_txmng_free(txmngpacket); } else if (capwap_is_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD)) { /* Data Keep-Alive timeout */ capwap_kill_timeout(timeout, CAPWAP_TIMER_DATA_KEEPALIVEDEAD); @@ -322,7 +239,7 @@ int wtp_dfa_state_run(struct capwap_packet* packet, struct timeout_control* time } /* */ -int wtp_dfa_state_run_to_dtlsteardown(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_run_to_dtlsteardown(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(packet == NULL); ASSERT(timeout != NULL); diff --git a/src/wtp/wtp_dfa_sulking.c b/src/wtp/wtp_dfa_sulking.c index a558613..14d5351 100644 --- a/src/wtp/wtp_dfa_sulking.c +++ b/src/wtp/wtp_dfa_sulking.c @@ -3,7 +3,7 @@ #include "wtp_dfa.h" /* */ -int wtp_dfa_state_sulking(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_sulking(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); @@ -13,7 +13,7 @@ int wtp_dfa_state_sulking(struct capwap_packet* packet, struct timeout_control* } /* */ -int wtp_dfa_state_sulking_to_idle(struct capwap_packet* packet, struct timeout_control* timeout) { +int wtp_dfa_state_sulking_to_idle(struct capwap_parsed_packet* packet, struct timeout_control* timeout) { ASSERT(timeout != NULL); ASSERT(packet == NULL); diff --git a/src/wtp/wtp_element_helper.c b/src/wtp/wtp_element_helper.c index 7e1c6f2..c7b5a97 100644 --- a/src/wtp/wtp_element_helper.c +++ b/src/wtp/wtp_element_helper.c @@ -1,10 +1,53 @@ #include "wtp.h" -void wtp_create_80211_wtpradioinformation_element(struct capwap_build_packet* buildpacket) { +/* */ +void wtp_create_radioopsstate_element(struct capwap_packet_txmng* txmngpacket) { int i; 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); - capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(&radio->radioinformation)); + struct capwap_radiooprstate_element radiooprstate; + + radiooprstate.radioid = (unsigned char)(i + 1); + radiooprstate.state = ((radio->status == WTP_RADIO_ENABLED) ? CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED : CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED); + + if (radio->status == WTP_RADIO_ENABLED) { + radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_NORMAL; + } else if (radio->status == WTP_RADIO_DISABLED) { + radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_ADMINSET; + } else if (radio->status == WTP_RADIO_HWFAILURE) { + radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_RADIOFAILURE; + } else if (radio->status == WTP_RADIO_SWFAILURE) { + radiooprstate.cause = CAPWAP_RADIO_OPERATIONAL_CAUSE_SOFTWAREFAILURE; + } else { + /* Unknown value */ + ASSERT(0); + } + + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RADIOOPRSTATE, &radiooprstate); + } +} + +/* */ +void wtp_create_radioadmstate_element(struct capwap_packet_txmng* txmngpacket) { + int i; + + 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); + struct capwap_radioadmstate_element radioadmstate; + + radioadmstate.radioid = (unsigned char)(i + 1); + radioadmstate.state = ((radio->status == WTP_RADIO_DISABLED) ? CAPWAP_RADIO_ADMIN_STATE_DISABLED : CAPWAP_RADIO_ADMIN_STATE_ENABLED); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_RADIOADMSTATE, &radioadmstate); + } +} + +/* */ +void wtp_create_80211_wtpradioinformation_element(struct capwap_packet_txmng* txmngpacket) { + int i; + + 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); + capwap_packet_txmng_add_message_element(txmngpacket, CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION, &radio->radioinformation); } }