diff options
Diffstat (limited to 'src/irmd')
| -rw-r--r-- | src/irmd/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/irmd/api_table.c | 190 | ||||
| -rw-r--r-- | src/irmd/api_table.h | 57 | ||||
| -rw-r--r-- | src/irmd/apn_table.c | 164 | ||||
| -rw-r--r-- | src/irmd/apn_table.h | 62 | ||||
| -rw-r--r-- | src/irmd/main.c | 768 | ||||
| -rw-r--r-- | src/irmd/registry.c | 504 | ||||
| -rw-r--r-- | src/irmd/registry.h | 116 | ||||
| -rw-r--r-- | src/irmd/utils.c | 67 | ||||
| -rw-r--r-- | src/irmd/utils.h | 22 | 
10 files changed, 1225 insertions, 727 deletions
| 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..bdf8f660 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; @@ -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); +                return -1; +        } + +        name_dup = strdup(name); +        if (name_dup == NULL) { +                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 -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; +        } + +        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(&rne->state_lock); +        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); -        rne->req_ae_name = ae_name; +        re->req_ae_name = ae_name; +        re->state = REG_NAME_FLOW_ARRIVED; -        rne->state = REG_NAME_FLOW_ARRIVED; +        pthread_mutex_unlock(&re->state_lock); -        rgi = reg_entry_get_reg_api(rne, f->n_api); +        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; +        } + +        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(&rne->state_lock); +        pthread_mutex_lock(&re->state_lock); -        while (rne->state == REG_NAME_FLOW_ARRIVED) -                pthread_cond_wait(&rne->state_cond, &rne->state_lock); +        while (re->state == REG_NAME_FLOW_ARRIVED) +                pthread_cond_wait(&re->state_cond, &re->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);          } @@ -1477,26 +1695,25 @@ void * irm_flow_cleaner()                  }                  pthread_rwlock_unlock(&irmd->flows_lock); -                  pthread_rwlock_wrlock(&irmd->reg_lock); -                registry_sanitize_apis(&irmd->registry); +                /* FIXME: clear registry of dead AP-I's */                  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); +                        struct pid_el * api = +                                list_entry(pos, struct pid_el, next); +                        waitpid(api->pid, &status, WNOHANG); -                        if (kill(api->api, 0) < 0) { +                        if (kill(api->pid, 0) < 0) {                                  LOG_INFO("Spawned process %d terminated "                                           "with exit status %d.", -                                         api->api, status); +                                         api->pid, 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) { +                                        if (e->api == api->pid) {                                                  list_del(&e->next);                                                  ipcp_entry_destroy(e);                                          } @@ -1595,25 +1812,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 +1848,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 +1890,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 +1913,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 +1967,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 +1975,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 +2007,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 +2061,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 +2151,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 +2171,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);          } 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 */ | 
