diff options
31 files changed, 1609 insertions, 149 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 243e5d6f..1d31262d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,8 +54,8 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ouroboros.pc" enable_testing() add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) -add_subdirectory(include) add_subdirectory(src) +add_subdirectory(include) # Uninstall target configure_file( diff --git a/include/ouroboros/config.h.in b/include/ouroboros/config.h.in index 01d7888e..6abce97a 100644 --- a/include/ouroboros/config.h.in +++ b/include/ouroboros/config.h.in @@ -23,10 +23,12 @@ #ifndef OUROBOROS_CONFIG #define OUROBOROS_CONFIG -#define PROJECT_NAME "@CMAKE_PROJECT_NAME@" -#define PROJECT_VERSION "@PACKAGE_VERSION@" -#define INSTALL_DIR "@CMAKE_INSTALL_PREFIX@" -#define BUILD_TYPE "@CMAKE_BUILD_TYPE@" -#define _POSIX_C_SOURCE 199506L +#define PROJECT_NAME "@CMAKE_PROJECT_NAME@" +#define PROJECT_VERSION "@PACKAGE_VERSION@" +#define INSTALL_DIR "@CMAKE_INSTALL_PREFIX@" +#define BUILD_TYPE "@CMAKE_BUILD_TYPE@" +#define _POSIX_C_SOURCE 199506L +#define IPCP_SHIM_UDP_EXEC "@IPCP_SHIM_UDP_TARGET@" +#define IPCP_NORMAL_EXEC "@IPCP_NORMAL_TARGET@" #endif diff --git a/include/ouroboros/dif_config.h b/include/ouroboros/dif_config.h index 91b44cb1..5d489b0c 100644 --- a/include/ouroboros/dif_config.h +++ b/include/ouroboros/dif_config.h @@ -21,12 +21,13 @@ */ #include <ouroboros/utils.h> +#include <ouroboros/common.h> #ifndef OUROBOROS_DIF_CONFIG_H #define OUROBOROS_DIF_CONFIG_H enum ipcp_type { - IPCP_NORMAL = 1, + IPCP_NORMAL = 0, IPCP_SHIM_UDP }; @@ -53,6 +54,7 @@ struct dif_config { /* Shim UDP */ struct { uint32_t ip_addr; + uint32_t dns_addr; }; }; }; diff --git a/include/ouroboros/flow.h b/include/ouroboros/flow.h index 7d8c311e..000de5ad 100644 --- a/include/ouroboros/flow.h +++ b/include/ouroboros/flow.h @@ -24,7 +24,7 @@ #define OUROBOROS_FLOW_H #include <ouroboros/common.h> - +#include <ouroboros/list.h> #include <pthread.h> /* same values as fcntl.h */ @@ -39,17 +39,19 @@ #define FLOW_O_INVALID (FLOW_O_WRONLY | FLOW_O_RDWR) enum flow_state { - FLOW_INIT = 0, + FLOW_NULL = 0, FLOW_ALLOCATED, FLOW_PENDING }; typedef struct flow { - int32_t port_id; - uint16_t oflags; - enum flow_state state; + struct list_head list; + + int32_t port_id; + uint16_t oflags; + enum flow_state state; - pthread_mutex_t lock; + pthread_mutex_t lock; } flow_t; flow_t * flow_create(int32_t port_id); diff --git a/src/ipcpd/CMakeLists.txt b/src/ipcpd/CMakeLists.txt index bcb5b986..6311e3dc 100644 --- a/src/ipcpd/CMakeLists.txt +++ b/src/ipcpd/CMakeLists.txt @@ -1,26 +1,8 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -include_directories(${CMAKE_SOURCE_DIR}/include) -include_directories(${CMAKE_BINARY_DIR}/include) - -set(SOURCE_FILES +set(IPCP_SOURCES # Add source files here - main.c - pci.c - shm_pci.c + ${CMAKE_CURRENT_SOURCE_DIR}/ipcp.c + ${CMAKE_CURRENT_SOURCE_DIR}/ipcp-data.c ) -add_executable (ipcpd ${SOURCE_FILES}) - -target_link_libraries (ipcpd LINK_PUBLIC ouroboros) - -include(MacroAddCompileFlags) -if (CMAKE_BUILD_TYPE MATCHES Debug) - MACRO_ADD_COMPILE_FLAGS(ipcpd -DCONFIG_OUROBOROS_DEBUG) -endif (CMAKE_BUILD_TYPE MATCHES Debug) - -install(TARGETS ipcpd RUNTIME DESTINATION bin) - -# Enable once ipcpd has tests -# add_subdirectory(tests) +add_subdirectory(normal) +add_subdirectory(shim-udp) diff --git a/src/ipcpd/ipcp-data.c b/src/ipcpd/ipcp-data.c new file mode 100644 index 00000000..17649b42 --- /dev/null +++ b/src/ipcpd/ipcp-data.c @@ -0,0 +1,477 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * IPC process utilities + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * Sander Vrijders <sander.vrijders@intec.ugent.be> + * + * 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 "ipcp-data.h" +#include <ouroboros/flow.h> +#include <ouroboros/shm_du_map.h> +#include <ouroboros/list.h> +#include <ouroboros/utils.h> + +#define OUROBOROS_PREFIX "ipcp-utils" + +#include <ouroboros/logs.h> + +#include <string.h> +#include <stdlib.h> + +struct reg_entry { + struct list_head list; + char * ap_name; + uint32_t reg_ap_id; +}; + +struct dir_entry { + struct list_head list; + char * ap_name; + uint64_t addr; +}; + +static struct reg_entry * reg_entry_create(const char * ap_name, + uint32_t reg_ap_id) +{ + struct reg_entry * entry = malloc(sizeof *entry); + if (entry == NULL) + return NULL; + + entry->reg_ap_id = reg_ap_id; + entry->ap_name = strdup(ap_name); + if (entry->ap_name == NULL) + return NULL; + + return entry; +} + +static void reg_entry_destroy(struct reg_entry * entry) +{ + if (entry == NULL) + return; + + free(entry->ap_name); + free(entry); +} + +static struct dir_entry * dir_entry_create(const char * ap_name, + uint64_t addr) +{ + struct dir_entry * entry = malloc(sizeof *entry); + if (entry == NULL) + return NULL; + + entry->addr = addr; + entry->ap_name = strdup(ap_name); + if (entry->ap_name == NULL) + return NULL; + + return entry; +} + +static void dir_entry_destroy(struct dir_entry * entry) +{ + if (entry == NULL) + return; + + free(entry->ap_name); + free(entry); +} + +struct ipcp_data * ipcp_data_create() +{ + struct ipcp_data * data = malloc(sizeof *data); + if (data == NULL) + return NULL; + + data->iname = NULL; + data->type = 0; + data->dum = NULL; + + return data; +} + +struct ipcp_data * ipcp_data_init(struct ipcp_data * dst, + instance_name_t * iname, + enum ipcp_type ipcp_type) +{ + if (dst == NULL) + return NULL; + + dst->iname = instance_name_dup(iname); + dst->type = ipcp_type; + + dst->dum = shm_du_map_open(); + if (dst->dum == NULL) + return NULL; + + /* init the lists */ + INIT_LIST_HEAD(&dst->registry); + INIT_LIST_HEAD(&dst->flows); + INIT_LIST_HEAD(&dst->directory); + + /* init the mutexes */ + pthread_mutex_init(&dst->reg_lock, NULL); + pthread_mutex_init(&dst->dir_lock, NULL); + pthread_mutex_init(&dst->flow_lock, NULL); + + return dst; +} + +static void clear_registry(struct ipcp_data * data) +{ + struct list_head * h; + struct list_head * t; + list_for_each_safe(h, t, &data->registry) + reg_entry_destroy(list_entry(h, struct reg_entry, list)); +} + +static void clear_directory(struct ipcp_data * data) +{ + struct list_head * h; + struct list_head * t; + list_for_each_safe(h, t, &data->directory) + dir_entry_destroy(list_entry(h, struct dir_entry, list)); +} + +static void clear_flows(struct ipcp_data * data) +{ + struct list_head * h; + struct list_head * t; + list_for_each_safe(h, t, &data->flows) + flow_destroy(list_entry(h, flow_t, list)); + +} + +void ipcp_data_destroy(struct ipcp_data * data) +{ + if (data == NULL) + return; + + /* FIXME: finish all pending operations here */ + + if (data->iname != NULL) + instance_name_destroy(data->iname); + data->iname = NULL; + + if (data->dum != NULL) + shm_du_map_close(data->dum); + data->dum = NULL; + + pthread_mutex_lock(&data->reg_lock); + pthread_mutex_lock(&data->dir_lock); + pthread_mutex_lock(&data->flow_lock); + + /* clear the lists */ + clear_registry(data); + clear_directory(data); + clear_flows(data); + + /* no need to unlock, just free the entire thing + pthread_mutex_unlock(&data->flow_lock); + pthread_mutex_unlock(&data->dir_lock); + pthread_mutex_unlock(&data->reg_lock); + */ + + free(data); +} + + + +static struct reg_entry * find_reg_entry_by_name(struct ipcp_data * data, + const char * ap_name) +{ + struct list_head * h; + list_for_each(h, &data->registry) { + struct reg_entry * e = list_entry(h, struct reg_entry, list); + if (!strcmp(e->ap_name, ap_name)) + return e; + } + + return NULL; +} + +static struct reg_entry * find_reg_entry_by_id(struct ipcp_data * data, + uint32_t reg_ap_id) +{ + struct list_head * h; + list_for_each(h, &data->registry) { + struct reg_entry * e = list_entry(h, struct reg_entry, list); + if (e->reg_ap_id == reg_ap_id) + return e; + } + + return NULL; +} + +static struct dir_entry * find_dir_entry(struct ipcp_data * data, + const char * ap_name, + uint64_t addr) +{ + struct list_head * h; + list_for_each(h, &data->directory) { + struct dir_entry * e = list_entry(h, struct dir_entry, list); + if (e->addr == addr && !strcmp(e->ap_name, ap_name)) + return e; + } + + return NULL; +} + +static struct dir_entry * find_dir_entry_any(struct ipcp_data * data, + const char * ap_name) +{ + struct list_head * h; + list_for_each(h, &data->directory) { + struct dir_entry * e = list_entry(h, struct dir_entry, list); + if (!strcmp(e->ap_name, ap_name)) + return e; + } + + return NULL; +} + +bool ipcp_data_is_in_directory(struct ipcp_data * data, + const char * ap_name) +{ + return find_dir_entry_any(data, ap_name) != NULL; +} + +int ipcp_data_del_reg_entry(struct ipcp_data * data, + uint32_t reg_ap_id) +{ + struct reg_entry * e; + if (data == NULL) + return -1; + + pthread_mutex_lock(&data->reg_lock); + + e = find_reg_entry_by_id(data, reg_ap_id); + if (e == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return 0; /* nothing to do */ + } + + list_del(&e->list); + + reg_entry_destroy(e); + + pthread_mutex_unlock(&data->reg_lock); + + return 0; +} + +int ipcp_data_del_dir_entry(struct ipcp_data * data, + const char * ap_name, + uint64_t addr) +{ + struct dir_entry * e; + if (data == NULL) + return -1; + + pthread_mutex_lock(&data->dir_lock); + + e = find_dir_entry(data, ap_name, addr); + if (e == NULL) { + pthread_mutex_unlock(&data->dir_lock); + return 0; /* nothing to do */ + } + + list_del(&e->list); + + dir_entry_destroy(e); + + pthread_mutex_unlock(&data->dir_lock); + + return 0; +} + +int ipcp_data_add_reg_entry(struct ipcp_data * data, + char * ap_name, + uint32_t reg_ap_id) +{ + struct reg_entry * entry; + + if (data == NULL || ap_name == NULL) + return -1; + + pthread_mutex_lock(&data->reg_lock); + + if (find_reg_entry_by_name(data, ap_name) || + find_reg_entry_by_id(data, reg_ap_id)) { + pthread_mutex_unlock(&data->reg_lock); + return -2; + } + + entry = reg_entry_create(ap_name, reg_ap_id); + if (entry == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return -1; + } + + list_add(&entry->list,&data->registry); + + pthread_mutex_unlock(&data->reg_lock); + + return 0; +} + +int ipcp_data_add_dir_entry(struct ipcp_data * data, + char * ap_name, + uint64_t addr) +{ + struct dir_entry * entry; + + if (data == NULL || ap_name == NULL) + return -1; + + pthread_mutex_lock(&data->dir_lock); + + if (find_dir_entry(data, ap_name, addr) != NULL) { + pthread_mutex_unlock(&data->dir_lock); + return -2; + } + + entry = dir_entry_create(ap_name, addr); + if (entry == NULL) { + pthread_mutex_unlock(&data->dir_lock); + return -1; + } + + list_add(&entry->list,&data->directory); + + pthread_mutex_unlock(&data->dir_lock); + + return 0; +} + +bool ipcp_data_is_in_registry(struct ipcp_data * data, + const char * ap_name) +{ + return find_reg_entry_by_name(data, ap_name) != NULL; +} + +uint32_t ipcp_data_get_reg_ap_id(struct ipcp_data * data, + const char * ap_name) +{ + struct reg_entry * entry; + uint32_t id; + + pthread_mutex_lock(&data->reg_lock); + + entry = find_reg_entry_by_name(data, ap_name); + + if (entry == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return 0; /* undefined behaviour */ + } + + id = entry->reg_ap_id; + + pthread_mutex_unlock(&data->reg_lock); + + return id; +} + +const char * ipcp_data_get_reg_ap_name(struct ipcp_data * data, + uint32_t reg_ap_id) +{ + struct reg_entry * entry; + char * name; + + pthread_mutex_lock(&data->reg_lock); + + entry = find_reg_entry_by_id(data, reg_ap_id); + + if (entry == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return NULL; + } + + name = strdup(entry->ap_name); + if (name == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return NULL; + } + + pthread_mutex_unlock(&data->reg_lock); + + return name; +} + +uint64_t ipcp_data_get_addr(struct ipcp_data * data, + const char * ap_name) +{ + struct dir_entry * entry; + uint64_t addr; + + pthread_mutex_lock(&data->dir_lock); + + entry = find_dir_entry_any(data, ap_name); + + if (entry == NULL) { + pthread_mutex_unlock(&data->dir_lock); + return 0; /* undefined behaviour, 0 may be a valid address */ + } + + addr = entry->addr; + + pthread_mutex_unlock(&data->dir_lock); + + return addr; +} + +static flow_t * find_flow(struct ipcp_data * data, + uint32_t port_id) +{ + struct list_head * h; + list_for_each(h, &data->flows) { + flow_t * f = list_entry(h, flow_t, list); + if (f->port_id == port_id) + return f; + } + + return NULL; +} + +bool ipcp_data_has_flow(struct ipcp_data * data, + uint32_t port_id) +{ + return find_flow(data, port_id) != NULL; +} + +int ipcp_data_add_flow(struct ipcp_data * data, + flow_t * flow) +{ + if (data == NULL || flow == NULL) + return -1; + + pthread_mutex_lock(&data->flow_lock); + + if (ipcp_data_has_flow(data, flow->port_id)) { + pthread_mutex_unlock(&data->flow_lock); + return -2; + } + + list_add(&flow->list,&data->flows); + + pthread_mutex_unlock(&data->flow_lock); + + return 0; +} diff --git a/src/ipcpd/ipcp-data.h b/src/ipcpd/ipcp-data.h new file mode 100644 index 00000000..d51f3730 --- /dev/null +++ b/src/ipcpd/ipcp-data.h @@ -0,0 +1,91 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Utitilies for building IPC processes + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * Sander Vrijders <sander.vrijders@intec.ugent.be> + * + * 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. + */ + +#ifndef IPCPD_IPCP_DATA_H +#define IPCPD_IPCP_DATA_H + +#include <ouroboros/common.h> +#include <ouroboros/instance_name.h> +#include <ouroboros/list.h> +#include <ouroboros/flow.h> +#include <sys/types.h> +#include <pthread.h> + +#include "ipcp-ops.h" + +struct ipcp_data { + instance_name_t * iname; + enum ipcp_type type; + + struct shm_du_map * dum; + + struct list_head registry; + pthread_mutex_t reg_lock; + + struct list_head flows; + pthread_mutex_t flow_lock; + + struct list_head directory; + pthread_mutex_t dir_lock; + + pthread_mutex_t lock; +}; + +struct ipcp_data * ipcp_data_create(); +struct ipcp_data * ipcp_data_init(struct ipcp_data * dst, + instance_name_t * iname, + enum ipcp_type ipcp_type); +void ipcp_data_destroy(struct ipcp_data * data); + +int ipcp_data_add_reg_entry(struct ipcp_data * data, + char * ap_name, + uint32_t reg_ap_id); +int ipcp_data_del_reg_entry(struct ipcp_data * data, + uint32_t reg_ap_id); +int ipcp_data_add_dir_entry(struct ipcp_data * data, + char * ap_name, + uint64_t addr); +int ipcp_data_del_dir_entry(struct ipcp_data * data, + const char * ap_name, + uint64_t addr); +bool ipcp_data_is_in_registry(struct ipcp_data * data, + const char * ap_name); +uint32_t ipcp_data_get_reg_ap_id(struct ipcp_data * data, + const char * ap_name); +const char * ipcp_data_get_reg_ap_name(struct ipcp_data * data, + uint32_t reg_ap_id); +bool ipcp_data_is_in_directory(struct ipcp_data * data, + const char * ap_name); +uint64_t ipcp_data_get_addr(struct ipcp_data * data, + const char * ap_name); +bool ipcp_data_has_flow(struct ipcp_data * data, + uint32_t port_id); +bool ipcp_data_has_flow_s(struct ipcp_data * data, + uint32_t port_id, + enum flow_state state); +int ipcp_data_add_flow(struct ipcp_data * data, + flow_t * flow); +int ipcp_data_remove_flow(struct ipcp_data * data, + uint32_t port_id); + +#endif /* IPCPD_IPCP_DATA_H */ diff --git a/src/ipcpd/ipcp-ops.h b/src/ipcpd/ipcp-ops.h new file mode 100644 index 00000000..69682739 --- /dev/null +++ b/src/ipcpd/ipcp-ops.h @@ -0,0 +1,59 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * IPC process ops + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * Sander Vrijders <sander.vrijders@intec.ugent.be> + * + * 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. + */ + +#ifndef IPCPD_IPCP_OPS_H +#define IPCPD_IPCP_OPS_H + +#include <ouroboros/common.h> +#include <ouroboros/dif_config.h> +#include <sys/types.h> + +struct ipcp_ops { + int (* ipcp_bootstrap)(struct dif_config * conf); + int (* ipcp_enroll)(char * member_name, + char * n_1_dif); + int (* ipcp_reg)(char ** dif_names, + size_t len); + int (* ipcp_unreg)(char ** dif_names, + size_t len); + int (* ipcp_ap_reg)(char * ap_name, + uint32_t reg_ap_id); + int (* ipcp_ap_unreg)(uint32_t reg_ap_id); + int (* ipcp_flow_alloc)(uint32_t port_id, + char * dst_ap_name, + char * src_ap_name, + char * src_ae_name, + struct qos_spec * qos); + int (* ipcp_flow_alloc_resp)(uint32_t port_id, + int result); + int (* ipcp_flow_dealloc)(uint32_t port_id); + + /* FIXME: let's see how this will work with the shm_du_map */ + int (* ipcp_du_write)(uint32_t port_id, + size_t map_index); + + int (* ipcp_du_read)(uint32_t port_id, + size_t map_index); +}; + +#endif /* IPCPD_IPCP_OPS_H */ diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c new file mode 100644 index 00000000..a1276769 --- /dev/null +++ b/src/ipcpd/ipcp.c @@ -0,0 +1,195 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * IPC process main loop + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * + * 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/ipcp.h> +#include <sys/socket.h> +#include <stdlib.h> +#include "ipcp.h" + +#define OUROBOROS_PREFIX "ipcpd/ipcp" +#include <ouroboros/logs.h> + +int ipcp_main_loop(struct ipcp * _ipcp) +{ + int lsockfd; + int sockfd; + uint8_t buf[IPCP_MSG_BUF_SIZE]; + + ipcp_msg_t * msg; + ssize_t count; + buffer_t buffer; + ipcp_msg_t ret_msg = IPCP_MSG__INIT; + + dif_config_msg_t * conf_msg; + struct dif_config conf; + + if (_ipcp == NULL) { + LOG_ERR("Invalid ipcp struct."); + return 1; + } + + sockfd = server_socket_open(ipcp_sock_path(getpid())); + if (sockfd < 0) { + LOG_ERR("Could not open server socket."); + return 1; + } + + while (true) { + ret_msg.code = IPCP_MSG_CODE__IPCP_REPLY; + + lsockfd = accept(sockfd, 0, 0); + if (lsockfd < 0) { + LOG_ERR("Cannot accept new connection"); + break; + } + + count = read(lsockfd, buf, IPCP_MSG_BUF_SIZE); + if (count <= 0) { + LOG_ERR("Failed to read from socket"); + close(lsockfd); + continue; + } + + msg = ipcp_msg__unpack(NULL, count, buf); + if (msg == NULL) { + close(lsockfd); + continue; + } + + switch (msg->code) { + case IPCP_MSG_CODE__IPCP_BOOTSTRAP: + conf_msg = msg->conf; + conf.type = conf_msg->ipcp_type; + if (conf_msg->ipcp_type == IPCP_NORMAL) { + conf.addr_size = conf_msg->addr_size; + conf.cep_id_size = conf_msg->cep_id_size; + conf.pdu_length_size + = conf_msg->pdu_length_size; + conf.qos_id_size = conf_msg->qos_id_size; + conf.seqno_size = conf_msg->seqno_size; + conf.ttl_size = conf_msg->seqno_size; + conf.chk_size = conf_msg->chk_size; + conf.min_pdu_size = conf_msg->min_pdu_size; + conf.max_pdu_size = conf_msg->max_pdu_size; + } + if (conf_msg->ipcp_type == IPCP_SHIM_UDP) { + conf.ip_addr = conf_msg->ip_addr; + conf.dns_addr = conf_msg->dns_addr; + } + + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_bootstrap(&conf); + break; + case IPCP_MSG_CODE__IPCP_ENROLL: + if (_ipcp->ops->ipcp_enroll == NULL) { + LOG_ERR("ipcp_enroll unsupported."); + } else { + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_enroll( + msg->member_name, msg->n_1_dif); + } + break; + + case IPCP_MSG_CODE__IPCP_REG: + if (_ipcp->ops->ipcp_reg == NULL) { + LOG_ERR("ipcp_reg unsupported."); + + } else { + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_reg( + msg->dif_names, msg->len); + } + break; + case IPCP_MSG_CODE__IPCP_UNREG: + if (_ipcp->ops->ipcp_unreg == NULL) { + LOG_ERR("ipcp_unreg unsupported."); + + } else { + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_unreg( + msg->dif_names, msg->len); + } + break; + case IPCP_MSG_CODE__IPCP_AP_REG: + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_ap_reg( + msg->ap_name, msg->reg_ap_id); + break; + case IPCP_MSG_CODE__IPCP_AP_UNREG: + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_ap_unreg( + msg->reg_ap_id); + break; + case IPCP_MSG_CODE__IPCP_FLOW_ALLOC: + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_flow_alloc( + msg->port_id, + msg->dst_ap_name, + msg->ap_name, + msg->ae_name, + NULL); + break; + case IPCP_MSG_CODE__IPCP_FLOW_ALLOC_RESP: + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_flow_alloc_resp( + msg->port_id, msg->result); + break; + case IPCP_MSG_CODE__IPCP_FLOW_DEALLOC: + ret_msg.has_result = true; + ret_msg.result = _ipcp->ops->ipcp_flow_dealloc( + msg->port_id); + break; + default: + LOG_ERR("Don't know that message code"); + break; + } + + ipcp_msg__free_unpacked(msg, NULL); + + buffer.size = ipcp_msg__get_packed_size(&ret_msg); + if (buffer.size == 0) { + LOG_ERR("Failed to send reply message"); + close(lsockfd); + continue; + } + + buffer.data = malloc(buffer.size); + if (buffer.data == NULL) { + close(lsockfd); + continue; + } + + ipcp_msg__pack(&ret_msg, buffer.data); + + if (write(lsockfd, buffer.data, buffer.size) == -1) { + free(buffer.data); + close(lsockfd); + continue; + } + + free(buffer.data); + close(lsockfd); + } + + return 0; +} diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h new file mode 100644 index 00000000..d6ddeb43 --- /dev/null +++ b/src/ipcpd/ipcp.h @@ -0,0 +1,48 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * IPC process structure + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * + * 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. + */ + +#ifndef IPCPD_IPCP_H +#define IPCPD_IPCP_H + +#include "ipcp-ops.h" +#include "ipcp-data.h" + +enum ipcp_state { + IPCP_INIT = 0, + IPCP_ENROLLING, + IPCP_BOOTSTRAPPING, + IPCP_ENROLLED, + IPCP_DISCONNECTED, + IPCP_SHUTDOWN +}; + +struct ipcp { + struct ipcp_data * data; + struct ipcp_ops * ops; + + enum ipcp_state state; + int irmd_fd; +}; + +int ipcp_main_loop(); + +#endif diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt new file mode 100644 index 00000000..c13cbaa3 --- /dev/null +++ b/src/ipcpd/normal/CMakeLists.txt @@ -0,0 +1,32 @@ +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_NORMAL_TARGET ipcpd-normal CACHE STRING "IPCP_NORMAL_TARGET") + +set(SOURCE_FILES + # Add source files here + main.c + pci.c +) + +add_executable (ipcpd-normal ${SOURCE_FILES} ${IPCP_SOURCES}) +target_link_libraries (ipcpd-normal LINK_PUBLIC ouroboros) + +include(MacroAddCompileFlags) +if (CMAKE_BUILD_TYPE MATCHES Debug) + MACRO_ADD_COMPILE_FLAGS(ipcpd-normal -DCONFIG_OUROBOROS_DEBUG) +endif (CMAKE_BUILD_TYPE MATCHES Debug) + +install(TARGETS ipcpd-normal RUNTIME DESTINATION bin) + +# Enable once ipcp-normal has tests +# add_subdirectory(tests) diff --git a/src/ipcpd/dt_const.h b/src/ipcpd/normal/dt_const.h index bc0c1466..bc0c1466 100644 --- a/src/ipcpd/dt_const.h +++ b/src/ipcpd/normal/dt_const.h diff --git a/src/ipcpd/main.c b/src/ipcpd/normal/main.c index 7ffd1c48..7ffd1c48 100644 --- a/src/ipcpd/main.c +++ b/src/ipcpd/normal/main.c diff --git a/src/ipcpd/pci.c b/src/ipcpd/normal/pci.c index 548e40e2..d7df52b6 100644 --- a/src/ipcpd/pci.c +++ b/src/ipcpd/normal/pci.c @@ -22,7 +22,7 @@ */ #include "pci.h" -#include <malloc.h> +#include <stdlib.h> #include <errno.h> #define OUROBOROS_PREFIX "ipcp/pci" diff --git a/src/ipcpd/pci.h b/src/ipcpd/normal/pci.h index 3c011723..3c011723 100644 --- a/src/ipcpd/pci.h +++ b/src/ipcpd/normal/pci.h diff --git a/src/ipcpd/shm_pci.c b/src/ipcpd/normal/shm_pci.c index d44e0e8f..e76d8009 100644 --- a/src/ipcpd/shm_pci.c +++ b/src/ipcpd/normal/shm_pci.c @@ -22,7 +22,7 @@ */ #include "shm_pci.h" -#include <malloc.h> +#include <stdlib.h> #include <errno.h> #define SHM_PCI_HEAD_SIZE(a, b) a.addr_size * 2 + \ diff --git a/src/ipcpd/shm_pci.h b/src/ipcpd/normal/shm_pci.h index cb8dd5dd..cb8dd5dd 100644 --- a/src/ipcpd/shm_pci.h +++ b/src/ipcpd/normal/shm_pci.h 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..1fb12dc0 --- /dev/null +++ b/src/ipcpd/shim-udp/main.c @@ -0,0 +1,323 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Shim IPC process over UDP + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * + * 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; + + /* FIXME: clean up argument checks */ + if (argc != 4) + LOG_ERR("Wrong arguments passed."); + + /* 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 <dimitri.staessens@intec.ugent.be> + * + * 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); +} diff --git a/src/irmd/main.c b/src/irmd/main.c index 1f1c4839..13076cd1 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -22,6 +22,7 @@ #define OUROBOROS_PREFIX "irmd" +#include <ouroboros/config.h> #include <ouroboros/logs.h> #include <ouroboros/common.h> #include <ouroboros/sockets.h> @@ -32,11 +33,14 @@ #include <ouroboros/instance_name.h> #include <ouroboros/utils.h> #include <ouroboros/dif_config.h> +#include <ouroboros/shm_du_map.h> #include <sys/socket.h> #include <sys/un.h> +#include <signal.h> #include <stdlib.h> #include <errno.h> +#include <string.h> struct ipcp_entry { struct list_head next; @@ -50,6 +54,7 @@ struct irm { }; struct irm * instance = NULL; +struct shm_du_map * dum; static pid_t find_pid_by_ipcp_name(instance_name_t * api) { @@ -59,8 +64,6 @@ static pid_t find_pid_by_ipcp_name(instance_name_t * api) struct ipcp_entry * tmp = list_entry(pos, struct ipcp_entry, next); - LOG_DBG("name is %s", api->name); - if (instance_name_cmp(api, tmp->api) == 0) return tmp->pid; } @@ -97,8 +100,9 @@ static int create_ipcp(instance_name_t * api, } tmp = malloc(sizeof(*tmp)); - if (tmp == NULL) + if (tmp == NULL) { return -1; + } INIT_LIST_HEAD(&tmp->next); @@ -330,12 +334,45 @@ static int flow_dealloc_ipcp(uint32_t port_id) return -1; } -/* FIXME: Close sockfd on closing and release irm */ +void irmd_sig_handler(int sig, siginfo_t * info, void * c) +{ + switch(sig) { + case SIGINT: + case SIGTERM: + case SIGHUP: + shm_du_map_close(dum); + free(instance); + exit(0); + default: + return; + } +} + int main() { int sockfd; uint8_t buf[IRM_MSG_BUF_SIZE]; + struct sigaction sig_act; + + /* init sig_act */ + memset (&sig_act, 0, sizeof sig_act); + + /* install signal traps */ + sig_act.sa_sigaction = &irmd_sig_handler; + sig_act.sa_flags = SA_SIGINFO; + + sigaction(SIGINT, &sig_act, NULL); + sigaction(SIGTERM, &sig_act, NULL); + sigaction(SIGHUP, &sig_act, NULL); + + + if (access("/dev/shm/" SHM_DU_MAP_FILENAME, F_OK) != -1) + unlink("/dev/shm/" SHM_DU_MAP_FILENAME); + + if ((dum = shm_du_map_create()) == NULL) + return -1; + instance = malloc(sizeof(*instance)); if (instance == NULL) return -1; @@ -343,8 +380,10 @@ int main() INIT_LIST_HEAD(&instance->ipcps); sockfd = server_socket_open(IRM_SOCK_PATH); - if (sockfd < 0) + if (sockfd < 0) { + free(instance); return -1; + } while (true) { int cli_sockfd; diff --git a/src/lib/dif_config.proto b/src/lib/dif_config.proto index 87cb222f..05b35ea7 100644 --- a/src/lib/dif_config.proto +++ b/src/lib/dif_config.proto @@ -1,16 +1,17 @@ message dif_config_msg { - required string dif_name = 1; - required int32 ipcp_type = 2; + required string dif_name = 1; + required int32 ipcp_type = 2; // Config for normal IPCP - optional uint32 addr_size = 3; - optional uint32 cep_id_size = 4; - optional uint32 pdu_length_size = 5; - optional uint32 qos_id_size = 6; - optional uint32 seqno_size = 7; - optional uint32 ttl_size = 8; - optional uint32 chk_size = 9; - optional uint32 min_pdu_size = 10; - optional uint32 max_pdu_size = 11; + optional uint32 addr_size = 3; + optional uint32 cep_id_size = 4; + optional uint32 pdu_length_size = 5; + optional uint32 qos_id_size = 6; + optional uint32 seqno_size = 7; + optional uint32 ttl_size = 8; + optional uint32 chk_size = 9; + optional uint32 min_pdu_size = 10; + optional uint32 max_pdu_size = 11; // Config for shim UDP - optional uint32 ip_addr = 12; + optional uint32 ip_addr = 12; + optional uint32 dns_addr = 13; }
\ No newline at end of file diff --git a/src/lib/flow.c b/src/lib/flow.c index 593bef1a..da0ca148 100644 --- a/src/lib/flow.c +++ b/src/lib/flow.c @@ -35,9 +35,11 @@ flow_t * flow_create(int32_t port_id) return NULL; } + INIT_LIST_HEAD(&flow->list); + flow->port_id = port_id; flow->oflags = FLOW_O_DEFAULT; - flow->state = FLOW_INIT; + flow->state = FLOW_NULL; pthread_mutex_init(&flow->lock, NULL); @@ -46,6 +48,8 @@ flow_t * flow_create(int32_t port_id) void flow_destroy(flow_t * flow) { + if (flow == NULL) + return; free(flow); } diff --git a/src/lib/ipcp.c b/src/lib/ipcp.c index a0febe4e..338d8683 100644 --- a/src/lib/ipcp.c +++ b/src/lib/ipcp.c @@ -61,7 +61,7 @@ static ipcp_msg_t * send_recv_ipcp_msg(pid_t pid, return NULL; } - buf.data = malloc(buf.size); + buf.data = malloc(IPCP_MSG_BUF_SIZE); if (buf.data == NULL) { close(sockfd); free(sock_path); @@ -103,10 +103,14 @@ pid_t ipcp_create(instance_name_t * api, enum ipcp_type ipcp_type) { pid_t pid = 0; + char irmd_pid[10]; char * api_id = NULL; size_t len = 0; - char * ipcp_dir = "bin/ipcpd"; + char * ipcp_dir = "bin"; char * full_name = NULL; + char * exec_name = NULL; + + sprintf (irmd_pid, "%u", getpid()); pid = fork(); if (pid == -1) { @@ -125,10 +129,21 @@ pid_t ipcp_create(instance_name_t * api, } sprintf(api_id, "%d", api->id); + if (ipcp_type == IPCP_NORMAL) + exec_name = IPCP_NORMAL_EXEC; + else if (ipcp_type == IPCP_SHIM_UDP) + exec_name = IPCP_SHIM_UDP_EXEC; + else { + free(api_id); + exit(EXIT_FAILURE); + } + len += strlen(INSTALL_DIR); len += strlen(ipcp_dir); - len += 2; - full_name = malloc(len); + len += strlen(exec_name); + len += 3; + + full_name = malloc(len + 1); if (full_name == NULL) { LOG_ERR("Failed to malloc"); free(api_id); @@ -138,9 +153,16 @@ pid_t ipcp_create(instance_name_t * api, strcpy(full_name, INSTALL_DIR); strcat(full_name, "/"); strcat(full_name, ipcp_dir); + strcat(full_name, "/"); + strcat(full_name, exec_name); + full_name[len] = '\0'; + + LOG_DBG("Full name is %s", full_name); char * argv[] = {full_name, - api->name, api_id, + irmd_pid, + api->name, + api_id, 0}; char * envp[] = {0}; @@ -172,22 +194,22 @@ int ipcp_destroy(pid_t pid) return 0; } -int ipcp_reg(pid_t pid, - char ** difs, - size_t difs_size) +int ipcp_reg(pid_t pid, + char ** dif_names, + size_t len) { ipcp_msg_t msg = IPCP_MSG__INIT; ipcp_msg_t * recv_msg = NULL; int ret = -1; - if (difs == NULL || - difs_size == 0 || - difs[0] == NULL) + if (dif_names == NULL || + len == 0 || + dif_names[0] == NULL) return -EINVAL; - msg.code = IPCP_MSG_CODE__IPCP_REG; - msg.dif_name = difs; - msg.n_dif_name = difs_size; + msg.code = IPCP_MSG_CODE__IPCP_REG; + msg.dif_names = dif_names; + msg.len = len; recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) @@ -205,21 +227,21 @@ int ipcp_reg(pid_t pid, } int ipcp_unreg(pid_t pid, - char ** difs, - size_t difs_size) + char ** dif_names, + size_t len) { ipcp_msg_t msg = IPCP_MSG__INIT; ipcp_msg_t * recv_msg = NULL; int ret = -1; - if (difs == NULL || - difs_size == 0 || - difs[0] == NULL) + if (dif_names == NULL || + len == 0 || + dif_names[0] == NULL) return -EINVAL; - msg.code = IPCP_MSG_CODE__IPCP_UNREG; - msg.dif_name = difs; - msg.n_dif_name = difs_size; + msg.code = IPCP_MSG_CODE__IPCP_UNREG; + msg.dif_names = dif_names; + msg.len = len; recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) @@ -276,36 +298,36 @@ int ipcp_enroll(pid_t pid, if (n_1_dif == NULL || member_name == NULL) return -EINVAL; - msg.code = IPCP_MSG_CODE__IPCP_ENROLL; - msg.dif_name = malloc(sizeof(*(msg.dif_name))); - if (msg.dif_name == NULL) { - LOG_ERR("Failed to malloc"); + msg.code = IPCP_MSG_CODE__IPCP_ENROLL; + msg.member_name = malloc(sizeof(*(msg.member_name))); + if (msg.member_name == NULL) { + LOG_ERR("Failed to malloc."); return -1; } - msg.dif_name[0] = n_1_dif; - msg.ap_name = member_name; + msg.n_1_dif = n_1_dif; + msg.member_name = member_name; recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) { - free(msg.dif_name); + free(msg.member_name); return -1; } if (recv_msg->has_result == false) { ipcp_msg__free_unpacked(recv_msg, NULL); - free(msg.dif_name); + free(msg.member_name); return -1; } ret = recv_msg->result; ipcp_msg__free_unpacked(recv_msg, NULL); - free(msg.dif_name); + free(msg.member_name); return ret; } int ipcp_ap_reg(pid_t pid, - uint32_t reg_api_id, + uint32_t reg_ap_id, char * ap_name) { ipcp_msg_t msg = IPCP_MSG__INIT; @@ -315,10 +337,10 @@ int ipcp_ap_reg(pid_t pid, if (ap_name == NULL) return -1; - msg.code = IPCP_MSG_CODE__IPCP_AP_REG; - msg.ap_name = ap_name; - msg.has_port_id = true; - msg.port_id = reg_api_id; + msg.code = IPCP_MSG_CODE__IPCP_AP_REG; + msg.ap_name = ap_name; + msg.has_reg_ap_id = true; + msg.reg_ap_id = reg_ap_id; recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) @@ -336,15 +358,15 @@ int ipcp_ap_reg(pid_t pid, } int ipcp_ap_unreg(pid_t pid, - uint32_t reg_api_id) + uint32_t reg_ap_id) { ipcp_msg_t msg = IPCP_MSG__INIT; ipcp_msg_t * recv_msg = NULL; int ret = -1; - msg.code = IPCP_MSG_CODE__IPCP_AP_UNREG; - msg.has_port_id = true; - msg.port_id = reg_api_id; + msg.code = IPCP_MSG_CODE__IPCP_AP_UNREG; + msg.has_reg_ap_id = true; + msg.reg_ap_id = reg_ap_id; recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) @@ -375,12 +397,12 @@ int ipcp_flow_alloc(pid_t pid, if (dst_ap_name == NULL || src_ap_name == NULL || src_ae_name == NULL) return -EINVAL; - msg.code = IPCP_MSG_CODE__IPCP_FLOW_ALLOC; - msg.ap_name = src_ap_name; - msg.ae_name = src_ae_name; + msg.code = IPCP_MSG_CODE__IPCP_FLOW_ALLOC; + msg.ap_name = src_ap_name; + msg.ae_name = src_ae_name; msg.dst_ap_name = dst_ap_name; + msg.port_id = port_id; msg.has_port_id = true; - msg.port_id = port_id; recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) @@ -405,11 +427,11 @@ int ipcp_flow_alloc_resp(pid_t pid, ipcp_msg_t * recv_msg = NULL; int ret = -1; - msg.code = IPCP_MSG_CODE__IPCP_FLOW_ALLOC_RESP; + msg.code = IPCP_MSG_CODE__IPCP_FLOW_ALLOC_RESP; msg.has_port_id = true; - msg.port_id = port_id; - msg.has_result = true; - msg.result = result; + msg.port_id = port_id; + msg.has_result = true; + msg.result = result; recv_msg = send_recv_ipcp_msg(pid, &msg); if (recv_msg == NULL) @@ -427,7 +449,7 @@ int ipcp_flow_alloc_resp(pid_t pid, } int ipcp_flow_req_arr(pid_t pid, - uint32_t reg_api_id, + uint32_t reg_ap_id, char * ap_name, char * ae_name) { @@ -438,13 +460,13 @@ int ipcp_flow_req_arr(pid_t pid, if (ap_name == NULL || ae_name == NULL) return -EINVAL; - msg.code = IRM_MSG_CODE__IPCP_FLOW_REQ_ARR; - msg.ap_name = ap_name; - msg.ae_name = ae_name; - msg.port_id = reg_api_id; - msg.has_port_id = true; - msg.pid = pid; - msg.has_pid = true; + msg.code = IRM_MSG_CODE__IPCP_FLOW_REQ_ARR; + msg.ap_name = ap_name; + msg.ae_name = ae_name; + msg.reg_ap_id = reg_ap_id; + msg.has_reg_ap_id = true; + msg.pid = pid; + msg.has_pid = true; recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) @@ -469,11 +491,11 @@ int ipcp_flow_alloc_reply(pid_t pid, irm_msg_t * recv_msg = NULL; int ret = -1; - msg.code = IRM_MSG_CODE__IPCP_FLOW_ALLOC_REPLY; - msg.port_id = port_id; + msg.code = IRM_MSG_CODE__IPCP_FLOW_ALLOC_REPLY; + msg.port_id = port_id; msg.has_port_id = true; - msg.result = result; - msg.has_result = true; + msg.result = result; + msg.has_result = true; recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) diff --git a/src/lib/ipcpd_messages.proto b/src/lib/ipcpd_messages.proto index b83c34c7..796638c7 100644 --- a/src/lib/ipcpd_messages.proto +++ b/src/lib/ipcpd_messages.proto @@ -14,12 +14,16 @@ enum ipcp_msg_code { }; message ipcp_msg { - required ipcp_msg_code code = 1; - optional string ap_name = 2; - optional dif_config_msg conf = 3; - repeated string dif_name = 4; - optional int32 result = 5; - optional uint32 port_id = 6; - optional string ae_name = 7; - optional string dst_ap_name = 8; + required ipcp_msg_code code = 1; + optional string member_name = 2; + optional string n_1_dif = 3; + repeated string dif_names = 4; + optional int32 len = 5; + optional string ap_name = 6; + optional int32 reg_ap_id = 7; + optional int32 port_id = 8; + optional string dst_ap_name = 9; + optional string ae_name = 10; + optional dif_config_msg conf = 11; + optional int32 result = 12; }; diff --git a/src/lib/irm.c b/src/lib/irm.c index 70b7b3a5..b17cb04c 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -44,6 +44,7 @@ int irm_create_ipcp(instance_name_t * api, msg.ap_name = api->name; msg.has_api_id = true; msg.api_id = api->id; + msg.has_ipcp_type = true; msg.ipcp_type = ipcp_type; recv_msg = send_recv_irm_msg(&msg); @@ -101,10 +102,10 @@ int irm_bootstrap_ipcp(instance_name_t * api, if (api == NULL || api->name == NULL || conf == NULL) return -EINVAL; - msg.code = IRM_MSG_CODE__IRM_BOOTSTRAP_IPCP; - msg.ap_name = api->name; + msg.code = IRM_MSG_CODE__IRM_BOOTSTRAP_IPCP; + msg.ap_name = api->name; msg.has_api_id = true; - msg.api_id = api->id; + msg.api_id = api->id; msg.conf = &config; config.dif_name = conf->dif_name; @@ -134,8 +135,9 @@ int irm_bootstrap_ipcp(instance_name_t * api, break; case IPCP_SHIM_UDP: config.has_ip_addr = true; - config.ip_addr = conf->ip_addr; + config.has_dns_addr = true; + config.dns_addr = conf->dns_addr; break; default: return -1; diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index 3a2432f3..92ea439e 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -24,17 +24,18 @@ enum irm_msg_code { }; message irm_msg { - required irm_msg_code code = 1; - optional string ap_name = 2; - optional uint32 api_id = 3; - optional string ae_name = 4; - optional uint32 ipcp_type = 5; - repeated string dif_name = 6; - optional int32 fd = 7; - optional int32 result = 8; - optional int32 oflags = 9; - optional string dst_ap_name = 10; - optional uint32 port_id = 11; - optional int32 pid = 12; - optional dif_config_msg conf = 13; + required irm_msg_code code = 1; + optional string ap_name = 2; + optional uint32 api_id = 3; + optional string ae_name = 4; + optional uint32 ipcp_type = 5; + repeated string dif_name = 6; + optional int32 fd = 7; + optional int32 result = 8; + optional int32 oflags = 9; + optional string dst_ap_name = 10; + optional uint32 port_id = 11; + optional uint32 reg_ap_id = 12; + optional int32 pid = 13; + optional dif_config_msg conf = 14; }; diff --git a/src/lib/sockets.c b/src/lib/sockets.c index 805dda39..4f777805 100644 --- a/src/lib/sockets.c +++ b/src/lib/sockets.c @@ -29,7 +29,6 @@ #include <sys/socket.h> #include <sys/un.h> -#include <sys/stat.h> #include <string.h> #include <stdlib.h> @@ -61,9 +60,8 @@ int server_socket_open(char * file_name) { int sockfd; struct sockaddr_un serv_addr; - struct stat sb; - if (!stat(file_name, &sb)) { + if (access(file_name, F_OK) != -1) { /* File exists */ if (unlink(file_name)) { LOG_ERR("Failed to unlink filename: %s", @@ -113,8 +111,7 @@ irm_msg_t * send_recv_irm_msg(irm_msg_t * msg) return NULL; } - LOG_DBG("Size will be %lu", buf.size); - buf.data = malloc(buf.size); + buf.data = malloc(IRM_MSG_BUF_SIZE); if (buf.data == NULL) { close(sockfd); return NULL; diff --git a/src/lib/utils.c b/src/lib/utils.c index 77a2d44c..5744fb7c 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -28,7 +28,7 @@ int n_digits(unsigned i) int n = 1; while (i > 9) { - n++; + ++n; i /= 10; } diff --git a/src/tools/irm/irm_bootstrap_ipcp.c b/src/tools/irm/irm_bootstrap_ipcp.c index 78a09362..b90e934f 100644 --- a/src/tools/irm/irm_bootstrap_ipcp.c +++ b/src/tools/irm/irm_bootstrap_ipcp.c @@ -43,6 +43,7 @@ #define DEFAULT_CHK_SIZE 2 #define DEFAULT_MIN_PDU_SIZE 0 #define DEFAULT_MAX_PDU_SIZE 9000 +#define DEFAULT_DDNS 0 static void usage() { @@ -64,12 +65,14 @@ static void usage() " [min_pdu <minimum PDU size> (default: %d)]\n" " [max_pdu <maximum PDU size> (default: %d)]\n" "if TYPE == " SHIM_UDP "\n" - " ip <IP address in dotted notation>\n", + " ip <IP address in dotted notation>\n" + " [dns <DDNS IP address in dotted notation>" + " (default = none: %d)]\n", DEFAULT_ADDR_SIZE, DEFAULT_CEP_ID_SIZE, DEFAULT_PDU_LEN_SIZE, DEFAULT_QOS_ID_SIZE, DEFAULT_SEQ_NO_SIZE, DEFAULT_TTL_SIZE, DEFAULT_CHK_SIZE, DEFAULT_MIN_PDU_SIZE, - DEFAULT_MAX_PDU_SIZE); + DEFAULT_MAX_PDU_SIZE, DEFAULT_DDNS); } int do_bootstrap_ipcp(int argc, char ** argv) @@ -86,6 +89,7 @@ int do_bootstrap_ipcp(int argc, char ** argv) uint32_t min_pdu_size = DEFAULT_MIN_PDU_SIZE; uint32_t max_pdu_size = DEFAULT_MAX_PDU_SIZE; uint32_t ip_addr = 0; + uint32_t dns_addr = DEFAULT_DDNS; char * ipcp_type = NULL; char * dif_name = NULL; @@ -103,6 +107,11 @@ int do_bootstrap_ipcp(int argc, char ** argv) usage(); return -1; } + } else if (matches(*argv, "dns") == 0) { + if (inet_pton (AF_INET, *(argv + 1), &dns_addr) != 1) { + usage(); + return -1; + } } else if (matches(*argv, "addr") == 0) { addr_size = atoi(*(argv + 1)); } else if (matches(*argv, "cep_id") == 0) { @@ -156,6 +165,7 @@ int do_bootstrap_ipcp(int argc, char ** argv) return -1; } conf.ip_addr = ip_addr; + conf.dns_addr = dns_addr; } else { usage(); return -1; |