diff options
| author | Sander Vrijders <sander.vrijders@intec.ugent.be> | 2016-04-19 11:15:51 +0200 | 
|---|---|---|
| committer | Sander Vrijders <sander.vrijders@intec.ugent.be> | 2016-04-19 11:15:51 +0200 | 
| commit | c0b2bb854f42ed5975a5c08465fd0012c9e5ce8c (patch) | |
| tree | 877236ec9d67fbb2182a2f591ab4fb1e9357fa01 /src | |
| parent | d8e9019fcb56a49c6730bbe7d47e5e1cec682a2d (diff) | |
| parent | 50cebfe6dbc6dd6740fc2e29b3c543d121bc1a18 (diff) | |
| download | ouroboros-c0b2bb854f42ed5975a5c08465fd0012c9e5ce8c.tar.gz ouroboros-c0b2bb854f42ed5975a5c08465fd0012c9e5ce8c.zip | |
Merged in dstaesse/ouroboros/ipcpd-udp (pull request #57)
ipcpd: initial IPC processes
Diffstat (limited to 'src')
27 files changed, 1633 insertions, 136 deletions
| 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..5c917229 --- /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      response); +        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..0b652ff6 --- /dev/null +++ b/src/ipcpd/ipcp.c @@ -0,0 +1,236 @@ +/* + * 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_arg_check(int argc, char * argv[]) +{ +        if (argc != 4) +                return -1; + +        /* argument 1: pid of irmd */ +        if (atoi(argv[1]) == 0) +                return -1; + +        /* name conformity responsibility of NMS */ + +        /* argument 2: ap name */ +        /* argument 3: instance id */ + +        return 0; +} + +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: +                        if (_ipcp->ops->ipcp_bootstrap == NULL) { +                                LOG_ERR("Bootstrap unsupported."); +                                break; +                        } +                        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("Enroll unsupported."); +                                break; +                        } +                        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("Reg unsupported."); +                                break; + +                        } +                        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("Unreg unsupported."); +                                break; +                        } +                        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: +                        if (_ipcp->ops->ipcp_ap_reg == NULL) { +                                LOG_ERR("Ap_reg unsupported."); +                                break; +                        } +                        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: +                        if (_ipcp->ops->ipcp_ap_unreg == NULL) { +                                LOG_ERR("Ap_unreg unsupported."); +                                break; +                        } +                        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: +                        if (_ipcp->ops->ipcp_flow_alloc == NULL) { +                                LOG_ERR("Flow_alloc unsupported."); +                                break; +                        } +                        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: +                        if (_ipcp->ops->ipcp_flow_alloc_resp == NULL) { +                                LOG_ERR("Flow_alloc_resp unsupported."); +                                break; +                        } +                        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: +                        if (_ipcp->ops->ipcp_flow_dealloc == NULL) { +                                LOG_ERR("Flow_dealloc unsupported."); +                                break; +                        } +                        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..9decac8b --- /dev/null +++ b/src/ipcpd/ipcp.h @@ -0,0 +1,49 @@ +/* + * 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(); +int ipcp_arg_check(int argc, char * argv[]); + +#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..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 <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; + +        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 <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; | 
