diff options
Diffstat (limited to 'src/ipcpd/shim-udp')
-rw-r--r-- | src/ipcpd/shim-udp/CMakeLists.txt | 31 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/main.c | 324 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/tests/CMakeLists.txt | 33 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/tests/shim_udp_test.c | 103 |
4 files changed, 491 insertions, 0 deletions
diff --git a/src/ipcpd/shim-udp/CMakeLists.txt b/src/ipcpd/shim-udp/CMakeLists.txt new file mode 100644 index 00000000..27907880 --- /dev/null +++ b/src/ipcpd/shim-udp/CMakeLists.txt @@ -0,0 +1,31 @@ +get_filename_component(CURRENT_SOURCE_PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) +get_filename_component(CURRENT_BINARY_PARENT_DIR ${CMAKE_CURRENT_BINARY_DIR} DIRECTORY) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${CURRENT_SOURCE_PARENT_DIR}) +include_directories(${CURRENT_BINARY_PARENT_DIR}) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_BINARY_DIR}/include) + +SET(IPCP_SHIM_UDP_TARGET ipcpd-shim-udp CACHE STRING "IPCP_SHIM_UDP_TARGET") + +set(SHIM_UDP_SOURCES + # Add source files here + ${CMAKE_CURRENT_SOURCE_DIR}/main.c +) + +add_executable (ipcpd-shim-udp ${SHIM_UDP_SOURCES} ${IPCP_SOURCES}) +target_link_libraries (ipcpd-shim-udp LINK_PUBLIC ouroboros) + +include(MacroAddCompileFlags) +if (CMAKE_BUILD_TYPE MATCHES Debug) + MACRO_ADD_COMPILE_FLAGS(ipcpd-shim-udp -DCONFIG_OUROBOROS_DEBUG) +endif (CMAKE_BUILD_TYPE MATCHES Debug) + +install(TARGETS ipcpd-shim-udp RUNTIME DESTINATION bin) + +# Enable once ipcp-shim-udp has tests +add_subdirectory(tests) diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c new file mode 100644 index 00000000..45620ee9 --- /dev/null +++ b/src/ipcpd/shim-udp/main.c @@ -0,0 +1,324 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Shim IPC process over UDP + * + * Dimitri Staessens <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <ouroboros/config.h> + +#include "ipcp.h" +#include <ouroboros/shm_du_map.h> +#include <ouroboros/list.h> +#include <ouroboros/flow.h> +#include <ouroboros/utils.h> +#include <ouroboros/ipcp.h> +#include <ouroboros/dif_config.h> + +#define OUROBOROS_PREFIX "ipcpd/shim-udp" + +#include <ouroboros/logs.h> + +#include <string.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <netinet/in.h> +#include <signal.h> +#include <stdlib.h> +#include <pthread.h> + +#define THIS_TYPE IPCP_SHIM_UDP + +#define shim_data(type) ((struct ipcp_udp_data *) type->data) + +/* global for trapping signal */ +int irmd_pid; + +/* this IPCP's data */ +#ifdef MAKE_CHECK +extern struct ipcp * _ipcp; /* defined in test */ +#else +struct ipcp * _ipcp; +#endif + +struct ipcp_udp_data { + /* IPCP_DATA STRUCT MUST BE FIRST!! */ + struct ipcp_data ipcp_data; + + uint32_t ip_addr; + uint32_t dns_addr; + + pthread_mutex_t lock; +}; + +struct udp_flow { + /* FLOW MUST BE FIRST !!!! */ + flow_t flow; + + uint16_t localport; + + struct sockaddr_in * remote; + int fd; +}; + +void ipcp_sig_handler(int sig, siginfo_t * info, void * c) +{ + switch(sig) { + case SIGINT: + case SIGTERM: + case SIGHUP: + LOG_DBG("Terminating by order of %d. Bye.", info->si_pid); + if (info->si_pid == irmd_pid) { + shm_du_map_close(_ipcp->data->dum); + exit(0); + } + default: + return; + } +} + +struct ipcp_udp_data * ipcp_udp_data_create(char * ap_name, + char * ap_id) +{ + struct ipcp_udp_data * udp_data; + struct ipcp_data * data; + instance_name_t * instance_name; + enum ipcp_type ipcp_type; + + instance_name = instance_name_create(); + if (instance_name == NULL) { + LOG_ERR("Failed to create instance name struct."); + return NULL; + } + + instance_name = instance_name_init_with( + instance_name, ap_name, (uint16_t)atoi(ap_id)); + + if (instance_name == NULL) { + LOG_ERR("Failed to create instance name struct."); + return NULL; + } + + udp_data= malloc (sizeof *udp_data); + if (udp_data == NULL) { + LOG_DBGF("Failed to allocate."); + return NULL; + } + + ipcp_type = THIS_TYPE; + data = (struct ipcp_data *) udp_data; + if (ipcp_data_init(data, instance_name, ipcp_type) == NULL) { + free(udp_data); + return NULL; + } + + return udp_data; +} + +int ipcp_udp_bootstrap(struct dif_config * conf) +{ + char ipstr[INET_ADDRSTRLEN]; + char dnsstr[INET_ADDRSTRLEN]; + + if (conf->type != THIS_TYPE) { + LOG_ERR("Config doesn't match IPCP type."); + return -1; + } + + if (_ipcp->state != IPCP_INIT) { + LOG_ERR("IPCP in wrong state."); + return -1; + } + + inet_ntop(AF_INET, + &conf->ip_addr, + ipstr, + INET_ADDRSTRLEN); + + if (conf->dns_addr != 0) + inet_ntop(AF_INET, + &conf->dns_addr, + dnsstr, + INET_ADDRSTRLEN); + else + strcpy(dnsstr, "not set"); + + shim_data(_ipcp)->ip_addr = conf->ip_addr; + shim_data(_ipcp)->dns_addr = conf->dns_addr; + + _ipcp->state = IPCP_ENROLLED; + + LOG_DBG("Bootstrapped shim IPCP over UDP %s-%d.", + _ipcp->data->iname->name, _ipcp->data->iname->id); + + LOG_DBG("Bound to IP address %s.", ipstr); + LOG_DBG("DNS server address is %s.", dnsstr); + + return 0; +} + +int ipcp_udp_ap_reg(char * ap_name, uint32_t reg_ap_id) +{ + LOG_DBG("Registering local ap %s, %u.", ap_name, reg_ap_id); + + if (_ipcp->state != IPCP_ENROLLED) { + LOG_DBGF("Won't register with non-enrolled IPCP."); + return -1; + } + + if (ipcp_data_add_reg_entry(_ipcp->data, ap_name, reg_ap_id)) { + LOG_ERR("Failed to add AP to local registry."); + return -1; + } + + LOG_MISSING; + + return 0; +} + +int ipcp_udp_ap_unreg(uint32_t reg_ap_id) +{ + char * name = strdup(ipcp_data_get_reg_ap_name(_ipcp->data, + reg_ap_id)); + LOG_DBG("Unregistering %s.", name); + + ipcp_data_del_reg_entry(_ipcp->data, reg_ap_id); + + /* we are using dns */ + LOG_MISSING; + + free (name); + + return 0; +} + +int ipcp_udp_flow_alloc(uint32_t port_id, + char * dst_ap_name, + char * src_ap_name, + char * src_ae_name, + struct qos_spec * qos) +{ + return 0; +} +int ipcp_udp_flow_alloc_resp(uint32_t port_id, + int result) +{ + return 0; +} + +int ipcp_udp_flow_dealloc(uint32_t port_id) +{ + return 0; +} + +int ipcp_udp_du_write(uint32_t port_id, + size_t map_index) +{ + return 0; +} + +int ipcp_udp_du_read(uint32_t port_id, + size_t map_index) +{ + return 0; +} + +struct ipcp * ipcp_udp_create(char * ap_name, char * i_id) +{ + struct ipcp * i; + struct ipcp_udp_data * data; + struct ipcp_ops * ops; + + i = malloc(sizeof *i); + if (i == NULL) + return NULL; + + data = ipcp_udp_data_create(ap_name, i_id); + if (data == NULL) { + free(i); + return NULL; + } + + ops = malloc (sizeof *ops); + if (ops == NULL) { + free(data); + free(i); + return NULL; + } + + ops->ipcp_bootstrap = ipcp_udp_bootstrap; + ops->ipcp_enroll = NULL; /* shim */ + ops->ipcp_reg = NULL; /* shim */ + ops->ipcp_unreg = NULL; /* shim */ + ops->ipcp_ap_reg = ipcp_udp_ap_reg; + ops->ipcp_ap_unreg = ipcp_udp_ap_unreg; + ops->ipcp_flow_alloc = ipcp_udp_flow_alloc; + ops->ipcp_flow_alloc_resp = ipcp_udp_flow_alloc_resp; + ops->ipcp_flow_dealloc = ipcp_udp_flow_dealloc; + ops->ipcp_du_read = ipcp_udp_du_read; + ops->ipcp_du_write = ipcp_udp_du_write; + + i->data = (struct ipcp_data *) data; + i->ops = ops; + + i->state = IPCP_INIT; + + return i; +} + +#ifndef MAKE_CHECK + +int main (int argc, char * argv[]) +{ + /* argument 1: pid of irmd ? */ + /* argument 2: ap name */ + /* argument 3: instance id */ + struct sigaction sig_act; + + if (ipcp_arg_check(argc, argv)) { + LOG_ERR("Wrong arguments."); + exit(1); + } + + /* store the process id of the irmd */ + irmd_pid = atoi(argv[1]); + + /* init sig_act */ + memset (&sig_act, 0, sizeof sig_act); + + /* install signal traps */ + sig_act.sa_sigaction = &ipcp_sig_handler; + sig_act.sa_flags = SA_SIGINFO; + + sigaction(SIGINT, &sig_act, NULL); + sigaction(SIGTERM, &sig_act, NULL); + sigaction(SIGHUP, &sig_act, NULL); + + _ipcp = ipcp_udp_create(argv[2], argv[3]); + if (_ipcp == NULL) { + LOG_ERR("Won't."); + exit(1); + } + + ipcp_main_loop(_ipcp); + + exit(0); +} + +#endif /* MAKE_CHECK */ diff --git a/src/ipcpd/shim-udp/tests/CMakeLists.txt b/src/ipcpd/shim-udp/tests/CMakeLists.txt new file mode 100644 index 00000000..bdd7defb --- /dev/null +++ b/src/ipcpd/shim-udp/tests/CMakeLists.txt @@ -0,0 +1,33 @@ +get_filename_component(PARENT_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) +get_filename_component(PARENT_BINARY_PATH ${CMAKE_CURRENT_BINARY_DIR} DIRECTORY) +get_filename_component(PARENT_DIR ${PARENT_SOURCE_PATH} NAME) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${PARENT_SOURCE_PATH}) +include_directories(${PARENT_BINARY_PATH}) + +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_BINARY_DIR}/include) + +create_test_sourcelist(${PARENT_DIR}_tests test_suite.c + # Add new tests here + shim_udp_test.c +) + +add_executable(${PARENT_DIR}_test EXCLUDE_FROM_ALL ${IPCP_SOURCES} ${${PARENT_DIR}_tests}) +target_link_libraries(${PARENT_DIR}_test ouroboros) + +include(MacroAddCompileFlags) +MACRO_ADD_COMPILE_FLAGS(${PARENT_DIR}_test -DMAKE_CHECK) + +add_dependencies(check ${PARENT_DIR}_test) + +set(tests_to_run ${${PARENT_DIR}_tests}) +remove(tests_to_run test_suite.c) + +foreach(test ${tests_to_run}) + get_filename_component(test_name ${test} NAME_WE) + add_test(${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name}) +endforeach(test) diff --git a/src/ipcpd/shim-udp/tests/shim_udp_test.c b/src/ipcpd/shim-udp/tests/shim_udp_test.c new file mode 100644 index 00000000..427d0e1e --- /dev/null +++ b/src/ipcpd/shim-udp/tests/shim_udp_test.c @@ -0,0 +1,103 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Test of the Shim UDP IPCP Daemon + * + * Dimitri Staessens <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <ouroboros/config.h> +#include <ouroboros/dif_config.h> +#include <ouroboros/utils.h> +#include <ouroboros/shm_du_map.h> +#include <sys/types.h> +#include <stdlib.h> +#include "main.c" + +#include <ouroboros/logs.h> + +struct ipcp * _ipcp; + +int shim_udp_test(int argc, char ** argv) +{ + /* argument 1: pid of irmd ? */ + /* argument 2: ap name */ + /* argument 3: instance id */ + struct shm_du_map * dum; + char * ipcp_name = "test-shim-ipcp"; + char * i_id = "1"; + int i = 0; + + char bogus[15]; + memset (&bogus, 0, 15); + + struct dif_config conf; + memset (&conf, 0, sizeof conf); + conf.dif_name = strdup("test-dif"); + conf.type = IPCP_SHIM_UDP; + conf.ip_addr = 0; + + dum = shm_du_map_create(); + if (dum == NULL) { + LOG_ERR("Failed to create shared memory."); + exit(1); + } + + _ipcp = ipcp_udp_create(ipcp_name, i_id); + if (_ipcp == NULL) { + LOG_ERR("Could not instantiate shim IPCP."); + shm_du_map_close(dum); + exit(1); + } + + if (ipcp_udp_bootstrap (&conf)) { + LOG_ERR("Could not bootstrap."); + } + + if(ipcp_udp_ap_reg("bogus ap", 1865)) { + LOG_ERR("Failed to register application."); + shm_du_map_close(dum); + exit(1); + } + + if (ipcp_udp_ap_unreg(1865)) { + LOG_ERR("Failed to unregister application."); + shm_du_map_close(dum); + exit(1); + } + + for (i = 0; i < 1000; ++i) { + sprintf (bogus, "bogus ap %4d", i); + if(ipcp_udp_ap_reg(bogus, i)) { + LOG_ERR("Failed to register application %s.", bogus); + shm_du_map_close(dum); + exit(1); + } + } + + for (i = 0; i < 1000; ++i) { + if(ipcp_udp_ap_unreg(i)) { + LOG_ERR("Failed to unregister application %d.", i); + shm_du_map_close(dum); + exit(1); + } + } + + shm_du_map_close(dum); + + exit(0); +} |