diff options
| -rw-r--r-- | include/ouroboros/cacep.h | 6 | ||||
| -rw-r--r-- | include/ouroboros/irm.h | 13 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.c | 28 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.h | 6 | ||||
| -rw-r--r-- | src/ipcpd/local/main.c | 4 | ||||
| -rw-r--r-- | src/ipcpd/normal/ae.h | 9 | ||||
| -rw-r--r-- | src/ipcpd/normal/connmgr.c | 127 | ||||
| -rw-r--r-- | src/ipcpd/normal/connmgr.h | 6 | ||||
| -rw-r--r-- | src/ipcpd/normal/dt.c | 3 | ||||
| -rw-r--r-- | src/ipcpd/normal/enroll.c | 14 | ||||
| -rw-r--r-- | src/ipcpd/normal/enroll.h | 3 | ||||
| -rw-r--r-- | src/ipcpd/normal/main.c | 5 | ||||
| -rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 2 | ||||
| -rw-r--r-- | src/ipcpd/shim-udp/main.c | 4 | ||||
| -rw-r--r-- | src/irmd/ipcp.c | 61 | ||||
| -rw-r--r-- | src/irmd/ipcp.h | 8 | ||||
| -rw-r--r-- | src/irmd/main.c | 82 | ||||
| -rw-r--r-- | src/lib/ipcpd_messages.proto | 7 | ||||
| -rw-r--r-- | src/lib/irm.c | 66 | ||||
| -rw-r--r-- | src/lib/irmd_messages.proto | 31 | ||||
| -rw-r--r-- | src/tools/irm/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/tools/irm/irm_ipcp.c | 18 | ||||
| -rw-r--r-- | src/tools/irm/irm_ipcp_connect.c | 94 | ||||
| -rw-r--r-- | src/tools/irm/irm_ipcp_disconnect.c | 94 | ||||
| -rw-r--r-- | src/tools/irm/irm_ops.h | 6 | 
25 files changed, 635 insertions, 64 deletions
diff --git a/include/ouroboros/cacep.h b/include/ouroboros/cacep.h index d2b0de9a..4b557b46 100644 --- a/include/ouroboros/cacep.h +++ b/include/ouroboros/cacep.h @@ -29,9 +29,11 @@  #include <stdint.h>  #include <sys/types.h> +#define CACEP_BUF_STRLEN 64 +  struct conn_info { -        char                       ae_name[64]; -        char                       protocol[64]; +        char                       ae_name[CACEP_BUF_STRLEN + 1]; +        char                       protocol[CACEP_BUF_STRLEN + 1];          uint32_t                   pref_version;          enum proto_concrete_syntax pref_syntax;          struct proto_field         fixed_conc_syntax[PROTO_MAX_FIELDS]; diff --git a/include/ouroboros/irm.h b/include/ouroboros/irm.h index 5ad8f754..dc723fc0 100644 --- a/include/ouroboros/irm.h +++ b/include/ouroboros/irm.h @@ -28,8 +28,11 @@  #include <sys/types.h> -/* Name binding options */ +/* Normal IPCP components. */ +#define DT_AE   "Data Transfer" +#define MGMT_AE "Management" +/* Name binding options. */  #define BIND_AP_AUTO   0x01  #define BIND_AP_UNIQUE 0x02 @@ -50,6 +53,14 @@ int     irm_enroll_ipcp(pid_t        api,  int     irm_bootstrap_ipcp(pid_t                      api,                             const struct ipcp_config * conf); +int     irm_connect_ipcp(pid_t        api, +                         const char * component, +                         const char * dst); + +int     irm_disconnect_ipcp(pid_t        api, +                            const char * component, +                            const char * dst); +  int     irm_bind_ap(const char * ap,                      const char * name,                      uint16_t     opts, diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index d4b3a7fc..41ea4784 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -301,6 +301,32 @@ static void * mainloop(void * o)                                  dif_info.dif_name      = info.dif_name;                          }                          break; +                case IPCP_MSG_CODE__IPCP_CONNECT: +                        ret_msg.has_result = true; + +                        if (ipcpi.ops->ipcp_connect == NULL) { +                                log_err("Connect unsupported."); +                                ret_msg.result = -ENOTSUP; +                                break; +                        } + +                        ret_msg.result = +                                ipcpi.ops->ipcp_connect(msg->dst_name, +                                                        msg->comp_name); +                        break; +                case IPCP_MSG_CODE__IPCP_DISCONNECT: +                        ret_msg.has_result = true; + +                        if (ipcpi.ops->ipcp_disconnect == NULL) { +                                log_err("Disconnect unsupported."); +                                ret_msg.result = -ENOTSUP; +                                break; +                        } + +                        ret_msg.result = +                                ipcpi.ops->ipcp_disconnect(msg->dst_name, +                                                           msg->comp_name); +                        break;                  case IPCP_MSG_CODE__IPCP_REG:                          ret_msg.has_result = true; @@ -435,6 +461,8 @@ static void * mainloop(void * o)                                  ipcpi.ops->ipcp_flow_dealloc(fd);                          break;                  default: +                        ret_msg.has_result = true; +                        ret_msg.result     = -1;                          log_err("Don't know that message code");                          break;                  } diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h index cd18d198..1b2a0334 100644 --- a/src/ipcpd/ipcp.h +++ b/src/ipcpd/ipcp.h @@ -45,6 +45,12 @@ struct ipcp_ops {          int   (* ipcp_enroll)(const char *      dst,                                struct dif_info * info); +        int   (* ipcp_connect)(const char * dst, +                               const char * component); + +        int   (* ipcp_disconnect)(const char * dst, +                                  const char * component); +          int   (* ipcp_reg)(const uint8_t * hash);          int   (* ipcp_unreg)(const uint8_t * hash); diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index 37d23fc3..c6f88d78 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -323,7 +323,9 @@ static int ipcp_local_flow_dealloc(int fd)  static struct ipcp_ops local_ops = {          .ipcp_bootstrap       = ipcp_local_bootstrap, -        .ipcp_enroll          = NULL,                       /* shim */ +        .ipcp_enroll          = NULL, +        .ipcp_connect         = NULL, +        .ipcp_disconnect      = NULL,          .ipcp_reg             = ipcp_local_reg,          .ipcp_unreg           = ipcp_local_unreg,          .ipcp_query           = ipcp_local_query, diff --git a/src/ipcpd/normal/ae.h b/src/ipcpd/normal/ae.h index 4534cefa..3d3bdc27 100644 --- a/src/ipcpd/normal/ae.h +++ b/src/ipcpd/normal/ae.h @@ -27,6 +27,8 @@  #include "dt.h" +#define DST_MAX_STRLEN 64 +  enum ae_id {          AEID_DT = 0,          AEID_ENROLL, @@ -36,9 +38,10 @@ enum ae_id {  struct conn {          struct conn_info conn_info; -        struct flow_info { -                int              fd; -                qosspec_t        qs; +        struct { +                char      dst[DST_MAX_STRLEN + 1]; +                int       fd; +                qosspec_t qs;          } flow_info;  }; diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c index b6e5e31a..11f83247 100644 --- a/src/ipcpd/normal/connmgr.c +++ b/src/ipcpd/normal/connmgr.c @@ -48,7 +48,7 @@ enum connmgr_state {          CONNMGR_RUNNING  }; -struct ae_conn { +struct conn_el {          struct list_head next;          struct conn      conn;  }; @@ -58,15 +58,17 @@ struct ae {          struct conn_info info;          struct list_head conns; +        struct list_head pending; +          pthread_cond_t   cond;          pthread_mutex_t  lock;  };  struct { -        struct ae                aes[AEID_MAX]; -        enum connmgr_state       state; +        struct ae          aes[AEID_MAX]; +        enum connmgr_state state; -        pthread_t                acceptor; +        pthread_t          acceptor;  } connmgr;  static int get_id_by_name(const char * name) @@ -85,23 +87,21 @@ static int add_ae_conn(enum ae_id         id,                         qosspec_t          qs,                         struct conn_info * rcv_info)  { -        struct ae_conn *   ae_conn; +        struct conn_el * el; -        ae_conn = malloc(sizeof(*ae_conn)); -        if (ae_conn == NULL) { +        el = malloc(sizeof(*el)); +        if (el == NULL) {                  log_err("Not enough memory.");                  return -1;          } -        ae_conn->conn.conn_info    = *rcv_info; -        ae_conn->conn.flow_info.fd = fd; -        ae_conn->conn.flow_info.qs = qs; - -        list_head_init(&ae_conn->next); +        el->conn.conn_info    = *rcv_info; +        el->conn.flow_info.fd = fd; +        el->conn.flow_info.qs = qs;          pthread_mutex_lock(&connmgr.aes[id].lock); -        list_add(&ae_conn->next, &connmgr.aes[id].conns); +        list_add(&el->next, &connmgr.aes[id].pending);          pthread_cond_signal(&connmgr.aes[id].cond);          pthread_mutex_unlock(&connmgr.aes[id].lock); @@ -217,6 +217,7 @@ int connmgr_ae_init(enum ae_id               id,          }          list_head_init(&ae->conns); +        list_head_init(&ae->pending);          memcpy(&connmgr.aes[id].info, info, sizeof(connmgr.aes[id].info)); @@ -241,7 +242,13 @@ void connmgr_ae_fini(enum ae_id id)          pthread_mutex_lock(&ae->lock);          list_for_each_safe(p, h, &ae->conns) { -                struct ae_conn * e = list_entry(p, struct ae_conn, next); +                struct conn_el * e = list_entry(p, struct conn_el, next); +                list_del(&e->next); +                free(e); +        } + +        list_for_each_safe(p, h, &ae->pending) { +                struct conn_el * e = list_entry(p, struct conn_el, next);                  list_del(&e->next);                  free(e);          } @@ -256,6 +263,84 @@ void connmgr_ae_fini(enum ae_id id)          connmgr.aes[id].nbs = NULL;  } +int connmgr_ipcp_connect(const char * dst, +                         const char * component) +{ +        struct conn_el * ce; +        int              id; + +        assert(dst); +        assert(component); + +        ce = malloc(sizeof(*ce)); +        if (ce == NULL) { +                log_dbg("Out of memory."); +                return -1; +        } + +        id = get_id_by_name(component); +        if (id < 0) { +                log_dbg("No such component: %s", component); +                free(ce); +                return -1; +        } + +        /* FIXME: get the correct qos for the component. */ +        if (connmgr_alloc(id, dst, NULL, &ce->conn)) { +                free(ce); +                return -1; +        } + +        if (strlen(dst) > DST_MAX_STRLEN) { +                log_warn("Truncating dst length for connection."); +                memcpy(ce->conn.flow_info.dst, dst, DST_MAX_STRLEN); +                ce->conn.flow_info.dst[DST_MAX_STRLEN] = '\0'; +        } else { +                strcpy(ce->conn.flow_info.dst, dst); +        } + +        pthread_mutex_lock(&connmgr.aes[id].lock); + +        list_add(&ce->next, &connmgr.aes[id].conns); + +        pthread_mutex_unlock(&connmgr.aes[id].lock); + +        return 0; +} + +int connmgr_ipcp_disconnect(const char * dst, +                            const char * component) +{ +        struct list_head * p; +        struct list_head * h; +        int                id; + +        assert(dst); +        assert(component); + +        id = get_id_by_name(component); +        if (id < 0) +                return -1; + +        pthread_mutex_lock(&connmgr.aes[id].lock); + +        list_for_each_safe(p,h, &connmgr.aes[id].conns) { +                struct conn_el * el = list_entry(p, struct conn_el, next); +                if (strcmp(el->conn.flow_info.dst, dst) == 0) { +                        int ret; +                        pthread_mutex_unlock(&connmgr.aes[id].lock); +                        list_del(&el->next); +                        ret = connmgr_dealloc(id, &el->conn); +                        free(el); +                        return ret; +                } +        } + +        pthread_mutex_unlock(&connmgr.aes[id].lock); + +        return 0; +} +  int connmgr_alloc(enum ae_id    id,                    const char *  dst,                    qosspec_t *   qs, @@ -329,7 +414,7 @@ int connmgr_dealloc(enum ae_id    id,  int connmgr_wait(enum ae_id    id,                   struct conn * conn)  { -        struct ae_conn * ae_conn; +        struct conn_el * el;          struct ae *      ae;          assert(id >= 0 && id < AEID_MAX); @@ -342,21 +427,21 @@ int connmgr_wait(enum ae_id    id,          pthread_cleanup_push((void(*)(void *))pthread_mutex_unlock,                               (void *) &ae->lock); -        while (list_is_empty(&ae->conns)) +        while (list_is_empty(&ae->pending))                  pthread_cond_wait(&ae->cond, &ae->lock);          pthread_cleanup_pop(false); -        ae_conn = list_first_entry((&ae->conns), struct ae_conn, next); -        if (ae_conn == NULL) { +        el = list_first_entry((&ae->pending), struct conn_el, next); +        if (el == NULL) {                  pthread_mutex_unlock(&ae->lock);                  return -1;          } -        *conn = ae_conn->conn; +        *conn = el->conn; -        list_del(&ae_conn->next); -        free(ae_conn); +        list_del(&el->next); +        free(el);          pthread_mutex_unlock(&ae->lock); diff --git a/src/ipcpd/normal/connmgr.h b/src/ipcpd/normal/connmgr.h index 920058da..379877e6 100644 --- a/src/ipcpd/normal/connmgr.h +++ b/src/ipcpd/normal/connmgr.h @@ -43,6 +43,12 @@ int         connmgr_ae_init(enum ae_id               id,  void        connmgr_ae_fini(enum ae_id id); +int         connmgr_ipcp_connect(const char * dst, +                                 const char * component); + +int         connmgr_ipcp_disconnect(const char * dst, +                                    const char * component); +  int         connmgr_alloc(enum ae_id    id,                            const char *  dst,                            qosspec_t *   qs, diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c index 19c2d3a6..aa089852 100644 --- a/src/ipcpd/normal/dt.c +++ b/src/ipcpd/normal/dt.c @@ -67,7 +67,6 @@ struct {          pthread_rwlock_t   lock;          struct nbs *       nbs; -        struct ae *        ae;          struct nb_notifier nb_notifier; @@ -163,6 +162,8 @@ static void * dt_conn_handle(void * o)                  log_dbg("Got new connection."); +                /* NOTE: connection acceptance policy could be here. */ +                  nbs_add(dt.nbs, conn);          } diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c index 2f7dd9bc..7f93ed3a 100644 --- a/src/ipcpd/normal/enroll.c +++ b/src/ipcpd/normal/enroll.c @@ -259,14 +259,17 @@ static void * enroll_handle(void * o)                          continue;                  } -                if (msg->code != ENROLL_CODE__ENROLL_DONE) { +                if (msg->code != ENROLL_CODE__ENROLL_DONE || !msg->has_result) {                          log_err("Wrong message type.");                          enroll_msg__free_unpacked(msg, NULL);                          connmgr_dealloc(AEID_ENROLL, &conn);                          continue;                  } -                log_dbg("Neighbor enrollment successful."); +                if (msg->result == 0) +                        log_dbg("Neighbor enrollment successful."); +                else +                        log_dbg("Neigbor reported failed enrollment.");                  connmgr_dealloc(AEID_ENROLL, &conn);          } @@ -287,13 +290,16 @@ int enroll_boot(struct conn * conn,          return 0;  } -int enroll_done(struct conn * conn) +int enroll_done(struct conn * conn, +                int           result)  {          enroll_msg_t msg = ENROLL_MSG__INIT;          uint8_t      buf[ENROLL_BUF_LEN];          ssize_t       len; -        msg.code = ENROLL_CODE__ENROLL_DONE; +        msg.code       = ENROLL_CODE__ENROLL_DONE; +        msg.has_result = true; +        msg.result     = result;          len = enroll_msg__get_packed_size(&msg);          if (len < 0) { diff --git a/src/ipcpd/normal/enroll.h b/src/ipcpd/normal/enroll.h index 67c9912d..3b277e44 100644 --- a/src/ipcpd/normal/enroll.h +++ b/src/ipcpd/normal/enroll.h @@ -40,7 +40,8 @@ void                 enroll_bootstrap(const struct ipcp_config * conf);  int                  enroll_boot(struct conn * conn,                                   const char *  dst); -int                  enroll_done(struct conn * conn); +int                  enroll_done(struct conn * conn, +                                 int           result);  struct ipcp_config * enroll_get_conf(void); diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index d9fbc2dd..bef04b7a 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -263,11 +263,12 @@ static int normal_ipcp_enroll(const char *      dst,          }          if (enroll_components(dt_conn.conn_info.addr)) { +                enroll_done(&er_conn, -1);                  log_err("Failed to enroll components.");                  goto fail_enroll_comp;          } -        if (enroll_done(&er_conn)) +        if (enroll_done(&er_conn, 0))                  log_warn("Failed to confirm enrollment with peer.");          if (connmgr_dealloc(AEID_DT, &dt_conn)) @@ -346,6 +347,8 @@ static int normal_ipcp_query(const uint8_t * dst)  static struct ipcp_ops normal_ops = {          .ipcp_bootstrap       = normal_ipcp_bootstrap,          .ipcp_enroll          = normal_ipcp_enroll, +        .ipcp_connect         = connmgr_ipcp_connect, +        .ipcp_disconnect      = connmgr_ipcp_disconnect,          .ipcp_reg             = dir_reg,          .ipcp_unreg           = dir_unreg,          .ipcp_query           = normal_ipcp_query, diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index bcf5abe2..3d186d7a 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -1216,6 +1216,8 @@ static int eth_llc_ipcp_flow_dealloc(int fd)  static struct ipcp_ops eth_llc_ops = {          .ipcp_bootstrap       = eth_llc_ipcp_bootstrap,          .ipcp_enroll          = NULL, +        .ipcp_connect         = NULL, +        .ipcp_disconnect      = NULL,          .ipcp_reg             = eth_llc_ipcp_reg,          .ipcp_unreg           = eth_llc_ipcp_unreg,          .ipcp_query           = eth_llc_ipcp_query, diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index 55fe19a6..0bf57741 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -1092,7 +1092,9 @@ static int ipcp_udp_flow_dealloc(int fd)  static struct ipcp_ops udp_ops = {          .ipcp_bootstrap       = ipcp_udp_bootstrap, -        .ipcp_enroll          = NULL,                       /* shim */ +        .ipcp_enroll          = NULL, +        .ipcp_connect         = NULL, +        .ipcp_disconnect      = NULL,          .ipcp_reg             = ipcp_udp_reg,          .ipcp_unreg           = ipcp_udp_unreg,          .ipcp_query           = ipcp_udp_query, diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c index e1689b91..ed1ad924 100644 --- a/src/irmd/ipcp.c +++ b/src/irmd/ipcp.c @@ -281,6 +281,67 @@ int ipcp_enroll(pid_t             api,          return 0;  } +int ipcp_connect(pid_t        api, +                 const char * dst, +                 const char * component) +{ +        ipcp_msg_t   msg      = IPCP_MSG__INIT; +        ipcp_msg_t * recv_msg = NULL; +        int          ret      = -1; + +        msg.code      = IPCP_MSG_CODE__IPCP_CONNECT; +        msg.dst_name  = (char *) dst; +        msg.comp_name = (char *) component; +        msg.has_api   = true; +        msg.api       = api; + +        recv_msg = send_recv_ipcp_msg(api, &msg); +        if (recv_msg == NULL) { +                log_dbg("bad msg"); +                return -EIPCP; +        } + +        if (recv_msg->has_result == false) { +                ipcp_msg__free_unpacked(recv_msg, NULL); +                log_dbg("no result."); +                return -EIPCP; +        } + +        ret = recv_msg->result; +        ipcp_msg__free_unpacked(recv_msg, NULL); + +        return ret; +} + +int ipcp_disconnect(pid_t        api, +                    const char * dst, +                    const char * component) +{ +        ipcp_msg_t   msg      = IPCP_MSG__INIT; +        ipcp_msg_t * recv_msg = NULL; +        int          ret      = -1; + +        msg.code      = IPCP_MSG_CODE__IPCP_DISCONNECT; +        msg.dst_name  = (char *) dst; +        msg.comp_name = (char *) component; +        msg.has_api   = true; +        msg.api       = api; + +        recv_msg = send_recv_ipcp_msg(api, &msg); +        if (recv_msg == NULL) +                return -EIPCP; + +        if (recv_msg->has_result == false) { +                ipcp_msg__free_unpacked(recv_msg, NULL); +                return -EIPCP; +        } + +        ret = recv_msg->result; +        ipcp_msg__free_unpacked(recv_msg, NULL); + +        return ret; +} +  int ipcp_reg(pid_t           api,               const uint8_t * hash,               size_t          len) diff --git a/src/irmd/ipcp.h b/src/irmd/ipcp.h index 67d0476f..9c861cde 100644 --- a/src/irmd/ipcp.h +++ b/src/irmd/ipcp.h @@ -42,6 +42,14 @@ int   ipcp_bootstrap(pid_t               api,                       ipcp_config_msg_t * conf,                       struct dif_info *   info); +int   ipcp_connect(pid_t        api, +                   const char * dst, +                   const char * component); + +int   ipcp_disconnect(pid_t        api, +                      const char * dst, +                      const char * component); +  int   ipcp_reg(pid_t           api,                 const uint8_t * hash,                 size_t          len); diff --git a/src/irmd/main.c b/src/irmd/main.c index e72153ae..cc15e092 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -555,6 +555,76 @@ static int enroll_ipcp(pid_t  api,          return 0;  } +static int connect_ipcp(pid_t        api, +                        const char * dst, +                        const char * component) +{ +        struct ipcp_entry * entry = NULL; + +        pthread_rwlock_rdlock(&irmd.reg_lock); + +        entry = get_ipcp_entry_by_api(api); +        if (entry == NULL) { +                pthread_rwlock_unlock(&irmd.reg_lock); +                log_err("No such IPCP."); +                return -EIPCP; +        } + +        if (entry->type != IPCP_NORMAL) { +                pthread_rwlock_unlock(&irmd.reg_lock); +                log_err("Cannot establish connections for this IPCP type."); +                return -EIPCP; +        } + +        pthread_rwlock_unlock(&irmd.reg_lock); + +        log_dbg("Connecting %s to %s.", component, dst); + +        if (ipcp_connect(api, dst, component)) { +                log_err("Could not connect IPCP."); +                return -EPERM; +        } + +        log_info("Established %s connection between IPCP %d and %s.", +                 component, api, dst); + +        return 0; +} + +static int disconnect_ipcp(pid_t        api, +                           const char * dst, +                           const char * component) +{ +        struct ipcp_entry * entry = NULL; + +        pthread_rwlock_rdlock(&irmd.reg_lock); + +        entry = get_ipcp_entry_by_api(api); +        if (entry == NULL) { +                pthread_rwlock_unlock(&irmd.reg_lock); +                log_err("No such IPCP."); +                return -EIPCP; +        } + +        if (entry->type != IPCP_NORMAL) { +                pthread_rwlock_unlock(&irmd.reg_lock); +                log_err("Cannot tear down connections for this IPCP type."); +                return -EIPCP; +        } + +        pthread_rwlock_unlock(&irmd.reg_lock); + +        if (ipcp_disconnect(api, dst, component)) { +                log_err("Could not disconnect IPCP."); +                return -EPERM; +        } + +        log_info("%s connection between IPCP %d and %s torn down.", +                 component, api, dst); + +        return 0; +} +  static int bind_ap(char *   ap,                     char *   name,                     uint16_t flags, @@ -1876,6 +1946,18 @@ void * mainloop(void * o)                          ret_msg.result = enroll_ipcp(msg->api,                                                       msg->dif_name[0]);                          break; +                case IRM_MSG_CODE__IRM_CONNECT_IPCP: +                        ret_msg.has_result = true; +                        ret_msg.result = connect_ipcp(msg->api, +                                                      msg->dst_name, +                                                      msg->comp_name); +                        break; +                case IRM_MSG_CODE__IRM_DISCONNECT_IPCP: +                        ret_msg.has_result = true; +                        ret_msg.result = disconnect_ipcp(msg->api, +                                                         msg->dst_name, +                                                         msg->comp_name); +                        break;                  case IRM_MSG_CODE__IRM_BIND_AP:                          ret_msg.has_result = true;                          ret_msg.result = bind_ap(msg->ap_name, diff --git a/src/lib/ipcpd_messages.proto b/src/lib/ipcpd_messages.proto index 2e6c0497..691b76ad 100644 --- a/src/lib/ipcpd_messages.proto +++ b/src/lib/ipcpd_messages.proto @@ -33,7 +33,9 @@ enum ipcp_msg_code {          IPCP_FLOW_ALLOC      =  6;          IPCP_FLOW_ALLOC_RESP =  7;          IPCP_FLOW_DEALLOC    =  8; -        IPCP_REPLY           =  9; +        IPCP_CONNECT         =  9; +        IPCP_DISCONNECT      = 10; +        IPCP_REPLY           = 11;  };  message ipcp_msg { @@ -47,5 +49,6 @@ message ipcp_msg {          optional int32 api             =  8;          optional dif_info_msg dif_info =  9;          optional int32 response        = 10; -        optional int32 result          = 11; +        optional string comp_name      = 11; +        optional int32 result          = 12;  }; diff --git a/src/lib/irm.c b/src/lib/irm.c index eec89338..ce17bf18 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -146,7 +146,65 @@ int irm_bootstrap_ipcp(pid_t                      api,          if (recv_msg->has_result == false) {                  irm_msg__free_unpacked(recv_msg, NULL); -                return -1; +                return -EIRMD; +        } + +        ret = recv_msg->result; +        irm_msg__free_unpacked(recv_msg, NULL); + +        return ret; +} + +int irm_connect_ipcp(pid_t        api, +                     const char * dst, +                     const char * component) +{ +        irm_msg_t   msg      = IRM_MSG__INIT; +        irm_msg_t * recv_msg = NULL; +        int         ret; + +        msg.code      = IRM_MSG_CODE__IRM_CONNECT_IPCP; +        msg.dst_name  = (char *) dst; +        msg.comp_name = (char *) component; +        msg.has_api   = true; +        msg.api       = api; + +        recv_msg = send_recv_irm_msg(&msg); +        if (recv_msg == NULL) +                return -EIRMD; + +        if (recv_msg->has_result == false) { +                irm_msg__free_unpacked(recv_msg, NULL); +                return -EIRMD; +        } + +        ret = recv_msg->result; +        irm_msg__free_unpacked(recv_msg, NULL); + +        return ret; +} + +int irm_disconnect_ipcp(pid_t        api, +                        const char * dst, +                        const char * component) +{ +        irm_msg_t   msg      = IRM_MSG__INIT; +        irm_msg_t * recv_msg = NULL; +        int         ret; + +        msg.code      = IRM_MSG_CODE__IRM_DISCONNECT_IPCP; +        msg.dst_name  = (char *) dst; +        msg.comp_name = (char *) component; +        msg.has_api   = true; +        msg.api       = api; + +        recv_msg = send_recv_irm_msg(&msg); +        if (recv_msg == NULL) +                return -EIRMD; + +        if (recv_msg->has_result == false) { +                irm_msg__free_unpacked(recv_msg, NULL); +                return -EIRMD;          }          ret = recv_msg->result; @@ -158,15 +216,15 @@ int irm_bootstrap_ipcp(pid_t                      api,  ssize_t irm_list_ipcps(const char * name,                         pid_t **     apis)  { -        irm_msg_t msg = IRM_MSG__INIT; +        irm_msg_t msg        = IRM_MSG__INIT;          irm_msg_t * recv_msg = NULL; -        size_t nr = 0; +        size_t nr            = 0;          size_t i;          if (apis == NULL)                  return -EINVAL; -        msg.code = IRM_MSG_CODE__IRM_LIST_IPCPS; +        msg.code     = IRM_MSG_CODE__IRM_LIST_IPCPS;          msg.dst_name = (char *) name;          recv_msg = send_recv_irm_msg(&msg); diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index 117752c8..723f6fb3 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -31,19 +31,21 @@ enum irm_msg_code {          IRM_LIST_IPCPS        =  4;          IRM_BOOTSTRAP_IPCP    =  5;          IRM_ENROLL_IPCP       =  6; -        IRM_BIND_AP           =  7; -        IRM_UNBIND_AP         =  8; -        IRM_API_ANNOUNCE      =  9; -        IRM_BIND_API          = 10; -        IRM_UNBIND_API        = 11; -        IRM_REG               = 12; -        IRM_UNREG             = 13; -        IRM_FLOW_ALLOC        = 14; -        IRM_FLOW_ACCEPT       = 15; -        IRM_FLOW_DEALLOC      = 16; -        IPCP_FLOW_REQ_ARR     = 17; -        IPCP_FLOW_ALLOC_REPLY = 18; -        IRM_REPLY             = 19; +        IRM_CONNECT_IPCP      =  7; +        IRM_DISCONNECT_IPCP   =  8; +        IRM_BIND_AP           =  9; +        IRM_UNBIND_AP         = 10; +        IRM_API_ANNOUNCE      = 11; +        IRM_BIND_API          = 12; +        IRM_UNBIND_API        = 13; +        IRM_REG               = 14; +        IRM_UNREG             = 15; +        IRM_FLOW_ALLOC        = 16; +        IRM_FLOW_ACCEPT       = 17; +        IRM_FLOW_DEALLOC      = 18; +        IPCP_FLOW_REQ_ARR     = 19; +        IPCP_FLOW_ALLOC_REPLY = 20; +        IRM_REPLY             = 21;  };  message irm_msg { @@ -63,5 +65,6 @@ message irm_msg {          repeated sint32 apis          = 14;          optional uint32 timeo_sec     = 15;          optional uint32 timeo_nsec    = 16; -        optional sint32 result        = 17; +        optional string comp_name     = 17; +        optional sint32 result        = 18;  }; diff --git a/src/tools/irm/CMakeLists.txt b/src/tools/irm/CMakeLists.txt index 300ad982..895bc746 100644 --- a/src/tools/irm/CMakeLists.txt +++ b/src/tools/irm/CMakeLists.txt @@ -14,6 +14,8 @@ set(SOURCE_FILES    irm_ipcp_destroy.c    irm_ipcp_bootstrap.c    irm_ipcp_enroll.c +  irm_ipcp_connect.c +  irm_ipcp_disconnect.c    irm_unbind_ap.c    irm_unbind_api.c    irm_unbind_ipcp.c diff --git a/src/tools/irm/irm_ipcp.c b/src/tools/irm/irm_ipcp.c index 2850ac89..2f7b01c9 100644 --- a/src/tools/irm/irm_ipcp.c +++ b/src/tools/irm/irm_ipcp.c @@ -45,17 +45,19 @@ static const struct cmd {          const char * cmd;          int (* func)(int argc, char ** argv);  } cmds[] = { -        { "create",    do_create_ipcp }, -        { "destroy",   do_destroy_ipcp }, -        { "bootstrap", do_bootstrap_ipcp }, -        { "enroll",    do_enroll_ipcp }, -        { "help",      do_help }, -        { NULL,        NULL } +        { "create",     do_create_ipcp }, +        { "destroy",    do_destroy_ipcp }, +        { "bootstrap",  do_bootstrap_ipcp }, +        { "enroll",     do_enroll_ipcp }, +        { "connect",    do_connect_ipcp }, +        { "disconnect", do_disconnect_ipcp }, +        { "help",       do_help }, +        { NULL,         NULL }  };  static int do_cmd(const char * argv0, -                  int argc, -                  char ** argv) +                  int          argc, +                  char **      argv)  {          const struct cmd * c; diff --git a/src/tools/irm/irm_ipcp_connect.c b/src/tools/irm/irm_ipcp_connect.c new file mode 100644 index 00000000..168c8d17 --- /dev/null +++ b/src/tools/irm/irm_ipcp_connect.c @@ -0,0 +1,94 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Connect components of normal IPC Processes + * + *    Dimitri Staessens <dimitri.staessens@ugent.be> + *    Sander Vrijders   <sander.vrijders@ugent.be> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#include <ouroboros/irm.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define DT      "dt" +#define MGMT    "mgmt" + +static void usage(void) +{ +        printf("Usage: irm ipcp connect\n" +               "                name <ipcp name>\n" +               "                comp <COMPONENT>\n" +               "                dst  <name of destination IPCP>\n" +               "where COMPONENT = {" DT " " MGMT "},\n\n"); +} + +int do_connect_ipcp(int     argc, +                    char ** argv) +{ +        char *  name      = NULL; +        char *  dst_name  = NULL; +        char *  comp_name = NULL; +        pid_t * apis      = NULL; +        ssize_t len       = 0; + +        while (argc > 0) { +                if (strcmp(*argv, "name") == 0) { +                        name = *(argv + 1); +                } else if (matches(*argv, "dst") == 0) { +                        dst_name = *(argv + 1); +                } else if (matches(*argv, "comp") == 0) { +                        comp_name = *(argv + 1); +                } else { +                        printf("\"%s\" is unknown, try \"irm " +                               "ipcpi connect\".\n", *argv); +                        return -1; +                } + +                argc -= 2; +                argv += 2; +        } + +        if (name == NULL || dst_name == NULL || comp_name == NULL) { +                usage(); +                return -1; +        } + +        len = irm_list_ipcps(name, &apis); +        if (len != 1) +                return -1; + +        if (!strcmp(comp_name, DT)) +                comp_name = DT_AE; + +        if (!strcmp(comp_name , MGMT)) +                comp_name = MGMT_AE; + +        if (irm_connect_ipcp(apis[0], dst_name, comp_name)) { +                free(apis); +                return -1; +        } + +        if (apis != NULL) +                free(apis); + +        return 0; +} diff --git a/src/tools/irm/irm_ipcp_disconnect.c b/src/tools/irm/irm_ipcp_disconnect.c new file mode 100644 index 00000000..8f83f3e8 --- /dev/null +++ b/src/tools/irm/irm_ipcp_disconnect.c @@ -0,0 +1,94 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Connect components of normal IPC Processes + * + *    Dimitri Staessens <dimitri.staessens@ugent.be> + *    Sander Vrijders   <sander.vrijders@ugent.be> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#include <ouroboros/irm.h> + +#include "irm_ops.h" +#include "irm_utils.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define DT      "dt" +#define MGMT    "mgmt" + +static void usage(void) +{ +        printf("Usage: irm ipcp disconnect\n" +               "                name <ipcp name>\n" +               "                comp <COMPONENT>\n" +               "                dst  <name of destination IPCP>\n" +               "where COMPONENT = {" DT " " MGMT "},\n\n"); +} + +int do_disconnect_ipcp(int     argc, +                       char ** argv) +{ +        char *  name      = NULL; +        char *  dst_name  = NULL; +        char *  comp_name = NULL; +        pid_t * apis      = NULL; +        ssize_t len       = 0; + +        while (argc > 0) { +                if (strcmp(*argv, "name") == 0) { +                        name = *(argv + 1); +                } else if (matches(*argv, "dst") == 0) { +                        dst_name = *(argv + 1); +                } else if (matches(*argv, "comp") == 0) { +                        comp_name = *(argv + 1); +                } else { +                        printf("\"%s\" is unknown, try \"irm " +                               "ipcpi connect\".\n", *argv); +                        return -1; +                } + +                argc -= 2; +                argv += 2; +        } + +        if (name == NULL || dst_name == NULL || comp_name == NULL) { +                usage(); +                return -1; +        } + +        len = irm_list_ipcps(name, &apis); +        if (len != 1) +                return -1; + +        if (!strcmp(comp_name, DT)) +                comp_name = DT_AE; + +        if (!strcmp(comp_name , MGMT)) +                comp_name = MGMT_AE; + +        if (irm_disconnect_ipcp(apis[0], dst_name, comp_name)) { +                free(apis); +                return -1; +        } + +        if (apis != NULL) +                free(apis); + +        return 0; +} diff --git a/src/tools/irm/irm_ops.h b/src/tools/irm/irm_ops.h index 749ea13d..a2bc40b4 100644 --- a/src/tools/irm/irm_ops.h +++ b/src/tools/irm/irm_ops.h @@ -35,6 +35,12 @@ int do_bootstrap_ipcp(int     argc,  int do_enroll_ipcp(int     argc,                     char ** argv); +int do_connect_ipcp(int     argc, +                    char ** argv); + +int do_disconnect_ipcp(int     argc, +                       char ** argv); +  int bind_cmd(int     argc,               char ** argv);  | 
