From 0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Sat, 20 Aug 2016 10:42:36 +0200 Subject: irmd, lib: Rebuild the IRMd data model The complete data model inside the IRMd has been restructured. The bind operation was revised to allow binding of AP and AP instances and register those names with different DIFs (see "irm bind" for details). Server applications require to call ap_init with a server name argument, client application that do not the be reachable over any DIF can call ap_init(NULL). Calling ap_init for a client with a specified name will not have adverse consequences for the application, but will consume unnecessary resources in the IRMd. Application servers can now be started at any point after the IRMd has been started. Starting servers, binding AP names and registering names in DIFs can be performed in any order that does not defy temporal logic. Supports naming instances by their pid. In case of IPCP Instances created with the IRM tool, the name assigned during "irm ipcp create" can be used. All the changes required updates in the tools. --- include/ouroboros/dev.h | 3 - include/ouroboros/irm.h | 23 +- include/ouroboros/irm_config.h | 3 +- include/ouroboros/list.h | 10 + src/ipcpd/ipcp.c | 2 +- src/ipcpd/normal/fmgr.c | 9 - src/irmd/CMakeLists.txt | 2 +- src/irmd/api_table.c | 190 ++++++++-- src/irmd/api_table.h | 57 ++- src/irmd/apn_table.c | 164 +++++++++ src/irmd/apn_table.h | 62 ++++ src/irmd/main.c | 768 ++++++++++++++++++++++++++--------------- src/irmd/registry.c | 504 +++++++++------------------ src/irmd/registry.h | 116 +++---- src/irmd/utils.c | 67 +++- src/irmd/utils.h | 22 ++ src/lib/dev.c | 72 ++-- src/lib/ipcp.c | 4 +- src/lib/irm.c | 85 ++++- src/lib/irmd_messages.proto | 55 +-- src/tools/cbr/cbr.c | 16 +- src/tools/cbr/cbr_server.c | 5 - src/tools/echo/echo.c | 24 +- src/tools/echo/echo_server.c | 5 - src/tools/irm/CMakeLists.txt | 6 + src/tools/irm/irm.c | 4 +- src/tools/irm/irm_bind.c | 87 ++--- src/tools/irm/irm_bind_ap.c | 98 ++++++ src/tools/irm/irm_bind_api.c | 68 ++++ src/tools/irm/irm_ipcp.c | 2 +- src/tools/irm/irm_ops.h | 10 +- src/tools/irm/irm_unbind.c | 58 ++-- src/tools/irm/irm_unbind_ap.c | 68 ++++ src/tools/irm/irm_unbind_api.c | 69 ++++ src/tools/oping/oping.c | 17 +- src/tools/oping/oping_server.c | 13 +- 36 files changed, 1823 insertions(+), 945 deletions(-) create mode 100644 src/irmd/apn_table.c create mode 100644 src/irmd/apn_table.h create mode 100644 src/tools/irm/irm_bind_ap.c create mode 100644 src/tools/irm/irm_bind_api.c create mode 100644 src/tools/irm/irm_unbind_ap.c create mode 100644 src/tools/irm/irm_unbind_api.c diff --git a/include/ouroboros/dev.h b/include/ouroboros/dev.h index a0885b70..d5fb744b 100644 --- a/include/ouroboros/dev.h +++ b/include/ouroboros/dev.h @@ -36,9 +36,6 @@ int ap_init(char * ap_name); void ap_fini(void); -/* This call binds an instance to a specific subset of applications */ -int api_bind(char * ap_subset); - /* Returns file descriptor (> 0) and client AE name. */ int flow_accept(char ** ae_name); int flow_alloc_resp(int fd, int result); diff --git a/include/ouroboros/irm.h b/include/ouroboros/irm.h index 9f27db05..cfad1295 100644 --- a/include/ouroboros/irm.h +++ b/include/ouroboros/irm.h @@ -31,7 +31,7 @@ pid_t irm_create_ipcp(char * name, int irm_destroy_ipcp(pid_t api); -/* APIs is an out-parameter */ +/* apis is an out-parameter */ ssize_t irm_list_ipcps(char * name, pid_t ** apis); @@ -41,15 +41,20 @@ int irm_enroll_ipcp(pid_t api, int irm_bootstrap_ipcp(pid_t api, struct dif_config * conf); -int irm_bind(char * name, - char * ap_name, - uint16_t opts, - int argc, - char ** argv); +int irm_bind_ap(char * ap, + char * name, + uint16_t opts, + int argc, + char ** argv); -int irm_unbind(char * name, - char * ap_name, - uint16_t opts); +int irm_unbind_ap(char * ap, + char * name); + +int irm_bind_api(pid_t api, + char * name); + +int irm_unbind_api(pid_t api, + char * name); int irm_reg(char * name, char ** difs, diff --git a/include/ouroboros/irm_config.h b/include/ouroboros/irm_config.h index dd68e4ec..f90ad927 100644 --- a/include/ouroboros/irm_config.h +++ b/include/ouroboros/irm_config.h @@ -30,8 +30,7 @@ #define BIND_AP_AUTO 0x01 #define BIND_AP_UNIQUE 0x02 - -#define UNBIND_AP_HARD 0x01 +#define BIND_AP_LOC 0x04 enum ipcp_type { IPCP_NORMAL = 0, diff --git a/include/ouroboros/list.h b/include/ouroboros/list.h index 49163efd..80fcb28c 100644 --- a/include/ouroboros/list.h +++ b/include/ouroboros/list.h @@ -134,6 +134,16 @@ void list_splice_init(struct list_head * list, #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) +/** + * list_first_entry - get the struct for the first entry + * expects the list to be non-empty + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop counter. diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 0263d7b5..cc77af89 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -188,7 +188,7 @@ void * ipcp_main_loop(void * o) } conf_msg = msg->conf; conf.type = conf_msg->ipcp_type; - conf.dif_name = strdup(conf_msg->dif_name); + conf.dif_name = conf_msg->dif_name; if (conf.dif_name == NULL) { ret_msg.has_result = true; ret_msg.result = -1; diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index 437dac13..70afff37 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -79,7 +79,6 @@ static void * fmgr_listen(void * o) { int fd; char * ae_name; - bool bound = false; while (true) { pthread_mutex_lock(&_ipcp->state_lock); @@ -94,14 +93,6 @@ static void * fmgr_listen(void * o) } pthread_mutex_unlock(&_ipcp->state_lock); - if (!bound && api_bind(_ipcp->data->dif_name) < 0) { - LOG_ERR("Failed to bind the server instance."); - pthread_mutex_unlock(&_ipcp->state_lock); - return (void *) -1; - } - - bound = true; - fd = flow_accept(&ae_name); if (fd < 0) { LOG_ERR("Failed to accept flow."); diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index ca068703..05919326 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -7,9 +7,9 @@ include_directories(${CMAKE_BINARY_DIR}/include) set(SOURCE_FILES # Add source files here api_table.c + apn_table.c irm_flow.c main.c - reg_api.c registry.c utils.c ) diff --git a/src/irmd/api_table.c b/src/irmd/api_table.c index b62b2b55..2747ed1a 100644 --- a/src/irmd/api_table.c +++ b/src/irmd/api_table.c @@ -23,92 +23,208 @@ #include #include #include +#include #include "api_table.h" +#include "registry.h" #include +#include +#include -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 +#include + +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 + * + * 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 +#include + +#include "apn_table.h" +#include "utils.h" + +#include +#include + +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 + * + * 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 + +#include +#include + +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 #include #include - -#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 +#include 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 #include -#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 + * Sander Vrijders + * + * 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 +#include +#include + +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 + +struct str_el { + struct list_head next; + char * str; +}; + +struct pid_el { + struct list_head next; + pid_t pid; +}; + int wildcard_match(const char * pattern, const char * string); + +/* functions for copying and destroying arguments list */ +char ** argvdup(char ** argv); +void argvfree(char ** argv); + +#endif /* OUROBOROS_IRM_UTILS_H */ diff --git a/src/lib/dev.c b/src/lib/dev.c index f27ef0fe..3a5fc8e0 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -54,6 +54,37 @@ struct ap_data { pthread_rwlock_t flows_lock; } * _ap_instance; +static int api_announce(char * ap_name) +{ + irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t * recv_msg = NULL; + int ret = -1; + + msg.code = IRM_MSG_CODE__IRM_API_ANNOUNCE; + msg.has_api = true; + + pthread_rwlock_rdlock(&_ap_instance->data_lock); + + msg.api = _ap_instance->api; + msg.ap_name = ap_name; + + pthread_rwlock_unlock(&_ap_instance->data_lock); + + recv_msg = send_recv_irm_msg(&msg); + if (recv_msg == NULL) { + return -1; + } + + if (!recv_msg->has_result || (ret = recv_msg->result)) { + irm_msg__free_unpacked(recv_msg, NULL); + return ret; + } + + irm_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + int ap_init(char * ap_name) { int i = 0; @@ -100,6 +131,9 @@ int ap_init(char * ap_name) pthread_rwlock_init(&_ap_instance->flows_lock, NULL); pthread_rwlock_init(&_ap_instance->data_lock, NULL); + if (ap_name != NULL) + return api_announce(ap_name); + return 0; } @@ -134,42 +168,6 @@ void ap_fini(void) free(_ap_instance); } -int api_bind(char * ap_subset) -{ - irm_msg_t msg = IRM_MSG__INIT; - irm_msg_t * recv_msg = NULL; - int ret = -1; - - msg.code = IRM_MSG_CODE__IRM_API_BIND; - msg.has_api = true; - - if (_ap_instance->ap_name == NULL) - return -EPERM; /* call init first */ - - pthread_rwlock_rdlock(&_ap_instance->data_lock); - - msg.api = _ap_instance->api; - msg.ap_name = _ap_instance->ap_name; - - pthread_rwlock_unlock(&_ap_instance->data_lock); - - msg.ap_subset = ap_subset; - - recv_msg = send_recv_irm_msg(&msg); - if (recv_msg == NULL) { - return -1; - } - - if (!recv_msg->has_result || (ret = recv_msg->result)) { - irm_msg__free_unpacked(recv_msg, NULL); - return ret; - } - - irm_msg__free_unpacked(recv_msg, NULL); - - return ret; -} - static int port_id_to_fd(int port_id) { int i; @@ -417,6 +415,8 @@ int flow_dealloc(int fd) msg.code = IRM_MSG_CODE__IRM_FLOW_DEALLOC; msg.has_port_id = true; + msg.has_api = true; + msg.api = getpid(); pthread_rwlock_rdlock(&_ap_instance->data_lock); pthread_rwlock_wrlock(&_ap_instance->flows_lock); diff --git a/src/lib/ipcp.c b/src/lib/ipcp.c index bdc980f9..e8e31e46 100644 --- a/src/lib/ipcp.c +++ b/src/lib/ipcp.c @@ -53,6 +53,7 @@ static ipcp_msg_t * send_recv_ipcp_msg(pid_t api, char * sock_path = NULL; ssize_t count = 0; ipcp_msg_t * recv_msg = NULL; + struct timeval tv = {(SOCKET_TIMEOUT / 1000), (SOCKET_TIMEOUT % 1000) * 1000}; @@ -260,9 +261,8 @@ int ipcp_enroll(pid_t api, msg.dif_name = dif_name; recv_msg = send_recv_ipcp_msg(api, &msg); - if (recv_msg == NULL) { + if (recv_msg == NULL) return -1; - } if (recv_msg->has_result == false) { ipcp_msg__free_unpacked(recv_msg, NULL); diff --git a/src/lib/irm.c b/src/lib/irm.c index 4c71817d..64a4fa0f 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -321,21 +321,21 @@ static int check_ap_path(char ** ap_name) return -ENOENT; } -int irm_bind(char * name, - char * ap_name, - uint16_t opts, - int argc, - char ** argv) +int irm_bind_ap(char * ap, + char * name, + uint16_t opts, + int argc, + char ** argv) { irm_msg_t msg = IRM_MSG__INIT; irm_msg_t * recv_msg = NULL; int ret = -1; char * full_ap_name; - if (name == NULL || ap_name == NULL) + if (ap == NULL || name == NULL) return -EINVAL; - full_ap_name = strdup(ap_name); + full_ap_name = strdup(ap); if (full_ap_name == NULL) return -ENOMEM; @@ -344,7 +344,7 @@ int irm_bind(char * name, return ret; } - msg.code = IRM_MSG_CODE__IRM_BIND; + msg.code = IRM_MSG_CODE__IRM_BIND_AP; msg.dst_name = name; msg.ap_name = full_ap_name; @@ -372,23 +372,76 @@ int irm_bind(char * name, return ret; } -int irm_unbind(char * name, - char * ap_name, - uint16_t opts) +int irm_bind_api(pid_t api, char * name) { irm_msg_t msg = IRM_MSG__INIT; irm_msg_t * recv_msg = NULL; int ret = -1; - if (name == NULL || ap_name == NULL) + if (name == NULL) return -EINVAL; - msg.code = IRM_MSG_CODE__IRM_UNBIND; + msg.code = IRM_MSG_CODE__IRM_BIND_API; + msg.has_api = true; + msg.api = api; + msg.dst_name = name; + + recv_msg = send_recv_irm_msg(&msg); + if (recv_msg == NULL) + return -1; + + if (recv_msg->has_result == false) { + irm_msg__free_unpacked(recv_msg, NULL); + return -1; + } + + ret = recv_msg->result; + irm_msg__free_unpacked(recv_msg, NULL); + return ret; +} + +int irm_unbind_ap(char * ap, char * name) +{ + irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t * recv_msg = NULL; + int ret = -1; + + if (name == NULL) + return -EINVAL; + + msg.code = IRM_MSG_CODE__IRM_UNBIND_AP; + msg.ap_name = ap; + msg.dst_name = name; + + recv_msg = send_recv_irm_msg(&msg); + if (recv_msg == NULL) + return -1; + + if (recv_msg->has_result == false) { + irm_msg__free_unpacked(recv_msg, NULL); + return -1; + } + + ret = recv_msg->result; + irm_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + +int irm_unbind_api(pid_t api, char * name) +{ + irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t * recv_msg = NULL; + int ret = -1; + + if (name == NULL) + return -EINVAL; + + msg.code = IRM_MSG_CODE__IRM_UNBIND_API; + msg.has_api = true; + msg.api = api; msg.dst_name = name; - msg.ap_name = ap_name; - msg.has_opts = true; - msg.opts = opts; recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index 5c320a17..7a634201 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -29,36 +29,37 @@ enum irm_msg_code { IRM_LIST_IPCPS = 4; IRM_BOOTSTRAP_IPCP = 5; IRM_ENROLL_IPCP = 6; - IRM_BIND = 7; - IRM_UNBIND = 8; - IRM_API_BIND = 9; - IRM_REG = 10; - IRM_UNREG = 11; - IRM_FLOW_ACCEPT = 12; - IRM_FLOW_ALLOC_RESP = 13; - IRM_FLOW_ALLOC = 14; - IRM_FLOW_ALLOC_RES = 15; - IRM_FLOW_DEALLOC = 16; - IPCP_FLOW_REQ_ARR = 17; - IPCP_FLOW_ALLOC_REPLY = 18; - IPCP_FLOW_DEALLOC = 19; - IRM_REPLY = 20; + IRM_BIND_AP = 7; + IRM_UNBIND_AP = 8; + IRM_API_ANNOUNCE = 9; + IRM_BIND_API = 10; + IRM_UNBIND_API = 11; + IRM_REG = 12; + IRM_UNREG = 13; + IRM_FLOW_ACCEPT = 14; + IRM_FLOW_ALLOC_RESP = 15; + IRM_FLOW_ALLOC = 16; + IRM_FLOW_ALLOC_RES = 17; + IRM_FLOW_DEALLOC = 18; + IPCP_FLOW_REQ_ARR = 19; + IPCP_FLOW_ALLOC_REPLY = 20; + IPCP_FLOW_DEALLOC = 21; + IRM_REPLY = 22; }; message irm_msg { required irm_msg_code code = 1; optional string ap_name = 2; - optional string ap_subset = 3; - optional string ae_name = 4; - optional sint32 api = 5; - optional uint32 ipcp_type = 6; - repeated string dif_name = 7; - repeated string args = 8; - optional sint32 response = 9; - optional string dst_name = 10; - optional sint32 port_id = 11; - optional dif_config_msg conf = 12; - optional uint32 opts = 13; - repeated sint32 apis = 14; - optional sint32 result = 15; + optional string ae_name = 3; + optional sint32 api = 4; + optional uint32 ipcp_type = 5; + repeated string dif_name = 6; + repeated string args = 7; + optional sint32 response = 8; + optional string dst_name = 9; + optional sint32 port_id = 10; + optional dif_config_msg conf = 11; + optional uint32 opts = 12; + repeated sint32 apis = 13; + optional sint32 result = 14; }; diff --git a/src/tools/cbr/cbr.c b/src/tools/cbr/cbr.c index 65783119..e42492df 100644 --- a/src/tools/cbr/cbr.c +++ b/src/tools/cbr/cbr.c @@ -72,14 +72,10 @@ int main(int argc, char ** argv) int ret = 0; char * rem = NULL; char * s_apn = NULL; + char ** argv_dup = argv; bool server = false; - if (ap_init(argv[0]) < 0) { - printf("Failed to init.\n"); - exit(EXIT_FAILURE); - } - server_settings.interval = 1; /* One second reporting interval */ server_settings.timeout = 1; @@ -133,8 +129,18 @@ int main(int argc, char ** argv) } if (server) { + if (ap_init(argv_dup[0]) < 0) { + printf("Failed to init.\n"); + exit(EXIT_FAILURE); + } + ret = server_main(); } else { + if (ap_init(NULL) < 0) { + printf("Failed to init.\n"); + exit(EXIT_FAILURE); + } + if (s_apn == NULL) { printf("No server specified.\n"); usage(); diff --git a/src/tools/cbr/cbr_server.c b/src/tools/cbr/cbr_server.c index d0666551..8eff4a4c 100644 --- a/src/tools/cbr/cbr_server.c +++ b/src/tools/cbr/cbr_server.c @@ -219,11 +219,6 @@ int server_main() return -1; } - if (api_bind(NULL) < 0) { - printf("Failed to bind the server api."); - return -1; - } - for (i = 0; i < THREADS_SIZE; i++) pthread_create(&threads[i], NULL, worker, NULL); diff --git a/src/tools/echo/echo.c b/src/tools/echo/echo.c index ab7d5557..28ae4c1a 100644 --- a/src/tools/echo/echo.c +++ b/src/tools/echo/echo.c @@ -41,19 +41,15 @@ static void usage() int main(int argc, char ** argv) { int ret = -1; - if (ap_init(argv[0])) { - printf("Failed to init AP.\n"); - return -1; - } + char ** argv_dup = argv; + bool server = false; argc--; argv++; while (argc > 0) { if (strcmp(*argv, "-l") == 0 || strcmp(*argv, "--listen") == 0) { - ret = server_main(); - ap_fini(); - return ret; + server = true; } else { usage(); return 0; @@ -62,7 +58,19 @@ int main(int argc, char ** argv) argv++; } - ret = client_main(); + if (server) { + if (ap_init(argv_dup[0])) { + printf("Failed to init AP.\n"); + return -1; + } + ret = server_main(); + } else { + if (ap_init(NULL)) { + printf("Failed to init AP.\n"); + return -1; + } + ret = client_main(); + } ap_fini(); diff --git a/src/tools/echo/echo_server.c b/src/tools/echo/echo_server.c index 3106ee35..e6ab9cfd 100644 --- a/src/tools/echo/echo_server.c +++ b/src/tools/echo/echo_server.c @@ -39,11 +39,6 @@ int server_main() char buf[BUF_SIZE]; ssize_t count = 0; - if (api_bind(NULL) < 0) { - printf("Failed to bind the server api."); - return -1; - } - printf("Starting the server.\n"); /* Manual cleanup is required for now */ diff --git a/src/tools/irm/CMakeLists.txt b/src/tools/irm/CMakeLists.txt index 68297615..f59d9af0 100644 --- a/src/tools/irm/CMakeLists.txt +++ b/src/tools/irm/CMakeLists.txt @@ -7,10 +7,16 @@ include_directories(${CMAKE_BINARY_DIR}/include) set(SOURCE_FILES # Add source files here irm.c + irm_bind_ap.c + irm_bind_api.c + irm_bind_ipcp.c irm_ipcp_create.c irm_ipcp_destroy.c irm_ipcp_bootstrap.c irm_ipcp_enroll.c + irm_unbind_ap.c + irm_unbind_api.c + irm_unbind_ipcp.c irm_unbind.c irm_bind.c irm_ipcp.c diff --git a/src/tools/irm/irm.c b/src/tools/irm/irm.c index 14420207..c260feb9 100644 --- a/src/tools/irm/irm.c +++ b/src/tools/irm/irm.c @@ -46,8 +46,8 @@ static const struct cmd { int (* func)(int argc, char ** argv); } cmds[] = { { "ipcp", ipcp_cmd }, - { "bind", do_bind }, - { "unbind", do_unbind }, + { "bind", bind_cmd }, + { "unbind", unbind_cmd }, { "register", do_register }, { "unregister", do_unregister }, { "help", do_help }, diff --git a/src/tools/irm/irm_bind.c b/src/tools/irm/irm_bind.c index 061aeef5..9b37e800 100644 --- a/src/tools/irm/irm_bind.c +++ b/src/tools/irm/irm_bind.c @@ -1,8 +1,9 @@ /* * Ouroboros - Copyright (C) 2016 * - * Bind AP to a name + * Bind names in the processing system * + * Dimitri Staessens * Sander Vrijders * * This program is free software; you can redistribute it and/or modify @@ -21,75 +22,57 @@ */ #include -#include #include -#include #include "irm_ops.h" #include "irm_utils.h" static void usage() { - printf("Usage: irm bind\n" - " name \n" - " apn \n" - " [auto] (instantiate apn if not running)\n" - " [unique] (there can only be one instantiation)\n" - " [-- ]\n"); + printf("Usage: irm bind [OPERATION]\n" + "where OPERATION = {ap api ipcp help}\n"); } - -int do_bind(int argc, char ** argv) +static int do_help(int argc, char **argv) { - char * name = NULL; - char * ap_name = NULL; - uint16_t flags = 0; - int ret = 0; + usage(); + return 0; +} - while (argc > 0) { - if (matches(*argv, "name") == 0) { - name = *(argv + 1); - ++argv; - --argc; - } else if (matches(*argv, "apn") == 0) { - ap_name = *(argv + 1); - ++argv; - --argc; - } else if (strcmp(*argv, "auto") == 0) { - flags |= BIND_AP_AUTO; - } else if (strcmp(*argv, "unique") == 0) { - flags |= BIND_AP_UNIQUE; - } else if (strcmp(*argv, "--") == 0) { - ++argv; - --argc; - break; - } else { - printf("\"%s\" is unknown, try \"irm " - "bind\".\n", *argv); - return -1; - } +static const struct cmd { + const char * cmd; + int (* func)(int argc, char ** argv); +} cmds[] = { + { "ap", do_bind_ap }, + { "api", do_bind_api }, + { "ipcp", do_bind_ipcp }, + { "help", do_help }, + { 0 } +}; - ++argv; - --argc; - } +static int do_cmd(const char * argv0, + int argc, + char ** argv) +{ + const struct cmd * c; - if (name == NULL || ap_name == NULL) { - usage(); - return -1; + for (c = cmds; c->cmd; ++c) { + if (!matches(argv0, c->cmd)) + return c->func(argc, argv); } - ret = irm_bind(name, ap_name, flags, argc, argv); - if (ret == -ENOENT) { - printf("%s does not exist.\n", ap_name); - return -1; - } + fprintf(stderr, "\"%s\" is unknown, try \"irm bind help\".\n", argv0); + + return -1; +} - if (ret == -EPERM) { - printf("Cannot execute %s, please check permissions.\n", - ap_name); +int bind_cmd(int argc, char ** argv) +{ + if (argc < 1) { + usage(); return -1; } - return ret; + return do_cmd(argv[0], argc, argv); } diff --git a/src/tools/irm/irm_bind_ap.c b/src/tools/irm/irm_bind_ap.c new file mode 100644 index 00000000..a525c077 --- /dev/null +++ b/src/tools/irm/irm_bind_ap.c @@ -0,0 +1,98 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Bind AP to a name + * + * Dimitri Staessens + * Sander Vrijders + * + * 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 +#include + +#include +#include + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ + printf("Usage: irm bind ap \n" + " name \n" + " [auto] (instantiate apn if not running)\n" + " [loc] (location-dependent application)\n" + " [unique] (there can only be one instantiation)\n" + " [-- ]\n"); +} + + +int do_bind_ap(int argc, char ** argv) +{ + char * name = NULL; + char * ap_name = NULL; + uint16_t flags = 0; + int ret = 0; + + while (argc > 0) { + if (matches(*argv, "name") == 0) { + name = *(argv + 1); + ++argv; + --argc; + } else if (matches(*argv, "ap") == 0) { + ap_name = *(argv + 1); + ++argv; + --argc; + } else if (strcmp(*argv, "auto") == 0) { + flags |= BIND_AP_AUTO; + } else if (strcmp(*argv, "unique") == 0) { + flags |= BIND_AP_UNIQUE; + } else if (strcmp(*argv, "loc") == 0) { + flags |= BIND_AP_LOC; + } else if (strcmp(*argv, "--") == 0) { + ++argv; + --argc; + break; + } else { + printf("\"%s\" is unknown, try \"irm " + "bind\".\n", *argv); + return -1; + } + + ++argv; + --argc; + } + + if (name == NULL || ap_name == NULL) { + usage(); + return -1; + } + + ret = irm_bind_ap(ap_name, name, flags, argc, argv); + if (ret == -ENOENT) { + printf("%s does not exist.\n", ap_name); + return -1; + } + + if (ret == -EPERM) { + printf("Cannot execute %s, please check permissions.\n", + ap_name); + return -1; + } + + return ret; +} diff --git a/src/tools/irm/irm_bind_api.c b/src/tools/irm/irm_bind_api.c new file mode 100644 index 00000000..b21d305c --- /dev/null +++ b/src/tools/irm/irm_bind_api.c @@ -0,0 +1,68 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Bind AP-I to a name + * + * Dimitri Staessens + * Sander Vrijders + * + * 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 +#include + +#include +#include + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ + printf("Usage: irm bind api name \n"); +} + +int do_bind_api(int argc, char ** argv) +{ + pid_t api = -1; + char * name = NULL; + + while (argc > 0) { + if (matches(*argv, "name") == 0) { + name = *(argv + 1); + ++argv; + --argc; + } else if (matches(*argv, "api") == 0) { + api = strtol(*(argv + 1), NULL, 10); + ++argv; + --argc; + } else { + printf("\"%s\" is unknown, try \"irm " + "bind api\".\n", *argv); + return -1; + } + + ++argv; + --argc; + } + + if (api < 0 || name == NULL) { + usage(); + return -1; + } + + return irm_bind_api(api, name); +} diff --git a/src/tools/irm/irm_ipcp.c b/src/tools/irm/irm_ipcp.c index f658ead5..1b523feb 100644 --- a/src/tools/irm/irm_ipcp.c +++ b/src/tools/irm/irm_ipcp.c @@ -29,7 +29,7 @@ static void usage() { printf("Usage: irm ipcp [OPERATION]\n\n" "where OPERATION = {create destroy\n" - " bootstrap enroll help\n"); + " bootstrap enroll help}\n"); } static int do_help(int argc, char **argv) diff --git a/src/tools/irm/irm_ops.h b/src/tools/irm/irm_ops.h index 24eee0df..9a59d69a 100644 --- a/src/tools/irm/irm_ops.h +++ b/src/tools/irm/irm_ops.h @@ -26,7 +26,13 @@ int do_destroy_ipcp(int argc, char ** argv); int do_bootstrap_ipcp(int argc, char ** argv); int do_enroll_ipcp(int argc, char ** argv); -int do_bind(int argc, char ** argv); -int do_unbind(int argc, char ** argv); +int bind_cmd(int argc, char ** argv); +int do_bind_ap(int argc, char ** argv); +int do_bind_api(int argc, char ** argv); +int do_bind_ipcp(int argc, char ** argv); +int unbind_cmd(int argc, char ** argv); +int do_unbind_ap(int argc, char ** argv); +int do_unbind_api(int argc, char ** argv); +int do_unbind_ipcp(int argc, char ** argv); int do_register(int argc, char ** argv); int do_unregister(int argc, char ** argv); diff --git a/src/tools/irm/irm_unbind.c b/src/tools/irm/irm_unbind.c index 9e8f3c9c..0290e678 100644 --- a/src/tools/irm/irm_unbind.c +++ b/src/tools/irm/irm_unbind.c @@ -3,6 +3,7 @@ * * Unbind names in the processing system * + * Dimitri Staessens * Sander Vrijders * * This program is free software; you can redistribute it and/or modify @@ -29,35 +30,46 @@ static void usage() { - printf("Usage: irm unbind\n" - " name \n" - " ap \n"); + printf("Usage: irm unbind [OPERATION]\n" + "where OPERATION = {ap api ipcp help}\n"); } -int do_unbind(int argc, char ** argv) +static int do_help(int argc, char **argv) { - char * name = NULL; - char * ap_name = NULL; - - while (argc > 0) { - if (matches(*argv, "name") == 0) { - name = *(argv + 1); - } else if (matches(*argv, "ap") == 0) { - ap_name = *(argv + 1); - } else { - printf("\"%s\" is unknown, try \"irm " - "unbind\".\n", *argv); - return -1; - } - - argc -= 2; - argv += 2; - } + usage(); + return 0; +} + +static const struct cmd { + const char * cmd; + int (* func)(int argc, char ** argv); +} cmds[] = { + { "ap", do_unbind_ap }, + { "api", do_unbind_api }, + { "ipcp", do_unbind_ipcp }, + { "help", do_help }, + { 0 } +}; + +static int do_cmd(const char * argv0, int argc, char ** argv) +{ + const struct cmd * c; - if (name == NULL && ap_name == NULL) { + for (c = cmds; c->cmd; ++c) + if (!matches(argv0, c->cmd)) + return c->func(argc, argv); + + fprintf(stderr, "\"%s\" is unknown, try \"irm unbind help\".\n", argv0); + + return -1; +} + +int unbind_cmd(int argc, char ** argv) +{ + if (argc < 1) { usage(); return -1; } - return irm_unbind(name, ap_name, 0); + return do_cmd(argv[0], argc, argv); } diff --git a/src/tools/irm/irm_unbind_ap.c b/src/tools/irm/irm_unbind_ap.c new file mode 100644 index 00000000..bdfcbaad --- /dev/null +++ b/src/tools/irm/irm_unbind_ap.c @@ -0,0 +1,68 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Unbind AP names + * + * Dimitri Staessens + * Sander Vrijders + * + * 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 +#include + +#include + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ + printf("Usage: irm unbind ap \n" + " [name , omit: remove all AP info]\n"); +} + +int do_unbind_ap(int argc, char ** argv) +{ + char * name = NULL; + char * ap_name = NULL; + + while (argc > 0) { + if (matches(*argv, "name") == 0) { + name = *(argv + 1); + ++argv; + --argc; + } else if (matches(*argv, "ap") == 0) { + ap_name = *(argv + 1); + ++argv; + --argc; + } else { + printf("\"%s\" is unknown, try \"irm " + "unbind ap\".\n", *argv); + return -1; + } + + ++argv; + --argc; + } + + if (ap_name == NULL) { + usage(); + return -1; + } + + return irm_unbind_ap(ap_name, name); +} diff --git a/src/tools/irm/irm_unbind_api.c b/src/tools/irm/irm_unbind_api.c new file mode 100644 index 00000000..b69a4579 --- /dev/null +++ b/src/tools/irm/irm_unbind_api.c @@ -0,0 +1,69 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Unbind AP-I names + * + * Dimitri Staessens + * Sander Vrijders + * + * 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 +#include +#include + +#include + +#include "irm_ops.h" +#include "irm_utils.h" + +static void usage() +{ + printf("Usage: irm unbind api \n" + " [name , omit: remove all AP-I info]\n"); +} + +int do_unbind_api(int argc, char ** argv) +{ + pid_t api = -1; + char * name = NULL; + + while (argc > 0) { + if (matches(*argv, "name") == 0) { + name = *(argv + 1); + ++argv; + --argc; + } else if (matches(*argv, "api") == 0) { + api = strtol(*(argv + 1), NULL, 10); + ++argv; + --argc; + } else { + printf("\"%s\" is unknown, try \"irm " + "unbind api\".\n", *argv); + return -1; + } + + ++argv; + --argc; + } + + if (api < 0) { + usage(); + return -1; + } + + return irm_unbind_api(api, name); +} diff --git a/src/tools/oping/oping.c b/src/tools/oping/oping.c index cf8dc485..2871e79e 100644 --- a/src/tools/oping/oping.c +++ b/src/tools/oping/oping.c @@ -60,6 +60,7 @@ struct c { struct s { struct timespec times[OPING_MAX_FLOWS]; + bool flows[OPING_MAX_FLOWS]; pthread_mutex_t lock; pthread_t cleaner_pt; @@ -95,11 +96,7 @@ int main(int argc, char ** argv) int ret = -1; char * rem = NULL; bool serv = false; - - if (ap_init(argv[0])) { - printf("Failed to init AP.\n"); - exit(EXIT_FAILURE); - } + char ** argv_dup = argv; argc--; argv++; @@ -138,8 +135,18 @@ int main(int argc, char ** argv) } if (serv) { + if (ap_init(argv_dup[0])) { + printf("Failed to init AP.\n"); + exit(EXIT_FAILURE); + } + ret = server_main(); } else { + if (ap_init(NULL)) { + printf("Failed to init AP.\n"); + exit(EXIT_FAILURE); + } + if (client.s_apn == NULL) { printf("No server specified.\n"); usage(); diff --git a/src/tools/oping/oping_server.c b/src/tools/oping/oping_server.c index 9e2fa12f..7761110d 100644 --- a/src/tools/oping/oping_server.c +++ b/src/tools/oping/oping_server.c @@ -53,8 +53,11 @@ void * cleaner_thread(void * o) clock_gettime(CLOCK_REALTIME, &now); pthread_mutex_lock(&server.lock); for (i = 0; i < OPING_MAX_FLOWS; ++i) - if (ts_diff_ms(&server.times[i], &now) > deadline_ms) + if (server.flows[i] && + ts_diff_ms(&server.times[i], &now) > deadline_ms) { + server.flows[i] = false; flow_dealloc(i); + } pthread_mutex_unlock(&server.lock); sleep(1); @@ -123,6 +126,7 @@ void * accept_thread(void * o) clock_gettime(CLOCK_REALTIME, &now); pthread_mutex_lock(&server.lock); + server.flows[fd] = true; server.times[fd] = now; pthread_mutex_unlock(&server.lock); @@ -135,6 +139,7 @@ void * accept_thread(void * o) int server_main() { struct sigaction sig_act; + int i = 0; memset(&sig_act, 0, sizeof sig_act); sig_act.sa_sigaction = &shutdown_server; @@ -148,10 +153,8 @@ int server_main() return -1; } - if (api_bind(NULL) < 0) { - printf("Failed to bind the server instance."); - return -1; - } + for (i = 0; i < OPING_MAX_FLOWS; ++i) + server.flows[i] = false; pthread_create(&server.cleaner_pt, NULL, cleaner_thread, NULL); pthread_create(&server.accept_pt, NULL, accept_thread, NULL); -- cgit v1.2.3