summaryrefslogtreecommitdiff
path: root/src/ipcpd
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipcpd')
-rw-r--r--src/ipcpd/ipcp-data.c308
-rw-r--r--src/ipcpd/ipcp-data.h56
-rw-r--r--src/ipcpd/ipcp-ops.h2
-rw-r--r--src/ipcpd/ipcp.c17
-rw-r--r--src/ipcpd/local/main.c25
-rw-r--r--src/ipcpd/normal/main.c30
-rw-r--r--src/ipcpd/shim-eth-llc/main.c114
-rw-r--r--src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto10
-rw-r--r--src/ipcpd/shim-udp/main.c130
9 files changed, 520 insertions, 172 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;
+}
diff --git a/src/ipcpd/ipcp-data.h b/src/ipcpd/ipcp-data.h
index 4472a1d7..5263b156 100644
--- a/src/ipcpd/ipcp-data.h
+++ b/src/ipcpd/ipcp-data.h
@@ -26,10 +26,28 @@
#include <ouroboros/shared.h>
#include <ouroboros/list.h>
+
+#include "ipcp-ops.h"
+
#include <sys/types.h>
#include <pthread.h>
-#include "ipcp-ops.h"
+enum dir_query_state {
+ QUERY_INIT = 0,
+ QUERY_PENDING,
+ QUERY_RESPONSE,
+ QUERY_DONE,
+ QUERY_DESTROY
+};
+
+struct dir_query {
+ struct list_head next;
+ char * name;
+ enum dir_query_state state;
+
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+};
struct ipcp_data {
enum ipcp_type type;
@@ -40,6 +58,9 @@ struct ipcp_data {
struct list_head directory;
pthread_rwlock_t dir_lock;
+
+ struct list_head dir_queries;
+ pthread_mutex_t dir_queries_lock;
};
struct ipcp_data * ipcp_data_create(void);
@@ -49,26 +70,35 @@ struct ipcp_data * ipcp_data_init(struct ipcp_data * dst,
void ipcp_data_destroy(struct ipcp_data * data);
-int ipcp_data_add_reg_entry(struct ipcp_data * data,
+int ipcp_data_reg_add_entry(struct ipcp_data * data,
char * name);
-int ipcp_data_del_reg_entry(struct ipcp_data * data,
+int ipcp_data_reg_del_entry(struct ipcp_data * data,
const char * name);
-int ipcp_data_add_dir_entry(struct ipcp_data * data,
- char * ap_name,
+bool ipcp_data_reg_has(struct ipcp_data * data,
+ const char * name);
+
+int ipcp_data_dir_add_entry(struct ipcp_data * data,
+ char * name,
uint64_t addr);
-int ipcp_data_del_dir_entry(struct ipcp_data * data,
- const char * ap_name,
+int ipcp_data_dir_del_entry(struct ipcp_data * data,
+ const char * name,
uint64_t addr);
-bool ipcp_data_is_in_registry(struct ipcp_data * data,
- const char * name);
+bool ipcp_data_dir_has(struct ipcp_data * data,
+ const char * name);
+
+uint64_t ipcp_data_dir_get_addr(struct ipcp_data * data,
+ const char * name);
+
+struct dir_query * ipcp_data_dir_query_create(char * name);
+
+void ipcp_data_dir_query_respond(struct dir_query * query);
-bool ipcp_data_is_in_directory(struct ipcp_data * data,
- const char * ap_name);
+void ipcp_data_dir_query_destroy(struct dir_query * query);
-uint64_t ipcp_data_get_addr(struct ipcp_data * data,
- const char * ap_name);
+int ipcp_data_dir_query_wait(struct dir_query * query,
+ const struct timespec * timeout);
#endif /* IPCPD_IPCP_DATA_H */
diff --git a/src/ipcpd/ipcp-ops.h b/src/ipcpd/ipcp-ops.h
index 815cda09..0b79a328 100644
--- a/src/ipcpd/ipcp-ops.h
+++ b/src/ipcpd/ipcp-ops.h
@@ -36,6 +36,8 @@ struct ipcp_ops {
int (* ipcp_name_unreg)(char * name);
+ int (* ipcp_name_query)(char * name);
+
int (* ipcp_flow_alloc)(int fd,
char * dst_ap_name,
char * src_ae_name,
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index c2d343f8..90fb94ef 100644
--- a/src/ipcpd/ipcp.c
+++ b/src/ipcpd/ipcp.c
@@ -20,7 +20,11 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+#define OUROBOROS_PREFIX "ipcpd/ipcp"
+
#include <ouroboros/config.h>
+#include <ouroboros/logs.h>
#include <ouroboros/time_utils.h>
#include <ouroboros/utils.h>
#include <ouroboros/sockets.h>
@@ -28,13 +32,11 @@
#include <ouroboros/dev.h>
#include <ouroboros/np1_flow.h>
-#define OUROBOROS_PREFIX "ipcpd/ipcp"
-#include <ouroboros/logs.h>
+#include "ipcp.h"
#include <string.h>
#include <sys/socket.h>
#include <stdlib.h>
-#include "ipcp.h"
int ipcp_init(enum ipcp_type type, struct ipcp_ops * ops)
{
@@ -307,6 +309,15 @@ void * ipcp_main_loop(void * o)
ret_msg.result =
ipcpi.ops->ipcp_name_unreg(msg->name);
break;
+ case IPCP_MSG_CODE__IPCP_NAME_QUERY:
+ if (ipcpi.ops->ipcp_name_query == NULL) {
+ LOG_ERR("Ap_query unsupported.");
+ break;
+ }
+ ret_msg.has_result = true;
+ ret_msg.result =
+ ipcpi.ops->ipcp_name_query(msg->name);
+ break;
case IPCP_MSG_CODE__IPCP_FLOW_ALLOC:
if (ipcpi.ops->ipcp_flow_alloc == NULL) {
LOG_ERR("Flow_alloc unsupported.");
diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c
index 192607c1..b8783d9d 100644
--- a/src/ipcpd/local/main.c
+++ b/src/ipcpd/local/main.c
@@ -20,17 +20,18 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define OUROBOROS_PREFIX "ipcpd/local"
+
#include <ouroboros/config.h>
-#include "ipcp.h"
+#include <ouroboros/logs.h>
#include <ouroboros/errno.h>
#include <ouroboros/dev.h>
#include <ouroboros/fcntl.h>
#include <ouroboros/fqueue.h>
#include <ouroboros/ipcp-dev.h>
#include <ouroboros/local-dev.h>
-#define OUROBOROS_PREFIX "ipcpd/local"
-#include <ouroboros/logs.h>
+#include "ipcp.h"
#include <string.h>
#include <signal.h>
@@ -176,7 +177,7 @@ static int ipcp_local_name_reg(char * name)
{
pthread_rwlock_rdlock(&ipcpi.state_lock);
- if (ipcp_data_add_reg_entry(ipcpi.data, name)) {
+ if (ipcp_data_reg_add_entry(ipcpi.data, name)) {
pthread_rwlock_unlock(&ipcpi.state_lock);
LOG_DBG("Failed to add %s to local registry.", name);
return -1;
@@ -193,7 +194,7 @@ static int ipcp_local_name_unreg(char * name)
{
pthread_rwlock_rdlock(&ipcpi.state_lock);
- ipcp_data_del_reg_entry(ipcpi.data, name);
+ ipcp_data_reg_del_entry(ipcpi.data, name);
pthread_rwlock_unlock(&ipcpi.state_lock);
@@ -202,6 +203,19 @@ static int ipcp_local_name_unreg(char * name)
return 0;
}
+static int ipcp_local_name_query(char * name)
+{
+ int ret;
+
+ pthread_rwlock_rdlock(&ipcpi.state_lock);
+
+ ret = (ipcp_data_reg_has(ipcpi.data, name) ? 0 : -1);
+
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+
+ return ret;
+}
+
static int ipcp_local_flow_alloc(int fd,
char * dst_name,
char * src_ae_name,
@@ -302,6 +316,7 @@ static struct ipcp_ops local_ops = {
.ipcp_enroll = NULL, /* shim */
.ipcp_name_reg = ipcp_local_name_reg,
.ipcp_name_unreg = ipcp_local_name_unreg,
+ .ipcp_name_query = ipcp_local_name_query,
.ipcp_flow_alloc = ipcp_local_flow_alloc,
.ipcp_flow_alloc_resp = ipcp_local_flow_alloc_resp,
.ipcp_flow_dealloc = ipcp_local_flow_dealloc
diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c
index 32aabdf2..2402972f 100644
--- a/src/ipcpd/normal/main.c
+++ b/src/ipcpd/normal/main.c
@@ -28,6 +28,11 @@
#include <ouroboros/ipcp-dev.h>
#include <ouroboros/time_utils.h>
+#include "fmgr.h"
+#include "ribmgr.h"
+#include "ipcp.h"
+#include "frct.h"
+
#include <stdbool.h>
#include <signal.h>
#include <stdlib.h>
@@ -35,11 +40,6 @@
#include <string.h>
#include <errno.h>
-#include "fmgr.h"
-#include "ribmgr.h"
-#include "ipcp.h"
-#include "frct.h"
-
#define THIS_TYPE IPCP_NORMAL
/* global for trapping signal */
@@ -72,7 +72,7 @@ static int normal_ipcp_name_reg(char * name)
{
pthread_rwlock_rdlock(&ipcpi.state_lock);
- if (ipcp_data_add_reg_entry(ipcpi.data, name)) {
+ if (ipcp_data_reg_add_entry(ipcpi.data, name)) {
pthread_rwlock_unlock(&ipcpi.state_lock);
LOG_ERR("Failed to add %s to local registry.", name);
return -1;
@@ -89,13 +89,28 @@ static int normal_ipcp_name_unreg(char * name)
{
pthread_rwlock_rdlock(&ipcpi.state_lock);
- ipcp_data_del_reg_entry(ipcpi.data, name);
+ ipcp_data_reg_del_entry(ipcpi.data, name);
pthread_rwlock_unlock(&ipcpi.state_lock);
return 0;
}
+static int normal_ipcp_name_query(char * name)
+{
+ LOG_MISSING;
+
+ (void) name;
+
+ /*
+ * NOTE: For the moment we just return -1,
+ * for testing purposes we may return zero here
+ * for certain names.
+ */
+
+ return -1;
+}
+
static int normal_ipcp_enroll(char * dif_name)
{
struct timespec timeout = {(ENROLL_TIMEOUT / 1000),
@@ -165,6 +180,7 @@ static struct ipcp_ops normal_ops = {
.ipcp_enroll = normal_ipcp_enroll,
.ipcp_name_reg = normal_ipcp_name_reg,
.ipcp_name_unreg = normal_ipcp_name_unreg,
+ .ipcp_name_query = normal_ipcp_name_query,
.ipcp_flow_alloc = fmgr_np1_alloc,
.ipcp_flow_alloc_resp = fmgr_np1_alloc_resp,
.ipcp_flow_dealloc = fmgr_np1_dealloc
diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c
index 6046d939..d4ea8eba 100644
--- a/src/ipcpd/shim-eth-llc/main.c
+++ b/src/ipcpd/shim-eth-llc/main.c
@@ -20,10 +20,11 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <ouroboros/config.h>
-
#define _DEFAULT_SOURCE
+#define OUROBOROS_PREFIX "ipcpd/shim-eth-llc"
+
+#include <ouroboros/config.h>
#include <ouroboros/errno.h>
#include <ouroboros/list.h>
#include <ouroboros/utils.h>
@@ -32,12 +33,10 @@
#include <ouroboros/ipcp-dev.h>
#include <ouroboros/fcntl.h>
#include <ouroboros/fqueue.h>
-
-#define OUROBOROS_PREFIX "ipcpd/shim-eth-llc"
-
#include <ouroboros/logs.h>
#include "ipcp.h"
+#include "shim_eth_llc_messages.pb-c.h"
#include <net/if.h>
#include <signal.h>
@@ -65,8 +64,6 @@
#include <poll.h>
#include <sys/mman.h>
-#include "shim_eth_llc_messages.pb-c.h"
-
typedef ShimEthLlcMsg shim_eth_llc_msg_t;
#define THIS_TYPE IPCP_SHIM_ETH_LLC
@@ -80,6 +77,7 @@ typedef ShimEthLlcMsg shim_eth_llc_msg_t;
+ SHIM_ETH_LLC_MAX_SDU_SIZE)
#define EVENT_WAIT_TIMEOUT 100 /* us */
+#define NAME_QUERY_TIMEOUT 100000000 /* ns */
/* global for trapping signal */
int irmd_api;
@@ -313,6 +311,7 @@ static int eth_llc_ipcp_sap_alloc(uint8_t * dst_addr,
shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT;
msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_REQ;
+ msg.has_ssap = true;
msg.ssap = ssap;
msg.dst_name = dst_name;
msg.src_ae_name = src_ae_name;
@@ -328,6 +327,7 @@ static int eth_llc_ipcp_sap_alloc_resp(uint8_t * dst_addr,
shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT;
msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_REPLY;
+ msg.has_ssap = true;
msg.ssap = ssap;
msg.has_dsap = true;
msg.dsap = dsap;
@@ -341,8 +341,9 @@ static int eth_llc_ipcp_sap_dealloc(uint8_t * dst_addr, uint8_t ssap)
{
shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT;
- msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC;
- msg.ssap = ssap;
+ msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC;
+ msg.has_ssap = true;
+ msg.ssap = ssap;
return eth_llc_ipcp_send_mgmt_frame(&msg, dst_addr);
}
@@ -438,6 +439,42 @@ static int eth_llc_ipcp_flow_dealloc_req(uint8_t ssap)
return 0;
}
+static int eth_llc_ipcp_name_query_req(char * name, uint8_t * r_addr)
+{
+ shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT;
+
+ if (ipcp_data_reg_has(ipcpi.data, name)) {
+ msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY;
+ msg.dst_name = name;
+
+ eth_llc_ipcp_send_mgmt_frame(&msg, r_addr);
+ }
+
+ return 0;
+}
+
+static int eth_llc_ipcp_name_query_reply(char * name, uint8_t * r_addr)
+{
+ uint64_t address = 0;
+ struct list_head * pos;
+
+ memcpy(&address, r_addr, MAC_SIZE);
+
+ ipcp_data_dir_add_entry(ipcpi.data, name, address);
+
+ pthread_mutex_lock(&ipcpi.data->dir_queries_lock);
+ list_for_each(pos, &ipcpi.data->dir_queries) {
+ struct dir_query * e =
+ list_entry(pos, struct dir_query, next);
+ if (strcmp(e->name, name) == 0) {
+ ipcp_data_dir_query_respond(e);
+ }
+ }
+ pthread_mutex_unlock(&ipcpi.data->dir_queries_lock);
+
+ return 0;
+}
+
static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr)
{
shim_eth_llc_msg_t * msg = shim_eth_llc_msg__unpack(NULL, len, buf);
@@ -448,7 +485,7 @@ static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr)
switch (msg->code) {
case SHIM_ETH_LLC_MSG_CODE__FLOW_REQ:
- if (ipcp_data_is_in_registry(ipcpi.data, msg->dst_name)) {
+ if (ipcp_data_reg_has(ipcpi.data, msg->dst_name)) {
eth_llc_ipcp_sap_req(msg->ssap,
r_addr,
msg->dst_name,
@@ -464,6 +501,12 @@ static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr)
case SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC:
eth_llc_ipcp_flow_dealloc_req(msg->ssap);
break;
+ case SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ:
+ eth_llc_ipcp_name_query_req(msg->dst_name, r_addr);
+ break;
+ case SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY:
+ eth_llc_ipcp_name_query_reply(msg->dst_name, r_addr);
+ break;
default:
LOG_ERR("Unknown message received %d.", msg->code);
shim_eth_llc_msg__free_unpacked(msg, NULL);
@@ -854,7 +897,7 @@ static int eth_llc_ipcp_name_reg(char * name)
{
pthread_rwlock_rdlock(&ipcpi.state_lock);
- if (ipcp_data_add_reg_entry(ipcpi.data, name)) {
+ if (ipcp_data_reg_add_entry(ipcpi.data, name)) {
pthread_rwlock_unlock(&ipcpi.state_lock);
LOG_ERR("Failed to add %s to local registry.", name);
return -1;
@@ -871,13 +914,49 @@ static int eth_llc_ipcp_name_unreg(char * name)
{
pthread_rwlock_rdlock(&ipcpi.state_lock);
- ipcp_data_del_reg_entry(ipcpi.data, name);
+ ipcp_data_reg_del_entry(ipcpi.data, name);
pthread_rwlock_unlock(&ipcpi.state_lock);
return 0;
}
+static int eth_llc_ipcp_name_query(char * name)
+{
+ uint8_t r_addr[MAC_SIZE];
+ struct timespec timeout = {0, NAME_QUERY_TIMEOUT};
+ shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT;
+ struct dir_query * query;
+ int ret;
+
+ if (ipcp_data_dir_has(ipcpi.data, name))
+ return 0;
+
+ msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ;
+ msg.dst_name = name;
+
+ memset(r_addr, 0xff, MAC_SIZE);
+
+ query = ipcp_data_dir_query_create(name);
+ if (query == NULL)
+ return -1;
+
+ pthread_mutex_lock(&ipcpi.data->dir_queries_lock);
+ list_add(&query->next, &ipcpi.data->dir_queries);
+ pthread_mutex_unlock(&ipcpi.data->dir_queries_lock);
+
+ eth_llc_ipcp_send_mgmt_frame(&msg, r_addr);
+
+ ret = ipcp_data_dir_query_wait(query, &timeout);
+
+ pthread_mutex_lock(&ipcpi.data->dir_queries_lock);
+ list_del(&query->next);
+ ipcp_data_dir_query_destroy(query);
+ pthread_mutex_unlock(&ipcpi.data->dir_queries_lock);
+
+ return ret;
+}
+
static int eth_llc_ipcp_flow_alloc(int fd,
char * dst_name,
char * src_ae_name,
@@ -885,6 +964,7 @@ static int eth_llc_ipcp_flow_alloc(int fd,
{
uint8_t ssap = 0;
uint8_t r_addr[MAC_SIZE];
+ uint64_t addr = 0;
LOG_DBG("Allocating flow to %s.", dst_name);
@@ -902,6 +982,13 @@ static int eth_llc_ipcp_flow_alloc(int fd,
return -1; /* -ENOTENROLLED */
}
+ if (!ipcp_data_dir_has(ipcpi.data, dst_name)) {
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+ LOG_ERR("Destination unreachable.");
+ return -1;
+ }
+ addr = ipcp_data_dir_get_addr(ipcpi.data, dst_name);
+
pthread_rwlock_wrlock(&eth_llc_data.flows_lock);
ssap = bmp_allocate(eth_llc_data.saps);
@@ -917,7 +1004,7 @@ static int eth_llc_ipcp_flow_alloc(int fd,
pthread_rwlock_unlock(&eth_llc_data.flows_lock);
pthread_rwlock_unlock(&ipcpi.state_lock);
- memset(r_addr, 0xff, MAC_SIZE);
+ memcpy(r_addr, &addr, MAC_SIZE);
if (eth_llc_ipcp_sap_alloc(r_addr,
ssap,
@@ -1025,6 +1112,7 @@ static struct ipcp_ops eth_llc_ops = {
.ipcp_enroll = NULL,
.ipcp_name_reg = eth_llc_ipcp_name_reg,
.ipcp_name_unreg = eth_llc_ipcp_name_unreg,
+ .ipcp_name_query = eth_llc_ipcp_name_query,
.ipcp_flow_alloc = eth_llc_ipcp_flow_alloc,
.ipcp_flow_alloc_resp = eth_llc_ipcp_flow_alloc_resp,
.ipcp_flow_dealloc = eth_llc_ipcp_flow_dealloc
diff --git a/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto b/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto
index 0e8a1ce2..4d027d98 100644
--- a/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto
+++ b/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto
@@ -1,14 +1,16 @@
enum shim_eth_llc_msg_code {
- FLOW_REQ = 1;
- FLOW_REPLY = 2;
- FLOW_DEALLOC = 3;
+ FLOW_REQ = 1;
+ FLOW_REPLY = 2;
+ FLOW_DEALLOC = 3;
+ NAME_QUERY_REQ = 4;
+ NAME_QUERY_REPLY = 5;
};
message shim_eth_llc_msg {
required shim_eth_llc_msg_code code = 1;
optional string dst_name = 2;
optional string src_ae_name = 3;
- required uint32 ssap = 4;
+ optional uint32 ssap = 4;
optional uint32 dsap = 5;
optional sint32 response = 6;
};
diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c
index 62e1b2d0..f779713c 100644
--- a/src/ipcpd/shim-udp/main.c
+++ b/src/ipcpd/shim-udp/main.c
@@ -20,9 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define OUROBOROS_PREFIX "ipcpd/shim-udp"
+
#include <ouroboros/config.h>
-#include "ipcp.h"
-#include "shim_udp_config.h"
#include <ouroboros/list.h>
#include <ouroboros/utils.h>
#include <ouroboros/dev.h>
@@ -30,11 +30,12 @@
#include <ouroboros/fqueue.h>
#include <ouroboros/fcntl.h>
#include <ouroboros/errno.h>
-
-#define OUROBOROS_PREFIX "ipcpd/shim-udp"
-
#include <ouroboros/logs.h>
+#include "shim_udp_messages.pb-c.h"
+#include "ipcp.h"
+#include "shim_udp_config.h"
+
#include <string.h>
#include <sys/socket.h>
#include <sys/select.h>
@@ -47,8 +48,6 @@
#include <sys/wait.h>
#include <fcntl.h>
-#include "shim_udp_messages.pb-c.h"
-
typedef ShimUdpMsg shim_udp_msg_t;
#define THIS_TYPE IPCP_SHIM_UDP
@@ -833,7 +832,7 @@ static int ipcp_udp_name_reg(char * name)
pthread_rwlock_rdlock(&ipcpi.state_lock);
- if (ipcp_data_add_reg_entry(ipcpi.data, name)) {
+ if (ipcp_data_reg_add_entry(ipcpi.data, name)) {
pthread_rwlock_unlock(&ipcpi.state_lock);
LOG_ERR("Failed to add %s to local registry.", name);
return -1;
@@ -864,7 +863,7 @@ static int ipcp_udp_name_reg(char * name)
if (ddns_send(cmd)) {
pthread_rwlock_rdlock(&ipcpi.state_lock);
- ipcp_data_del_reg_entry(ipcpi.data, name);
+ ipcp_data_reg_del_entry(ipcpi.data, name);
pthread_rwlock_unlock(&ipcpi.state_lock);
return -1;
}
@@ -885,7 +884,6 @@ static int ipcp_udp_name_unreg(char * name)
char cmd[100];
uint32_t dns_addr;
#endif
-
if (strlen(name) > 24) {
LOG_ERR("DNS names cannot be longer than 24 chars.");
return -1;
@@ -914,7 +912,74 @@ static int ipcp_udp_name_unreg(char * name)
pthread_rwlock_rdlock(&ipcpi.state_lock);
- ipcp_data_del_reg_entry(ipcpi.data, name);
+ ipcp_data_reg_del_entry(ipcpi.data, name);
+
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+
+ return 0;
+}
+
+static int ipcp_udp_name_query(char * name)
+{
+ uint32_t ip_addr = 0;
+ struct hostent * h;
+#ifdef CONFIG_OUROBOROS_ENABLE_DNS
+ uint32_t dns_addr = 0;
+#endif
+
+ assert(name);
+
+ if (strlen(name) > 24) {
+ LOG_ERR("DNS names cannot be longer than 24 chars.");
+ return -1;
+ }
+
+ pthread_rwlock_rdlock(&ipcpi.state_lock);
+
+ if (ipcp_get_state() != IPCP_ENROLLED) {
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+ LOG_DBG("Won't query a name on a non-enrolled IPCP.");
+ return -1; /* -ENOTENROLLED */
+ }
+
+#ifdef CONFIG_OUROBOROS_ENABLE_DNS
+ dns_addr = udp_data.dns_addr;
+
+ if (dns_addr != 0) {
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+
+ ip_addr = ddns_resolve(name, dns_addr);
+ if (ip_addr == 0) {
+ LOG_DBG("Could not resolve %s.", name);
+ return -1;
+ }
+
+ pthread_rwlock_rdlock(&ipcpi.state_lock);
+
+ if (ipcp_get_state() != IPCP_ENROLLED) {
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+ LOG_DBG("Won't add name to the directory.");
+ return -1; /* -ENOTENROLLED */
+ }
+ } else {
+#endif
+ h = gethostbyname(name);
+ if (h == NULL) {
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+ LOG_DBG("Could not resolve %s.", name);
+ return -1;
+ }
+
+ ip_addr = *((uint32_t *) (h->h_addr_list[0]));
+#ifdef CONFIG_OUROBOROS_ENABLE_DNS
+ }
+#endif
+
+ if (ipcp_data_dir_add_entry(ipcpi.data, name, ip_addr)) {
+ pthread_rwlock_unlock(&ipcpi.state_lock);
+ LOG_ERR("Failed to add directory entry.");
+ return -1;
+ }
pthread_rwlock_unlock(&ipcpi.state_lock);
@@ -930,15 +995,13 @@ static int ipcp_udp_flow_alloc(int fd,
struct sockaddr_in f_saddr; /* flow */
socklen_t f_saddr_len = sizeof(f_saddr);
int skfd;
- struct hostent * h;
uint32_t ip_addr = 0;
-#ifdef CONFIG_OUROBOROS_ENABLE_DNS
- uint32_t dns_addr = 0;
-#endif
+
LOG_DBG("Allocating flow to %s.", dst_name);
if (dst_name == NULL || src_ae_name == NULL)
return -1;
+
if (strlen(dst_name) > 255
|| strlen(src_ae_name) > 255) {
LOG_ERR("Name too long for this shim.");
@@ -976,39 +1039,13 @@ static int ipcp_udp_flow_alloc(int fd,
return -1; /* -ENOTENROLLED */
}
-#ifdef CONFIG_OUROBOROS_ENABLE_DNS
- dns_addr = udp_data.dns_addr;
-
- if (dns_addr != 0) {
+ if (!ipcp_data_dir_has(ipcpi.data, dst_name)) {
pthread_rwlock_unlock(&ipcpi.state_lock);
-
- ip_addr = ddns_resolve(dst_name, dns_addr);
- if (ip_addr == 0) {
- LOG_DBG("Could not resolve %s.", dst_name);
- close(fd);
- return -1;
- }
-
- pthread_rwlock_rdlock(&ipcpi.state_lock);
- if (ipcp_get_state() != IPCP_ENROLLED) {
- pthread_rwlock_unlock(&ipcpi.state_lock);
- LOG_DBG("Won't allocate flow with non-enrolled IPCP.");
- close(skfd);
- return -1; /* -ENOTENROLLED */
- }
- } else {
-#endif
- h = gethostbyname(dst_name);
- if (h == NULL) {
- LOG_DBG("Could not resolve %s.", dst_name);
- close(skfd);
- return -1;
- }
-
- ip_addr = *((uint32_t *) (h->h_addr_list[0]));
-#ifdef CONFIG_OUROBOROS_ENABLE_DNS
+ LOG_DBG("Could not resolve destination.");
+ close(skfd);
+ return -1;
}
-#endif
+ ip_addr = (uint32_t) ipcp_data_dir_get_addr(ipcpi.data, dst_name);
/* connect to server (store the remote IP address in the fd) */
memset((char *) &r_saddr, 0, sizeof(r_saddr));
@@ -1171,6 +1208,7 @@ static struct ipcp_ops udp_ops = {
.ipcp_enroll = NULL, /* shim */
.ipcp_name_reg = ipcp_udp_name_reg,
.ipcp_name_unreg = ipcp_udp_name_unreg,
+ .ipcp_name_query = ipcp_udp_name_query,
.ipcp_flow_alloc = ipcp_udp_flow_alloc,
.ipcp_flow_alloc_resp = ipcp_udp_flow_alloc_resp,
.ipcp_flow_dealloc = ipcp_udp_flow_dealloc