summaryrefslogtreecommitdiff
path: root/src/ipcpd/ipcp-data.c
diff options
context:
space:
mode:
authorSander Vrijders <[email protected]>2016-10-25 13:22:51 +0200
committerSander Vrijders <[email protected]>2016-10-26 11:52:53 +0200
commitf0646875d0bc941e339d305d0c68b13543cd6f2a (patch)
tree0a3dde0e4f6284ece935d6eff99f26234126f1ab /src/ipcpd/ipcp-data.c
parent1c06b9ff80a2bf7ee6042534fee6098f7e452b59 (diff)
downloadouroboros-f0646875d0bc941e339d305d0c68b13543cd6f2a.tar.gz
ouroboros-f0646875d0bc941e339d305d0c68b13543cd6f2a.zip
lib, irmd, ipcpd: Add name querying to IPCPs
This adds the ability to query IPCPs if a name can be reached through them, e.g. if a name is available in a DIF. This means that in the shim-udp a DNS query is performed, in the shim-eth-llc an ARP-like query has been added, in the local a check is done to see if the name is registered, and in the normal currently no application is reachable through it.
Diffstat (limited to 'src/ipcpd/ipcp-data.c')
-rw-r--r--src/ipcpd/ipcp-data.c308
1 files changed, 227 insertions, 81 deletions
diff --git a/src/ipcpd/ipcp-data.c b/src/ipcpd/ipcp-data.c
index ed7e578d..b3078054 100644
--- a/src/ipcpd/ipcp-data.c
+++ b/src/ipcpd/ipcp-data.c
@@ -21,14 +21,16 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <ouroboros/config.h>
-#include <ouroboros/list.h>
-
#define OUROBOROS_PREFIX "ipcp-utils"
+#include <ouroboros/config.h>
+#include <ouroboros/list.h>
+#include <ouroboros/time_utils.h>
#include <ouroboros/logs.h>
+#include <ouroboros/errno.h>
#include "ipcp-data.h"
+#include "ipcp.h"
#include <string.h>
#include <stdlib.h>
@@ -41,8 +43,8 @@ struct reg_entry {
struct dir_entry {
struct list_head list;
- char * ap_name;
- uint64_t addr;
+ char * name;
+ uint64_t addr;
};
static struct reg_entry * reg_entry_create(char * name)
@@ -70,18 +72,18 @@ static void reg_entry_destroy(struct reg_entry * entry)
free(entry);
}
-static struct dir_entry * dir_entry_create(char * ap_name,
+static struct dir_entry * dir_entry_create(char * name,
uint64_t addr)
{
struct dir_entry * entry = malloc(sizeof(*entry));
if (entry == NULL)
return NULL;
- assert(ap_name);
+ assert(name);
entry->addr = addr;
- entry->ap_name = ap_name;
- if (entry->ap_name == NULL)
+ entry->name = name;
+ if (entry->name == NULL)
return NULL;
return entry;
@@ -91,8 +93,8 @@ static void dir_entry_destroy(struct dir_entry * entry)
{
assert(entry);
- if (entry->ap_name != NULL)
- free(entry->ap_name);
+ if (entry->name != NULL)
+ free(entry->name);
free(entry);
}
@@ -120,10 +122,12 @@ struct ipcp_data * ipcp_data_init(struct ipcp_data * dst,
/* init the lists */
INIT_LIST_HEAD(&dst->registry);
INIT_LIST_HEAD(&dst->directory);
+ INIT_LIST_HEAD(&dst->dir_queries);
/* init the locks */
pthread_rwlock_init(&dst->reg_lock, NULL);
pthread_rwlock_init(&dst->dir_lock, NULL);
+ pthread_mutex_init(&dst->dir_queries_lock, NULL);
return dst;
}
@@ -156,6 +160,20 @@ static void clear_directory(struct ipcp_data * data)
}
}
+static void clear_dir_queries(struct ipcp_data * data)
+{
+ struct list_head * h;
+ struct list_head * t;
+
+ assert(data);
+
+ list_for_each_safe(h, t, &data->dir_queries) {
+ struct dir_query * e = list_entry(h, struct dir_query, next);
+ list_del(&e->next);
+ ipcp_data_dir_query_destroy(e);
+ }
+}
+
void ipcp_data_destroy(struct ipcp_data * data)
{
if (data == NULL)
@@ -163,27 +181,27 @@ void ipcp_data_destroy(struct ipcp_data * data)
/* clear the lists */
pthread_rwlock_wrlock(&data->reg_lock);
-
clear_registry(data);
-
pthread_rwlock_unlock(&data->reg_lock);
- pthread_rwlock_wrlock(&data->dir_lock);
+ pthread_rwlock_wrlock(&data->dir_lock);
clear_directory(data);
-
pthread_rwlock_unlock(&data->dir_lock);
+ pthread_mutex_lock(&data->dir_queries_lock);
+ clear_dir_queries(data);
+ pthread_mutex_unlock(&data->dir_queries_lock);
+
if (data->dif_name != NULL)
free(data->dif_name);
pthread_rwlock_destroy(&data->dir_lock);
pthread_rwlock_destroy(&data->reg_lock);
+ pthread_mutex_destroy(&data->dir_queries_lock);
free(data);
}
-
-
static struct reg_entry * find_reg_entry_by_name(struct ipcp_data * data,
const char * name)
{
@@ -202,13 +220,13 @@ static struct reg_entry * find_reg_entry_by_name(struct ipcp_data * data,
}
static struct dir_entry * find_dir_entry(struct ipcp_data * data,
- const char * ap_name,
+ const char * name,
uint64_t addr)
{
struct list_head * h;
list_for_each(h, &data->directory) {
struct dir_entry * e = list_entry(h, struct dir_entry, list);
- if (e->addr == addr && !strcmp(e->ap_name, ap_name))
+ if (e->addr == addr && !strcmp(e->name, name))
return e;
}
@@ -216,33 +234,47 @@ static struct dir_entry * find_dir_entry(struct ipcp_data * data,
}
static struct dir_entry * find_dir_entry_any(struct ipcp_data * data,
- const char * ap_name)
+ const char * name)
{
struct list_head * h;
list_for_each(h, &data->directory) {
struct dir_entry * e = list_entry(h, struct dir_entry, list);
- if (!strcmp(e->ap_name, ap_name))
+ if (!strcmp(e->name, name))
return e;
}
return NULL;
}
-bool ipcp_data_is_in_directory(struct ipcp_data * data,
- const char * ap_name)
+int ipcp_data_reg_add_entry(struct ipcp_data * data,
+ char * name)
{
- bool ret = false;
+ struct reg_entry * entry;
- pthread_rwlock_rdlock(&data->dir_lock);
+ if (data == NULL || name == NULL)
+ return -1;
- ret = (find_dir_entry_any(data, ap_name) != NULL);
+ pthread_rwlock_wrlock(&data->reg_lock);
- pthread_rwlock_unlock(&data->dir_lock);
+ if (find_reg_entry_by_name(data, name)) {
+ pthread_rwlock_unlock(&data->reg_lock);
+ return -1;
+ }
- return ret;
+ entry = reg_entry_create(name);
+ if (entry == NULL) {
+ pthread_rwlock_unlock(&data->reg_lock);
+ return -1;
+ }
+
+ list_add(&entry->list, &data->registry);
+
+ pthread_rwlock_unlock(&data->reg_lock);
+
+ return 0;
}
-int ipcp_data_del_reg_entry(struct ipcp_data * data,
+int ipcp_data_reg_del_entry(struct ipcp_data * data,
const char * name)
{
struct reg_entry * e;
@@ -266,114 +298,109 @@ int ipcp_data_del_reg_entry(struct ipcp_data * data,
return 0;
}
-int ipcp_data_del_dir_entry(struct ipcp_data * data,
- const char * ap_name,
- uint64_t addr)
+bool ipcp_data_reg_has(struct ipcp_data * data,
+ const char * name)
{
- struct dir_entry * e;
- if (data == NULL)
- return -1;
-
- pthread_rwlock_wrlock(&data->dir_lock);
+ bool ret = false;
- e = find_dir_entry(data, ap_name, addr);
- if (e == NULL) {
- pthread_rwlock_unlock(&data->dir_lock);
- return 0; /* nothing to do */
- }
+ if (data == NULL || name == NULL)
+ return false;
- list_del(&e->list);
+ pthread_rwlock_rdlock(&data->reg_lock);
- pthread_rwlock_unlock(&data->dir_lock);
+ ret = (find_reg_entry_by_name(data, name) != NULL);
- dir_entry_destroy(e);
+ pthread_rwlock_unlock(&data->reg_lock);
- return 0;
+ return ret;
}
-int ipcp_data_add_reg_entry(struct ipcp_data * data,
- char * name)
+int ipcp_data_dir_add_entry(struct ipcp_data * data,
+ char * name,
+ uint64_t addr)
{
- struct reg_entry * entry;
+ struct dir_entry * entry;
+ char * entry_name;
if (data == NULL || name == NULL)
return -1;
- pthread_rwlock_wrlock(&data->reg_lock);
+ pthread_rwlock_wrlock(&data->dir_lock);
- if (find_reg_entry_by_name(data, name)) {
- pthread_rwlock_unlock(&data->reg_lock);
+ if (find_dir_entry(data, name, addr) != NULL) {
+ pthread_rwlock_unlock(&data->dir_lock);
return -1;
}
- entry = reg_entry_create(name);
+ entry_name = strdup(name);
+ if (entry_name == NULL) {
+ pthread_rwlock_unlock(&data->dir_lock);
+ return -1;
+ }
+
+ entry = dir_entry_create(entry_name, addr);
if (entry == NULL) {
- pthread_rwlock_unlock(&data->reg_lock);
+ pthread_rwlock_unlock(&data->dir_lock);
return -1;
}
- list_add(&entry->list, &data->registry);
+ list_add(&entry->list,&data->directory);
- pthread_rwlock_unlock(&data->reg_lock);
+ pthread_rwlock_unlock(&data->dir_lock);
+
+ LOG_DBG("Added directory entry for %s.", entry_name);
return 0;
}
-int ipcp_data_add_dir_entry(struct ipcp_data * data,
- char * ap_name,
+int ipcp_data_dir_del_entry(struct ipcp_data * data,
+ const char * name,
uint64_t addr)
{
- struct dir_entry * entry;
-
- if (data == NULL || ap_name == NULL)
+ struct dir_entry * e;
+ if (data == NULL)
return -1;
pthread_rwlock_wrlock(&data->dir_lock);
- if (find_dir_entry(data, ap_name, addr) != NULL) {
- pthread_rwlock_unlock(&data->dir_lock);
- return -1;
- }
-
- entry = dir_entry_create(ap_name, addr);
- if (entry == NULL) {
+ e = find_dir_entry(data, name, addr);
+ if (e == NULL) {
pthread_rwlock_unlock(&data->dir_lock);
- return -1;
+ return 0; /* nothing to do */
}
- list_add(&entry->list,&data->directory);
+ list_del(&e->list);
pthread_rwlock_unlock(&data->dir_lock);
+ dir_entry_destroy(e);
+
return 0;
}
-bool ipcp_data_is_in_registry(struct ipcp_data * data,
- const char * ap_name)
+bool ipcp_data_dir_has(struct ipcp_data * data,
+ const char * name)
{
bool ret = false;
- if (data == NULL || ap_name == NULL)
- return false;
-
- pthread_rwlock_rdlock(&data->reg_lock);
+ pthread_rwlock_rdlock(&data->dir_lock);
- ret = (find_reg_entry_by_name(data, ap_name) != NULL);
+ ret = (find_dir_entry_any(data, name) != NULL);
- pthread_rwlock_unlock(&data->reg_lock);
+ pthread_rwlock_unlock(&data->dir_lock);
return ret;
}
-uint64_t ipcp_data_get_addr(struct ipcp_data * data,
- const char * ap_name)
+uint64_t ipcp_data_dir_get_addr(struct ipcp_data * data,
+ const char * name)
{
struct dir_entry * entry;
uint64_t addr;
pthread_rwlock_rdlock(&data->dir_lock);
- entry = find_dir_entry_any(data, ap_name);
+ entry = find_dir_entry_any(data, name);
if (entry == NULL) {
pthread_rwlock_unlock(&data->dir_lock);
@@ -386,3 +413,122 @@ uint64_t ipcp_data_get_addr(struct ipcp_data * data,
return addr;
}
+
+struct dir_query * ipcp_data_dir_query_create(char * name)
+{
+ struct dir_query * query;
+ pthread_condattr_t cattr;
+
+ query = malloc(sizeof(*query));
+ if (query == NULL)
+ return NULL;
+
+ query->name = strdup(name);
+ if (query->name == NULL) {
+ free(query);
+ return NULL;
+ }
+
+ query->state = QUERY_INIT;
+
+ pthread_condattr_init(&cattr);
+#ifndef __APPLE__
+ pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK);
+#endif
+ pthread_cond_init(&query->cond, &cattr);
+ pthread_mutex_init(&query->lock, NULL);
+
+ INIT_LIST_HEAD(&query->next);
+
+ return query;
+}
+
+void ipcp_data_dir_query_respond(struct dir_query * query)
+{
+ assert(query);
+
+ pthread_mutex_lock(&query->lock);
+
+ if (query->state != QUERY_PENDING) {
+ pthread_mutex_unlock(&query->lock);
+ return;
+ }
+
+ query->state = QUERY_RESPONSE;
+ pthread_cond_broadcast(&query->cond);
+
+ while (query->state == QUERY_RESPONSE)
+ pthread_cond_wait(&query->cond, &query->lock);
+
+ pthread_mutex_unlock(&query->lock);
+}
+
+void ipcp_data_dir_query_destroy(struct dir_query * query)
+{
+ assert(query);
+
+ pthread_mutex_lock(&query->lock);
+
+ if (query->state == QUERY_DESTROY) {
+ pthread_mutex_unlock(&query->lock);
+ return;
+ }
+
+ if (query->state == QUERY_INIT)
+ query->state = QUERY_DONE;
+
+ if (query->state == QUERY_PENDING) {
+ query->state = QUERY_DESTROY;
+ pthread_cond_broadcast(&query->cond);
+ }
+
+ while (query->state != QUERY_DONE)
+ pthread_cond_wait(&query->cond, &query->lock);
+
+ pthread_mutex_unlock(&query->lock);
+
+ pthread_cond_destroy(&query->cond);
+ pthread_mutex_destroy(&query->lock);
+
+ free(query->name);
+ free(query);
+}
+
+int ipcp_data_dir_query_wait(struct dir_query * query,
+ const struct timespec * timeout)
+{
+ struct timespec abstime;
+ int ret = 0;
+
+ assert(query);
+ assert(timeout);
+
+ clock_gettime(PTHREAD_COND_CLOCK, &abstime);
+ ts_add(&abstime, timeout, &abstime);
+
+ pthread_mutex_lock(&query->lock);
+
+ if (query->state != QUERY_INIT) {
+ pthread_mutex_unlock(&query->lock);
+ return -EINVAL;
+ }
+
+ query->state = QUERY_PENDING;
+
+ while (query->state == QUERY_PENDING) {
+ if ((ret = -pthread_cond_timedwait(&query->cond,
+ &query->lock,
+ &abstime)) == -ETIMEDOUT)
+ break;
+ }
+
+ if (query->state == QUERY_DESTROY)
+ ret = -1;
+
+ query->state = QUERY_DONE;
+ pthread_cond_broadcast(&query->cond);
+
+ pthread_mutex_unlock(&query->lock);
+
+ return ret;
+}