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 <[email protected]> + * Sander Vrijders <[email protected]> + * + * 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 <[email protected]> + * Sander Vrijders <[email protected]> + * + * 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); |