diff options
36 files changed, 1876 insertions, 992 deletions
| diff --git a/include/ouroboros/dev.h b/include/ouroboros/dev.h index a0885b70..d5fb744b 100644 --- a/include/ouroboros/dev.h +++ b/include/ouroboros/dev.h @@ -36,9 +36,6 @@  int     ap_init(char * ap_name);  void    ap_fini(void); -/* This call binds an instance to a specific subset of applications */ -int     api_bind(char * ap_subset); -  /* Returns file descriptor (> 0) and client AE name. */  int     flow_accept(char ** ae_name);  int     flow_alloc_resp(int fd, int result); diff --git a/include/ouroboros/irm.h b/include/ouroboros/irm.h index 9f27db05..cfad1295 100644 --- a/include/ouroboros/irm.h +++ b/include/ouroboros/irm.h @@ -31,7 +31,7 @@ pid_t   irm_create_ipcp(char *         name,  int     irm_destroy_ipcp(pid_t api); -/* APIs is an out-parameter */ +/* apis is an out-parameter */  ssize_t irm_list_ipcps(char *   name,                         pid_t ** apis); @@ -41,15 +41,20 @@ int     irm_enroll_ipcp(pid_t  api,  int     irm_bootstrap_ipcp(pid_t               api,                             struct dif_config * conf); -int     irm_bind(char *   name, -                 char *   ap_name, -                 uint16_t opts, -                 int      argc, -                 char **  argv); +int     irm_bind_ap(char *   ap, +                    char *   name, +                    uint16_t opts, +                    int      argc, +                    char **  argv); -int     irm_unbind(char *   name, -                   char *   ap_name, -                   uint16_t opts); +int     irm_unbind_ap(char * ap, +                      char * name); + +int     irm_bind_api(pid_t api, +                     char * name); + +int     irm_unbind_api(pid_t api, +                       char * name);  int     irm_reg(char *  name,                  char ** difs, diff --git a/include/ouroboros/irm_config.h b/include/ouroboros/irm_config.h index dd68e4ec..f90ad927 100644 --- a/include/ouroboros/irm_config.h +++ b/include/ouroboros/irm_config.h @@ -30,8 +30,7 @@  #define BIND_AP_AUTO   0x01  #define BIND_AP_UNIQUE 0x02 - -#define UNBIND_AP_HARD 0x01 +#define BIND_AP_LOC    0x04  enum ipcp_type {          IPCP_NORMAL = 0, diff --git a/include/ouroboros/list.h b/include/ouroboros/list.h index 49163efd..80fcb28c 100644 --- a/include/ouroboros/list.h +++ b/include/ouroboros/list.h @@ -135,6 +135,16 @@ void list_splice_init(struct list_head * list,          ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))  /** + * list_first_entry - get the struct for the first entry + * expects the list to be non-empty + * @ptr:        the &struct list_head pointer. + * @type:       the type of the struct this is embedded in. + * @member:     the name of the list_struct within the struct. + */ +#define list_first_entry(ptr, type, member) \ +        list_entry((ptr)->next, type, member) + +/**   * list_for_each - iterate over a list   * @pos:        the &struct list_head to use as a loop counter.   * @head:       the head for your list. diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 0263d7b5..cc77af89 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -188,7 +188,7 @@ void * ipcp_main_loop(void * o)                          }                          conf_msg = msg->conf;                          conf.type = conf_msg->ipcp_type; -                        conf.dif_name = strdup(conf_msg->dif_name); +                        conf.dif_name = conf_msg->dif_name;                          if (conf.dif_name == NULL) {                                  ret_msg.has_result = true;                                  ret_msg.result = -1; diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index 437dac13..70afff37 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -79,7 +79,6 @@ static void * fmgr_listen(void * o)  {          int fd;          char * ae_name; -        bool bound = false;          while (true) {                  pthread_mutex_lock(&_ipcp->state_lock); @@ -94,14 +93,6 @@ static void * fmgr_listen(void * o)                  }                  pthread_mutex_unlock(&_ipcp->state_lock); -                if (!bound && api_bind(_ipcp->data->dif_name) < 0) { -                        LOG_ERR("Failed to bind the server instance."); -                        pthread_mutex_unlock(&_ipcp->state_lock); -                        return (void *) -1; -                } - -                bound = true; -                  fd = flow_accept(&ae_name);                  if (fd < 0) {                          LOG_ERR("Failed to accept flow."); diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index ca068703..05919326 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -7,9 +7,9 @@ include_directories(${CMAKE_BINARY_DIR}/include)  set(SOURCE_FILES          # Add source files here          api_table.c +        apn_table.c          irm_flow.c          main.c -        reg_api.c          registry.c          utils.c  ) diff --git a/src/irmd/api_table.c b/src/irmd/api_table.c index b62b2b55..2747ed1a 100644 --- a/src/irmd/api_table.c +++ b/src/irmd/api_table.c @@ -23,92 +23,208 @@  #include <ouroboros/config.h>  #include <ouroboros/list.h>  #include <ouroboros/errno.h> +#include <ouroboros/time_utils.h>  #include "api_table.h" +#include "registry.h"  #include <stdlib.h> +#include <unistd.h> +#include <limits.h> -struct api_entry * api_entry_create(pid_t api, -                                    char * apn, -                                    char * ap_subset) +struct api_entry * api_entry_create(pid_t api, char * apn)  { -        struct api_entry * e = malloc(sizeof(*e)); +        struct api_entry * e; + +        if (apn == NULL) +                return NULL; + +        e = malloc(sizeof(*e));          if (e == NULL)                  return NULL;          INIT_LIST_HEAD(&e->next); +        INIT_LIST_HEAD(&e->names); + +        e->api      = api; +        e->apn      = apn; +        e->daf_name = NULL; -        e->api = api; -        e->apn = apn; -        e->ap_subset = ap_subset; +        e->re       = NULL; + +        e->state    = API_INIT; + +        pthread_mutex_init(&e->state_lock, NULL); +        pthread_cond_init(&e->state_cond, NULL);          return e;  }  void api_entry_destroy(struct api_entry * e)  { +        struct list_head * p; +        struct list_head * h; + +        if (e == NULL) +                return; + +        pthread_mutex_lock(&e->state_lock); + +        if (e->state == API_SLEEP) +                e->state = API_DESTROY; + +        pthread_cond_signal(&e->state_cond); + +        while (e->state != API_INIT) +                pthread_cond_wait(&e->state_cond, &e->state_lock); + +        pthread_mutex_unlock(&e->state_lock); + +        pthread_cond_destroy(&e->state_cond); +        pthread_mutex_destroy(&e->state_lock); +          if (e->apn != NULL)                  free(e->apn); -        if (e->ap_subset != NULL) -                free(e->ap_subset); + +        list_for_each_safe(p, h, &e->names) { +                struct str_el * n = list_entry(p, struct str_el, next); +                list_del(&n->next); +                if (n->str != NULL) +                        free(n->str); +                free(n); +        } +          free(e);  } -int api_table_add_api(struct list_head * api_table, -                      pid_t api, char * apn, char * ap_subset) +int api_entry_add_name(struct api_entry * e, char * name)  { -        if (apn == NULL) +        struct str_el * s; +        if (e == NULL || name == NULL)                  return -EINVAL; -        struct api_entry * e = api_entry_create(api, apn, ap_subset); -        if (e == NULL) +        s = malloc(sizeof(*s)); +        if (s == NULL)                  return -ENOMEM; -        list_add(&e->next, api_table); +        s->str = name; +        list_add(&s->next, &e->names);          return 0;  } -void api_table_del_api(struct list_head * api_table, pid_t api) +void api_entry_del_name(struct api_entry * e, char * name)  { -        struct list_head * p; -        struct list_head * h; +        struct list_head * p = NULL; +        struct list_head * h = NULL; + +        list_for_each_safe(p, h, &e->names) { +                struct str_el * s = list_entry(p, struct str_el, next); +                if (!wildcard_match(name, s->str)) { +                        list_del(&s->next); +                        if (s->str != NULL) +                                free(s->str); +                        free(s); +                } +        } +} -        list_for_each_safe(p, h, api_table) { -                struct api_entry * e = -                        list_entry(p, struct api_entry, next); +int api_entry_sleep(struct api_entry * e) +{ +        struct timespec timeout = {(IRMD_ACCEPT_TIMEOUT / 1000), +                                   (IRMD_ACCEPT_TIMEOUT % 1000) * MILLION}; +        struct timespec now; +        struct timespec dl; -                if (api == e->api) { -                        list_del(&e->next); -                        api_entry_destroy(e); +        int ret = 0; + +        if (e == NULL) +                return -EINVAL; + +        e->re = NULL; + +        clock_gettime(CLOCK_REALTIME, &now); + +        ts_add(&now, &timeout, &dl); + +        pthread_mutex_lock(&e->state_lock); +        if (e->state != API_INIT) { +                pthread_mutex_unlock(&e->state_lock); +                return -EINVAL; +        } + +        e->state = API_SLEEP; + +        while (e->state == API_SLEEP) { +                if ((ret = -pthread_cond_timedwait(&e->state_cond, +                                                   &e->state_lock, +                                                   &dl)) == -ETIMEDOUT) { +                        break;                  }          } + +        e->state = API_INIT; +        pthread_cond_broadcast(&e->state_cond); +        pthread_mutex_unlock(&e->state_lock); + +        return ret;  } -char * api_table_get_apn(struct list_head * api_table, pid_t api) +void api_entry_wake(struct api_entry * e, struct reg_entry * re)  { -        struct list_head * h; +        if (e == NULL) +                return; -        list_for_each(h, api_table) { -                struct api_entry * e = -                        list_entry(h, struct api_entry, next); +        pthread_mutex_lock(&e->state_lock); -                if (api == e->api) -                        return e->apn; +        if (e->state == API_NULL) { +                pthread_mutex_unlock(&e->state_lock); +                return;          } -        return NULL; +        e->state = API_WAKE; +        e->re    = re; + +        pthread_cond_broadcast(&e->state_cond); + +        while (e->state == API_WAKE) +                pthread_cond_wait(&e->state_cond, &e->state_lock); + +        pthread_mutex_unlock(&e->state_lock); +} + +int api_table_add(struct list_head * api_table, struct api_entry * e) +{ +        if (api_table == NULL || e == NULL) +                return -EINVAL; + +        list_add(&e->next, api_table); + +        return 0;  } -char * api_table_get_ap_subset(struct list_head * api_table, pid_t api) + +void api_table_del(struct list_head * api_table, pid_t api)  { +        struct list_head * p;          struct list_head * h; -        list_for_each(h, api_table) { -                struct api_entry * e = -                        list_entry(h, struct api_entry, next); +        list_for_each_safe(p, h, api_table) { +                struct api_entry * e = list_entry(p, struct api_entry, next); +                if (api == e->api) { +                        list_del(&e->next); +                        api_entry_destroy(e); +                } +        } +} +struct api_entry * api_table_get(struct list_head * api_table, pid_t api) +{ +        struct list_head * h; + +        list_for_each(h, api_table) { +                struct api_entry * e = list_entry(h, struct api_entry, next);                  if (api == e->api) -                        return e->ap_subset; +                        return e;          }          return NULL; diff --git a/src/irmd/api_table.h b/src/irmd/api_table.h index 694de6da..0758fdb8 100644 --- a/src/irmd/api_table.h +++ b/src/irmd/api_table.h @@ -23,24 +23,57 @@  #ifndef OUROBOROS_IRMD_API_TABLE_H  #define OUROBOROS_IRMD_API_TABLE_H +#include "utils.h" +  #include <unistd.h> +#include <pthread.h> + +enum api_state { +        API_NULL = 0, +        API_INIT, +        API_SLEEP, +        API_WAKE, +        API_DESTROY +};  struct api_entry { -        struct list_head next; -        pid_t  api; -        char * apn; -        char * ap_subset; /* unique instance identifier */ +        struct list_head   next; +        pid_t              api; +        char *             apn;      /* application process instantiated */ +        char *             daf_name; /* DAF this AP-I belongs to */ +        struct list_head   names;    /* names for which this api accepts flows */ + +        struct reg_entry * re;       /* reg_entry for which a flow arrived */ + +        /* the api will block on this */ +        enum api_state     state; +        pthread_cond_t     state_cond; +        pthread_mutex_t    state_lock;  }; -struct api_entry * api_entry_create(pid_t api, char * apn, char * ap_subset); +struct api_entry * api_entry_create(pid_t  api, +                                    char * apn); +  void               api_entry_destroy(struct api_entry * e); -int    api_table_add_api(struct list_head * api_table, -                         pid_t api, -                         char * apn, -                         char * ap_subset); -void   api_table_del_api(struct list_head * api_table, pid_t api); -char * api_table_get_apn(struct list_head * api_table, pid_t api); -char * api_table_get_ap_subset(struct list_head * api_table, pid_t api); +int                api_entry_sleep(struct api_entry * e); + +void               api_entry_wake(struct api_entry * e, +                                  struct reg_entry * re); + +int                api_entry_add_name(struct api_entry * e, +                                      char *             name); + +void               api_entry_del_name(struct api_entry * e, +                                      char *             name); + +int                api_table_add(struct list_head * api_table, +                                 struct api_entry * e); + +void               api_table_del(struct list_head * api_table, +                                 pid_t              api); + +struct api_entry * api_table_get(struct list_head * api_table, +                                 pid_t              api);  #endif /* OUROBOROS_IRMD_API_TABLE_H */ diff --git a/src/irmd/apn_table.c b/src/irmd/apn_table.c new file mode 100644 index 00000000..31c45a78 --- /dev/null +++ b/src/irmd/apn_table.c @@ -0,0 +1,164 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - Application Process Table + * + *    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/errno.h> +#include <ouroboros/irm_config.h> + +#include "apn_table.h" +#include "utils.h" + +#include <stdlib.h> +#include <string.h> + +struct apn_entry * apn_entry_create(char * apn, +                                    char * ap, +                                    uint32_t flags, +                                    char ** argv) +{ +        struct apn_entry * e; +        if (apn == NULL) +                return NULL; + +        e = malloc(sizeof(*e)); +        if (e == NULL) +                return NULL; + +        INIT_LIST_HEAD(&e->next); +        INIT_LIST_HEAD(&e->names); + +        e->apn   = apn; +        e->ap    = ap; +        e->flags = flags; + +        if (flags & BIND_AP_AUTO) { +                e->argv = argv; +        } else { +                e->argv  = NULL; +                argvfree(argv); +                argv = NULL; +        } + +        return e; +} +void apn_entry_destroy(struct apn_entry * e) +{ +        struct list_head * p = NULL; +        struct list_head * h = NULL; + +        if (e == NULL) +                return; + +        if (e->apn != NULL) +                free(e->apn); + +        if (e->ap != NULL) +                free(e->ap); + +        if (e->argv != NULL) +                argvfree(e->argv); + +        list_for_each_safe(p, h, &e->names) { +                struct str_el * s = list_entry(p, struct str_el, next); +                list_del(&s->next); +                if (s->str != NULL) +                        free(s->str); +                free(s); +        } + +        free(e); +} + +int apn_entry_add_name(struct apn_entry * e, char * name) +{ +        struct str_el * s; + +        if (e == NULL || name == NULL) +                return -EINVAL; + +        s = malloc(sizeof(*s)); +        if (s == NULL) +                return -ENOMEM; + +        s->str = name; +        list_add(&s->next, &e->names); + +        return 0; +} + +void apn_entry_del_name(struct apn_entry * e, char * name) +{ +        struct list_head * p = NULL; +        struct list_head * h = NULL; + +        list_for_each_safe(p, h, &e->names) { +                struct str_el * s = list_entry(p, struct str_el, next); +                if (!wildcard_match(name, s->str)) { +                        list_del(&s->next); +                        if (s->str != NULL) +                                free(s->str); +                        free(s); +                } +        } +} + +int apn_table_add(struct list_head * apn_table, struct apn_entry * e) +{ +        if (apn_table == NULL || e == NULL) +                return -EINVAL; + +        list_add(&e->next, apn_table); + +        return 0; +} + +void apn_table_del(struct list_head * apn_table, char * ap) +{ +        struct list_head * p; +        struct list_head * h; + +        if (apn_table == NULL || ap == NULL) +                return; + +        list_for_each_safe(p, h, apn_table) { +                struct apn_entry * e = list_entry(p, struct apn_entry, next); +                if (!wildcard_match(ap, e->ap)) { +                        list_del(&e->next); +                        apn_entry_destroy(e); +                } +        } +} + +struct apn_entry * apn_table_get(struct list_head * apn_table, char * ap) +{ +        struct list_head * p; + +        if (apn_table == NULL || ap == NULL) +                return NULL; + +        list_for_each(p, apn_table) { +                struct apn_entry * e = list_entry(p, struct apn_entry, next); +                if (!strcmp(e->ap, ap)) +                        return e; +        } + +        return NULL; +} diff --git a/src/irmd/apn_table.h b/src/irmd/apn_table.h new file mode 100644 index 00000000..88a2548a --- /dev/null +++ b/src/irmd/apn_table.h @@ -0,0 +1,62 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - Application Process Names Table + * + *    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 OUROBOROS_IRMD_APN_TABLE_H +#define OUROBOROS_IRMD_APN_TABLE_H + +#include <ouroboros/list.h> + +#include <unistd.h> +#include <stdint.h> + +struct apn_entry { +        struct list_head next; +        char *           apn;   /* name for irmd */ +        char *           ap;    /* name of binary */ +        uint32_t         flags; +        char **          argv; +        struct list_head names; /* names that all instances will listen for */ +}; + +struct apn_entry * apn_entry_create(char *   apn, +                                    char *   ap, +                                    uint32_t flags, +                                    char **  argv); + +void               apn_entry_destroy(struct apn_entry * e); + +int                apn_entry_add_name(struct apn_entry * e, +                                      char *             name); + +void               apn_entry_del_name(struct apn_entry * e, +                                      char *             name); + +int                apn_table_add(struct list_head * apn_table, +                                 struct apn_entry * e); + +void               apn_table_del(struct list_head * apn_table, +                                 char *             ap); + +struct apn_entry * apn_table_get(struct list_head * apn_table, +                                 char *             ap); + +#endif /* OUROBOROS_IRMD_APN_TABLE_H */ diff --git a/src/irmd/main.c b/src/irmd/main.c index 102d1872..06cf0e07 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -74,20 +74,15 @@ enum irm_state {          IRMD_RUNNING  }; -struct spawned_api { -        struct list_head next; -        pid_t            api; -}; -  struct irm { -        /* FIXME: list of ipcps could be merged into the registry */ -        struct list_head    ipcps; -          struct list_head    registry; -        pthread_rwlock_t    reg_lock; + +        struct list_head    ipcps;          struct list_head    api_table; +        struct list_head    apn_table;          struct list_head    spawned_apis; +        pthread_rwlock_t    reg_lock;          /* keep track of all flows in this processing system */          struct bmp *        port_ids; @@ -103,7 +98,7 @@ struct irm {          enum irm_state      state;          pthread_rwlock_t    state_lock; -        pthread_t           cleanup_flows; +        pthread_t           irm_sanitize;          pthread_t           shm_sanitize;  } * irmd = NULL; @@ -165,38 +160,36 @@ static void ipcp_entry_destroy(struct ipcp_entry * e)  static struct ipcp_entry * get_ipcp_entry_by_api(pid_t api)  { -        struct list_head * pos = NULL; +        struct list_head * p = NULL; -        list_for_each(pos, &irmd->ipcps) { -                struct ipcp_entry * tmp = -                        list_entry(pos, struct ipcp_entry, next); -                if (api == tmp->api) -                        return tmp; +        list_for_each(p, &irmd->ipcps) { +                struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); +                if (api == e->api) +                        return e;          }          return NULL;  } -  /* FIXME: Check if the name exists anywhere in a DIF. */  static pid_t get_ipcp_by_dst_name(char * dst_name)  { -        struct list_head * pos = NULL; +        struct list_head * p = NULL;          char * dif_name =                  registry_get_dif_for_dst(&irmd->registry, dst_name);          if (dif_name == NULL) { -                list_for_each(pos, &irmd->ipcps) { +                list_for_each(p, &irmd->ipcps) {                          struct ipcp_entry * e = -                                list_entry(pos, struct ipcp_entry, next); +                                list_entry(p, struct ipcp_entry, next);                          if (e->type == IPCP_NORMAL) {                                  dif_name = e->dif_name;                                  break;                          }                  } -                list_for_each(pos, &irmd->ipcps) { +                list_for_each(p, &irmd->ipcps) {                          struct ipcp_entry * e = -                                list_entry(pos, struct ipcp_entry, next); +                                list_entry(p, struct ipcp_entry, next);                          if (e->type == IPCP_SHIM_ETH_LLC) {                                  dif_name = e->dif_name;                                  break; @@ -204,9 +197,9 @@ static pid_t get_ipcp_by_dst_name(char * dst_name)                  } -                list_for_each(pos, &irmd->ipcps) { +                list_for_each(p, &irmd->ipcps) {                          struct ipcp_entry * e = -                                list_entry(pos, struct ipcp_entry, next); +                                list_entry(p, struct ipcp_entry, next);                          if (e->type == IPCP_SHIM_UDP) {                                  dif_name = e->dif_name;                                  break; @@ -217,9 +210,8 @@ static pid_t get_ipcp_by_dst_name(char * dst_name)          if (dif_name == NULL)                  return -1; -        list_for_each(pos, &irmd->ipcps) { -                struct ipcp_entry * e = -                        list_entry(pos, struct ipcp_entry, next); +        list_for_each(p, &irmd->ipcps) { +                struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next);                  if (strcmp(e->dif_name, dif_name) == 0)                          return e->api;          } @@ -230,10 +222,9 @@ static pid_t get_ipcp_by_dst_name(char * dst_name)  static pid_t create_ipcp(char *         name,                           enum ipcp_type ipcp_type)  { -        struct spawned_api * api = NULL; +        struct pid_el *      api = NULL;          struct ipcp_entry *  tmp = NULL; - -        struct list_head * pos; +        struct list_head *   p   = NULL;          api = malloc(sizeof(*api));          if (api == NULL) @@ -248,8 +239,8 @@ static pid_t create_ipcp(char *         name,          pthread_rwlock_wrlock(&irmd->reg_lock); -        api->api = ipcp_create(ipcp_type); -        if (api->api == -1) { +        api->pid = ipcp_create(ipcp_type); +        if (api->pid == -1) {                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock);                  LOG_ERR("Failed to create IPCP."); @@ -265,7 +256,7 @@ static pid_t create_ipcp(char *         name,          INIT_LIST_HEAD(&tmp->next); -        tmp->api = api->api; +        tmp->api = api->pid;          tmp->name = strdup(name);          if (tmp->name  == NULL) {                  ipcp_entry_destroy(tmp); @@ -281,9 +272,8 @@ static pid_t create_ipcp(char *         name,          tmp->type = ipcp_type;          tmp->init = false; -        list_for_each(pos, &irmd->ipcps) { -                struct ipcp_entry * e = -                        list_entry(pos, struct ipcp_entry, next); +        list_for_each(p, &irmd->ipcps) { +                struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next);                  if (e->type < ipcp_type)                          break;          } @@ -302,9 +292,9 @@ static pid_t create_ipcp(char *         name,          pthread_mutex_unlock(&tmp->init_lock); -        LOG_INFO("Created IPCP %d.", api->api); +        LOG_INFO("Created IPCP %d.", api->pid); -        return api->api; +        return api->pid;  }  static int create_ipcp_r(pid_t api) @@ -338,10 +328,8 @@ static void clear_spawned_api(pid_t api)          struct list_head * n   = NULL;          list_for_each_safe(pos, n, &(irmd->spawned_apis)) { -                struct spawned_api * a = -                        list_entry(pos, struct spawned_api, next); - -                if (api == a->api) { +                struct pid_el * a = list_entry(pos, struct pid_el, next); +                if (api == a->pid) {                          list_del(&a->next);                          free(a);                  } @@ -473,17 +461,20 @@ static int enroll_ipcp(pid_t  api,          return 0;  } -static int bind_name(char *   name, -                     char *   ap_name, -                     uint16_t opts, -                     int      argc, -                     char **  argv) +static int bind_ap(char *   ap, +                   char *   name, +                   uint16_t flags, +                   int      argc, +                   char **  argv)  { -        char * apn       = path_strip(ap_name); +        char * aps; +        char * apn;          char ** argv_dup = NULL; -        int i            = 0; +        int i; +        char * name_dup = NULL; +        struct apn_entry * e = NULL; -        if (name == NULL || ap_name == NULL) +        if (ap == NULL || name == NULL)                  return -EINVAL;          pthread_rwlock_rdlock(&irmd->state_lock); @@ -495,44 +486,90 @@ static int bind_name(char *   name,          pthread_rwlock_wrlock(&irmd->reg_lock); -        if (opts & BIND_AP_AUTO) { -                /* we need to duplicate argv */ -                if (argc != 0) { +        e = apn_table_get(&irmd->apn_table, path_strip(ap)); + +        if (e == NULL) { +                aps = strdup(path_strip(ap)); +                if (aps == NULL) { +                        pthread_rwlock_unlock(&irmd->reg_lock); +                        pthread_rwlock_unlock(&irmd->state_lock); +                        return -ENOMEM; +                } + +                apn = strdup(name); +                if (apn == NULL) { +                        pthread_rwlock_unlock(&irmd->reg_lock); +                        pthread_rwlock_unlock(&irmd->state_lock); +                        free(aps); +                        return -ENOMEM; +                } + +                if ((flags & BIND_AP_AUTO) && argc) { +                /* we need to duplicate argv and set argv[0] to ap */                          argv_dup = malloc((argc + 2) * sizeof(*argv_dup)); -                        argv_dup[0] = strdup(ap_name); -                        for (i = 1; i <= argc; ++i) +                        argv_dup[0] = strdup(ap); +                        for (i = 1; i <= argc; ++i) {                                  argv_dup[i] = strdup(argv[i - 1]); +                                if (argv_dup[i] == NULL) { +                                        pthread_rwlock_unlock(&irmd->reg_lock); +                                        pthread_rwlock_unlock( +                                                &irmd->state_lock); +                                        argvfree(argv_dup); +                                        LOG_ERR("Failed to bind ap %s to  %s.", +                                                ap, name); +                                        free(aps); +                                        free(apn); +                                        return -ENOMEM; +                                } +                        }                          argv_dup[argc + 1] = NULL;                  } +                e = apn_entry_create(apn, aps, flags, argv_dup); +                if (e == NULL) { +                        pthread_rwlock_unlock(&irmd->reg_lock); +                        pthread_rwlock_unlock(&irmd->state_lock); +                        free(aps); +                        free(apn); +                        argvfree(argv_dup); +                        return -ENOMEM; +                } + +                apn_table_add(&irmd->apn_table, e); + +        } + +        name_dup = strdup(name); +        if (name_dup == NULL) { +                pthread_rwlock_unlock(&irmd->state_lock); +                return -ENOMEM;          } -        if (registry_add_binding(&irmd->registry, -                                 strdup(name), strdup(apn), -                                 opts, argv_dup) < 0) { +        if (apn_entry_add_name(e, name_dup)) { +                LOG_ERR("Failed adding name.");                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock); -                LOG_ERR("Failed to register %s.", name); -                return -1; +                free(name_dup); +                return -ENOMEM;          }          pthread_rwlock_unlock(&irmd->reg_lock);          pthread_rwlock_unlock(&irmd->state_lock); -        LOG_INFO("Bound %s to registered name %s.", ap_name, name); +        LOG_INFO("Bound AP %s to name %s.", ap, name);          return 0;  } -static int unbind_name(char *   name, -                       char *   apn, -                       uint16_t opts) - +static int bind_api(pid_t  api, +                    char * name)  { +        char * name_dup = NULL; +        struct api_entry * e = NULL; +          if (name == NULL)                  return -EINVAL; -        if (!(opts & UNBIND_AP_HARD) && apn == NULL) -                return -EINVAL; +        LOG_DBG("BIND_API called %d, %s", api, name);          pthread_rwlock_rdlock(&irmd->state_lock); @@ -543,23 +580,99 @@ static int unbind_name(char *   name,          pthread_rwlock_wrlock(&irmd->reg_lock); -        if ((opts & UNBIND_AP_HARD) && apn == NULL) { -                registry_deassign(&irmd->registry, name); -                pthread_rwlock_unlock(&irmd->reg_lock); +        e = api_table_get(&irmd->api_table, api); +        if (e == NULL) { +                LOG_ERR("AP-I %d does not exist.", api); +                pthread_rwlock_wrlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock); -                LOG_INFO("Removed all bindings of %s.", name); -        } else { -                registry_del_binding(&irmd->registry, name, apn); +                return -1; +        } + +        name_dup = strdup(name); +        if (name_dup == NULL) { +                pthread_rwlock_wrlock(&irmd->reg_lock); +                pthread_rwlock_unlock(&irmd->state_lock); +                return -ENOMEM; +        } + +        if (api_entry_add_name(e, name_dup)) {                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock); -                LOG_INFO("Removed binding from %s to %s.", apn, name); +                LOG_ERR("Failed to add name %s to api %d.", name, api); +                free(name_dup); +                return -1; +        } + +        pthread_rwlock_unlock(&irmd->reg_lock); +        pthread_rwlock_unlock(&irmd->state_lock); + +        LOG_INFO("Bound AP-I %d to name %s.", api, name); + +        return 0; +} + +static int unbind_ap(char * ap, char * name) +{ +        if (ap == NULL) +                return -EINVAL; + +        pthread_rwlock_rdlock(&irmd->state_lock); + +        if (irmd->state != IRMD_RUNNING) { +                pthread_rwlock_unlock(&irmd->state_lock); +                return -1;          } +        pthread_rwlock_wrlock(&irmd->reg_lock); + +        if (name == NULL) +                apn_table_del(&irmd->apn_table, ap); +        else { +                struct apn_entry * e = apn_table_get(&irmd->apn_table, ap); +                apn_entry_del_name(e, name); +        } + +        pthread_rwlock_unlock(&irmd->reg_lock); +        pthread_rwlock_unlock(&irmd->state_lock); + +        if (name  == NULL) +                LOG_INFO("AP %s removed.", ap); +        else +                LOG_INFO("All names matching %s cleared for %s.", name, ap); +          return 0;  } -static ssize_t list_ipcps(char * name, -                          pid_t ** apis) +static int unbind_api(pid_t api, char * name) +{ +        pthread_rwlock_rdlock(&irmd->state_lock); + +        if (irmd->state != IRMD_RUNNING) { +                pthread_rwlock_unlock(&irmd->state_lock); +                return -1; +        } + +        pthread_rwlock_wrlock(&irmd->reg_lock); + +        if (name == NULL) +                api_table_del(&irmd->api_table, api); +        else { +                struct api_entry * e = api_table_get(&irmd->api_table, api); +                api_entry_del_name(e, name); +        } + +        pthread_rwlock_unlock(&irmd->reg_lock); +        pthread_rwlock_unlock(&irmd->state_lock); + +        if (name  == NULL) +                LOG_INFO("AP-I %d removed.", api); +        else +                LOG_INFO("All names matching %s cleared for %d.", name, api); + +        return 0; +} + +static ssize_t list_ipcps(char * name, pid_t ** apis)  {          struct list_head * pos = NULL;          ssize_t count = 0; @@ -571,10 +684,8 @@ static ssize_t list_ipcps(char * name,          list_for_each(pos, &irmd->ipcps) {                  struct ipcp_entry * tmp =                          list_entry(pos, struct ipcp_entry, next); - -                if (wildcard_match(name, tmp->name) == 0) { +                if (wildcard_match(name, tmp->name) == 0)                          count++; -                }          }          *apis = malloc(count * sizeof(pid_t)); @@ -587,10 +698,8 @@ static ssize_t list_ipcps(char * name,          list_for_each(pos, &irmd->ipcps) {                  struct ipcp_entry * tmp =                          list_entry(pos, struct ipcp_entry, next); - -                if (wildcard_match(name, tmp->name) == 0) { +                if (wildcard_match(name, tmp->name) == 0)                          (*apis)[i++] = tmp->api; -                }          }          pthread_rwlock_unlock(&irmd->reg_lock); @@ -599,13 +708,11 @@ static ssize_t list_ipcps(char * name,          return count;  } -static int ap_reg(char *  name, -                  char ** difs, -                  size_t  len) +static int name_reg(char *  name, char ** difs, size_t  len)  {          int i;          int ret = 0; -        struct list_head * pos = NULL; +        struct list_head * p = NULL;          if (name == NULL || difs == NULL || len == 0 || difs[0] == NULL)                  return -EINVAL; @@ -625,10 +732,44 @@ static int ap_reg(char *  name,                  return -1;          } -        list_for_each(pos, &irmd->ipcps) { -                struct ipcp_entry * e = -                        list_entry(pos, struct ipcp_entry, next); +        if (!registry_has_name(&irmd->registry, name)) { +                struct reg_entry * re = +                        registry_add_name(&irmd->registry, strdup(name)); +                if (re == NULL) { +                        LOG_ERR("Failed creating registry entry for %s.", name); +                        pthread_rwlock_unlock(&irmd->reg_lock); +                        pthread_rwlock_unlock(&irmd->state_lock); +                        return -1; +                } + +                /* check the tables for client ap's */ +                list_for_each(p, &irmd->api_table) { +                        struct list_head * q; +                        struct api_entry * e = +                                list_entry(p, struct api_entry, next); +                        list_for_each(q, &e->names) { +                                struct str_el * s = +                                        list_entry(q, struct str_el, next); +                                if (!strcmp(s->str, name)) +                                        reg_entry_add_api(re, e->api); +                        } +                } + +                list_for_each(p, &irmd->apn_table) { +                        struct list_head * q; +                        struct apn_entry * e = +                                list_entry(p, struct apn_entry, next); +                        list_for_each(q, &e->names) { +                                struct str_el * s = +                                        list_entry(q, struct str_el, next); +                                if (!strcmp(s->str, name)) +                                        reg_entry_add_apn(re, e); +                        } +                } +        } +        list_for_each(p, &irmd->ipcps) { +                struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next);                  if (e->dif_name == NULL)                          continue; @@ -647,14 +788,15 @@ static int ap_reg(char *  name,                                          LOG_WARN("Registered unbound name %s. "                                                   "Registry may be inconsistent",                                                   name); -                                LOG_INFO("Registered %s in %s.", -                                         name, e->dif_name); +                                LOG_INFO("Registered %s in %s as %s.", +                                         name, e->dif_name, name);                                  ++ret;                          }                  }          }          if (ret == 0) { +                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock);                  return -1; @@ -666,9 +808,7 @@ static int ap_reg(char *  name,          return ret;  } -static int ap_unreg(char *  name, -                    char ** difs, -                    size_t  len) +static int name_unreg(char *  name, char ** difs, size_t  len)  {          int i;          int ret = 0; @@ -717,11 +857,11 @@ static int ap_unreg(char *  name,          return ret;  } -static int api_bind(pid_t api, char * apn, char * ap_subset) +static int api_announce(pid_t api, char * apn)  { -        int ret = 0; +        struct api_entry * e = NULL; +        struct apn_entry * a = NULL;          char * apn_dup; -        char * ap_s_dup = ap_subset;          if (apn == NULL)                  return -EINVAL; @@ -732,43 +872,60 @@ static int api_bind(pid_t api, char * apn, char * ap_subset)                  return -EPERM;          } -        pthread_rwlock_wrlock(&irmd->reg_lock); -          apn_dup = strdup(apn);          if (apn_dup == NULL) { -                pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock);                  return -ENOMEM;          } -        if (ap_subset != NULL) { -                ap_s_dup = strdup(ap_subset); -                if (ap_s_dup == NULL) { -                        pthread_rwlock_unlock(&irmd->reg_lock); -                        pthread_rwlock_unlock(&irmd->state_lock); -                        return -ENOMEM; -                } +        e = api_entry_create(api, apn_dup); +        if (e == NULL) { +                pthread_rwlock_unlock(&irmd->state_lock); +                return -ENOMEM;          } -        ret = api_table_add_api(&irmd->api_table, -                                api, -                                apn_dup, -                                ap_s_dup); +        pthread_rwlock_wrlock(&irmd->reg_lock); + +        api_table_add(&irmd->api_table, e); + +        /* copy listen names from apn if it exists */ + +        a = apn_table_get(&irmd->apn_table, e->apn); +        if (a != NULL) { +                struct list_head * p; +                list_for_each(p, &a->names) { +                        struct str_el * s = list_entry(p, struct str_el, next); +                        struct str_el * n = malloc(sizeof(*n)); +                        if (n == NULL) { +                                pthread_rwlock_unlock(&irmd->reg_lock); +                                pthread_rwlock_unlock(&irmd->state_lock); +                                return -ENOMEM; +                        } +                        n->str = strdup(s->str); +                        if (n->str == NULL) { +                                pthread_rwlock_unlock(&irmd->reg_lock); +                                pthread_rwlock_unlock(&irmd->state_lock); +                                free(n); +                        } + +                        list_add(&n->next, &e->names); +                        LOG_DBG("API %d inherits listen name %s from AP %s.", +                                api, n->str, e->apn); +                } +        }          pthread_rwlock_unlock(&irmd->reg_lock);          pthread_rwlock_unlock(&irmd->state_lock); -        return ret; +        return 0;  } -static struct irm_flow * flow_accept(pid_t   api, -                                     char ** dst_ae_name) +static struct irm_flow * flow_accept(pid_t api, char ** dst_ae_name)  { -        struct irm_flow *  f   = NULL; -        struct reg_entry * rne = NULL; -        struct reg_api *   rgi = NULL; - -        char * srv_ap_name; +        struct irm_flow *  f  = NULL; +        struct api_entry * e  = NULL; +        struct reg_entry * re = NULL; +        struct list_head * p;          pthread_rwlock_rdlock(&irmd->state_lock); @@ -779,36 +936,31 @@ static struct irm_flow * flow_accept(pid_t   api,          pthread_rwlock_wrlock(&irmd->reg_lock); -        srv_ap_name = api_table_get_apn(&irmd->api_table, api); -        if (srv_ap_name == NULL) -                return NULL; - -        rne = registry_get_entry_by_apn(&irmd->registry, srv_ap_name); -        if (rne == NULL) { -                pthread_rwlock_unlock(&irmd->reg_lock); -                pthread_rwlock_unlock(&irmd->state_lock); -                LOG_ERR("AP %s is unknown.", srv_ap_name); +        e = api_table_get(&irmd->api_table, api); +        if (e == NULL) { +                /* Can only happen if server called ap_init(NULL); */ +                LOG_ERR("Unknown instance %d calling accept.", api);                  return NULL;          } -        if ((rgi = reg_entry_get_reg_api(rne, api)) == NULL) { -                rgi = registry_add_api_name(&irmd->registry, -                                            api, -                                            rne->name); -                if (rgi == NULL) { -                        pthread_rwlock_unlock(&irmd->reg_lock); -                        pthread_rwlock_unlock(&irmd->state_lock); -                        LOG_ERR("Failed to register instance %d with %s.", -                                api,srv_ap_name); -                        return NULL; +        LOG_INFO("New instance (%d) of %s added.", api, e->apn); + +        LOG_DBG("This instance accepts flows for:"); +        list_for_each(p, &e->names) { +                struct str_el * s = list_entry(p, struct str_el, next); +                LOG_DBG("        %s", s->str); +                re = registry_get_entry(&irmd->registry, s->str); +                if (re != NULL) { +                        pthread_mutex_lock(&re->state_lock); +                        reg_entry_add_api(re, api); +                        pthread_mutex_unlock(&re->state_lock);                  } -                LOG_INFO("New instance (%d) of %s added.", api, srv_ap_name);          }          pthread_rwlock_unlock(&irmd->reg_lock);          pthread_rwlock_unlock(&irmd->state_lock); -        while (reg_api_sleep(rgi) == -ETIMEDOUT) { +        while (api_entry_sleep(e) == -ETIMEDOUT) {                  pthread_rwlock_rdlock(&irmd->state_lock);                  if (irmd->state != IRMD_RUNNING) {                          pthread_rwlock_unlock(&irmd->state_lock); @@ -818,17 +970,37 @@ static struct irm_flow * flow_accept(pid_t   api,          }          pthread_rwlock_rdlock(&irmd->state_lock); + +        if (irmd->state != IRMD_RUNNING) { +                pthread_rwlock_unlock(&irmd->state_lock); +                return NULL; +        } +          pthread_rwlock_rdlock(&irmd->reg_lock); -        pthread_mutex_lock(&rne->state_lock); -        if (rne->state != REG_NAME_FLOW_ARRIVED) { -                pthread_mutex_unlock(&rne->state_lock); +        e = api_table_get(&irmd->api_table, api); +        if (e == NULL) { +                LOG_DBG("Process gone while accepting flow.");                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock);                  return NULL;          } -        pthread_mutex_unlock(&rne->state_lock); +        pthread_mutex_lock(&e->state_lock); + +        re = e->re; + +        pthread_mutex_unlock(&e->state_lock); + +        pthread_mutex_lock(&re->state_lock); + +        if (re->state != REG_NAME_FLOW_ARRIVED) { +                pthread_mutex_unlock(&re->state_lock); +                pthread_rwlock_unlock(&irmd->reg_lock); +                pthread_rwlock_unlock(&irmd->state_lock); +                return NULL; +        } +        pthread_mutex_unlock(&re->state_lock);          pthread_rwlock_unlock(&irmd->reg_lock);          pthread_rwlock_rdlock(&irmd->flows_lock); @@ -842,7 +1014,7 @@ static struct irm_flow * flow_accept(pid_t   api,          }          if (dst_ae_name != NULL) -                *dst_ae_name = rne->req_ae_name; +                *dst_ae_name = re->req_ae_name;          pthread_rwlock_unlock(&irmd->flows_lock);          pthread_rwlock_unlock(&irmd->state_lock); @@ -854,10 +1026,14 @@ static int flow_alloc_resp(pid_t n_api,                             int   port_id,                             int   response)  { -        struct irm_flow * f    = NULL; -        struct reg_entry * rne = NULL; +        struct irm_flow *  f  = NULL; +        struct reg_entry * re = NULL; +        struct api_entry * e  = NULL;          int ret = -1; +        pid_t f_n_1_api; +        pid_t f_n_api; +          pthread_rwlock_rdlock(&irmd->state_lock);          if (irmd->state != IRMD_RUNNING) { @@ -867,51 +1043,63 @@ static int flow_alloc_resp(pid_t n_api,          pthread_rwlock_wrlock(&irmd->reg_lock); -        rne = registry_get_entry_by_api(&irmd->registry, n_api); -        if (rne == NULL) { +        e = api_table_get(&irmd->api_table, n_api); +        if (e == NULL) {                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock); +                LOG_ERR("Unknown AP-I %d responding for port_id %d.", +                        n_api, port_id);                  return -1;          } -        pthread_mutex_lock(&rne->state_lock); +        re = e->re; +        if (re == NULL) { +                pthread_rwlock_unlock(&irmd->reg_lock); +                pthread_rwlock_unlock(&irmd->state_lock); +                LOG_ERR("AP-I %d is not handling a flow request.", n_api); +                return -1; +        } + +        pthread_mutex_lock(&re->state_lock); -        if (rne->state != REG_NAME_FLOW_ARRIVED) { -                pthread_mutex_unlock(&rne->state_lock); +        if (re->state != REG_NAME_FLOW_ARRIVED) { +                pthread_mutex_unlock(&re->state_lock);                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock); -                LOG_ERR("Process not listening for this name."); +                LOG_ERR("Name %s has no pending flow request.", re->name);                  return -1;          } -        pthread_mutex_unlock(&rne->state_lock); +        pthread_mutex_unlock(&re->state_lock);          registry_del_api(&irmd->registry, n_api);          pthread_rwlock_unlock(&irmd->reg_lock); -        if (!response) { -                pthread_rwlock_wrlock(&irmd->flows_lock); +        pthread_rwlock_wrlock(&irmd->flows_lock); -                f = get_irm_flow(port_id); -                if (f == NULL) { -                        pthread_rwlock_unlock(&irmd->flows_lock); -                        pthread_rwlock_unlock(&irmd->state_lock); -                        return -1; -                } +        f = get_irm_flow(port_id); +        if (f == NULL) { +                pthread_rwlock_unlock(&irmd->flows_lock); +                pthread_rwlock_unlock(&irmd->state_lock); +                return -1; +        } +        f_n_api   = f->n_api; +        f_n_1_api = f->n_1_api; + +        if (!response) {                  f->state = FLOW_ALLOCATED;                  pthread_cond_signal(&f->state_cond); -                pthread_rwlock_unlock(&irmd->flows_lock); - -                ret = ipcp_flow_alloc_resp(f->n_1_api, -                                           port_id, -                                           f->n_api, -                                           response);          } +        pthread_rwlock_unlock(&irmd->flows_lock);          pthread_rwlock_unlock(&irmd->state_lock); +        ret = ipcp_flow_alloc_resp(f_n_1_api, +                                   port_id, +                                   f_n_api, +                                   response);          return ret;  } @@ -1078,6 +1266,8 @@ static int flow_dealloc(int port_id)          irm_flow_destroy(f); +        LOG_INFO("Deallocated flow with port_id %d.", port_id); +          return ret;  } @@ -1117,13 +1307,15 @@ static struct irm_flow * flow_req_arr(pid_t  api,                                        char * dst_name,                                        char * ae_name)  { -        struct reg_entry * rne = NULL; -        struct irm_flow *  f   = NULL; -        struct reg_api *   rgi = NULL; +        struct reg_entry * re = NULL; +        struct apn_entry * a  = NULL; +        struct api_entry * e  = NULL; +        struct irm_flow *  f  = NULL;          enum reg_name_state state; -        struct spawned_api * c_api; +        struct pid_el * c_api; +        pid_t h_api = -1;          f = irm_flow_create();          if (f == NULL) { @@ -1139,8 +1331,8 @@ static struct irm_flow * flow_req_arr(pid_t  api,          pthread_rwlock_rdlock(&irmd->state_lock);          pthread_rwlock_wrlock(&irmd->reg_lock); -        rne = registry_get_entry_by_name(&irmd->registry, dst_name); -        if (rne == NULL) { +        re = registry_get_entry(&irmd->registry, dst_name); +        if (re == NULL) {                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock);                  LOG_ERR("Unknown name: %s.", dst_name); @@ -1148,9 +1340,9 @@ static struct irm_flow * flow_req_arr(pid_t  api,                  return NULL;          } -        pthread_mutex_lock(&rne->state_lock); -        state = rne->state; -        pthread_mutex_unlock(&rne->state_lock); +        pthread_mutex_lock(&re->state_lock); +        state = re->state; +        pthread_mutex_unlock(&re->state_lock);          switch (state) {          case REG_NAME_IDLE: @@ -1168,17 +1360,19 @@ static struct irm_flow * flow_req_arr(pid_t  api,                          return NULL;                  } -                pthread_mutex_lock(&rne->state_lock); -                rne->state = REG_NAME_AUTO_EXEC; -                pthread_mutex_unlock(&rne->state_lock); +                pthread_mutex_lock(&re->state_lock); -                if ((c_api->api = auto_execute(reg_entry_get_auto_info(rne))) -                    < 0) { -                        pthread_mutex_lock(&rne->state_lock); -                        rne->state = REG_NAME_AUTO_ACCEPT; -                        pthread_mutex_unlock(&rne->state_lock); +                re->state = REG_NAME_AUTO_EXEC; +                a = apn_table_get(&irmd->apn_table, reg_entry_get_apn(re)); +                pthread_mutex_unlock(&re->state_lock); +                if (a == NULL || (c_api->pid = auto_execute(a->argv)) < 0) { +                        pthread_mutex_lock(&re->state_lock); +                        re->state = REG_NAME_AUTO_ACCEPT; +                        pthread_mutex_unlock(&re->state_lock);                          pthread_rwlock_unlock(&irmd->reg_lock);                          pthread_rwlock_unlock(&irmd->state_lock); +                        LOG_ERR("Could not get start apn for reg_entry %s.", +                                re->name);                          free(f);                          free(c_api);                          return NULL; @@ -1189,26 +1383,32 @@ static struct irm_flow * flow_req_arr(pid_t  api,                  pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock); -                pthread_mutex_lock(&rne->state_lock); +                pthread_mutex_lock(&re->state_lock); -                while (rne->state == REG_NAME_AUTO_EXEC) -                        pthread_cond_wait(&rne->state_cond, &rne->state_lock); +                while (re->state == REG_NAME_AUTO_EXEC) +                        pthread_cond_wait(&re->state_cond, &re->state_lock); -                pthread_mutex_unlock(&rne->state_lock); +                pthread_mutex_unlock(&re->state_lock);                  pthread_rwlock_rdlock(&irmd->state_lock);                  pthread_rwlock_rdlock(&irmd->reg_lock); -                pthread_mutex_lock(&rne->state_lock); -                if (rne->state == REG_NAME_DESTROY) { -                        rne->state = REG_NAME_NULL; -                        pthread_mutex_unlock(&rne->state_lock); + +                pthread_mutex_lock(&re->state_lock); + +                if (re->state == REG_NAME_DESTROY) { +                        re->state = REG_NAME_NULL; +                        pthread_mutex_unlock(&re->state_lock);                          pthread_rwlock_unlock(&irmd->reg_lock);                          pthread_rwlock_unlock(&irmd->state_lock);                          return NULL;                  } -                pthread_mutex_unlock(&rne->state_lock); + +                pthread_mutex_unlock(&re->state_lock); +          case REG_NAME_FLOW_ACCEPT: -                f->n_api = reg_entry_resolve_api(rne); +                pthread_mutex_lock(&re->state_lock); +                h_api = f->n_api = reg_entry_get_api(re); +                pthread_mutex_unlock(&re->state_lock);                  if (f->n_api == -1) {                          pthread_rwlock_unlock(&irmd->reg_lock);                          pthread_rwlock_unlock(&irmd->state_lock); @@ -1235,26 +1435,33 @@ static struct irm_flow * flow_req_arr(pid_t  api,          pthread_rwlock_unlock(&irmd->flows_lock);          pthread_rwlock_rdlock(&irmd->reg_lock); -        pthread_mutex_lock(&rne->state_lock); +        pthread_mutex_lock(&re->state_lock); + +        re->req_ae_name = ae_name; +        re->state = REG_NAME_FLOW_ARRIVED; -        rne->req_ae_name = ae_name; +        pthread_mutex_unlock(&re->state_lock); -        rne->state = REG_NAME_FLOW_ARRIVED; +        e = api_table_get(&irmd->api_table, h_api); +        if (e == NULL) { +                LOG_ERR("Could not get api table entry for %d.", h_api); +                pthread_rwlock_unlock(&irmd->reg_lock); +                pthread_rwlock_unlock(&irmd->state_lock); +                free(f); +                return NULL; +        } -        rgi = reg_entry_get_reg_api(rne, f->n_api); +        api_entry_wake(e, re); -        pthread_mutex_unlock(&rne->state_lock);          pthread_rwlock_unlock(&irmd->reg_lock);          pthread_rwlock_unlock(&irmd->state_lock); -        reg_api_wake(rgi); +        pthread_mutex_lock(&re->state_lock); -        pthread_mutex_lock(&rne->state_lock); +        while (re->state == REG_NAME_FLOW_ARRIVED) +                pthread_cond_wait(&re->state_cond, &re->state_lock); -        while (rne->state == REG_NAME_FLOW_ARRIVED) -                pthread_cond_wait(&rne->state_cond, &rne->state_lock); - -        pthread_mutex_unlock(&rne->state_lock); +        pthread_mutex_unlock(&re->state_lock);          return f;  } @@ -1319,8 +1526,8 @@ static int flow_dealloc_ipcp(int port_id)  static void irm_destroy()  { +        struct list_head * p;          struct list_head * h; -        struct list_head * t;          pthread_rwlock_rdlock(&irmd->state_lock); @@ -1332,8 +1539,8 @@ static void irm_destroy()          pthread_rwlock_wrlock(&irmd->reg_lock);          /* clear the lists */ -        list_for_each_safe(h, t, &irmd->ipcps) { -                struct ipcp_entry * e = list_entry(h, struct ipcp_entry, next); +        list_for_each_safe(p, h, &irmd->ipcps) { +                struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next);                  list_del(&e->next);                  ipcp_destroy(e->api);                  clear_spawned_api(e->api); @@ -1342,24 +1549,35 @@ static void irm_destroy()          registry_destroy(&irmd->registry); -        list_for_each_safe(h, t, &irmd->spawned_apis) { -                struct spawned_api * api = -                        list_entry(h, struct spawned_api, next); +        list_for_each_safe(p, h, &irmd->spawned_apis) { +                struct pid_el * e = list_entry(p, struct pid_el, next);                  int status; -                if (kill(api->api, SIGTERM)) -                        LOG_DBG("Could not send kill signal to %d.", api->api); -                else if (waitpid(api->api, &status, 0) < 0) -                        LOG_DBG("Error waiting for %d to exit.", api->api); -                list_del(&api->next); -                free(api); +                if (kill(e->pid, SIGTERM)) +                        LOG_DBG("Could not send kill signal to %d.", e->pid); +                else if (waitpid(e->pid, &status, 0) < 0) +                        LOG_DBG("Error waiting for %d to exit.", e->pid); +                list_del(&e->next); +                free(e); +        } + +        list_for_each_safe(p, h, &irmd->apn_table) { +                struct apn_entry * e = list_entry(p, struct apn_entry, next); +                list_del(&e->next); +                apn_entry_destroy(e); +        } + +        list_for_each_safe(p, h, &irmd->api_table) { +                struct api_entry * e = list_entry(p, struct api_entry, next); +                list_del(&e->next); +                api_entry_destroy(e);          }          pthread_rwlock_unlock(&irmd->reg_lock);          pthread_rwlock_wrlock(&irmd->flows_lock); -        list_for_each_safe(h, t, &irmd->irm_flows) { -                struct irm_flow * f = list_entry(h, struct irm_flow, next); +        list_for_each_safe(p, h, &irmd->irm_flows) { +                struct irm_flow * f = list_entry(p, struct irm_flow, next);                  list_del(&f->next);                  irm_flow_destroy(f);          } @@ -1406,17 +1624,15 @@ void irmd_sig_handler(int sig, siginfo_t * info, void * c)          }  } -void * irm_flow_cleaner() +void * irm_sanitize()  {          struct timespec now; -        struct list_head * pos = NULL; -        struct list_head * n   = NULL; -        struct list_head * h   = NULL; -        struct list_head * t   = NULL; +        struct list_head * p = NULL; +        struct list_head * h = NULL;          struct timespec timeout = {IRMD_CLEANUP_TIMER / BILLION,                                     IRMD_CLEANUP_TIMER % BILLION}; -        int status; +        int s;          while (true) {                  if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) @@ -1430,11 +1646,61 @@ void * irm_flow_cleaner()                          return (void *) 0;                  } +                pthread_rwlock_wrlock(&irmd->reg_lock); + +                list_for_each_safe(p, h, &irmd->spawned_apis) { +                        struct pid_el * e = list_entry(p, struct pid_el, next); +                        if (kill(e->pid, 0) >= 0) +                                continue; +                        waitpid(e->pid, &s, WNOHANG); +                        LOG_DBG("Child process %d died, error %d.", e->pid, s); +                        list_del(&e->next); +                        free(e); +                } + +                list_for_each_safe(p, h, &irmd->api_table) { +                        struct api_entry * e = +                                list_entry(p, struct api_entry, next); +                        if (kill(e->api, 0) >= 0) +                                continue; +                        LOG_DBG("Dead AP-I removed: %d.", e->api); +                        list_del(&e->next); +                        api_entry_destroy(e); +                } + +                list_for_each_safe(p, h, &irmd->ipcps) { +                        struct ipcp_entry * e = +                                list_entry(p, struct ipcp_entry, next); +                        if (kill(e->api, 0) >= 0) +                                continue; +                        LOG_DBG("Dead ipcp removed: %d.", e->api); +                        list_del(&e->next); +                        ipcp_entry_destroy(e); +                } + +                list_for_each_safe(p, h, &irmd->registry) { +                        struct list_head * p2; +                        struct list_head * h2; +                        struct reg_entry * e = +                                list_entry(p, struct reg_entry, next); +                        list_for_each_safe(p2, h2, &e->reg_apis) { +                                struct pid_el * a = +                                        list_entry(p2, struct pid_el, next); +                                if (kill(a->pid, 0) >= 0) +                                        continue; +                                LOG_DBG("Dead AP-I removed from: %d %s.", +                                        a->pid, e->name); +                                list_del(&a->next); +                                free(a); +                        } +                } + +                pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_wrlock(&irmd->flows_lock); -                list_for_each_safe(pos, n, &(irmd->irm_flows)) { +                list_for_each_safe(p, h, &irmd->irm_flows) {                          struct irm_flow * f = -                                list_entry(pos, struct irm_flow, next); +                                list_entry(p, struct irm_flow, next);                          pthread_mutex_lock(&f->state_lock); @@ -1456,7 +1722,7 @@ void * irm_flow_cleaner()                                  bmp_release(irmd->port_ids, f->port_id);                                  list_del(&f->next); -                                LOG_INFO("Process %d gone, %d deallocated.", +                                LOG_INFO("AP-I %d gone, flow %d deallocated.",                                           f->n_api, f->port_id);                                  ipcp_flow_dealloc(f->n_1_api, f->port_id);                                  if (n_rb != NULL) @@ -1477,49 +1743,6 @@ void * irm_flow_cleaner()                  }                  pthread_rwlock_unlock(&irmd->flows_lock); - -                pthread_rwlock_wrlock(&irmd->reg_lock); - -                registry_sanitize_apis(&irmd->registry); - -                list_for_each_safe(pos, n, &irmd->spawned_apis) { -                        struct spawned_api * api = -                                list_entry(pos, struct spawned_api, next); -                        waitpid(api->api, &status, WNOHANG); - -                        if (kill(api->api, 0) < 0) { -                                LOG_INFO("Spawned process %d terminated " -                                         "with exit status %d.", -                                         api->api, status); - -                                list_for_each_safe(h, t, &irmd->ipcps) { -                                        struct ipcp_entry * e = -                                                list_entry(h, struct ipcp_entry, -                                                           next); -                                        if (e->api == api->api) { -                                                list_del(&e->next); -                                                ipcp_entry_destroy(e); -                                        } -                                } - -                                list_del(&api->next); -                                free(api); -                        } -                } - -                list_for_each_safe(pos, n, &irmd->api_table) { -                        struct api_entry * e = -                                list_entry(pos, struct api_entry, next); - -                        if (kill(e->api, 0) < 0) { -                                LOG_INFO("Instance %d removed from api table.", -                                         e->api); -                                list_del(&e->next); -                                api_entry_destroy(e); -                        } -                } - -                pthread_rwlock_unlock(&irmd->reg_lock);                  pthread_rwlock_unlock(&irmd->state_lock);                  nanosleep(&timeout, NULL); @@ -1595,25 +1818,33 @@ void * mainloop()                          ret_msg.result = enroll_ipcp(msg->api,                                                       msg->dif_name[0]);                          break; -                case IRM_MSG_CODE__IRM_BIND: +                case IRM_MSG_CODE__IRM_BIND_AP: +                        ret_msg.has_result = true; +                        ret_msg.result = bind_ap(msg->ap_name, +                                                 msg->dst_name, +                                                 msg->opts, +                                                 msg->n_args, +                                                 msg->args); +                        break; +                case IRM_MSG_CODE__IRM_UNBIND_AP:                          ret_msg.has_result = true; -                        ret_msg.result = bind_name(msg->dst_name, -                                                   msg->ap_name, -                                                   msg->opts, -                                                   msg->n_args, -                                                   msg->args); +                        ret_msg.result = unbind_ap(msg->ap_name, +                                                   msg->dst_name);                          break; -                case IRM_MSG_CODE__IRM_UNBIND: +                case IRM_MSG_CODE__IRM_API_ANNOUNCE:                          ret_msg.has_result = true; -                        ret_msg.result = unbind_name(msg->dst_name, -                                                     msg->ap_name, -                                                     msg->opts); +                        ret_msg.result = api_announce(msg->api, +                                                      msg->ap_name);                          break; -                case IRM_MSG_CODE__IRM_API_BIND: +                case IRM_MSG_CODE__IRM_BIND_API:                          ret_msg.has_result = true; -                        ret_msg.result = api_bind(msg->api, -                                                  msg->ap_name, -                                                  msg->ap_subset); +                        ret_msg.result = bind_api(msg->api, +                                                  msg->dst_name); +                        break; +                case IRM_MSG_CODE__IRM_UNBIND_API: +                        ret_msg.has_result = true; +                        ret_msg.result = unbind_api(msg->api, +                                                    msg->dst_name);                          break;                  case IRM_MSG_CODE__IRM_LIST_IPCPS:                          ret_msg.n_apis = list_ipcps(msg->dst_name, @@ -1623,15 +1854,15 @@ void * mainloop()                          break;                  case IRM_MSG_CODE__IRM_REG:                          ret_msg.has_result = true; -                        ret_msg.result = ap_reg(msg->dst_name, -                                                msg->dif_name, -                                                msg->n_dif_name); +                        ret_msg.result = name_reg(msg->dst_name, +                                                  msg->dif_name, +                                                  msg->n_dif_name);                          break;                  case IRM_MSG_CODE__IRM_UNREG:                          ret_msg.has_result = true; -                        ret_msg.result = ap_unreg(msg->dst_name, -                                                  msg->dif_name, -                                                  msg->n_dif_name); +                        ret_msg.result = name_unreg(msg->dst_name, +                                                    msg->dif_name, +                                                    msg->n_dif_name);                          break;                  case IRM_MSG_CODE__IRM_FLOW_ACCEPT:                          e = flow_accept(msg->api, @@ -1665,6 +1896,7 @@ void * mainloop()                                  break;                          } +                        /* FIXME: badly timed dealloc may give SEGV */                          ret_msg.has_port_id = true;                          ret_msg.port_id     = e->port_id;                          ret_msg.has_api     = true; @@ -1687,7 +1919,7 @@ void * mainloop()                                  ret_msg.result = -1;                                  break;                          } - +                        /* FIXME: badly timed dealloc may give SEGV */                          ret_msg.has_port_id = true;                          ret_msg.port_id     = e->port_id;                          ret_msg.has_api     = true; @@ -1741,7 +1973,7 @@ void * mainloop()          return (void *) 0;  } -static struct irm * irm_create() +static int irm_create()  {          struct stat st = {0};          struct timeval timeout = {(IRMD_ACCEPT_TIMEOUT / 1000), @@ -1749,30 +1981,31 @@ static struct irm * irm_create()          irmd = malloc(sizeof(*irmd));          if (irmd == NULL) -                return NULL; +                return -ENOMEM;          irmd->state = IRMD_NULL;          if (pthread_rwlock_init(&irmd->state_lock, NULL)) {                  LOG_ERR("Failed to initialize rwlock.");                  free(irmd); -                return NULL; +                return -1;          }          if (pthread_rwlock_init(&irmd->reg_lock, NULL)) {                  LOG_ERR("Failed to initialize rwlock.");                  free(irmd); -                return NULL; +                return -1;          }          if (pthread_rwlock_init(&irmd->flows_lock, NULL)) {                  LOG_ERR("Failed to initialize rwlock.");                  free(irmd); -                return NULL; +                return -1;          }          INIT_LIST_HEAD(&irmd->ipcps);          INIT_LIST_HEAD(&irmd->api_table); +        INIT_LIST_HEAD(&irmd->apn_table);          INIT_LIST_HEAD(&irmd->spawned_apis);          INIT_LIST_HEAD(&irmd->registry);          INIT_LIST_HEAD(&irmd->irm_flows); @@ -1780,47 +2013,47 @@ static struct irm * irm_create()          irmd->port_ids = bmp_create(IRMD_MAX_FLOWS, 0);          if (irmd->port_ids == NULL) {                  irm_destroy(); -                return NULL; +                return -ENOMEM;          }          irmd->threadpool = malloc(sizeof(pthread_t) * IRMD_THREADPOOL_SIZE);          if (irmd->threadpool == NULL) {                  irm_destroy(); -                return NULL; +                return -ENOMEM;          }          if (stat(SOCK_PATH, &st) == -1) {                  if (mkdir(SOCK_PATH, 0777)) {                          LOG_ERR("Failed to create sockets directory.");                          irm_destroy(); -                        return NULL; +                        return -1;                  }          }          irmd->sockfd = server_socket_open(IRM_SOCK_PATH);          if (irmd->sockfd < 0) {                  irm_destroy(); -                return NULL; +                return -1;          }          if (setsockopt(irmd->sockfd, SOL_SOCKET, SO_RCVTIMEO,                         (char *) &timeout, sizeof(timeout)) < 0) {                  LOG_ERR("Failed setting socket option.");                  irm_destroy(); -                return NULL; +                return -1;          }          if (chmod(IRM_SOCK_PATH, 0666)) {                  LOG_ERR("Failed to chmod socket.");                  irm_destroy(); -                return NULL; +                return -1;          }          if ((irmd->lf = lockfile_create()) == NULL) {                  if ((irmd->lf = lockfile_open()) == NULL) {                          LOG_ERR("Lockfile error.");                          irm_destroy(); -                        return NULL; +                        return -1;                  }                  if (kill(lockfile_owner(irmd->lf), 0) < 0) { @@ -1834,25 +2067,25 @@ static struct irm * irm_create()                                   lockfile_owner(irmd->lf));                          lockfile_close(irmd->lf);                          free(irmd); -                        return NULL; +                        return -1;                  }          }          if (irmd->lf == NULL) {                  irm_destroy(); -                return NULL; +                return -1;          }          if ((irmd->dum = shm_du_map_create()) == NULL) {                  irm_destroy(); -                return NULL; +                return -1;          }          irmd->state = IRMD_RUNNING; -        LOG_INFO("IRMd started..."); +        LOG_INFO("Ouroboros IPC Resource Manager daemon started..."); -        return irmd; +        return 0;  }  static void usage() @@ -1924,11 +2157,9 @@ int main(int argc, char ** argv)                  closedir(log_dir);          } -        if (!use_stdout) -                if (set_logfile(log_file)) -                        LOG_ERR("Cannot open %s, falling back to " -                                "stdout for logs.", -                                log_file); +        if (!use_stdout && (set_logfile(log_file) < 0)) +                LOG_ERR("Cannot open %s, falling back to stdout for logs.", +                        log_file);          /* init sig_act */          memset(&sig_act, 0, sizeof sig_act); @@ -1946,8 +2177,7 @@ int main(int argc, char ** argv)          if (sigaction(SIGPIPE, &sig_act, NULL) < 0)                  exit(EXIT_FAILURE); -        irmd = irm_create(); -        if (irmd == NULL) { +        if (irm_create() < 0) {                  close_logfile();                  exit(EXIT_FAILURE);          } @@ -1955,7 +2185,7 @@ int main(int argc, char ** argv)          for (t = 0; t < IRMD_THREADPOOL_SIZE; ++t)                  pthread_create(&irmd->threadpool[t], NULL, mainloop, NULL); -        pthread_create(&irmd->cleanup_flows, NULL, irm_flow_cleaner, NULL); +        pthread_create(&irmd->irm_sanitize, NULL, irm_sanitize, NULL);          pthread_create(&irmd->shm_sanitize, NULL,                         shm_du_map_sanitize, irmd->dum); @@ -1963,7 +2193,7 @@ int main(int argc, char ** argv)          for (t = 0; t < IRMD_THREADPOOL_SIZE; ++t)                  pthread_join(irmd->threadpool[t], NULL); -        pthread_join(irmd->cleanup_flows, NULL); +        pthread_join(irmd->irm_sanitize, NULL);          pthread_cancel(irmd->shm_sanitize);          pthread_join(irmd->shm_sanitize, NULL); diff --git a/src/irmd/registry.c b/src/irmd/registry.c index 687ff30d..f57d833a 100644 --- a/src/irmd/registry.c +++ b/src/irmd/registry.c @@ -21,6 +21,7 @@   */  #include "registry.h" +#include "utils.h"  #define OUROBOROS_PREFIX "registry" @@ -32,18 +33,8 @@  #include <stdbool.h>  #include <string.h>  #include <signal.h> - -#define reg_entry_has_auto_binding(e)  (reg_entry_get_auto_info(e) != NULL) -#define reg_entry_has_api(e, api)      (reg_entry_get_reg_api(e, api) != NULL) -#define reg_entry_has_binding(e, name) (reg_entry_get_binding(e, name) != NULL) - - -struct reg_binding { -        struct list_head next; -        char *           apn; -        uint32_t         flags; -        char **          argv; -}; +#include <unistd.h> +#include <limits.h>  struct reg_dif {          struct list_head next; @@ -51,39 +42,6 @@ struct reg_dif {          enum ipcp_type   type;  }; -static struct reg_binding * reg_binding_create(char *   apn, -                                               uint32_t flags, -                                               char **  argv) -{ -        struct reg_binding * b = malloc(sizeof(*b)); -        if (b == NULL) -                return NULL; - -        INIT_LIST_HEAD(&b->next); - -        b->apn   = apn; -        b->flags = flags; -        b->argv  = argv; - -        return b; -} - -static void reg_binding_destroy(struct reg_binding * b) -{ -        if (b == NULL) -                return; - -        if (b->argv != NULL) { -                char ** t = b->argv; -                while (*t != NULL) -                        free(*t++); -                free(b->argv); -        } - -        free(b->apn); -        free(b); -} -  static struct reg_entry * reg_entry_create()  {          struct reg_entry * e = malloc(sizeof(*e)); @@ -107,7 +65,7 @@ static struct reg_entry * reg_entry_init(struct reg_entry * e,          INIT_LIST_HEAD(&e->next);          INIT_LIST_HEAD(&e->difs); -        INIT_LIST_HEAD(&e->bindings); +        INIT_LIST_HEAD(&e->reg_apns);          INIT_LIST_HEAD(&e->reg_apis);          e->name = name; @@ -125,8 +83,8 @@ static struct reg_entry * reg_entry_init(struct reg_entry * e,  static void reg_entry_destroy(struct reg_entry * e)  { -        struct list_head * pos = NULL; -        struct list_head * n   = NULL; +        struct list_head * p = NULL; +        struct list_head * h = NULL;          if (e == NULL)                  return; @@ -144,20 +102,22 @@ static void reg_entry_destroy(struct reg_entry * e)          if (e->name != NULL)                  free(e->name); -        list_for_each_safe(pos, n, &e->reg_apis) { -                struct reg_api * i = list_entry(pos, struct reg_api, next); -                reg_api_destroy(i); +        list_for_each_safe(p, h, &e->reg_apis) { +                struct pid_el * i = list_entry(p, struct pid_el, next); +                list_del(&i->next); +                free(i);          } -        list_for_each_safe(pos, n, &e->bindings) { -                struct reg_binding * b = -                        list_entry(pos, struct reg_binding, next); -                reg_binding_destroy(b); +        list_for_each_safe(p, h, &e->reg_apns) { +                struct str_el * a = list_entry(p, struct str_el, next); +                list_del(&a->next); +                free(a->str); +                free(a);          } -        list_for_each_safe(pos, n, &e->difs) { -                struct reg_dif * d = -                        list_entry(pos, struct reg_dif, next); +        list_for_each_safe(p, h, &e->difs) { +                struct reg_dif * d = list_entry(p, struct reg_dif, next); +                list_del(&d->next);                  free(d->dif_name);                  free(d);          } @@ -165,15 +125,12 @@ static void reg_entry_destroy(struct reg_entry * e)          free(e);  } -bool reg_entry_is_local_in_dif(struct reg_entry * e, -                               char *             dif_name) +static bool reg_entry_is_local_in_dif(struct reg_entry * e, char * dif_name)  { -        struct list_head * pos = NULL; - -        list_for_each(pos, &e->difs) { -                struct reg_dif * d = -                        list_entry(pos, struct reg_dif, next); +        struct list_head * p = NULL; +        list_for_each(p, &e->difs) { +                struct reg_dif * d = list_entry(p, struct reg_dif, next);                  if (!strcmp(dif_name, d->dif_name))                          return true;          } @@ -181,9 +138,9 @@ bool reg_entry_is_local_in_dif(struct reg_entry * e,          return false;  } -int reg_entry_add_local_in_dif(struct reg_entry * e, -                               char *             dif_name, -                               enum ipcp_type     type) +static int reg_entry_add_local_in_dif(struct reg_entry * e, +                                      char *             dif_name, +                                      enum ipcp_type     type)  {          if (!reg_entry_is_local_in_dif(e, dif_name)) {                  struct reg_dif * rdn = malloc(sizeof(*rdn)); @@ -198,16 +155,14 @@ int reg_entry_add_local_in_dif(struct reg_entry * e,          return 0; /* already registered. Is ok */  } -void reg_entry_del_local_from_dif(struct reg_entry * e, -                                  char *             dif_name) +static void reg_entry_del_local_from_dif(struct reg_entry * e, +                                         char *             dif_name)  { -        struct list_head * pos = NULL; -        struct list_head * n   = NULL; - -        list_for_each_safe(pos, n, &e->difs) { -                struct reg_dif * d = -                        list_entry(pos, struct reg_dif, next); +        struct list_head * p = NULL; +        struct list_head * h = NULL; +        list_for_each_safe(p, h, &e->difs) { +                struct reg_dif * d = list_entry(p, struct reg_dif, next);                  if (!strcmp(dif_name, d->dif_name)) {                          list_del(&d->next);                          free(d); @@ -215,165 +170,181 @@ void reg_entry_del_local_from_dif(struct reg_entry * e,          }  } -struct reg_binding * reg_entry_get_binding(struct reg_entry * e, -                                           char *             apn) +static bool reg_entry_has_apn(struct reg_entry * e, char * apn)  { -        struct list_head * pos = NULL; +        struct list_head * p; -        list_for_each(pos, &e->bindings) { -                struct reg_binding * n = -                        list_entry(pos, struct reg_binding, next); - -                if (strcmp(apn, n->apn) == 0) -                        return n; +        list_for_each(p, &e->reg_apns) { +                struct str_el * e = list_entry(p, struct str_el, next); +                if (!strcmp(e->str, apn)) +                        return true;          } -        return NULL; +        return false;  } -void reg_entry_del_binding(struct reg_entry * e, -                           char *             apn) +int reg_entry_add_apn(struct reg_entry * e, struct apn_entry * a)  { -        struct reg_binding * b = reg_entry_get_binding(e, apn); -        if (b == NULL) -                return; - -        list_del(&b->next); -        free(b); -} +        struct str_el * n; -struct reg_binding * reg_entry_add_binding(struct reg_entry * e, -                                           char *             apn, -                                           uint32_t           flags, -                                           char **            argv) -{ -        struct reg_binding * b; -        if ((b = reg_entry_get_binding(e, apn)) != NULL) { -                LOG_DBG("Updating AP name %s binding with %s.", -                        apn, e->name); -                reg_entry_del_binding(e, b->apn); +        if (reg_entry_has_apn(e, a->apn)) { +                LOG_WARN("AP %s already accepting flows for %s.", +                         a->apn, e->name); +                return 0;          } -        if (flags & BIND_AP_AUTO) { -                b = reg_binding_create(apn, flags, argv); -                if (e->state == REG_NAME_IDLE) -                        e->state = REG_NAME_AUTO_ACCEPT; -        } else { -                flags &= ~BIND_AP_AUTO; -                b = reg_binding_create(apn, flags, NULL); +        if (!(a->flags & BIND_AP_AUTO)) { +                LOG_DBG("AP %s cannot be auto-instantiated.", a->apn); +                return -EINVAL;          } -        list_add(&b->next, &e->bindings); +        n = malloc(sizeof(*n)); +        if (n == NULL) +                return -ENOMEM; + +        n->str = strdup(a->apn); +        if (n->str == NULL) +                return -ENOMEM; + +        list_add(&n->next, &e->reg_apns); + +        if (e->state == REG_NAME_IDLE) +                e->state = REG_NAME_AUTO_ACCEPT; -        return b; +        return 0;  } -char ** reg_entry_get_auto_info(struct reg_entry * e) +void reg_entry_del_apn(struct reg_entry * e, char * apn)  { -        struct list_head * pos = NULL; +        struct list_head * p = NULL; +        struct list_head * h = NULL; -        list_for_each(pos, &e->bindings) { -                struct reg_binding * b = -                        list_entry(pos, struct reg_binding, next); -                if (b->flags & BIND_AP_AUTO) -                    return b->argv; +        list_for_each_safe(p, h, &e->reg_apns) { +                struct str_el * e = list_entry(p, struct str_el, next); +                if (!wildcard_match(apn, e->str)) { +                        list_del(&e->next); +                        free(e->str); +                        free(e); +                } +        } + +        if (e->state == REG_NAME_AUTO_ACCEPT && list_empty(&e->reg_apns)) { +                e->state = REG_NAME_IDLE; +                pthread_cond_broadcast(&e->state_cond);          } -        return NULL;  } -struct reg_api * reg_entry_get_reg_api(struct reg_entry * e, -                                       pid_t              api) +char * reg_entry_get_apn(struct reg_entry * e)  { -        struct list_head * pos = NULL; +        if (!list_empty(&e->reg_apis) || list_empty(&e->reg_apns)) +                return NULL; + +        return list_first_entry(&e->reg_apns, struct str_el, next)->str; +} -        list_for_each(pos, &e->reg_apis) { -                struct reg_api * r = -                        list_entry(pos, struct reg_api, next); +static bool reg_entry_has_api(struct reg_entry * e, pid_t api) +{ +        struct list_head * p; -                if (r->api == api) -                        return r; +        list_for_each(p, &e->reg_apns) { +                struct pid_el * e = list_entry(p, struct pid_el, next); +                if (e->pid == api) +                        return true;          } -        return NULL; +        return false;  } -pid_t reg_entry_resolve_api(struct reg_entry * e) +int reg_entry_add_api(struct reg_entry * e, pid_t api)  { -        struct list_head * pos = NULL; +        struct pid_el * i; + +        if (e == NULL) +                return -EINVAL; -        /* FIXME: now just returns the first accepting instance */ -        list_for_each(pos, &e->reg_apis) { -                struct reg_api * r = -                        list_entry(pos, struct reg_api, next); -                return r->api; +        if (reg_entry_has_api(e, api)) { +                LOG_DBG("Instance already registered with this name."); +                return -EPERM;          } -        return -1; -} +        if (e->state == REG_NAME_NULL) { +                LOG_DBG("Tried to add instance in NULL state."); +                return -EPERM; +        } -struct reg_entry * registry_get_entry_by_name(struct list_head * registry, -                                              char *             name) -{ -        struct list_head * pos = NULL; +        i = malloc(sizeof(*i)); +        if (i == NULL) +                return -ENOMEM; -        list_for_each(pos, registry) { -                struct reg_entry * e = -                        list_entry(pos, struct reg_entry, next); +        i->pid = api; +        list_add(&i->next, &e->reg_apis); -                if (strcmp(name, e->name) == 0) -                        return e; +        if (e->state == REG_NAME_IDLE || +            e->state == REG_NAME_AUTO_ACCEPT || +            e->state == REG_NAME_AUTO_EXEC) { +                e->state = REG_NAME_FLOW_ACCEPT; +                pthread_cond_signal(&e->state_cond);          } -        return NULL; +        return 0;  } -struct reg_entry * registry_get_entry_by_apn(struct list_head * registry, -                                             char *             apn) +void reg_entry_del_api(struct reg_entry * e, pid_t api)  { -        struct list_head * pos = NULL; - -        list_for_each(pos, registry) { -                struct list_head * p = NULL; -                struct reg_entry * e = -                        list_entry(pos, struct reg_entry, next); +        struct list_head * p; +        struct list_head * h; -                list_for_each(p, &e->bindings) { -                        struct reg_binding * b = -                                list_entry(p, struct reg_binding, next); +        if (e == NULL) +                return; -                        if (strcmp(b->apn, apn) == 0) -                                return e; +        list_for_each_safe(p, h, &e->reg_apis) { +                struct pid_el * a = list_entry(p, struct pid_el, next); +                if (a->pid == api) { +                        list_del(&a->next); +                        free(a);                  }          } -        return NULL; +        if (list_empty(&e->reg_apis)) { +                if (!list_empty(&e->reg_apns)) +                        e->state = REG_NAME_AUTO_ACCEPT; +                else +                        e->state = REG_NAME_IDLE; +        } else { +                e->state = REG_NAME_FLOW_ACCEPT; +        } + +        pthread_cond_broadcast(&e->state_cond);  } -struct reg_entry * registry_get_entry_by_api(struct list_head * registry, -                                             pid_t              api) +pid_t reg_entry_get_api(struct reg_entry * e)  { -        struct list_head * pos = NULL; +        if (e == NULL) +                return -1; -        list_for_each(pos, registry) { -                struct list_head * p = NULL; -                struct reg_entry * e = -                        list_entry(pos, struct reg_entry, next); +        if (list_empty(&e->reg_apis)) +                return -1; -                list_for_each(p, &e->reg_apis) { -                        struct reg_api * r = -                                list_entry(p, struct reg_api, next); +        return list_first_entry(&e->reg_apis, struct pid_el, next)->pid; +} -                        if (r->api == api) -                                return e; -                } +struct reg_entry * registry_get_entry(struct list_head * registry, +                                      char *             name) +{ +        struct list_head * p   = NULL; + +        list_for_each(p, registry) { +                struct reg_entry * e = list_entry(p, struct reg_entry, next); +                if (!wildcard_match(name, e->name)) +                        return e;          }          return NULL;  } -struct reg_entry * registry_assign(struct list_head * registry, -                                   char *             name) +struct reg_entry * registry_add_name(struct list_head * registry, +                                     char *             name)  {          struct reg_entry * e = NULL; @@ -403,10 +374,10 @@ struct reg_entry * registry_assign(struct list_head * registry,          return e;  } -void registry_deassign(struct list_head * registry, +void registry_del_name(struct list_head * registry,                         char *             name)  { -        struct reg_entry * e = registry_get_entry_by_name(registry, name); +        struct reg_entry * e = registry_get_entry(registry, name);          if (e == NULL)                  return; @@ -416,177 +387,30 @@ void registry_deassign(struct list_head * registry,          return;  } -int registry_add_binding(struct list_head * registry, -                         char *             name, -                         char *             apn, -                         uint32_t           flags, -                         char **            argv) -{ -        struct reg_entry * e; - -        if (name == NULL || apn == NULL) -                return -EINVAL; - -        e = registry_get_entry_by_name(registry, name); -        if (e == NULL) { -                LOG_DBG("Adding new name to registry: %s.", name); -                e = registry_assign(registry, name); -        } - -        if (e->state == REG_NAME_NULL) { -                LOG_DBG("Tried to add binding in NULL state."); -                return -1; -        } - -        if(reg_entry_add_binding(e, apn, flags, argv) == NULL) -                return -1; - -        return 0; -} - - -void registry_del_binding(struct list_head * registry, -                          char *             name, -                          char *             apn) -{ -        struct reg_entry *   e = NULL; - -        if (name == NULL || apn == NULL) -                return; - -        e = registry_get_entry_by_name(registry, name); -        if (e == NULL) { -                LOG_DBG("Name %s not found in registry.", name); -                return; -        } - -        reg_entry_del_binding(e, apn); - -        if (e->state == REG_NAME_AUTO_ACCEPT && !reg_entry_has_auto_binding(e)) -                e->state = REG_NAME_IDLE; - -        return; -} - - -struct reg_api * registry_add_api_name(struct list_head * registry, -                                       pid_t              api, -                                       char *             name) -{ -        struct reg_entry * e = NULL; -        struct reg_api *   i = NULL; - -        if (name == NULL || api == -1) -                return NULL; - -        e = registry_get_entry_by_name(registry, name); -        if (e == NULL) { -                LOG_DBG("Name %s not found in registry.", name); -                return NULL; -        } - -        if (e->state == REG_NAME_NULL) { -                LOG_DBG("Tried to add instance in NULL state."); -                return NULL; -        } - -        if (reg_entry_has_api(e, api)) { -                LOG_DBG("Instance already registered with this name."); -                return NULL; -        } - -        i = reg_api_create(api); -        if (i == NULL) { -                LOG_DBG("Failed to create reg_instance"); -                return NULL; -        } - -        pthread_mutex_lock(&e->state_lock); - -        if (e->state == REG_NAME_IDLE || e->state == REG_NAME_AUTO_ACCEPT -           || e->state == REG_NAME_AUTO_EXEC) { -                e->state = REG_NAME_FLOW_ACCEPT; -                pthread_cond_signal(&e->state_cond); -        } - -        list_add(&i->next, &e->reg_apis); - -        pthread_mutex_unlock(&e->state_lock); - -        return i; -} -  void registry_del_api(struct list_head * registry,                        pid_t              api)  { -        struct reg_entry * e = NULL; -        struct reg_api * i   = NULL; +        struct list_head * p;          if ( api == -1)                  return; -        e = registry_get_entry_by_api(registry, api); -        if (e == NULL) { -                LOG_DBG("Instance %d not found.", api); -                return; +        list_for_each(p, registry) { +                struct reg_entry * e = list_entry(p, struct reg_entry, next); +                pthread_mutex_lock(&e->state_lock); +                reg_entry_del_api(e, api); +                pthread_mutex_unlock(&e->state_lock);          } -        i = reg_entry_get_reg_api(e, api); -        if (i == NULL) { -                LOG_DBG("Instance %d is not accepting flows for %s.", -                         api, e->name); -                return; -        } - -        list_del(&i->next); - -        reg_api_destroy(i); - -        pthread_mutex_lock(&e->state_lock); - -        if (list_empty(&e->reg_apis)) { -                if (reg_entry_has_auto_binding(e)) -                        e->state = REG_NAME_AUTO_ACCEPT; -                else -                        e->state = REG_NAME_IDLE; -        } else { -                e->state = REG_NAME_FLOW_ACCEPT; -        } - -        pthread_cond_signal(&e->state_cond); -        pthread_mutex_unlock(&e->state_lock); -          return;  } -void registry_sanitize_apis(struct list_head * registry) -{ -        struct list_head * pos = NULL; -        struct list_head * n   = NULL; - -        struct list_head * pos2 = NULL; -        struct list_head * n2   = NULL; - -        list_for_each_safe(pos, n, registry) { -                struct reg_entry * e = list_entry(pos, struct reg_entry, next); -                list_for_each_safe(pos2, n2, &e->reg_apis) { -                        struct reg_api * r -                                = list_entry(pos2, struct reg_api, next); -                        if (kill(r->api, 0) < 0) { -                                LOG_DBG("Process %d gone, binding removed.", -                                        r->api); -                                registry_del_api(registry, r->api); -                        } -                } -        } -} -  char * registry_get_dif_for_dst(struct list_head * registry,                                  char *             dst_name)  {          struct list_head * pos = NULL;          struct reg_entry * re = -                registry_get_entry_by_name(registry, dst_name); +                registry_get_entry(registry, dst_name);          if (re != NULL) { /* local AP */                  list_for_each(pos, &re->difs) { @@ -624,7 +448,7 @@ int registry_add_name_to_dif(struct list_head * registry,                               char *             dif_name,                               enum ipcp_type     type)  { -        struct reg_entry * re = registry_get_entry_by_name(registry, name); +        struct reg_entry * re = registry_get_entry(registry, name);          if (re == NULL)                  return -1; @@ -635,7 +459,7 @@ void registry_del_name_from_dif(struct list_head * registry,                                  char *             name,                                  char *             dif_name)  { -        struct reg_entry * re = registry_get_entry_by_name(registry, name); +        struct reg_entry * re = registry_get_entry(registry, name);          if (re == NULL)                  return; @@ -644,14 +468,14 @@ void registry_del_name_from_dif(struct list_head * registry,  void registry_destroy(struct list_head * registry)  { +        struct list_head * p = NULL;          struct list_head * h = NULL; -        struct list_head * t = NULL;          if (registry == NULL)                  return; -        list_for_each_safe(h, t, registry) { -                struct reg_entry * e = list_entry(h, struct reg_entry, next); +        list_for_each_safe(p, h, registry) { +                struct reg_entry * e = list_entry(p, struct reg_entry, next);                  list_del(&e->next);                  reg_entry_destroy(e);          } diff --git a/src/irmd/registry.h b/src/irmd/registry.h index 19e27a21..35c4c10b 100644 --- a/src/irmd/registry.h +++ b/src/irmd/registry.h @@ -33,12 +33,11 @@  #include <string.h>  #include <sys/types.h> -#include "reg_api.h" +#include "api_table.h" +#include "apn_table.h"  #define registry_has_name(r, name) \ -        (registry_get_entry_by_name(r, name) != NULL) -#define registry_name_has_api(r, name) \ -        (registry_get_api_by_name(r, name) != NULL) +        (registry_get_entry(r, name) != NULL)  enum reg_name_state {          REG_NAME_NULL = 0, @@ -50,20 +49,18 @@ enum reg_name_state {          REG_NAME_DESTROY  }; -/* an entry in the registry */ +/* An entry in the registry */  struct reg_entry {          struct list_head    next;          char *              name;          /* DIFs in which this name is registered */          struct list_head    difs; - -        /* names of the APs that can listen to this name */ -        struct list_head    bindings; -        /* known instances */ +        /* APs that can be instantiated by the irmd */ +        struct list_head    reg_apns; +        /* Instances that are listening for this name */          struct list_head    reg_apis; -        /* FIXME: flow handling information should not be here */          enum reg_name_state state;          char *              req_ae_name;          int                 response; @@ -71,58 +68,49 @@ struct reg_entry {          pthread_mutex_t     state_lock;  }; -struct reg_binding *  reg_entry_get_binding(struct reg_entry * e, -                                            char *             apn); -char **               reg_entry_get_auto_info(struct reg_entry * e); -void                  reg_entry_del_binding(struct reg_entry * e, -                                            char *             apn); -struct reg_api *      reg_entry_get_reg_api(struct reg_entry * e, -                                            pid_t              api); - -pid_t                 reg_entry_resolve_api(struct reg_entry * e); -bool                  reg_entry_is_local_in_dif(struct reg_entry * e, -                                                char *             dif_name); -int                   reg_entry_add_local_in_dif(struct reg_entry * e, -                                                 char *             dif_name, -                                                 enum ipcp_type     type); -void                  reg_entry_del_local_from_dif(struct reg_entry * e, -                                                   char *             dif_name); - -struct reg_entry *    registry_assign(struct list_head * registry, +int                reg_entry_add_apn(struct reg_entry * e, +                                     struct apn_entry * a); + +void               reg_entry_del_apn(struct reg_entry * e, +                                     char *             apn); + +char *             reg_entry_get_apn(struct reg_entry * e); + + +int                reg_entry_add_api(struct reg_entry * e, +                                     pid_t              api); + +void               reg_entry_del_api(struct reg_entry * e, +                                     pid_t              api); + +pid_t              reg_entry_get_api(struct reg_entry * e); + +struct reg_entry * registry_add_name(struct list_head * registry, +                                     char *             name); + +void               registry_del_name(struct list_head * registry, +                                     char *             name); + +void               registry_del_api(struct list_head * registry, +                                    pid_t              api); + +void               registry_sanitize_apis(struct list_head * registry); + +struct reg_entry * registry_get_entry(struct list_head * registry,                                        char *             name); -void                  registry_deassign(struct list_head * registry, -                                        char *             name); -int                   registry_add_binding(struct list_head * registry, -                                           char *             name, -                                           char *             apn, -                                           uint32_t           flags, -                                           char **            argv); -void                  registry_del_binding(struct list_head * registry, -                                           char *             name, -                                           char *             apn); -struct reg_api *      registry_add_api_name(struct list_head * registry, -                                            pid_t              api, -                                            char *             name); -void                  registry_del_api(struct list_head * registry, -                                       pid_t              api); -void                  registry_sanitize_apis(struct list_head * registry); -struct reg_api *      registry_get_api_by_name(struct list_head * registry, -                                               char *             name); -struct reg_entry *    registry_get_entry_by_name(struct list_head * registry, -                                                 char *             name); -struct reg_entry *    registry_get_entry_by_apn(struct list_head * registry, -                                                char *             apn); -struct reg_entry *    registry_get_entry_by_api(struct list_head * registry, -                                                pid_t              api); -char *                registry_get_dif_for_dst(struct list_head * registry, -                                               char *             dst_name); -int                   registry_add_name_to_dif(struct list_head * registry, -                                               char *             name, -                                               char *             dif_name, -                                               enum ipcp_type     type); -void                  registry_del_name_from_dif(struct list_head * registry, -                                                 char *             name, -                                                 char *             dif_name); -void                  registry_destroy(struct list_head * registry); - -#endif + +char *             registry_get_dif_for_dst(struct list_head * registry, +                                            char *             dst_name); + +int                registry_add_name_to_dif(struct list_head * registry, +                                            char *             name, +                                            char *             dif_name, +                                            enum ipcp_type     type); + +void               registry_del_name_from_dif(struct list_head * registry, +                                              char *             name, +                                              char *             dif_name); + +void               registry_destroy(struct list_head * registry); + +#endif /* OUROBOROS_IRMD_REGISTRY_H */ diff --git a/src/irmd/utils.c b/src/irmd/utils.c index 9cc1dd2f..2fbe2456 100644 --- a/src/irmd/utils.c +++ b/src/irmd/utils.c @@ -1,8 +1,73 @@  /* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - 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 <ouroboros/config.h> +#include <stdlib.h> +#include <string.h> + +void argvfree(char ** argv) +{ +        char ** argv_dup = argv; +        if (argv == NULL) +                return; + +        while (*argv_dup != NULL) +                free(*(argv_dup++)); + +        free(argv); +} + +char ** argvdup(char ** argv) +{ +        int argc = 0; +        char ** argv_dup = argv; +        int i; + +        if (argv == NULL) +                return NULL; + +        while (*(argv_dup++) != NULL) +                argc++; + +        if (argc != 0) { +                argv_dup = malloc((argc + 1) * sizeof(*argv_dup)); +                for (i = 0; i < argc; ++i) { +                        argv_dup[i] = strdup(argv[i]); +                        if (argv_dup[i] == NULL) { +                                argvfree(argv_dup); +                                return NULL; +                        } +                } +        } +        argv_dup[argc] = NULL; +        return argv_dup; +} + +/*   * Copyright (c) 1989, 1993, 1994   *      The Regents of the University of California.  All rights reserved.   * - * This code is derived from software contributed to Berkeley by + * Wildcard Match code below is derived from software contributed to Berkeley by   * Guido van Rossum.   *   * Copyright (c) 2011 The FreeBSD Foundation diff --git a/src/irmd/utils.h b/src/irmd/utils.h index aa8a38f1..37c745af 100644 --- a/src/irmd/utils.h +++ b/src/irmd/utils.h @@ -24,4 +24,26 @@   * Checks whether the string argument matches the pattern argument,   * which is a wildcard pattern.   */ + +#ifndef OUROBOROS_IRMD_UTILS_H +#define OUROBOROS_IRMD_UTILS_H + +#include <sys/types.h> + +struct str_el { +        struct list_head next; +        char *           str; +}; + +struct pid_el { +        struct list_head next; +        pid_t            pid; +}; +  int wildcard_match(const char * pattern, const char * string); + +/* functions for copying and destroying arguments list */ +char ** argvdup(char ** argv); +void    argvfree(char ** argv); + +#endif /* OUROBOROS_IRM_UTILS_H */ diff --git a/src/lib/dev.c b/src/lib/dev.c index f27ef0fe..3a5fc8e0 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -54,6 +54,37 @@ struct ap_data {          pthread_rwlock_t      flows_lock;  } * _ap_instance; +static int api_announce(char * ap_name) +{ +        irm_msg_t msg = IRM_MSG__INIT; +        irm_msg_t * recv_msg = NULL; +        int ret = -1; + +        msg.code    = IRM_MSG_CODE__IRM_API_ANNOUNCE; +        msg.has_api = true; + +        pthread_rwlock_rdlock(&_ap_instance->data_lock); + +        msg.api = _ap_instance->api; +        msg.ap_name = ap_name; + +        pthread_rwlock_unlock(&_ap_instance->data_lock); + +        recv_msg = send_recv_irm_msg(&msg); +        if (recv_msg == NULL) { +                return -1; +        } + +        if (!recv_msg->has_result || (ret = recv_msg->result)) { +                irm_msg__free_unpacked(recv_msg, NULL); +                return ret; +        } + +        irm_msg__free_unpacked(recv_msg, NULL); + +        return ret; +} +  int ap_init(char * ap_name)  {          int i = 0; @@ -100,6 +131,9 @@ int ap_init(char * ap_name)          pthread_rwlock_init(&_ap_instance->flows_lock, NULL);          pthread_rwlock_init(&_ap_instance->data_lock, NULL); +        if (ap_name != NULL) +                return api_announce(ap_name); +          return 0;  } @@ -134,42 +168,6 @@ void ap_fini(void)          free(_ap_instance);  } -int api_bind(char * ap_subset) -{ -        irm_msg_t msg = IRM_MSG__INIT; -        irm_msg_t * recv_msg = NULL; -        int ret = -1; - -        msg.code    = IRM_MSG_CODE__IRM_API_BIND; -        msg.has_api = true; - -        if (_ap_instance->ap_name == NULL) -                return -EPERM; /* call init first */ - -        pthread_rwlock_rdlock(&_ap_instance->data_lock); - -        msg.api = _ap_instance->api; -        msg.ap_name = _ap_instance->ap_name; - -        pthread_rwlock_unlock(&_ap_instance->data_lock); - -        msg.ap_subset = ap_subset; - -        recv_msg = send_recv_irm_msg(&msg); -        if (recv_msg == NULL) { -                return -1; -        } - -        if (!recv_msg->has_result || (ret = recv_msg->result)) { -                irm_msg__free_unpacked(recv_msg, NULL); -                return ret; -        } - -        irm_msg__free_unpacked(recv_msg, NULL); - -        return ret; -} -  static int port_id_to_fd(int port_id)  {          int i; @@ -417,6 +415,8 @@ int flow_dealloc(int fd)          msg.code         = IRM_MSG_CODE__IRM_FLOW_DEALLOC;          msg.has_port_id  = true; +        msg.has_api      = true; +        msg.api          = getpid();          pthread_rwlock_rdlock(&_ap_instance->data_lock);          pthread_rwlock_wrlock(&_ap_instance->flows_lock); diff --git a/src/lib/ipcp.c b/src/lib/ipcp.c index bdc980f9..e8e31e46 100644 --- a/src/lib/ipcp.c +++ b/src/lib/ipcp.c @@ -53,6 +53,7 @@ static ipcp_msg_t * send_recv_ipcp_msg(pid_t api,         char * sock_path = NULL;         ssize_t count = 0;         ipcp_msg_t * recv_msg = NULL; +         struct timeval tv = {(SOCKET_TIMEOUT / 1000),                              (SOCKET_TIMEOUT % 1000) * 1000}; @@ -260,9 +261,8 @@ int ipcp_enroll(pid_t  api,          msg.dif_name = dif_name;          recv_msg = send_recv_ipcp_msg(api, &msg); -        if (recv_msg == NULL) { +        if (recv_msg == NULL)                  return -1; -        }          if (recv_msg->has_result == false) {                  ipcp_msg__free_unpacked(recv_msg, NULL); diff --git a/src/lib/irm.c b/src/lib/irm.c index 4c71817d..64a4fa0f 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -321,21 +321,21 @@ static int check_ap_path(char ** ap_name)          return -ENOENT;  } -int irm_bind(char *   name, -             char *   ap_name, -             uint16_t opts, -             int      argc, -             char **  argv) +int irm_bind_ap(char *   ap, +                char *   name, +                uint16_t opts, +                int      argc, +                char **  argv)  {          irm_msg_t msg = IRM_MSG__INIT;          irm_msg_t * recv_msg = NULL;          int ret = -1;          char * full_ap_name; -        if (name == NULL || ap_name == NULL) +        if (ap == NULL || name == NULL)                  return -EINVAL; -        full_ap_name = strdup(ap_name); +        full_ap_name = strdup(ap);          if (full_ap_name == NULL)                  return -ENOMEM; @@ -344,7 +344,7 @@ int irm_bind(char *   name,                  return ret;          } -        msg.code = IRM_MSG_CODE__IRM_BIND; +        msg.code = IRM_MSG_CODE__IRM_BIND_AP;          msg.dst_name = name;          msg.ap_name = full_ap_name; @@ -372,23 +372,76 @@ int irm_bind(char *   name,          return ret;  } -int irm_unbind(char *   name, -               char *   ap_name, -               uint16_t opts) +int irm_bind_api(pid_t api, char * name)  {          irm_msg_t msg = IRM_MSG__INIT;          irm_msg_t * recv_msg = NULL;          int ret = -1; -        if (name == NULL || ap_name == NULL) +        if (name == NULL)                  return -EINVAL; -        msg.code = IRM_MSG_CODE__IRM_UNBIND; +        msg.code = IRM_MSG_CODE__IRM_BIND_API; +        msg.has_api  = true; +        msg.api      = api; +        msg.dst_name = name; + +        recv_msg = send_recv_irm_msg(&msg); +        if (recv_msg == NULL) +                return -1; + +        if (recv_msg->has_result == false) { +                irm_msg__free_unpacked(recv_msg, NULL); +                return -1; +        } + +        ret = recv_msg->result; +        irm_msg__free_unpacked(recv_msg, NULL); +        return ret; +} + +int irm_unbind_ap(char * ap, char * name) +{ +        irm_msg_t msg = IRM_MSG__INIT; +        irm_msg_t * recv_msg = NULL; +        int ret = -1; + +        if (name == NULL) +                return -EINVAL; + +        msg.code = IRM_MSG_CODE__IRM_UNBIND_AP; +        msg.ap_name  = ap; +        msg.dst_name = name; + +        recv_msg = send_recv_irm_msg(&msg); +        if (recv_msg == NULL) +                return -1; + +        if (recv_msg->has_result == false) { +                irm_msg__free_unpacked(recv_msg, NULL); +                return -1; +        } + +        ret = recv_msg->result; +        irm_msg__free_unpacked(recv_msg, NULL); + +        return ret; +} + +int irm_unbind_api(pid_t api, char * name) +{ +        irm_msg_t msg = IRM_MSG__INIT; +        irm_msg_t * recv_msg = NULL; +        int ret = -1; + +        if (name == NULL) +                return -EINVAL; + +        msg.code = IRM_MSG_CODE__IRM_UNBIND_API; +        msg.has_api  = true; +        msg.api      = api;          msg.dst_name = name; -        msg.ap_name = ap_name; -        msg.has_opts = true; -        msg.opts = opts;          recv_msg = send_recv_irm_msg(&msg);          if (recv_msg == NULL) diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index 5c320a17..7a634201 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -29,36 +29,37 @@ enum irm_msg_code {          IRM_LIST_IPCPS        =  4;          IRM_BOOTSTRAP_IPCP    =  5;          IRM_ENROLL_IPCP       =  6; -        IRM_BIND              =  7; -        IRM_UNBIND            =  8; -        IRM_API_BIND          =  9; -        IRM_REG               = 10; -        IRM_UNREG             = 11; -        IRM_FLOW_ACCEPT       = 12; -        IRM_FLOW_ALLOC_RESP   = 13; -        IRM_FLOW_ALLOC        = 14; -        IRM_FLOW_ALLOC_RES    = 15; -        IRM_FLOW_DEALLOC      = 16; -        IPCP_FLOW_REQ_ARR     = 17; -        IPCP_FLOW_ALLOC_REPLY = 18; -        IPCP_FLOW_DEALLOC     = 19; -        IRM_REPLY             = 20; +        IRM_BIND_AP           =  7; +        IRM_UNBIND_AP         =  8; +        IRM_API_ANNOUNCE      =  9; +        IRM_BIND_API          = 10; +        IRM_UNBIND_API        = 11; +        IRM_REG               = 12; +        IRM_UNREG             = 13; +        IRM_FLOW_ACCEPT       = 14; +        IRM_FLOW_ALLOC_RESP   = 15; +        IRM_FLOW_ALLOC        = 16; +        IRM_FLOW_ALLOC_RES    = 17; +        IRM_FLOW_DEALLOC      = 18; +        IPCP_FLOW_REQ_ARR     = 19; +        IPCP_FLOW_ALLOC_REPLY = 20; +        IPCP_FLOW_DEALLOC     = 21; +        IRM_REPLY             = 22;  };  message irm_msg {          required irm_msg_code code   =  1;          optional string ap_name      =  2; -        optional string ap_subset    =  3; -        optional string ae_name      =  4; -        optional sint32 api          =  5; -        optional uint32 ipcp_type    =  6; -        repeated string dif_name     =  7; -        repeated string args         =  8; -        optional sint32 response     =  9; -        optional string dst_name     = 10; -        optional sint32 port_id      = 11; -        optional dif_config_msg conf = 12; -        optional uint32 opts         = 13; -        repeated sint32 apis         = 14; -        optional sint32 result       = 15; +        optional string ae_name      =  3; +        optional sint32 api          =  4; +        optional uint32 ipcp_type    =  5; +        repeated string dif_name     =  6; +        repeated string args         =  7; +        optional sint32 response     =  8; +        optional string dst_name     =  9; +        optional sint32 port_id      = 10; +        optional dif_config_msg conf = 11; +        optional uint32 opts         = 12; +        repeated sint32 apis         = 13; +        optional sint32 result       = 14;  }; diff --git a/src/tools/cbr/cbr.c b/src/tools/cbr/cbr.c index 65783119..e42492df 100644 --- a/src/tools/cbr/cbr.c +++ b/src/tools/cbr/cbr.c @@ -72,14 +72,10 @@ int main(int argc, char ** argv)          int    ret = 0;          char * rem = NULL;          char * s_apn = NULL; +        char ** argv_dup = argv;          bool server = false; -        if (ap_init(argv[0]) < 0) { -                printf("Failed to init.\n"); -                exit(EXIT_FAILURE); -        } -          server_settings.interval = 1; /* One second reporting interval */          server_settings.timeout  = 1; @@ -133,8 +129,18 @@ int main(int argc, char ** argv)          }          if (server) { +                if (ap_init(argv_dup[0]) < 0) { +                        printf("Failed to init.\n"); +                        exit(EXIT_FAILURE); +                } +                  ret = server_main();          } else { +                if (ap_init(NULL) < 0) { +                        printf("Failed to init.\n"); +                        exit(EXIT_FAILURE); +                } +                  if (s_apn == NULL) {                          printf("No server specified.\n");                          usage(); diff --git a/src/tools/cbr/cbr_server.c b/src/tools/cbr/cbr_server.c index d0666551..8eff4a4c 100644 --- a/src/tools/cbr/cbr_server.c +++ b/src/tools/cbr/cbr_server.c @@ -219,11 +219,6 @@ int server_main()                  return -1;          } -        if (api_bind(NULL) < 0) { -                printf("Failed to bind the server api."); -                return -1; -        } -          for (i = 0; i < THREADS_SIZE; i++)                  pthread_create(&threads[i], NULL, worker, NULL); diff --git a/src/tools/echo/echo.c b/src/tools/echo/echo.c index ab7d5557..28ae4c1a 100644 --- a/src/tools/echo/echo.c +++ b/src/tools/echo/echo.c @@ -41,19 +41,15 @@ static void usage()  int main(int argc, char ** argv)  {          int ret = -1; -        if (ap_init(argv[0])) { -                printf("Failed to init AP.\n"); -                return -1; -        } +        char ** argv_dup = argv; +        bool server = false;          argc--;          argv++;          while (argc > 0) {                  if (strcmp(*argv, "-l") == 0 ||                      strcmp(*argv, "--listen") == 0) { -                        ret = server_main(); -                        ap_fini(); -                        return ret; +                        server = true;                  } else {                          usage();                          return 0; @@ -62,7 +58,19 @@ int main(int argc, char ** argv)                  argv++;          } -        ret = client_main(); +        if (server) { +                if (ap_init(argv_dup[0])) { +                        printf("Failed to init AP.\n"); +                        return -1; +                } +                ret = server_main(); +        } else { +                if (ap_init(NULL)) { +                        printf("Failed to init AP.\n"); +                        return -1; +                } +                ret = client_main(); +        }          ap_fini(); diff --git a/src/tools/echo/echo_server.c b/src/tools/echo/echo_server.c index 3106ee35..e6ab9cfd 100644 --- a/src/tools/echo/echo_server.c +++ b/src/tools/echo/echo_server.c @@ -39,11 +39,6 @@ int server_main()          char   buf[BUF_SIZE];          ssize_t count = 0; -        if (api_bind(NULL) < 0) { -                printf("Failed to bind the server api."); -                return -1; -        } -          printf("Starting the server.\n");          /* Manual cleanup is required for now */ diff --git a/src/tools/irm/CMakeLists.txt b/src/tools/irm/CMakeLists.txt index 68297615..f59d9af0 100644 --- a/src/tools/irm/CMakeLists.txt +++ b/src/tools/irm/CMakeLists.txt @@ -7,10 +7,16 @@ include_directories(${CMAKE_BINARY_DIR}/include)  set(SOURCE_FILES          # Add source files here          irm.c +        irm_bind_ap.c +        irm_bind_api.c +        irm_bind_ipcp.c          irm_ipcp_create.c          irm_ipcp_destroy.c          irm_ipcp_bootstrap.c          irm_ipcp_enroll.c +        irm_unbind_ap.c +        irm_unbind_api.c +        irm_unbind_ipcp.c          irm_unbind.c          irm_bind.c          irm_ipcp.c diff --git a/src/tools/irm/irm.c b/src/tools/irm/irm.c index 14420207..c260feb9 100644 --- a/src/tools/irm/irm.c +++ b/src/tools/irm/irm.c @@ -46,8 +46,8 @@ static const struct cmd {          int (* func)(int argc, char ** argv);  } cmds[] = {          { "ipcp",            ipcp_cmd }, -        { "bind",            do_bind }, -        { "unbind",          do_unbind }, +        { "bind",            bind_cmd }, +        { "unbind",          unbind_cmd },          { "register",        do_register },          { "unregister",      do_unregister },          { "help",            do_help }, diff --git a/src/tools/irm/irm_bind.c b/src/tools/irm/irm_bind.c index 061aeef5..9b37e800 100644 --- a/src/tools/irm/irm_bind.c +++ b/src/tools/irm/irm_bind.c @@ -1,8 +1,9 @@  /*   * Ouroboros - Copyright (C) 2016   * - * Bind AP to a name + * Bind names in the processing system   * + *    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 @@ -21,75 +22,57 @@   */  #include <stdio.h> -#include <string.h>  #include <ouroboros/irm.h> -#include <ouroboros/errno.h>  #include "irm_ops.h"  #include "irm_utils.h"  static void usage()  { -        printf("Usage: irm bind\n" -               "           name <name>\n" -               "           apn <application process name>\n" -               "           [auto] (instantiate apn if not running)\n" -               "           [unique] (there can only be one instantiation)\n" -               "           [-- <application arguments>]\n"); +        printf("Usage: irm bind [OPERATION]\n" +               "where OPERATION = {ap api ipcp help}\n");  } - -int do_bind(int argc, char ** argv) +static int do_help(int argc, char **argv)  { -        char * name = NULL; -        char * ap_name = NULL; -        uint16_t flags = 0; -        int ret = 0; +        usage(); +        return 0; +} -        while (argc > 0) { -                if (matches(*argv, "name") == 0) { -                        name = *(argv + 1); -                        ++argv; -                        --argc; -                } else if (matches(*argv, "apn") == 0) { -                        ap_name = *(argv + 1); -                        ++argv; -                        --argc; -                } else if (strcmp(*argv, "auto") == 0) { -                        flags |= BIND_AP_AUTO; -                } else if (strcmp(*argv, "unique") == 0) { -                        flags |= BIND_AP_UNIQUE; -                } else if (strcmp(*argv, "--") == 0) { -                        ++argv; -                        --argc; -                        break; -                } else { -                        printf("\"%s\" is unknown, try \"irm " -                               "bind\".\n", *argv); -                        return -1; -                } +static const struct cmd { +        const char * cmd; +        int (* func)(int argc, char ** argv); +} cmds[] = { +        { "ap",   do_bind_ap }, +        { "api",  do_bind_api }, +        { "ipcp", do_bind_ipcp }, +        { "help", do_help }, +        { 0 } +}; -                ++argv; -                --argc; -        } +static int do_cmd(const char * argv0, +                  int argc, +                  char ** argv) +{ +        const struct cmd * c; -        if (name == NULL || ap_name == NULL) { -                usage(); -                return -1; +        for (c = cmds; c->cmd; ++c) { +                if (!matches(argv0, c->cmd)) +                        return c->func(argc, argv);          } -        ret = irm_bind(name, ap_name, flags, argc, argv); -        if (ret == -ENOENT) { -                printf("%s does not exist.\n", ap_name); -                return -1; -        } +        fprintf(stderr, "\"%s\" is unknown, try \"irm bind help\".\n", argv0); + +        return -1; +} -        if (ret == -EPERM) { -                printf("Cannot execute %s, please check permissions.\n", -                        ap_name); +int bind_cmd(int argc, char ** argv) +{ +        if (argc < 1) { +                usage();                  return -1;          } -        return ret; +        return do_cmd(argv[0], argc, argv);  } diff --git a/src/tools/irm/irm_bind_ap.c b/src/tools/irm/irm_bind_ap.c new file mode 100644 index 00000000..a525c077 --- /dev/null +++ b/src/tools/irm/irm_bind_ap.c @@ -0,0 +1,98 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Bind AP to a name + * + *    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 <stdio.h> +#include <string.h> + +#include <ouroboros/irm.h> +#include <ouroboros/errno.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ +        printf("Usage: irm bind ap <ap>\n" +               "           name <name>\n" +               "           [auto] (instantiate apn if not running)\n" +               "           [loc] (location-dependent application)\n" +               "           [unique] (there can only be one instantiation)\n" +               "           [-- <application arguments>]\n"); +} + + +int do_bind_ap(int argc, char ** argv) +{ +        char * name = NULL; +        char * ap_name = NULL; +        uint16_t flags = 0; +        int ret = 0; + +        while (argc > 0) { +                if (matches(*argv, "name") == 0) { +                        name = *(argv + 1); +                        ++argv; +                        --argc; +                } else if (matches(*argv, "ap") == 0) { +                        ap_name = *(argv + 1); +                        ++argv; +                        --argc; +                } else if (strcmp(*argv, "auto") == 0) { +                        flags |= BIND_AP_AUTO; +                } else if (strcmp(*argv, "unique") == 0) { +                        flags |= BIND_AP_UNIQUE; +                } else if (strcmp(*argv, "loc") == 0) { +                        flags |= BIND_AP_LOC; +                } else if (strcmp(*argv, "--") == 0) { +                        ++argv; +                        --argc; +                        break; +                } else { +                        printf("\"%s\" is unknown, try \"irm " +                               "bind\".\n", *argv); +                        return -1; +                } + +                ++argv; +                --argc; +        } + +        if (name == NULL || ap_name == NULL) { +                usage(); +                return -1; +        } + +        ret = irm_bind_ap(ap_name, name, flags, argc, argv); +        if (ret == -ENOENT) { +                printf("%s does not exist.\n", ap_name); +                return -1; +        } + +        if (ret == -EPERM) { +                printf("Cannot execute %s, please check permissions.\n", +                        ap_name); +                return -1; +        } + +        return ret; +} diff --git a/src/tools/irm/irm_bind_api.c b/src/tools/irm/irm_bind_api.c new file mode 100644 index 00000000..b21d305c --- /dev/null +++ b/src/tools/irm/irm_bind_api.c @@ -0,0 +1,68 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Bind AP-I to a name + * + *    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 <stdio.h> +#include <stdlib.h> + +#include <ouroboros/irm.h> +#include <ouroboros/errno.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ +        printf("Usage: irm bind api <pid> name <name>\n"); +} + +int do_bind_api(int argc, char ** argv) +{ +        pid_t api = -1; +        char * name = NULL; + +        while (argc > 0) { +                if (matches(*argv, "name") == 0) { +                        name = *(argv + 1); +                        ++argv; +                        --argc; +                } else if (matches(*argv, "api") == 0) { +                        api = strtol(*(argv + 1), NULL, 10); +                        ++argv; +                        --argc; +                } else { +                        printf("\"%s\" is unknown, try \"irm " +                               "bind api\".\n", *argv); +                        return -1; +                } + +                ++argv; +                --argc; +        } + +        if (api < 0 || name == NULL) { +                usage(); +                return -1; +        } + +        return irm_bind_api(api, name); +} diff --git a/src/tools/irm/irm_ipcp.c b/src/tools/irm/irm_ipcp.c index f658ead5..1b523feb 100644 --- a/src/tools/irm/irm_ipcp.c +++ b/src/tools/irm/irm_ipcp.c @@ -29,7 +29,7 @@ static void usage()  {          printf("Usage: irm ipcp [OPERATION]\n\n"                 "where OPERATION = {create destroy\n" -               "                   bootstrap enroll help\n"); +               "                   bootstrap enroll help}\n");  }  static int do_help(int argc, char **argv) diff --git a/src/tools/irm/irm_ops.h b/src/tools/irm/irm_ops.h index 24eee0df..9a59d69a 100644 --- a/src/tools/irm/irm_ops.h +++ b/src/tools/irm/irm_ops.h @@ -26,7 +26,13 @@ int do_destroy_ipcp(int argc, char ** argv);  int do_bootstrap_ipcp(int argc, char ** argv);  int do_enroll_ipcp(int argc, char ** argv); -int do_bind(int argc, char ** argv); -int do_unbind(int argc, char ** argv); +int bind_cmd(int argc, char ** argv); +int do_bind_ap(int argc, char ** argv); +int do_bind_api(int argc, char ** argv); +int do_bind_ipcp(int argc, char ** argv); +int unbind_cmd(int argc, char ** argv); +int do_unbind_ap(int argc, char ** argv); +int do_unbind_api(int argc, char ** argv); +int do_unbind_ipcp(int argc, char ** argv);  int do_register(int argc, char ** argv);  int do_unregister(int argc, char ** argv); diff --git a/src/tools/irm/irm_unbind.c b/src/tools/irm/irm_unbind.c index 9e8f3c9c..0290e678 100644 --- a/src/tools/irm/irm_unbind.c +++ b/src/tools/irm/irm_unbind.c @@ -3,6 +3,7 @@   *   * Unbind names in the processing system   * + *    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 @@ -29,35 +30,46 @@  static void usage()  { -        printf("Usage: irm unbind\n" -               "           name <name>\n" -               "           ap <application process name>\n"); +        printf("Usage: irm unbind [OPERATION]\n" +               "where OPERATION = {ap api ipcp help}\n");  } -int do_unbind(int argc, char ** argv) +static int do_help(int argc, char **argv)  { -        char * name = NULL; -        char * ap_name = NULL; - -        while (argc > 0) { -                if (matches(*argv, "name") == 0) { -                        name = *(argv + 1); -                } else if (matches(*argv, "ap") == 0) { -                        ap_name = *(argv + 1); -                } else { -                        printf("\"%s\" is unknown, try \"irm " -                               "unbind\".\n", *argv); -                        return -1; -                } - -                argc -= 2; -                argv += 2; -        } +        usage(); +        return 0; +} + +static const struct cmd { +        const char * cmd; +        int (* func)(int argc, char ** argv); +} cmds[] = { +        { "ap",   do_unbind_ap }, +        { "api",  do_unbind_api }, +        { "ipcp", do_unbind_ipcp }, +        { "help", do_help }, +        { 0 } +}; + +static int do_cmd(const char * argv0, int argc, char ** argv) +{ +        const struct cmd * c; -        if (name == NULL && ap_name == NULL) { +        for (c = cmds; c->cmd; ++c) +                if (!matches(argv0, c->cmd)) +                        return c->func(argc, argv); + +        fprintf(stderr, "\"%s\" is unknown, try \"irm unbind help\".\n", argv0); + +        return -1; +} + +int unbind_cmd(int argc, char ** argv) +{ +        if (argc < 1) {                  usage();                  return -1;          } -        return irm_unbind(name, ap_name, 0); +        return do_cmd(argv[0], argc, argv);  } diff --git a/src/tools/irm/irm_unbind_ap.c b/src/tools/irm/irm_unbind_ap.c new file mode 100644 index 00000000..bdfcbaad --- /dev/null +++ b/src/tools/irm/irm_unbind_ap.c @@ -0,0 +1,68 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Unbind AP names + * + *    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 <stdio.h> +#include <stdlib.h> + +#include <ouroboros/irm.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ +        printf("Usage: irm unbind ap <ap>\n" +               "          [name <name>, omit: remove all AP info]\n"); +} + +int do_unbind_ap(int argc, char ** argv) +{ +        char * name = NULL; +        char * ap_name = NULL; + +        while (argc > 0) { +                if (matches(*argv, "name") == 0) { +                        name = *(argv + 1); +                        ++argv; +                        --argc; +                } else if (matches(*argv, "ap") == 0) { +                        ap_name = *(argv + 1); +                        ++argv; +                        --argc; +                } else { +                        printf("\"%s\" is unknown, try \"irm " +                               "unbind ap\".\n", *argv); +                        return -1; +                } + +                ++argv; +                --argc; +        } + +        if (ap_name == NULL) { +                usage(); +                return -1; +        } + +        return irm_unbind_ap(ap_name, name); +} diff --git a/src/tools/irm/irm_unbind_api.c b/src/tools/irm/irm_unbind_api.c new file mode 100644 index 00000000..b69a4579 --- /dev/null +++ b/src/tools/irm/irm_unbind_api.c @@ -0,0 +1,69 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Unbind AP-I names + * + *    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 <stdio.h> +#include <stdlib.h> +#include <sys/types.h> + +#include <ouroboros/irm.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ +        printf("Usage: irm unbind api <pid>\n" +               "          [name <name>, omit: remove all AP-I info]\n"); +} + +int do_unbind_api(int argc, char ** argv) +{ +        pid_t api = -1; +        char * name = NULL; + +        while (argc > 0) { +                if (matches(*argv, "name") == 0) { +                        name = *(argv + 1); +                        ++argv; +                        --argc; +                } else if (matches(*argv, "api") == 0) { +                        api = strtol(*(argv + 1), NULL, 10); +                        ++argv; +                        --argc; +                } else { +                        printf("\"%s\" is unknown, try \"irm " +                               "unbind api\".\n", *argv); +                        return -1; +                } + +                ++argv; +                --argc; +        } + +        if (api < 0) { +                usage(); +                return -1; +        } + +        return irm_unbind_api(api, name); +} diff --git a/src/tools/oping/oping.c b/src/tools/oping/oping.c index cf8dc485..2871e79e 100644 --- a/src/tools/oping/oping.c +++ b/src/tools/oping/oping.c @@ -60,6 +60,7 @@ struct c {  struct s {          struct timespec times[OPING_MAX_FLOWS]; +        bool            flows[OPING_MAX_FLOWS];          pthread_mutex_t lock;          pthread_t cleaner_pt; @@ -95,11 +96,7 @@ int main(int argc, char ** argv)          int ret = -1;          char * rem = NULL;          bool serv = false; - -        if (ap_init(argv[0])) { -                printf("Failed to init AP.\n"); -                exit(EXIT_FAILURE); -        } +        char ** argv_dup = argv;          argc--;          argv++; @@ -138,8 +135,18 @@ int main(int argc, char ** argv)          }          if (serv) { +                if (ap_init(argv_dup[0])) { +                        printf("Failed to init AP.\n"); +                        exit(EXIT_FAILURE); +                } +                  ret = server_main();          } else { +                if (ap_init(NULL)) { +                        printf("Failed to init AP.\n"); +                        exit(EXIT_FAILURE); +                } +                  if (client.s_apn == NULL) {                          printf("No server specified.\n");                          usage(); diff --git a/src/tools/oping/oping_server.c b/src/tools/oping/oping_server.c index 9e2fa12f..7761110d 100644 --- a/src/tools/oping/oping_server.c +++ b/src/tools/oping/oping_server.c @@ -53,8 +53,11 @@ void * cleaner_thread(void * o)                  clock_gettime(CLOCK_REALTIME, &now);                  pthread_mutex_lock(&server.lock);                  for (i = 0; i < OPING_MAX_FLOWS; ++i) -                        if (ts_diff_ms(&server.times[i], &now) > deadline_ms) +                        if (server.flows[i] && +                            ts_diff_ms(&server.times[i], &now) > deadline_ms) { +                                server.flows[i] = false;                                  flow_dealloc(i); +                        }                  pthread_mutex_unlock(&server.lock);                  sleep(1); @@ -123,6 +126,7 @@ void * accept_thread(void * o)                  clock_gettime(CLOCK_REALTIME, &now);                  pthread_mutex_lock(&server.lock); +                server.flows[fd] = true;                  server.times[fd] = now;                  pthread_mutex_unlock(&server.lock); @@ -135,6 +139,7 @@ void * accept_thread(void * o)  int server_main()  {          struct sigaction sig_act; +        int i = 0;          memset(&sig_act, 0, sizeof sig_act);          sig_act.sa_sigaction = &shutdown_server; @@ -148,10 +153,8 @@ int server_main()                  return -1;          } -        if (api_bind(NULL) < 0) { -                printf("Failed to bind the server instance."); -                return -1; -        } +        for (i = 0; i < OPING_MAX_FLOWS; ++i) +                server.flows[i] = false;          pthread_create(&server.cleaner_pt, NULL, cleaner_thread, NULL);          pthread_create(&server.accept_pt, NULL, accept_thread, NULL); | 
