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