diff options
Diffstat (limited to 'src/ipcpd')
| -rw-r--r-- | src/ipcpd/ipcp-data.c | 308 | ||||
| -rw-r--r-- | src/ipcpd/ipcp-data.h | 56 | ||||
| -rw-r--r-- | src/ipcpd/ipcp-ops.h | 2 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.c | 17 | ||||
| -rw-r--r-- | src/ipcpd/local/main.c | 25 | ||||
| -rw-r--r-- | src/ipcpd/normal/main.c | 30 | ||||
| -rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 114 | ||||
| -rw-r--r-- | src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto | 10 | ||||
| -rw-r--r-- | src/ipcpd/shim-udp/main.c | 130 | 
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 347c7f2f..a8d5c273 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> @@ -179,7 +180,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; @@ -196,7 +197,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); @@ -205,6 +206,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, @@ -305,6 +319,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 836144ea..f6cded2b 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; @@ -324,6 +322,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; @@ -339,6 +338,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; @@ -352,8 +352,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);  } @@ -449,6 +450,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); @@ -459,7 +496,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, @@ -475,6 +512,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); @@ -859,7 +902,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; @@ -876,13 +919,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, @@ -890,6 +969,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); @@ -907,6 +987,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(ð_llc_data.flows_lock);          ssap =  bmp_allocate(eth_llc_data.saps); @@ -922,7 +1009,7 @@ static int eth_llc_ipcp_flow_alloc(int           fd,          pthread_rwlock_unlock(ð_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, @@ -1030,6 +1117,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 5abe0050..e06787ce 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 @@ -832,7 +831,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; @@ -863,7 +862,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;                  } @@ -884,7 +883,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; @@ -913,7 +911,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); @@ -929,15 +994,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."); @@ -975,39 +1038,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)); @@ -1170,6 +1207,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 | 
