summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@ugent.be>2017-08-28 18:54:22 +0200
committerdimitri staessens <dimitri.staessens@ugent.be>2017-08-28 20:49:34 +0200
commit9de8dc4948cf7ce239232aae0889c39ffa39ede2 (patch)
tree396295b2d36f69ee55e5080e556891f11210aed8 /src
parent176698e8c2fd7ab8007b8074515d6144e7177d8e (diff)
downloadouroboros-9de8dc4948cf7ce239232aae0889c39ffa39ede2.zip
ouroboros-9de8dc4948cf7ce239232aae0889c39ffa39ede2.tar.gz
tools: Add tool to connect IPCP components
This enables user-written tools to instruct IPCPs to establish and tear down connections (a.k.a. adjacencies) between its internal components (Management and Data Transfer). For more info, do "irm ipcp connect" or "irm ipcp disconnect" on the command line. This commit exposes a deletion bug in the RIB where FSO's fail to unpack/parse. This will be fixed when the RIB is deprecated.
Diffstat (limited to 'src')
-rw-r--r--src/ipcpd/ipcp.c28
-rw-r--r--src/ipcpd/ipcp.h6
-rw-r--r--src/ipcpd/local/main.c4
-rw-r--r--src/ipcpd/normal/ae.h9
-rw-r--r--src/ipcpd/normal/connmgr.c127
-rw-r--r--src/ipcpd/normal/connmgr.h6
-rw-r--r--src/ipcpd/normal/dt.c3
-rw-r--r--src/ipcpd/normal/enroll.c14
-rw-r--r--src/ipcpd/normal/enroll.h3
-rw-r--r--src/ipcpd/normal/main.c5
-rw-r--r--src/ipcpd/shim-eth-llc/main.c2
-rw-r--r--src/ipcpd/shim-udp/main.c4
-rw-r--r--src/irmd/ipcp.c61
-rw-r--r--src/irmd/ipcp.h8
-rw-r--r--src/irmd/main.c82
-rw-r--r--src/lib/ipcpd_messages.proto7
-rw-r--r--src/lib/irm.c66
-rw-r--r--src/lib/irmd_messages.proto31
-rw-r--r--src/tools/irm/CMakeLists.txt2
-rw-r--r--src/tools/irm/irm_ipcp.c18
-rw-r--r--src/tools/irm/irm_ipcp_connect.c94
-rw-r--r--src/tools/irm/irm_ipcp_disconnect.c94
-rw-r--r--src/tools/irm/irm_ops.h6
23 files changed, 619 insertions, 61 deletions
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index d4b3a7f..41ea478 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 cd18d19..1b2a033 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 37d23fc..c6f88d7 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 4534cef..3d3bdc2 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 b6e5e31..11f8324 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 920058d..379877e 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 19c2d3a..aa08985 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 2f7dd9b..7f93ed3 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 67c9912..3b277e4 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 d9fbc2d..bef04b7 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 bcf5abe..3d186d7 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 55fe19a..0bf5774 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 e1689b9..ed1ad92 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 67d0476..9c861cd 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 e72153a..cc15e09 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 2e6c049..691b76a 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 eec8933..ce17bf1 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 117752c..723f6fb 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 300ad98..895bc74 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 2850ac8..2f7b01c 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 0000000..168c8d1
--- /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 0000000..8f83f3e
--- /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 749ea13..a2bc40b 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);