summaryrefslogtreecommitdiff
path: root/src/irmd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd/main.c')
-rw-r--r--src/irmd/main.c768
1 files changed, 496 insertions, 272 deletions
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);
}