diff options
Diffstat (limited to 'src')
52 files changed, 1447 insertions, 1340 deletions
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index ff45407b..41ea4784 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -227,8 +227,6 @@ static void * mainloop(void * o) conf.fd_size = conf_msg->fd_size; conf.has_ttl = conf_msg->has_ttl; conf.addr_auth_type = conf_msg->addr_auth_type; - conf.dt_gam_type = conf_msg->dt_gam_type; - conf.rm_gam_type = conf_msg->rm_gam_type; conf.routing_type = conf_msg->routing_type; switch(conf_msg->dif_info->dir_hash_algo) { @@ -303,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; @@ -437,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/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt index 7a40e94c..aebc6c35 100644 --- a/src/ipcpd/normal/CMakeLists.txt +++ b/src/ipcpd/normal/CMakeLists.txt @@ -15,6 +15,8 @@ include_directories(${CMAKE_BINARY_DIR}/include) set(IPCP_NORMAL_TARGET ipcpd-normal CACHE INTERNAL "") protobuf_generate_c(FLOW_ALLOC_SRCS FLOW_ALLOC_HDRS flow_alloc.proto) +protobuf_generate_c(ENROLL_PROTO_SRCS ENROLL_PROTO_HDRS enroll.proto + ${CMAKE_SOURCE_DIR}/src/lib/ipcp_config.proto) protobuf_generate_c(KAD_PROTO_SRCS KAD_PROTO_HDRS kademlia.proto) # Add GPB sources of policies last @@ -34,7 +36,6 @@ set(SOURCE_FILES dt_pci.c enroll.c fa.c - gam.c main.c neighbors.c pff.c @@ -42,14 +43,13 @@ set(SOURCE_FILES routing.c sdu_sched.c # Add policies last - pol/complete.c pol/flat.c pol/link_state.c pol/graph.c ) add_executable(ipcpd-normal ${SOURCE_FILES} ${IPCP_SOURCES} - ${FLOW_ALLOC_SRCS} ${FSO_SRCS} ${KAD_PROTO_SRCS}) + ${FLOW_ALLOC_SRCS} ${FSO_SRCS} ${KAD_PROTO_SRCS} ${ENROLL_PROTO_SRCS}) target_link_libraries(ipcpd-normal LINK_PUBLIC ouroboros) include(AddCompileFlags) diff --git a/src/ipcpd/normal/addr_auth.c b/src/ipcpd/normal/addr_auth.c index e327e2fa..e4aacccd 100644 --- a/src/ipcpd/normal/addr_auth.c +++ b/src/ipcpd/normal/addr_auth.c @@ -35,7 +35,8 @@ struct addr_auth { struct pol_addr_auth_ops * ops; } addr_auth; -int addr_auth_init(enum pol_addr_auth type) +int addr_auth_init(enum pol_addr_auth type, + const void * info) { switch (type) { case FLAT_RANDOM: @@ -46,7 +47,7 @@ int addr_auth_init(enum pol_addr_auth type) return -1; } - return addr_auth.ops->init(); + return addr_auth.ops->init(info); } uint64_t addr_auth_address(void) diff --git a/src/ipcpd/normal/addr_auth.h b/src/ipcpd/normal/addr_auth.h index 5a6dec05..14754660 100644 --- a/src/ipcpd/normal/addr_auth.h +++ b/src/ipcpd/normal/addr_auth.h @@ -27,7 +27,8 @@ #include <stdint.h> -int addr_auth_init(enum pol_addr_auth type); +int addr_auth_init(enum pol_addr_auth type, + const void * info); int addr_auth_fini(void); diff --git a/src/ipcpd/normal/ae.h b/src/ipcpd/normal/ae.h index 6285ba6a..3d3bdc27 100644 --- a/src/ipcpd/normal/ae.h +++ b/src/ipcpd/normal/ae.h @@ -23,8 +23,26 @@ #ifndef OUROBOROS_IPCPD_NORMAL_AE_H #define OUROBOROS_IPCPD_NORMAL_AE_H -#define MGMT_AE "Management" -#define DT_AE "Data transfer" -#define ENROLL_AE "Enrollment" +#include <ouroboros/cacep.h> + +#include "dt.h" + +#define DST_MAX_STRLEN 64 + +enum ae_id { + AEID_DT = 0, + AEID_ENROLL, + AEID_MGMT, + AEID_MAX +}; + +struct conn { + struct conn_info conn_info; + struct { + char dst[DST_MAX_STRLEN + 1]; + int fd; + qosspec_t qs; + } flow_info; +}; #endif /* OUROBOROS_IPCPD_NORMAL_AE_H */ diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c index a83d71c3..fa43b97a 100644 --- a/src/ipcpd/normal/connmgr.c +++ b/src/ipcpd/normal/connmgr.c @@ -22,7 +22,7 @@ #define _POSIX_C_SOURCE 200112L -#define OUROBOROS_PREFIX "normal-ipcp" +#define OUROBOROS_PREFIX "Connection manager" #include <ouroboros/dev.h> #include <ouroboros/cacep.h> @@ -42,92 +42,69 @@ #include <stdlib.h> #include <assert.h> -struct ae_conn { +enum connmgr_state { + CONNMGR_NULL = 0, + CONNMGR_INIT, + CONNMGR_RUNNING +}; + +struct conn_el { struct list_head next; struct conn conn; }; struct ae { - struct list_head next; + struct nbs * nbs; struct conn_info info; - struct list_head conn_list; - pthread_cond_t conn_cond; - pthread_mutex_t conn_lock; + struct list_head conns; + struct list_head pending; + + pthread_cond_t cond; + pthread_mutex_t lock; }; struct { - pthread_t acceptor; + struct ae aes[AEID_MAX]; + enum connmgr_state state; - struct list_head aes; - pthread_rwlock_t aes_lock; + pthread_t acceptor; } connmgr; - -static int get_info_by_name(const char * name, - struct conn_info * info) +static int get_id_by_name(const char * name) { - struct list_head * p; + enum ae_id i; - pthread_rwlock_rdlock(&connmgr.aes_lock); - - list_for_each(p, &connmgr.aes) { - struct ae * ae = list_entry(p, struct ae, next); - if (strcmp(ae->info.ae_name, name) == 0) { - memcpy(info, &ae->info, sizeof(*info)); - pthread_rwlock_unlock(&connmgr.aes_lock); - return 0; - } - } - - pthread_rwlock_unlock(&connmgr.aes_lock); + for (i = 0; i < AEID_MAX; ++i) + if (strcmp(name, connmgr.aes[i].info.ae_name) == 0) + return i; return -1; } -static int add_ae_conn(const char * name, +static int add_ae_conn(enum ae_id id, int fd, qosspec_t qs, struct conn_info * rcv_info) { - struct ae_conn * ae_conn; - struct list_head * p; - struct ae * ae = NULL; + 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; + el->conn.conn_info = *rcv_info; + el->conn.flow_info.fd = fd; + el->conn.flow_info.qs = qs; - list_head_init(&ae_conn->next); + pthread_mutex_lock(&connmgr.aes[id].lock); - pthread_rwlock_wrlock(&connmgr.aes_lock); + list_add(&el->next, &connmgr.aes[id].pending); + pthread_cond_signal(&connmgr.aes[id].cond); - list_for_each(p, &connmgr.aes) { - ae = list_entry(p, struct ae, next); - if (strcmp(ae->info.ae_name, name) == 0) - break; - } - - /* Check if entry was removed during allocation. */ - if (ae == NULL || strcmp(ae->info.ae_name, name) != 0) { - pthread_rwlock_unlock(&connmgr.aes_lock); - return -1; - } - - pthread_mutex_lock(&ae->conn_lock); - - list_add(&ae_conn->next, &ae->conn_list); - pthread_cond_signal(&ae->conn_cond); - - pthread_mutex_unlock(&ae->conn_lock); - - pthread_rwlock_unlock(&connmgr.aes_lock); + pthread_mutex_unlock(&connmgr.aes[id].lock); return 0; } @@ -136,7 +113,6 @@ static void * flow_acceptor(void * o) { int fd; qosspec_t qs; - struct conn_info snd_info; struct conn_info rcv_info; struct conn_info fail_info; @@ -145,10 +121,7 @@ static void * flow_acceptor(void * o) memset(&fail_info, 0, sizeof(fail_info)); while (true) { - if (ipcp_get_state() != IPCP_OPERATIONAL) { - log_info("Shutting down flow acceptor."); - return 0; - } + int id; fd = flow_accept(&qs, NULL); if (fd < 0) { @@ -158,26 +131,30 @@ static void * flow_acceptor(void * o) } if (cacep_rcv(fd, &rcv_info)) { - log_err("Error establishing application connection."); + log_dbg("Error establishing application connection."); flow_dealloc(fd); continue; } - if (get_info_by_name(rcv_info.ae_name, &snd_info)) { - log_err("Failed to get info for %s.", rcv_info.ae_name); + id = get_id_by_name(rcv_info.ae_name); + if (id < 0) { + log_dbg("Connection request for unknown AE %s.", + rcv_info.ae_name); cacep_snd(fd, &fail_info); flow_dealloc(fd); continue; } - if (cacep_snd(fd, &snd_info)) { - log_err("Failed to respond to request."); + assert(id < AEID_MAX); + + if (cacep_snd(fd, &connmgr.aes[id].info)) { + log_dbg("Failed to respond to request."); flow_dealloc(fd); continue; } - if (add_ae_conn(rcv_info.ae_name, fd, qs, &rcv_info)) { - log_err("Failed to add new connection."); + if (add_ae_conn(id, fd, qs, &rcv_info)) { + log_dbg("Failed to add new connection."); flow_dealloc(fd); continue; } @@ -188,130 +165,192 @@ static void * flow_acceptor(void * o) int connmgr_init(void) { - if (pthread_rwlock_init(&connmgr.aes_lock, NULL)) - return -1; - - list_head_init(&connmgr.aes); + connmgr.state = CONNMGR_INIT; return 0; } +void connmgr_fini(void) +{ + int i; + + if (connmgr.state == CONNMGR_RUNNING) + pthread_join(connmgr.acceptor, NULL); + + for (i = 0; i < AEID_MAX; ++i) + connmgr_ae_fini(i); +} + int connmgr_start(void) { if (pthread_create(&connmgr.acceptor, NULL, flow_acceptor, NULL)) return -1; + connmgr.state = CONNMGR_RUNNING; + return 0; } void connmgr_stop(void) { - pthread_cancel(connmgr.acceptor); + if (connmgr.state == CONNMGR_RUNNING) + pthread_cancel(connmgr.acceptor); } -static void destroy_ae(struct ae * ae) +int connmgr_ae_init(enum ae_id id, + const struct conn_info * info, + struct nbs * nbs) { - struct list_head * p; - struct list_head * h; + struct ae * ae; - pthread_mutex_lock(&ae->conn_lock); + assert(id >= 0 && id < AEID_MAX); - list_for_each_safe(p, h, &ae->conn_list) { - struct ae_conn * e = list_entry(p, struct ae_conn, next); - list_del(&e->next); - free(e); + ae = connmgr.aes + id; + + if (pthread_mutex_init(&ae->lock, NULL)) + return -1; + + if (pthread_cond_init(&ae->cond, NULL)) { + pthread_mutex_destroy(&ae->lock); + return -1; } - pthread_mutex_unlock(&ae->conn_lock); + list_head_init(&ae->conns); + list_head_init(&ae->pending); + + memcpy(&connmgr.aes[id].info, info, sizeof(connmgr.aes[id].info)); - pthread_cond_destroy(&ae->conn_cond); - pthread_mutex_destroy(&ae->conn_lock); + connmgr.aes[id].nbs = nbs; - free(ae); + return 0; } -void connmgr_fini(void) +void connmgr_ae_fini(enum ae_id id) { struct list_head * p; struct list_head * h; + struct ae * ae; + + assert(id >= 0 && id < AEID_MAX); - pthread_join(connmgr.acceptor, NULL); + if (strlen(connmgr.aes[id].info.ae_name) == 0) + return; - pthread_rwlock_wrlock(&connmgr.aes_lock); + ae = connmgr.aes + id; - list_for_each_safe(p, h, &connmgr.aes) { - struct ae * e = list_entry(p, struct ae, next); + pthread_mutex_lock(&ae->lock); + + list_for_each_safe(p, h, &ae->conns) { + 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); - destroy_ae(e); + free(e); } - pthread_rwlock_unlock(&connmgr.aes_lock); + pthread_mutex_unlock(&ae->lock); - pthread_rwlock_destroy(&connmgr.aes_lock); + pthread_cond_destroy(&ae->cond); + pthread_mutex_destroy(&ae->lock); + + memset(&connmgr.aes[id].info, 0, sizeof(connmgr.aes[id].info)); + + connmgr.aes[id].nbs = NULL; } -struct ae * connmgr_ae_create(struct conn_info info) +int connmgr_ipcp_connect(const char * dst, + const char * component) { - struct ae * ae; + struct conn_el * ce; + int id; - ae = malloc(sizeof(*ae)); - if (ae == NULL) - goto fail_malloc; + assert(dst); + assert(component); - list_head_init(&ae->next); - list_head_init(&ae->conn_list); - - ae->info = info; + ce = malloc(sizeof(*ce)); + if (ce == NULL) { + log_dbg("Out of memory."); + return -1; + } - if (pthread_mutex_init(&ae->conn_lock, NULL)) - goto fail_mutex_init; + id = get_id_by_name(component); + if (id < 0) { + log_dbg("No such component: %s", component); + free(ce); + return -1; + } - if (pthread_cond_init(&ae->conn_cond, NULL)) - goto fail_cond_init; + /* FIXME: get the correct qos for the component. */ + if (connmgr_alloc(id, dst, NULL, &ce->conn)) { + free(ce); + return -1; + } - pthread_rwlock_wrlock(&connmgr.aes_lock); + 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); + } - list_add(&ae->next, &connmgr.aes); + pthread_mutex_lock(&connmgr.aes[id].lock); - pthread_rwlock_unlock(&connmgr.aes_lock); + list_add(&ce->next, &connmgr.aes[id].conns); - return ae; + pthread_mutex_unlock(&connmgr.aes[id].lock); - fail_cond_init: - pthread_mutex_destroy(&ae->conn_lock); - fail_mutex_init: - free(ae); - fail_malloc: - return NULL; + return 0; } -void connmgr_ae_destroy(struct ae * ae) +int connmgr_ipcp_disconnect(const char * dst, + const char * component) { - assert(ae); + struct list_head * p; + struct list_head * h; + int id; - pthread_rwlock_wrlock(&connmgr.aes_lock); + assert(dst); + assert(component); - list_del(&ae->next); + id = get_id_by_name(component); + if (id < 0) + return -1; - pthread_rwlock_unlock(&connmgr.aes_lock); + 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); - destroy_ae(ae); + return 0; } -int connmgr_alloc(struct ae * ae, - const char * dst_name, +int connmgr_alloc(enum ae_id id, + const char * dst, qosspec_t * qs, struct conn * conn) { - assert(ae); - assert(dst_name); - assert(conn); - - memset(&conn->conn_info, 0, sizeof(conn->conn_info)); + assert(id >= 0 && id < AEID_MAX); + assert(dst); - conn->flow_info.fd = flow_alloc(dst_name, qs, NULL); + conn->flow_info.fd = flow_alloc(dst, qs, NULL); if (conn->flow_info.fd < 0) { - log_err("Failed to allocate flow to %s.", dst_name); + log_dbg("Failed to allocate flow to %s.", dst); return -1; } @@ -320,58 +359,90 @@ int connmgr_alloc(struct ae * ae, else memset(&conn->flow_info.qs, 0, sizeof(conn->flow_info.qs)); - if (cacep_snd(conn->flow_info.fd, &ae->info)) { - log_err("Failed to create application connection."); + log_dbg("Sending cacep info for protocol %s to fd %d.", + connmgr.aes[id].info.protocol, conn->flow_info.fd); + + if (cacep_snd(conn->flow_info.fd, &connmgr.aes[id].info)) { + log_dbg("Failed to create application connection."); flow_dealloc(conn->flow_info.fd); return -1; } if (cacep_rcv(conn->flow_info.fd, &conn->conn_info)) { - log_err("Failed to connect to application."); + log_dbg("Failed to connect to application."); flow_dealloc(conn->flow_info.fd); return -1; } - if (strcmp(ae->info.protocol, conn->conn_info.protocol) || - ae->info.pref_version != conn->conn_info.pref_version || - ae->info.pref_syntax != conn->conn_info.pref_syntax) { + if (strcmp(connmgr.aes[id].info.protocol, conn->conn_info.protocol)) { + log_dbg("Unknown protocol (requested %s, got %s).", + connmgr.aes[id].info.protocol, + conn->conn_info.protocol); flow_dealloc(conn->flow_info.fd); return -1; } + if (connmgr.aes[id].info.pref_version != conn->conn_info.pref_version) { + log_dbg("Unknown protocol version."); + flow_dealloc(conn->flow_info.fd); + return -1; + } + + if (connmgr.aes[id].info.pref_syntax != conn->conn_info.pref_syntax) { + log_dbg("Unknown protocol syntax."); + flow_dealloc(conn->flow_info.fd); + return -1; + } + + if (connmgr.aes[id].nbs != NULL) + nbs_add(connmgr.aes[id].nbs, *conn); + return 0; } -int connmgr_wait(struct ae * ae, +int connmgr_dealloc(enum ae_id id, + struct conn * conn) +{ + if (connmgr.aes[id].nbs != NULL) + nbs_del(connmgr.aes[id].nbs, conn->flow_info.fd); + + return flow_dealloc(conn->flow_info.fd); +} + + +int connmgr_wait(enum ae_id id, struct conn * conn) { - struct ae_conn * ae_conn; + struct conn_el * el; + struct ae * ae; - assert(ae); + assert(id >= 0 && id < AEID_MAX); assert(conn); - pthread_mutex_lock(&ae->conn_lock); + ae = connmgr.aes + id; + + pthread_mutex_lock(&ae->lock); pthread_cleanup_push((void(*)(void *))pthread_mutex_unlock, - (void *) &ae->conn_lock); + (void *) &ae->lock); - while (list_is_empty(&ae->conn_list)) - pthread_cond_wait(&ae->conn_cond, &ae->conn_lock); + while (list_is_empty(&ae->pending)) + pthread_cond_wait(&ae->cond, &ae->lock); pthread_cleanup_pop(false); - ae_conn = list_first_entry((&ae->conn_list), struct ae_conn, next); - if (ae_conn == NULL) { - pthread_mutex_unlock(&ae->conn_lock); + 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->conn_lock); + pthread_mutex_unlock(&ae->lock); return 0; } diff --git a/src/ipcpd/normal/connmgr.h b/src/ipcpd/normal/connmgr.h index 40d74348..379877e6 100644 --- a/src/ipcpd/normal/connmgr.h +++ b/src/ipcpd/normal/connmgr.h @@ -26,13 +26,8 @@ #include <ouroboros/cacep.h> #include <ouroboros/qos.h> -struct conn { - struct conn_info conn_info; - struct flow_info { - int fd; - qosspec_t qs; - } flow_info; -}; +#include "ae.h" +#include "neighbors.h" int connmgr_init(void); @@ -42,16 +37,27 @@ int connmgr_start(void); void connmgr_stop(void); -struct ae * connmgr_ae_create(struct conn_info info); +int connmgr_ae_init(enum ae_id id, + const struct conn_info * info, + struct nbs * nbs); -void connmgr_ae_destroy(struct ae * ae); +void connmgr_ae_fini(enum ae_id id); -int connmgr_alloc(struct ae * ae, +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, struct conn * conn); -int connmgr_wait(struct ae * ae, +int connmgr_dealloc(enum ae_id id, + struct conn * conn); + +int connmgr_wait(enum ae_id id, struct conn * conn); #endif /* OUROBOROS_IPCPD_NORMAL_CONNMGR_H */ diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c index feae7013..2e2c113a 100644 --- a/src/ipcpd/normal/dir.c +++ b/src/ipcpd/normal/dir.c @@ -46,80 +46,21 @@ struct dht * dht; -static uint64_t find_peer_addr(void) +int dir_init(void) { - ssize_t i; - char ** members; - ssize_t n_members; - size_t reset; - char path[RIB_MAX_PATH_LEN + 1]; - - strcpy(path, MEMBERS_PATH); - - reset = strlen(path); - - n_members = rib_children(path, &members); - if (n_members == 1) { - freepp(ssize_t, members, n_members); - return 0; - } - - for (i = 0; i < n_members; ++i) { - uint64_t addr; - rib_path_append(path, members[i]); - if (rib_read(path, &addr, sizeof(addr)) != sizeof(addr)) { - log_err("Failed to read address from RIB."); - freepp(ssize_t, members, n_members); - return ipcpi.dt_addr; - } - - if (addr != ipcpi.dt_addr) { - freepp(ssize_t, members, n_members); - return addr; - } - - path[reset] = '\0'; - } - - freepp(ssize_t, members, n_members); - - return 0; -} - -int dir_init() -{ - uint64_t addr; - dht = dht_create(ipcpi.dt_addr); if (dht == NULL) return -ENOMEM; - addr = find_peer_addr(); - if (addr == ipcpi.dt_addr) { - log_err("Failed to get peer address."); - dht_destroy(dht); - return -EPERM; - } - - if (addr != 0) { - size_t retr = 0; - log_dbg("Enrolling directory with peer %" PRIu64 ".", addr); - /* NOTE: we could try other members if dht_enroll times out. */ - while (dht_enroll(dht, addr)) { - if (retr++ == ENROL_RETR) { - dht_destroy(dht); - return -EPERM; - } - - log_dbg("Directory enrollment failed, retrying..."); - sleep(ENROL_INTV); - } - - log_dbg("Directory enrolled."); + return 0; +} - return 0; - } +void dir_fini(void) +{ + dht_destroy(dht); +} +int dir_bootstrap(void) { log_dbg("Bootstrapping directory."); /* TODO: get parameters for bootstrap from IRM tool. */ @@ -133,9 +74,20 @@ int dir_init() return 0; } -void dir_fini(void) -{ - dht_destroy(dht); +int dir_enroll(uint64_t addr) { + size_t retr = 0; + log_dbg("Enrolling directory with peer %" PRIu64 ".", addr); + while (dht_enroll(dht, addr)) { + if (retr++ == ENROL_RETR) + return -EPERM; + + log_dbg("Directory enrollment failed, retrying..."); + sleep(ENROL_INTV); + } + + log_dbg("Directory enrolled."); + + return 0; } int dir_reg(const uint8_t * hash) diff --git a/src/ipcpd/normal/dir.h b/src/ipcpd/normal/dir.h index 5f3f738e..13571b68 100644 --- a/src/ipcpd/normal/dir.h +++ b/src/ipcpd/normal/dir.h @@ -27,6 +27,10 @@ int dir_init(void); void dir_fini(void); +int dir_bootstrap(void); + +int dir_enroll(uint64_t peer); + int dir_reg(const uint8_t * hash); int dir_unreg(const uint8_t * hash); diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c index f4ab2440..282f6bee 100644 --- a/src/ipcpd/normal/dt.c +++ b/src/ipcpd/normal/dt.c @@ -38,7 +38,6 @@ #include "dt_pci.h" #include "pff.h" #include "neighbors.h" -#include "gam.h" #include "routing.h" #include "sdu_sched.h" #include "ae.h" @@ -67,11 +66,11 @@ struct { struct ae_info aes[AP_RES_FDS]; pthread_rwlock_t lock; - struct gam * gam; struct nbs * nbs; - struct ae * ae; struct nb_notifier nb_notifier; + + pthread_t listener; } dt; static int dt_neighbor_event(enum nb_event event, @@ -149,36 +148,48 @@ static int sdu_handler(int fd, return 0; } -int dt_init(void) +static void * dt_conn_handle(void * o) { - int i; - int j; - struct conn_info info; - enum pol_routing pr; + struct conn conn; - if (rib_read(BOOT_PATH "/dt/routing/type", &pr, sizeof(pr)) - != sizeof(pr)) { - log_err("Failed to read policy for routing."); - return -1; - } + (void) o; - if (dt_pci_init()) { - log_err("Failed to init shm dt_pci."); - return -1; + while (true) { + if (connmgr_wait(AEID_DT, &conn)) { + log_err("Failed to get next DT connection."); + continue; + } + + log_dbg("Got new connection."); + + /* NOTE: connection acceptance policy could be here. */ + + nbs_add(dt.nbs, conn); } + return 0; +} + +int dt_init(enum pol_routing pr, + uint8_t addr_size, + uint8_t fd_size, + bool has_ttl) +{ + int i; + int j; + struct conn_info info; + memset(&info, 0, sizeof(info)); strcpy(info.ae_name, DT_AE); strcpy(info.protocol, DT_PROTO); info.pref_version = 1; - info.pref_syntax = PROTO_FIXED; - info.addr = ipcpi.dt_addr; + info.pref_syntax = PROTO_FIXED; + info.addr = ipcpi.dt_addr; - dt.ae = connmgr_ae_create(info); - if (dt.ae == NULL) { - log_err("Failed to create AE struct."); - goto fail_connmgr; + if (dt_pci_init(addr_size, fd_size, has_ttl)) { + log_err("Failed to init shm dt_pci."); + goto fail_pci_init; } dt.nbs = nbs_create(); @@ -193,6 +204,11 @@ int dt_init(void) goto fail_nbs_notifier; } + if (connmgr_ae_init(AEID_DT, &info, dt.nbs)) { + log_err("Failed to register with connmgr."); + goto fail_connmgr_ae_init; + } + if (routing_init(pr, dt.nbs)) { log_err("Failed to init routing."); goto fail_routing; @@ -233,6 +249,8 @@ int dt_init(void) for (j = 0; j < QOS_CUBE_MAX; ++j) routing_i_destroy(dt.routing[j]); fail_routing_i: + connmgr_ae_fini(AEID_DT); + fail_connmgr_ae_init: for (i = 0; i < QOS_CUBE_MAX; ++i) pff_destroy(dt.pff[i]); fail_pff: @@ -242,9 +260,9 @@ int dt_init(void) fail_nbs_notifier: nbs_destroy(dt.nbs); fail_nbs: - connmgr_ae_destroy(dt.ae); - fail_connmgr: dt_pci_fini(); + fail_pci_init: + connmgr_ae_fini(AEID_DT); return -1; } @@ -268,28 +286,19 @@ void dt_fini(void) nbs_destroy(dt.nbs); - connmgr_ae_destroy(dt.ae); + connmgr_ae_fini(AEID_DT); } int dt_start(void) { - enum pol_gam pg; - - if (rib_read(BOOT_PATH "/dt/gam/type", &pg, sizeof(pg)) - != sizeof(pg)) { - log_err("Failed to read policy for ribmgr gam."); - return -1; - } - dt.sdu_sched = sdu_sched_create(sdu_handler); if (dt.sdu_sched == NULL) { log_err("Failed to create N-1 SDU scheduler."); return -1; } - dt.gam = gam_create(pg, dt.nbs, dt.ae); - if (dt.gam == NULL) { - log_err("Failed to init dt graph adjacency manager."); + if (pthread_create(&dt.listener, NULL, dt_conn_handle, NULL)) { + log_err("Failed to create listener thread."); sdu_sched_destroy(dt.sdu_sched); return -1; } @@ -299,8 +308,8 @@ int dt_start(void) void dt_stop(void) { - gam_destroy(dt.gam); - + pthread_cancel(dt.listener); + pthread_join(dt.listener, NULL); sdu_sched_destroy(dt.sdu_sched); } diff --git a/src/ipcpd/normal/dt.h b/src/ipcpd/normal/dt.h index 99918ea5..09716153 100644 --- a/src/ipcpd/normal/dt.h +++ b/src/ipcpd/normal/dt.h @@ -23,13 +23,20 @@ #ifndef OUROBOROS_IPCPD_NORMAL_DT_H #define OUROBOROS_IPCPD_NORMAL_DT_H +#include <ouroboros/ipcp.h> #include <ouroboros/shm_rdrbuff.h> #include "dt_pci.h" +#define DT_AE "Data Transfer" +#define DT_PROTO "dtp" #define INVALID_ADDR 0 -int dt_init(void); +int dt_init(enum pol_routing pr, + uint8_t addr_size, + uint8_t fd_size, + bool has_ttl +); void dt_fini(void); diff --git a/src/ipcpd/normal/dt_pci.c b/src/ipcpd/normal/dt_pci.c index 9e6dfa89..5704a09a 100644 --- a/src/ipcpd/normal/dt_pci.c +++ b/src/ipcpd/normal/dt_pci.c @@ -44,19 +44,13 @@ struct { size_t fd_o; } dt_pci_info; -int dt_pci_init() +int dt_pci_init(uint8_t addr_size, + uint8_t fd_size, + bool has_ttl) { - /* read dt constants from the RIB */ - if (rib_read(BOOT_PATH "/dt/const/addr_size", - &dt_pci_info.addr_size, - sizeof(dt_pci_info.addr_size)) < 0 || - rib_read(BOOT_PATH "/dt/const/fd_size", - &dt_pci_info.fd_size, - sizeof(dt_pci_info.fd_size)) < 0 || - rib_read(BOOT_PATH "/dt/const/has_ttl", - &dt_pci_info.has_ttl, - sizeof(dt_pci_info.has_ttl)) < 0) - return -1; + dt_pci_info.addr_size = addr_size; + dt_pci_info.fd_size = fd_size; + dt_pci_info.has_ttl = has_ttl; dt_pci_info.qc_o = dt_pci_info.addr_size; dt_pci_info.ttl_o = dt_pci_info.qc_o + QOS_LEN; diff --git a/src/ipcpd/normal/dt_pci.h b/src/ipcpd/normal/dt_pci.h index 5f14527c..efb4d0c0 100644 --- a/src/ipcpd/normal/dt_pci.h +++ b/src/ipcpd/normal/dt_pci.h @@ -30,8 +30,6 @@ #include <stdint.h> #include <stdbool.h> -#define DT_PROTO "dt" - /* Abstract syntax */ enum dtp_fields { DTP_DST = 0, /* DST ADDRESS */ @@ -54,7 +52,9 @@ struct dt_pci { uint32_t fd; }; -int dt_pci_init(void); +int dt_pci_init(uint8_t addr_size, + uint8_t fd_size, + bool has_ttl); void dt_pci_fini(void); diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c index a33239a0..7f93ed3a 100644 --- a/src/ipcpd/normal/enroll.c +++ b/src/ipcpd/normal/enroll.c @@ -22,19 +22,19 @@ #define _POSIX_C_SOURCE 199309L -#define OUROBOROS_PREFIX "enrollment" +#define OUROBOROS_PREFIX "Enrollment" #include <ouroboros/endian.h> #include <ouroboros/errno.h> -#include <ouroboros/cdap.h> #include <ouroboros/time_utils.h> #include <ouroboros/dev.h> #include <ouroboros/logs.h> #include <ouroboros/rib.h> #include <ouroboros/errno.h> -#include "ae.h" #include "connmgr.h" +#include "enroll.h" +#include "ipcp.h" #include "ribconfig.h" #include <assert.h> @@ -42,302 +42,337 @@ #include <string.h> #include <pthread.h> -/* Symbolic, will return current time */ -#define TIME_NAME "localtime" -#define TIME_PATH DLR TIME_NAME +#include "enroll.pb-c.h" +typedef EnrollMsg enroll_msg_t; +typedef IpcpConfigMsg ipcp_config_msg_t; +typedef DifInfoMsg dif_info_msg_t; + +#define ENROLL_AE "Enrollment" +#define ENROLL_PROTO "OEP" /* Ouroboros enrollment protocol */ #define ENROLL_WARN_TIME_OFFSET 20 +#define ENROLL_BUF_LEN 1024 + +enum enroll_state { + ENROLL_NULL = 0, + ENROLL_INIT, + ENROLL_RUNNING +}; struct { - struct ae * ae; - struct cdap * cdap; - pthread_t listener; + struct ipcp_config conf; + enum enroll_state state; + pthread_t listener; } enroll; -static void * enroll_handle(void * o) +static int send_rcv_enroll_msg(int fd) { - struct cdap * cdap; - struct conn conn; - cdap_key_t key; - enum cdap_opcode oc; - char * name; - uint8_t * buf; - uint8_t * data; - ssize_t len; - uint32_t flags; + enroll_msg_t req = ENROLL_MSG__INIT; + enroll_msg_t * reply; + uint8_t buf[ENROLL_BUF_LEN]; + ssize_t len; + ssize_t delta_t; + struct timespec t0; + struct timespec rtt; - bool boot_r = false; - bool members_r = false; + req.code = ENROLL_CODE__ENROLL_REQ; - char * boot_ro = BOOT_PATH; - char * members_ro = MEMBERS_PATH; + len = enroll_msg__get_packed_size(&req); + if (len < 0) { + log_dbg("Failed pack request message."); + return -1; + } - cdap = (struct cdap *) o; + enroll_msg__pack(&req, buf); - assert(cdap); + clock_gettime(CLOCK_REALTIME, &t0); - while (true) { - if (connmgr_wait(enroll.ae, &conn)) { - log_err("Failed to get next connection."); - continue; - } + if (flow_write(fd, buf, len)) { + log_dbg("Failed to send request message."); + return -1; + } - if (cdap_add_flow(cdap, conn.flow_info.fd)) { - log_warn("Failed to add flow to CDAP."); - flow_dealloc(conn.flow_info.fd); - continue; - } + len = flow_read(fd, buf, ENROLL_BUF_LEN); + if (len < 0) { + log_dbg("No enrollment reply received."); + return -1; + } - while (!(boot_r && members_r)) { - key = cdap_request_wait(cdap, &oc, &name, &data, - (size_t *) &len , &flags); - assert(key >= 0); - assert(name); - - if (data != NULL) { - free(data); - log_warn("Received data with enroll request."); - } - - if (oc != CDAP_READ) { - log_warn("Invalid request."); - cdap_reply_send(cdap, key, -1, NULL, 0); - free(name); - continue; - } - - if (strcmp(name, boot_ro) == 0) { - boot_r = true; - } else if (strcmp(name, members_ro) == 0) { - members_r = true; - } else if (strcmp(name, TIME_PATH) == 0) { - struct timespec t; - uint64_t buf[2]; - clock_gettime(CLOCK_REALTIME, &t); - buf[0] = hton64(t.tv_sec); - buf[1] = hton64(t.tv_nsec); - cdap_reply_send(cdap, key, 0, buf, sizeof(buf)); - free(name); - continue; - } else { - log_warn("Illegal read: %s.", name); - cdap_reply_send(cdap, key, -1, NULL, 0); - free(name); - continue; - } - - len = rib_pack(name, &buf, PACK_HASH_ROOT); - if (len < 0) { - log_err("Failed to pack %s.", name); - cdap_reply_send(cdap, key, -1, NULL, 0); - free(name); - continue; - } - - log_dbg("Packed %s (%zu bytes).", name, len); - - free(name); - - if (cdap_reply_send(cdap, key, 0, buf, len)) { - log_err("Failed to send CDAP reply."); - free(buf); - continue; - } - - free(buf); - } + log_dbg("Received enrollment info (%zd bytes).", len); - log_dbg("Sent boot info to new member."); + reply = enroll_msg__unpack(NULL, len, buf); + if (reply == NULL) { + log_dbg("No enrollment response."); + return -1; + } - cdap_del_flow(cdap, conn.flow_info.fd); - flow_dealloc(conn.flow_info.fd); + if (reply->code != ENROLL_CODE__ENROLL_BOOT) { + log_dbg("Failed to unpack enrollment response."); + enroll_msg__free_unpacked(reply, NULL); + return -1; + } - boot_r = members_r = false; + if (!(reply->has_t_sec && reply->has_t_nsec)) { + log_dbg("No time in response message."); + enroll_msg__free_unpacked(reply, NULL); + return -1; } + clock_gettime(CLOCK_REALTIME, &rtt); + + delta_t = ts_diff_ms(&t0, &rtt); + + rtt.tv_sec = reply->t_sec; + rtt.tv_nsec = reply->t_nsec; + + if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET) + log_warn("Clock offset above threshold."); + + strcpy(enroll.conf.dif_info.dif_name, reply->conf->dif_info->dif_name); + enroll.conf.type = reply->conf->ipcp_type; + enroll.conf.addr_size = reply->conf->addr_size; + enroll.conf.fd_size = reply->conf->fd_size; + enroll.conf.has_ttl = reply->conf->has_ttl; + enroll.conf.addr_auth_type = reply->conf->addr_auth_type; + enroll.conf.routing_type = reply->conf->routing_type; + enroll.conf.dif_info.dir_hash_algo + = reply->conf->dif_info->dir_hash_algo; + + enroll_msg__free_unpacked(reply, NULL); + return 0; } -int enroll_boot(const char * dst) +static ssize_t enroll_pack(uint8_t ** buf) { - struct cdap * cdap; - cdap_key_t * key; - uint8_t * data; - size_t len; - struct conn conn; + enroll_msg_t msg = ENROLL_MSG__INIT; + ipcp_config_msg_t config = IPCP_CONFIG_MSG__INIT; + dif_info_msg_t dif_info = DIF_INFO_MSG__INIT; + struct timespec now; + ssize_t len; + + clock_gettime(CLOCK_REALTIME, &now); + + msg.code = ENROLL_CODE__ENROLL_BOOT; + msg.has_t_sec = true; + msg.t_sec = now.tv_sec; + msg.has_t_nsec = true; + msg.t_nsec = now.tv_nsec; + msg.conf = &config; + + config.ipcp_type = enroll.conf.type; + config.has_addr_size = true; + config.addr_size = enroll.conf.addr_size; + config.has_fd_size = true; + config.fd_size = enroll.conf.fd_size; + config.has_has_ttl = true; + config.has_ttl = enroll.conf.has_ttl; + config.has_addr_auth_type = true; + config.addr_auth_type = enroll.conf.addr_auth_type; + config.has_routing_type = true; + config.routing_type = enroll.conf.routing_type; + config.dif_info = &dif_info; + + dif_info.dif_name = (char *) enroll.conf.dif_info.dif_name; + dif_info.dir_hash_algo = enroll.conf.dif_info.dir_hash_algo; + + len = enroll_msg__get_packed_size(&msg); + + *buf = malloc(len); + if (*buf == NULL) + return -1; - struct timespec t0; - struct timespec rtt; + enroll_msg__pack(&msg, *buf); - ssize_t delta_t; + return len; +} - char * boot_ro = BOOT_PATH; - char * members_ro = MEMBERS_PATH; +static void * enroll_handle(void * o) +{ + struct conn conn; + uint8_t buf[ENROLL_BUF_LEN]; + uint8_t * reply; + ssize_t len; + enroll_msg_t * msg; - cdap = cdap_create(); - if (cdap == NULL) { - log_err("Failed to instantiate CDAP."); - return -1; - } + (void) o; - if (connmgr_alloc(enroll.ae, dst, NULL, &conn)) { - log_err("Failed to get connection."); - cdap_destroy(cdap); - return -1; - } + while (true) { + if (connmgr_wait(AEID_ENROLL, &conn)) { + log_err("Failed to get next connection."); + continue; + } - if (cdap_add_flow(cdap, conn.flow_info.fd)) { - log_warn("Failed to add flow to CDAP."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN); + if (len < 0) { + log_err("Failed to read from flow."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - log_dbg("Getting boot information from %s.", dst); + msg = enroll_msg__unpack(NULL, len, buf); + if (msg == NULL) { + log_err("Failed to unpack message."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - clock_gettime(CLOCK_REALTIME, &t0); + if (msg->code != ENROLL_CODE__ENROLL_REQ) { + log_err("Wrong message type."); + connmgr_dealloc(AEID_ENROLL, &conn); + enroll_msg__free_unpacked(msg, NULL); + continue; + } - key = cdap_request_send(cdap, CDAP_READ, TIME_PATH, NULL, 0, 0); - if (key == NULL || key[0] == INVALID_CDAP_KEY) { - log_err("Failed to send CDAP request."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + log_dbg("Enrolling a new neighbor."); - if (cdap_reply_wait(cdap, key[0], &data, &len)) { - log_err("Failed to get CDAP reply."); - free(key); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + enroll_msg__free_unpacked(msg, NULL); - free(key); + len = enroll_pack(&reply); + if (reply == NULL) { + log_err("Failed to pack enrollment message."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - clock_gettime(CLOCK_REALTIME, &rtt); + log_dbg("Sending enrollment info (%zd bytes).", len); - delta_t = ts_diff_ms(&t0, &rtt); + if (flow_write(conn.flow_info.fd, reply, len)) { + log_err("Failed respond to enrollment request."); + connmgr_dealloc(AEID_ENROLL, &conn); + free(reply); + continue; + } - assert(len == 2 * sizeof (uint64_t)); + free(reply); - rtt.tv_sec = ntoh64(((uint64_t *) data)[0]); - rtt.tv_nsec = ntoh64(((uint64_t *) data)[1]); + len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN); + if (len < 0) { + log_err("Failed to read from flow."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET) - log_warn("Clock offset above threshold."); + msg = enroll_msg__unpack(NULL, len, buf); + if (msg == NULL) { + log_err("Failed to unpack message."); + connmgr_dealloc(AEID_ENROLL, &conn); + continue; + } - free(data); + 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; + } - key = cdap_request_send(cdap, CDAP_READ, boot_ro, NULL, 0, 0); - if (key == NULL || key[0] == INVALID_CDAP_KEY) { - log_err("Failed to send CDAP request."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } + if (msg->result == 0) + log_dbg("Neighbor enrollment successful."); + else + log_dbg("Neigbor reported failed enrollment."); - if (cdap_reply_wait(cdap, key[0], &data, &len)) { - log_err("Failed to get CDAP reply."); - free(key); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; + connmgr_dealloc(AEID_ENROLL, &conn); } - free(key); + return 0; +} - log_dbg("Packed information received (%zu bytes).", len); +int enroll_boot(struct conn * conn, + const char * dst) +{ + log_dbg("Getting boot information from %s.", dst); - if (rib_unpack(data, len, UNPACK_CREATE)) { - log_warn("Error unpacking RIB data."); - rib_del(boot_ro); - free(data); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + if (send_rcv_enroll_msg(conn->flow_info.fd)) { + log_err("Failed to enroll."); return -1; } - log_dbg("Packed information inserted into RIB."); + return 0; +} - key = cdap_request_send(cdap, CDAP_READ, members_ro, NULL, 0, 0); - if (key == NULL || key[0] == INVALID_CDAP_KEY) { - log_err("Failed to send CDAP request."); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); - return -1; - } +int enroll_done(struct conn * conn, + int result) +{ + enroll_msg_t msg = ENROLL_MSG__INIT; + uint8_t buf[ENROLL_BUF_LEN]; + ssize_t len; - if (cdap_reply_wait(cdap, key[0], &data, &len)) { - log_err("Failed to get CDAP reply."); - free(key); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + msg.code = ENROLL_CODE__ENROLL_DONE; + msg.has_result = true; + msg.result = result; + + len = enroll_msg__get_packed_size(&msg); + if (len < 0) { + log_dbg("Failed pack request message."); return -1; } - free(key); - - log_dbg("Packed information received (%zu bytes).", len); + enroll_msg__pack(&msg, buf); - if (rib_unpack(data, len, UNPACK_CREATE)) { - log_warn("Error unpacking RIB data."); - rib_del(boot_ro); - free(data); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + if (flow_write(conn->flow_info.fd, buf, len)) { + log_dbg("Failed to send acknowledgment."); return -1; } - log_dbg("Packed information inserted into RIB."); + return 0; +} + +void enroll_bootstrap(const struct ipcp_config * conf) +{ + assert(conf); - cdap_destroy(cdap); - flow_dealloc(conn.flow_info.fd); + memcpy(&enroll.conf, conf, sizeof(enroll.conf)); +} - return 0; +struct ipcp_config * enroll_get_conf(void) +{ + return &enroll.conf; } int enroll_init(void) { struct conn_info info; - enroll.cdap = cdap_create(); - if (enroll.cdap == NULL) { - log_err("Failed to instantiate CDAP."); - return -1; - } - memset(&info, 0, sizeof(info)); strcpy(info.ae_name, ENROLL_AE); - strcpy(info.protocol, CDAP_PROTO); + strcpy(info.protocol, ENROLL_PROTO); info.pref_version = 1; info.pref_syntax = PROTO_GPB; + info.addr = 0; - enroll.ae = connmgr_ae_create(info); - if (enroll.ae == NULL) { - cdap_destroy(enroll.cdap); + if (connmgr_ae_init(AEID_ENROLL, &info, NULL)) { + log_err("Failed to register with connmgr."); return -1; } + enroll.state = ENROLL_INIT; + return 0; } void enroll_fini(void) { - pthread_join(enroll.listener, NULL); - cdap_destroy(enroll.cdap); - connmgr_ae_destroy(enroll.ae); + if (enroll.state == ENROLL_RUNNING) + pthread_join(enroll.listener, NULL); + + connmgr_ae_fini(AEID_ENROLL); } int enroll_start(void) { - if (pthread_create(&enroll.listener, NULL, enroll_handle, enroll.cdap)) + if (pthread_create(&enroll.listener, NULL, enroll_handle, NULL)) return -1; + enroll.state = ENROLL_RUNNING; + return 0; } void enroll_stop(void) { - pthread_cancel(enroll.listener); + if (enroll.state == ENROLL_RUNNING) + pthread_cancel(enroll.listener); + + enroll.state = ENROLL_INIT; } diff --git a/src/ipcpd/normal/enroll.h b/src/ipcpd/normal/enroll.h index 9b50f6bb..3b277e44 100644 --- a/src/ipcpd/normal/enroll.h +++ b/src/ipcpd/normal/enroll.h @@ -23,14 +23,26 @@ #ifndef OUROBOROS_IPCPD_NORMAL_ENROLL_H #define OUROBOROS_IPCPD_NORMAL_ENROLL_H -int enroll_init(void); +#include <ouroboros/ipcp.h> -void enroll_fini(void); +#include "ae.h" -int enroll_start(void); +int enroll_init(void); -void enroll_stop(void); +void enroll_fini(void); -int enroll_boot(const char * dst); +int enroll_start(void); + +void enroll_stop(void); + +void enroll_bootstrap(const struct ipcp_config * conf); + +int enroll_boot(struct conn * conn, + const char * dst); + +int enroll_done(struct conn * conn, + int result); + +struct ipcp_config * enroll_get_conf(void); #endif /* OUROBOROS_IPCPD_NORMAL_ENROLL_H */ diff --git a/src/ipcpd/normal/pol-gam-ops.h b/src/ipcpd/normal/enroll.proto index e63752c0..2347fb8f 100644 --- a/src/ipcpd/normal/pol-gam-ops.h +++ b/src/ipcpd/normal/enroll.proto @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * Graph adjacency manager policy ops + * Enrollment message * * Dimitri Staessens <dimitri.staessens@ugent.be> * Sander Vrijders <sander.vrijders@ugent.be> @@ -20,17 +20,20 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#ifndef OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H -#define OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H +syntax = "proto2"; -#include <ouroboros/cacep.h> -#include <ouroboros/qos.h> +import "ipcp_config.proto"; -struct pol_gam_ops { - void * (* create)(struct nbs * nbs, - struct ae * ae); - - void (* destroy)(void * o); +enum enroll_code { + ENROLL_REQ = 1; + ENROLL_BOOT = 2; + ENROLL_DONE = 4; }; -#endif /* OUROBOROS_IPCPD_NORMAL_POL_GAM_OPS_H */ +message enroll_msg { + required enroll_code code = 1; + optional ipcp_config_msg conf = 2; + optional int64 t_sec = 3; + optional uint32 t_nsec = 4; + optional int32 result = 5; +};
\ No newline at end of file diff --git a/src/ipcpd/normal/flow_alloc.proto b/src/ipcpd/normal/flow_alloc.proto index 717a1a81..eb078674 100644 --- a/src/ipcpd/normal/flow_alloc.proto +++ b/src/ipcpd/normal/flow_alloc.proto @@ -23,16 +23,16 @@ syntax = "proto2"; enum flow_alloc_code { - FLOW_REQ = 1; - FLOW_REPLY = 2; + FLOW_REQ = 1; + FLOW_REPLY = 2; }; message flow_alloc_msg { - required flow_alloc_code code = 1; - optional bytes hash = 2; - optional uint32 qc = 3; - optional sint32 response = 4; - optional uint32 r_fd = 5; - optional uint32 s_fd = 6; - optional uint64 s_addr = 7; + required flow_alloc_code code = 1; + optional bytes hash = 2; + optional uint32 qc = 3; + optional sint32 response = 4; + optional uint32 r_fd = 5; + optional uint32 s_fd = 6; + optional uint64 s_addr = 7; }; diff --git a/src/ipcpd/normal/gam.c b/src/ipcpd/normal/gam.c deleted file mode 100644 index 3b4cc5de..00000000 --- a/src/ipcpd/normal/gam.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Data transfer graph adjacency manager - * - * 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/. - */ - -#define _POSIX_C_SOURCE 200112L - -#define OUROBOROS_PREFIX "dt-gam" - -#include <ouroboros/cdap.h> -#include <ouroboros/dev.h> -#include <ouroboros/logs.h> -#include <ouroboros/list.h> -#include <ouroboros/errno.h> -#include <ouroboros/rib.h> - -#include "ipcp.h" -#include "gam.h" -#include "pol-gam-ops.h" -#include "pol/complete.h" - -#include <assert.h> -#include <stdlib.h> -#include <pthread.h> -#include <string.h> - -struct gam { - struct pol_gam_ops * ops; - void * ops_o; -}; - -struct gam * gam_create(enum pol_gam gam_type, - struct nbs * nbs, - struct ae * ae) -{ - struct gam * gam; - - gam = malloc(sizeof(*gam)); - if (gam == NULL) - return NULL; - - switch (gam_type) { - case COMPLETE: - gam->ops = &complete_ops; - break; - default: - log_err("Unknown gam policy: %d.", gam_type); - return NULL; - } - - gam->ops_o = gam->ops->create(nbs, ae); - if (gam->ops_o == NULL) { - free(gam); - return NULL; - } - - return gam; -} - -void gam_destroy(struct gam * gam) -{ - assert(gam); - - gam->ops->destroy(gam->ops_o); - free(gam); -} diff --git a/src/ipcpd/normal/gam.h b/src/ipcpd/normal/gam.h deleted file mode 100644 index 3dd01a75..00000000 --- a/src/ipcpd/normal/gam.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Data transfer graph adjacency manager - * - * 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/. - */ - -#ifndef OUROBOROS_IPCPD_NORMAL_GAM_H -#define OUROBOROS_IPCPD_NORMAL_GAM_H - -#include <ouroboros/ipcp.h> -#include <ouroboros/cacep.h> - -#include "neighbors.h" - -struct gam * gam_create(enum pol_gam gam_type, - struct nbs * nbs, - struct ae * ae); - -void gam_destroy(struct gam * gam); - -#endif /* OUROBOROS_IPCPD_NORMAL_GAM_H */ diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index 53762415..0a41f883 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -54,50 +54,25 @@ #define THIS_TYPE IPCP_NORMAL -static int boot_components(void) +static int initialize_components(const struct ipcp_config * conf) { - char buf[256]; - ssize_t len; - enum pol_addr_auth pa; - char path[RIB_MAX_PATH_LEN + 1]; - - len = rib_read(BOOT_PATH "/general/dif_name", buf, 256); - if (len < 0) { - log_err("Failed to read DIF name: %zd.", len); - return -1; + if (rib_init()) { + log_err("Failed to initialize RIB."); + goto fail_rib_init; } - ipcpi.dif_name = strdup(buf); + ipcpi.dif_name = strdup(conf->dif_info.dif_name); if (ipcpi.dif_name == NULL) { log_err("Failed to set DIF name."); - return -1; + goto fail_dif_name; } - len = rib_read(BOOT_PATH "/general/dir_hash_algo", - &ipcpi.dir_hash_algo, sizeof(ipcpi.dir_hash_algo)); - if (len < 0) { - log_err("Failed to read hash length: %zd.", len); - goto fail_addr_auth; - } - - ipcpi.dir_hash_algo = ntoh32(ipcpi.dir_hash_algo); + ipcpi.dir_hash_algo = conf->dif_info.dir_hash_algo; assert(ipcp_dir_hash_len() != 0); - if (rib_add(MEMBERS_PATH, ipcpi.name)) { - log_err("Failed to add name to " MEMBERS_PATH); - goto fail_addr_auth; - } - - log_dbg("Starting components."); - - if (rib_read(BOOT_PATH "/dt/addr_auth/type", &pa, sizeof(pa)) - != sizeof(pa)) { - log_err("Failed to read policy for address authority."); - goto fail_addr_auth; - } - - if (addr_auth_init(pa)) { + if (addr_auth_init(conf->addr_auth_type, + &conf->addr_size)) { log_err("Failed to init address authority."); goto fail_addr_auth; } @@ -105,40 +80,84 @@ static int boot_components(void) ipcpi.dt_addr = addr_auth_address(); if (ipcpi.dt_addr == 0) { log_err("Failed to get a valid address."); - goto fail_dir; - } - - path[0] = '\0'; - rib_path_append(rib_path_append(path, MEMBERS_NAME), ipcpi.name); - if (rib_write(path, &ipcpi.dt_addr, sizeof(&ipcpi.dt_addr))) { - log_err("Failed to write address to member object."); - goto fail_dir; + goto fail_addr_auth; } log_dbg("IPCP got address %" PRIu64 ".", ipcpi.dt_addr); - log_dbg("Starting ribmgr."); - if (ribmgr_init()) { log_err("Failed to initialize RIB manager."); goto fail_ribmgr; } - log_dbg("Ribmgr started."); - - if (dt_init()) { - log_err("Failed to initialize data transfer ae."); + if (dt_init(conf->routing_type, + conf->addr_size, + conf->fd_size, + conf->has_ttl)) { + log_err("Failed to initialize data transfer component."); goto fail_dt; } if (fa_init()) { - log_err("Failed to initialize flow allocator ae."); + log_err("Failed to initialize flow allocator component."); goto fail_fa; } - if (dt_start()) { - log_err("Failed to start data transfer ae."); - goto fail_dt_start; + if (dir_init()) { + log_err("Failed to initialize directory."); + goto fail_dir; + } + + ipcp_set_state(IPCP_INIT); + + return 0; + + fail_dir: + fa_fini(); + fail_fa: + dt_fini(); + fail_dt: + ribmgr_fini(); + fail_ribmgr: + addr_auth_fini(); + fail_addr_auth: + free(ipcpi.dif_name); + fail_dif_name: + rib_fini(); + fail_rib_init: + return -1; +} + +static void finalize_components(void) +{ + dir_fini(); + + fa_fini(); + + dt_fini(); + + ribmgr_fini(); + + addr_auth_fini(); + + free(ipcpi.dif_name); + + enroll_fini(); + + connmgr_fini(); + + rib_fini(); +} + +static int start_components(void) +{ + assert(ipcp_get_state() == IPCP_INIT); + + ipcp_set_state(IPCP_OPERATIONAL); + + if (ribmgr_start()) { + log_err("Failed to start RIB manager."); + goto fail_ribmgr_start; } if (fa_start()) { @@ -146,20 +165,12 @@ static int boot_components(void) goto fail_fa_start; } - if (dir_init()) { - log_err("Failed to initialize directory."); - goto fail_dir; - } - if (enroll_start()) { - log_err("Failed to start enroll."); + log_err("Failed to start enrollment."); goto fail_enroll_start; } - ipcp_set_state(IPCP_OPERATIONAL); - if (connmgr_start()) { - ipcp_set_state(IPCP_INIT); log_err("Failed to start AP connection manager."); goto fail_connmgr_start; } @@ -169,184 +180,163 @@ static int boot_components(void) fail_connmgr_start: enroll_stop(); fail_enroll_start: - dir_fini(); - fail_dir: fa_stop(); fail_fa_start: - dt_stop(); - fail_dt_start: - fa_fini(); - fail_fa: - dt_fini(); - fail_dt: - ribmgr_fini(); - fail_ribmgr: - addr_auth_fini(); - fail_addr_auth: - free(ipcpi.dif_name); - + ribmgr_stop(); + fail_ribmgr_start: + ipcp_set_state(IPCP_INIT); return -1; } -void shutdown_components(void) +static void stop_components(void) { + assert(ipcp_get_state() == IPCP_OPERATIONAL || + ipcp_get_state() == IPCP_SHUTDOWN); + connmgr_stop(); enroll_stop(); - dir_fini(); - fa_stop(); - dt_stop(); + ribmgr_stop(); - fa_fini(); + ipcp_set_state(IPCP_INIT); +} - dt_fini(); +static int bootstrap_components(void) +{ + if (dir_bootstrap()) { + log_err("Failed to bootstrap directory."); + dt_stop(); + return -1; + } - ribmgr_fini(); + return 0; +} - addr_auth_fini(); +static int enroll_components(uint64_t peer) +{ + if (dir_enroll(peer)) { + log_err("Failed to enroll directory."); + return -1; + } - free(ipcpi.dif_name); + return 0; } static int normal_ipcp_enroll(const char * dst, struct dif_info * info) { - if (rib_add(RIB_ROOT, MEMBERS_NAME)) { - log_err("Failed to create members."); - return -1; + struct conn er_conn; + struct conn dt_conn; + + if (connmgr_alloc(AEID_ENROLL, dst, NULL, &er_conn)) { + log_err("Failed to get connection."); + goto fail_er_flow; } - /* Get boot state from peer */ - if (enroll_boot(dst)) { - log_err("Failed to boot IPCP components."); - return -1; + /* Get boot state from peer. */ + if (enroll_boot(&er_conn, dst)) { + log_err("Failed to get boot information."); + goto fail_enroll_boot; } - if (boot_components()) { - log_err("Failed to boot IPCP components."); - return -1; + if (initialize_components(enroll_get_conf())) { + log_err("Failed to initialize IPCP components."); + goto fail_enroll_boot; + } + + if (dt_start()) { + log_err("Failed to initialize IPCP components."); + goto fail_dt_start; + } + + if (connmgr_alloc(AEID_DT, dst, NULL, &dt_conn)) { + log_err("Failed to create a data transfer flow."); + goto fail_dt_flow; + } + + if (start_components()) { + log_err("Failed to start components."); + goto fail_start_comp; + } + + 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, 0)) + log_warn("Failed to confirm enrollment with peer."); + + if (connmgr_dealloc(AEID_DT, &dt_conn)) + log_warn("Failed to deallocate data transfer flow."); + + if (connmgr_dealloc(AEID_ENROLL, &er_conn)) + log_warn("Failed to deallocate enrollment flow."); + log_dbg("Enrolled with %s.", dst); info->dir_hash_algo = ipcpi.dir_hash_algo; strcpy(info->dif_name, ipcpi.dif_name); return 0; -} - -const struct ros { - char * parent; - char * child; -} ros[] = { - /* BOOT INFO */ - {RIB_ROOT, BOOT_NAME}, - /* OTHER RIB STRUCTURES */ - {RIB_ROOT, MEMBERS_NAME}, - - /* GENERAL IPCP INFO */ - {BOOT_PATH, "general"}, - - {BOOT_PATH "/general", "dif_name"}, - {BOOT_PATH "/general", "dir_hash_algo"}, - - /* DT COMPONENT */ - {BOOT_PATH, "dt"}, - - {BOOT_PATH "/dt", "gam"}, - {BOOT_PATH "/dt/gam", "type"}, - {BOOT_PATH "/dt/gam", "cacep"}, - {BOOT_PATH "/dt", "const"}, - {BOOT_PATH "/dt/const", "addr_size"}, - {BOOT_PATH "/dt/const", "fd_size"}, - {BOOT_PATH "/dt/const", "has_ttl"}, - {BOOT_PATH "/dt", "addr_auth"}, - {BOOT_PATH "/dt/addr_auth", "type"}, - {BOOT_PATH "/dt", "routing"}, - {BOOT_PATH "/dt/routing", "type"}, - - /* RIB MGR COMPONENT */ - {BOOT_PATH, "rm"}, - {BOOT_PATH "/rm","gam"}, - {BOOT_PATH "/rm/gam", "type"}, - {BOOT_PATH "/rm/gam", "cacep"}, - - {NULL, NULL} -}; -int normal_rib_init(void) -{ - struct ros * r; - - for (r = (struct ros *) ros; r->parent; ++r) { - if (rib_add(r->parent, r->child)) { - log_err("Failed to create %s/%s", - r->parent, r->child); - return -1; - } - } - - return 0; + fail_enroll_comp: + stop_components(); + fail_start_comp: + connmgr_dealloc(AEID_DT, &dt_conn); + fail_dt_flow: + dt_stop(); + fail_dt_start: + finalize_components(); + fail_enroll_boot: + connmgr_dealloc(AEID_ENROLL, &er_conn); + fail_er_flow: + return -1; } static int normal_ipcp_bootstrap(const struct ipcp_config * conf) { - uint32_t hash_algo; - assert(conf); assert(conf->type == THIS_TYPE); - hash_algo = hton32((uint32_t) conf->dif_info.dir_hash_algo); + enroll_bootstrap(conf); - assert(ntoh32(hash_algo) != 0); - - if (normal_rib_init()) { - log_err("Failed to write initial structure to the RIB."); - return -1; + if (initialize_components(conf)) { + log_err("Failed to init IPCP components."); + goto fail_init; } - if (rib_write(BOOT_PATH "/general/dif_name", - conf->dif_info.dif_name, - strlen(conf->dif_info.dif_name) + 1) || - rib_write(BOOT_PATH "/general/dir_hash_algo", - &hash_algo, - sizeof(hash_algo)) || - rib_write(BOOT_PATH "/dt/const/addr_size", - &conf->addr_size, - sizeof(conf->addr_size)) || - rib_write(BOOT_PATH "/dt/const/fd_size", - &conf->fd_size, - sizeof(conf->fd_size)) || - rib_write(BOOT_PATH "/dt/const/has_ttl", - &conf->has_ttl, - sizeof(conf->has_ttl)) || - rib_write(BOOT_PATH "/dt/gam/type", - &conf->dt_gam_type, - sizeof(conf->dt_gam_type)) || - rib_write(BOOT_PATH "/rm/gam/type", - &conf->rm_gam_type, - sizeof(conf->rm_gam_type)) || - rib_write(BOOT_PATH "/dt/addr_auth/type", - &conf->addr_auth_type, - sizeof(conf->addr_auth_type)) || - rib_write(BOOT_PATH "/dt/routing/type", - &conf->routing_type, - sizeof(conf->routing_type))) { - log_err("Failed to write boot info to RIB."); - return -1; + if (dt_start()) { + log_err("Failed to initialize IPCP components."); + goto fail_dt_start; + }; + + if (start_components()) { + log_err("Failed to init IPCP components."); + goto fail_start; } - if (boot_components()) { - log_err("Failed to boot IPCP components."); - return -1; + if (bootstrap_components()) { + log_err("Failed to bootstrap IPCP components."); + goto fail_bootstrap; } log_dbg("Bootstrapped in DIF %s.", conf->dif_info.dif_name); return 0; + + fail_bootstrap: + stop_components(); + fail_start: + dt_stop(); + fail_dt_start: + finalize_components(); + fail_init: + return -1; } static int normal_ipcp_query(const uint8_t * dst) @@ -357,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, @@ -378,18 +370,14 @@ int main(int argc, goto fail_bind_api; } - if (rib_init()) { - log_err("Failed to initialize RIB."); - goto fail_rib_init; - } - + /* These components must be init at creation. */ if (connmgr_init()) { log_err("Failed to initialize connection manager."); goto fail_connmgr_init; } if (enroll_init()) { - log_err("Failed to initialize enroll component."); + log_err("Failed to initialize enrollment component."); goto fail_enroll_init; } @@ -406,14 +394,10 @@ int main(int argc, ipcp_shutdown(); - if (ipcp_get_state() == IPCP_SHUTDOWN) - shutdown_components(); - - enroll_fini(); - - connmgr_fini(); - - rib_fini(); + if (ipcp_get_state() == IPCP_SHUTDOWN) { + dt_stop(); + stop_components(); + } irm_unbind_api(getpid(), ipcpi.name); @@ -428,8 +412,6 @@ int main(int argc, fail_enroll_init: connmgr_fini(); fail_connmgr_init: - rib_fini(); - fail_rib_init: irm_unbind_api(getpid(), ipcpi.name); fail_bind_api: ipcp_fini(); diff --git a/src/ipcpd/normal/neighbors.c b/src/ipcpd/normal/neighbors.c index 5da0f0df..c32e9aa2 100644 --- a/src/ipcpd/normal/neighbors.c +++ b/src/ipcpd/normal/neighbors.c @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * Data transfer neighbors + * Neighbors * * Dimitri Staessens <dimitri.staessens@ugent.be> * Sander Vrijders <sander.vrijders@ugent.be> diff --git a/src/ipcpd/normal/neighbors.h b/src/ipcpd/normal/neighbors.h index 7047d027..9c5a6e50 100644 --- a/src/ipcpd/normal/neighbors.h +++ b/src/ipcpd/normal/neighbors.h @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * Data transfer neighbors + * Neighbors * * Dimitri Staessens <dimitri.staessens@ugent.be> * Sander Vrijders <sander.vrijders@ugent.be> @@ -29,7 +29,7 @@ #include <ouroboros/fqueue.h> #include <ouroboros/cacep.h> -#include "connmgr.h" +#include "ae.h" enum nb_event { NEIGHBOR_ADDED, @@ -40,14 +40,14 @@ enum nb_event { typedef int (* nb_notify_t)(enum nb_event event, struct conn conn); -struct nb_notifier { +struct nb { struct list_head next; - nb_notify_t notify_call; + struct conn conn; }; -struct nb { +struct nb_notifier { struct list_head next; - struct conn conn; + nb_notify_t notify_call; }; struct nbs { diff --git a/src/ipcpd/normal/pol-addr-auth-ops.h b/src/ipcpd/normal/pol-addr-auth-ops.h index a3b39298..5d90c64f 100644 --- a/src/ipcpd/normal/pol-addr-auth-ops.h +++ b/src/ipcpd/normal/pol-addr-auth-ops.h @@ -24,7 +24,7 @@ #define OUROBOROS_IPCPD_NORMAL_POL_ADDR_AUTH_OPS_H struct pol_addr_auth_ops { - int (* init)(void); + int (* init)(const void * info); int (* fini)(void); diff --git a/src/ipcpd/normal/pol/complete.c b/src/ipcpd/normal/pol/complete.c deleted file mode 100644 index 6c6e7372..00000000 --- a/src/ipcpd/normal/pol/complete.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Sets up a complete graph - * - * 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/. - */ - -#define _POSIX_C_SOURCE 200112L - -#define OUROBOROS_PREFIX "complete" - -#include <ouroboros/qoscube.h> -#include <ouroboros/rib.h> -#include <ouroboros/dev.h> -#include <ouroboros/logs.h> -#include <ouroboros/errno.h> -#include <ouroboros/cacep.h> - -#include "neighbors.h" -#include "ribconfig.h" -#include "ipcp.h" -#include "ae.h" - -#include <string.h> -#include <stdlib.h> -#include <assert.h> - -#define COMPLETE_REFRESH 1000 /* ms */ - -struct complete { - struct nbs * nbs; - struct ae * ae; - pthread_t allocator; - pthread_t listener; -}; - -static void * listener(void * o) -{ - struct complete * complete; - struct conn conn; - - complete = (struct complete *) o; - - while (true) { - if (connmgr_wait(complete->ae, &conn)) { - log_err("Error while getting next connection."); - continue; - } - - if (nbs_add(complete->nbs, conn)) { - log_err("Failed to add neighbor."); - continue; - } - } - - return (void *) 0; -} - -static void path_reset(char * path) -{ - path[strlen(MEMBERS_PATH)] = '\0'; -} - -static void * allocator(void * o) -{ - qosspec_t qs; - ssize_t len; - char ** children; - ssize_t i; - struct complete * complete; - struct conn conn; - uint64_t addr; - char path[RIB_MAX_PATH_LEN]; - struct timespec to = {(COMPLETE_REFRESH / 1000), - (COMPLETE_REFRESH % 1000) * 1000000}; - - strcpy(path, MEMBERS_PATH); - - complete = (struct complete *) o; - - qosspec_init(&qs); - - while (true) { - len = rib_children(MEMBERS_PATH, &children); - for (i = 0; i < len; ++i) { - if (strcmp(children[i], ipcpi.name) != 0) { - path_reset(path); - rib_path_append(path, children[i]); - if (rib_read(path, &addr, - sizeof(addr)) != - sizeof(addr)) { - log_err("Failed to read address."); - free(children[i]); - continue; - } - - if (nbs_has(complete->nbs, addr)) { - free(children[i]); - continue; - } - - if (connmgr_alloc(complete->ae, children[i], - &qs, &conn)) { - log_warn("Failed conn to neighbor."); - free(children[i]); - continue; - } - - if (nbs_add(complete->nbs, conn)) { - log_err("Failed to add neighbor."); - free(children[i]); - continue; - } - } - - free(children[i]); - } - - if (len > 0) - free(children); - - nanosleep(&to, NULL); - } - - return (void *) 0; -} - -void * complete_create(struct nbs * nbs, - struct ae * ae) -{ - struct complete * complete; - - complete = malloc(sizeof(*complete)); - if (complete == NULL) - return NULL; - - complete->nbs = nbs; - complete->ae = ae; - - if (pthread_create(&complete->allocator, NULL, - allocator, (void *) complete)) - return NULL; - - if (pthread_create(&complete->listener, NULL, - listener, (void *) complete)) - return NULL; - - return complete; -} - -void complete_destroy(void * ops_o) -{ - struct complete * complete; - - assert(ops_o); - - complete = (struct complete *) ops_o; - - pthread_cancel(complete->allocator); - pthread_cancel(complete->listener); - pthread_join(complete->allocator, NULL); - pthread_join(complete->listener, NULL); - - free(complete); -} diff --git a/src/ipcpd/normal/pol/complete.h b/src/ipcpd/normal/pol/complete.h deleted file mode 100644 index 54c4a9ef..00000000 --- a/src/ipcpd/normal/pol/complete.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2017 - * - * Sets up a complete graph - * - * 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/. - */ - -#ifndef OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H -#define OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H - -#include <ouroboros/ipcp.h> -#include <ouroboros/qos.h> - -#include "pol-gam-ops.h" - -void * complete_create(struct nbs * nbs, - struct ae * ae); - -void complete_destroy(void * ops_o); - -struct pol_gam_ops complete_ops = { - .create = complete_create, - .destroy = complete_destroy -}; - -#endif /* OUROBOROS_IPCPD_NORMAL_POL_COMPLETE_H */ diff --git a/src/ipcpd/normal/pol/flat.c b/src/ipcpd/normal/pol/flat.c index 1fece07f..7a5a785e 100644 --- a/src/ipcpd/normal/pol/flat.c +++ b/src/ipcpd/normal/pol/flat.c @@ -42,47 +42,21 @@ #define NAME_LEN 8 #define REC_DIF_SIZE 10000 -/* convert 32 bit addr to a hex string */ -static void addr_name(char * name, - uint32_t addr) -{ - sprintf(name, "%8x", (uint32_t) (addr)); -} - -static int addr_taken(char * name, - char ** members, - size_t len) -{ - size_t i; - char path[RIB_MAX_PATH_LEN + 1]; - - size_t reset; - strcpy(path, MEMBERS_PATH); - - reset = strlen(path); - - for (i = 0; i < len; ++i) { - ssize_t j; - ssize_t c; - char ** addrs; - rib_path_append(path, members[i]); - c = rib_children(path, &addrs); - for (j = 0; j < c; ++j) - if (strcmp(addrs[j], name) == 0) { - freepp(char, addrs, c); - return 1; - } - freepp(char, addrs, c); - path[reset] = '\0'; - } - - return 0; -} +struct { + uint8_t addr_size; +} flat; #define INVALID_ADDRESS 0 -int flat_init(void) +int flat_init(const void * info) { + flat.addr_size = *((uint8_t *) info); + + if (flat.addr_size != 4) { + log_err("Flat address policy mandates 4 byte addresses."); + return -1; + } + return 0; } @@ -94,66 +68,12 @@ int flat_fini(void) uint64_t flat_address(void) { struct timespec t; - - char path[RIB_MAX_PATH_LEN]; - char name[NAME_LEN + 1]; - uint32_t addr; - uint8_t addr_size; - - char ** members; - ssize_t n_members; - - strcpy(path, MEMBERS_PATH); - - if (!rib_has(path)) { - log_err("Could not read members from RIB."); - return INVALID_ADDRESS; - } - - if (rib_read("/" BOOT_NAME "/dt/const/addr_size", - &addr_size, sizeof(addr_size)) != sizeof(addr_size)) { - log_err("Failed to read address size."); - return INVALID_ADDRESS; - } - - if (addr_size != 4) { - log_err("Flat address policy mandates 4 byte addresses."); - return INVALID_ADDRESS; - } - - n_members = rib_children(path, &members); - if (n_members > REC_DIF_SIZE) - log_warn("DIF exceeding recommended size for flat addresses."); - - rib_path_append(path, ipcpi.name); - - if (!rib_has(path)) { - log_err("This ipcp is not a member."); - freepp(char, members, n_members); - return INVALID_ADDRESS; - } + uint32_t addr; clock_gettime(CLOCK_REALTIME, &t); srand(t.tv_nsec); - assert(n_members > 0); - - do { - addr = (rand() % (RAND_MAX - 1) + 1) & 0xFFFFFFFF; - addr_name(name, addr); - } while (addr_taken(name, members, n_members)); - - freepp(char, members, n_members); - - if (rib_add(path, name)) { - log_err("Failed to add address to RIB."); - return INVALID_ADDRESS; - } - - if (rib_write(path, &addr, sizeof(addr))) { - log_err("Failed to write address in RIB."); - return INVALID_ADDRESS; - } + addr = (rand() % (RAND_MAX - 1) + 1) & 0xFFFFFFFF; return addr; } diff --git a/src/ipcpd/normal/pol/flat.h b/src/ipcpd/normal/pol/flat.h index af49d283..57af591e 100644 --- a/src/ipcpd/normal/pol/flat.h +++ b/src/ipcpd/normal/pol/flat.h @@ -25,8 +25,10 @@ #include "pol-addr-auth-ops.h" -int flat_init(void); +int flat_init(const void * info); + int flat_fini(void); + uint64_t flat_address(void); struct pol_addr_auth_ops flat_ops = { diff --git a/src/ipcpd/normal/pol/link_state.c b/src/ipcpd/normal/pol/link_state.c index 9dfed5c0..512ced7f 100644 --- a/src/ipcpd/normal/pol/link_state.c +++ b/src/ipcpd/normal/pol/link_state.c @@ -130,10 +130,6 @@ static int link_state_neighbor_event(enum nb_event event, size_t len; uint8_t * data; - /* Only announce the flow if our address is bigger */ - if (ipcpi.dt_addr < conn.conn_info.addr) - return 0; - path[0] = '\0'; sprintf(fso_name, "%" PRIu64 "-%" PRIu64, ipcpi.dt_addr, conn.conn_info.addr); @@ -305,42 +301,42 @@ int link_state_init(struct nbs * nbs) { link_state.graph = graph_create(); if (link_state.graph == NULL) - return -1; + goto fail_graph; - if (rib_add(RIB_ROOT, ROUTING_NAME)) { - graph_destroy(link_state.graph); - return -1; - } + if (rib_add(RIB_ROOT, ROUTING_NAME)) + goto fail_rib_add; link_state.nbs = nbs; link_state.nb_notifier.notify_call = link_state_neighbor_event; - if (nbs_reg_notifier(link_state.nbs, &link_state.nb_notifier)) { - graph_destroy(link_state.graph); - rib_del(ROUTING_PATH); - return -1; - } + if (nbs_reg_notifier(link_state.nbs, &link_state.nb_notifier)) + goto fail_nbs_reg_notifier; link_state.set = ro_set_create(); - if (link_state.set == NULL) { - nbs_unreg_notifier(link_state.nbs, &link_state.nb_notifier); - graph_destroy(link_state.graph); - rib_del(ROUTING_PATH); - return -1; - } + if (link_state.set == NULL) + goto fail_ro_set_create; link_state.queue = rqueue_create(); - if (link_state.queue == NULL) { - ro_set_destroy(link_state.set); - nbs_unreg_notifier(link_state.nbs, &link_state.nb_notifier); - graph_destroy(link_state.graph); - rib_del(ROUTING_PATH); - return -1; - } + if (link_state.queue == NULL) + goto fail_rqueue_create; - pthread_create(&link_state.rib_listener, NULL, rib_listener, NULL); + if (pthread_create(&link_state.rib_listener, NULL, rib_listener, NULL)) + goto fail_listener_create; return 0; + + fail_listener_create: + ro_set_destroy(link_state.set); + fail_rqueue_create: + ro_set_destroy(link_state.set); + fail_ro_set_create: + nbs_unreg_notifier(link_state.nbs, &link_state.nb_notifier); + fail_nbs_reg_notifier: + rib_del(ROUTING_PATH); + fail_rib_add: + graph_destroy(link_state.graph); + fail_graph: + return -1; } void link_state_fini(void) diff --git a/src/ipcpd/normal/ribconfig.h b/src/ipcpd/normal/ribconfig.h index 3a9b6ecb..f6d10133 100644 --- a/src/ipcpd/normal/ribconfig.h +++ b/src/ipcpd/normal/ribconfig.h @@ -27,11 +27,7 @@ #define RIB_MAX_PATH_LEN 256 #define DLR "/" -#define BOOT_NAME "boot" -#define MEMBERS_NAME "members" #define ROUTING_NAME "fsdb" -#define BOOT_PATH DLR BOOT_NAME -#define MEMBERS_PATH DLR MEMBERS_NAME #define ROUTING_PATH DLR ROUTING_NAME #endif /* OUROBOROS_IPCPD_NORMAL_RIB_CONFIG_H */ diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c index ab2aa430..a5e7d6ce 100644 --- a/src/ipcpd/normal/ribmgr.c +++ b/src/ipcpd/normal/ribmgr.c @@ -35,10 +35,11 @@ #include <ouroboros/rib.h> #include "ae.h" -#include "gam.h" +#include "connmgr.h" +#include "ipcp.h" +#include "neighbors.h" #include "ribconfig.h" #include "ribmgr.h" -#include "ipcp.h" #include <stdlib.h> #include <pthread.h> @@ -46,10 +47,12 @@ #include <errno.h> #include <assert.h> +#define MGMT_AE "Management" #define RIB_SYNC_TIMEOUT 1 enum ribmgr_state { RIBMGR_NULL = 0, + RIBMGR_INIT, RIBMGR_OPERATIONAL, RIBMGR_SHUTDOWN }; @@ -60,7 +63,6 @@ struct { pthread_t reader; pthread_t sync; - struct gam * gam; struct nbs * nbs; struct ae * ae; @@ -300,9 +302,8 @@ static void * sync_rib(void *o) rib_path_append(path, children[--ch]); free(children[ch]); - /* Only sync fsdb and members */ - if (strcmp(path, MEMBERS_PATH) == 0 - || strcmp(path, ROUTING_PATH) == 0) + /* Sync fsdb */ + if (strcmp(path, ROUTING_PATH) == 0) ribmgr_sync(path); } @@ -314,7 +315,6 @@ static void * sync_rib(void *o) int ribmgr_init(void) { - enum pol_gam pg; struct conn_info info; memset(&info, 0, sizeof(info)); @@ -323,82 +323,90 @@ int ribmgr_init(void) strcpy(info.protocol, CDAP_PROTO); info.pref_version = 1; info.pref_syntax = PROTO_GPB; - /* NOTE: Use the same name as the DT AE of this IPCP */ - info.addr = ipcpi.dt_addr; + info.addr = 0; ribmgr.nbs = nbs_create(); if (ribmgr.nbs == NULL) { log_err("Failed to create neighbors."); - return -1; - } - - ribmgr.ae = connmgr_ae_create(info); - if (ribmgr.ae == NULL) { - log_err("Failed to create AE struct."); - nbs_destroy(ribmgr.nbs); - return -1; + goto fail_nbs_create; } - if (rib_read(BOOT_PATH "/rm/gam/type", &pg, sizeof(pg)) - != sizeof(pg)) { - log_err("Failed to read policy for ribmgr gam."); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; - } + if (connmgr_ae_init(AEID_MGMT, &info, ribmgr.nbs)) { + log_err("Failed to register with connmgr."); + goto fail_connmgr_ae_init; + }; ribmgr.cdap = cdap_create(); if (ribmgr.cdap == NULL) { log_err("Failed to create CDAP instance."); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; + goto fail_cdap_create; } ribmgr.nb_notifier.notify_call = ribmgr_neighbor_event; if (nbs_reg_notifier(ribmgr.nbs, &ribmgr.nb_notifier)) { log_err("Failed to register notifier."); - cdap_destroy(ribmgr.cdap); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; + goto fail_nbs_reg_notifier; } - ribmgr.gam = gam_create(pg, ribmgr.nbs, ribmgr.ae); - if (ribmgr.gam == NULL) { - log_err("Failed to create gam."); - nbs_unreg_notifier(ribmgr.nbs, &ribmgr.nb_notifier); - cdap_destroy(ribmgr.cdap); - connmgr_ae_destroy(ribmgr.ae); - nbs_destroy(ribmgr.nbs); - return -1; + if (pthread_rwlock_init(&ribmgr.state_lock, NULL)) { + log_err("Failed to init rwlock."); + goto fail_rwlock_init; } - pthread_rwlock_init(&ribmgr.state_lock, NULL); - - ribmgr.state = RIBMGR_OPERATIONAL; - - pthread_create(&ribmgr.sync, NULL, sync_rib, NULL); - - pthread_create(&ribmgr.reader, NULL, reader, NULL); + ribmgr.state = RIBMGR_INIT; return 0; + + fail_rwlock_init: + nbs_unreg_notifier(ribmgr.nbs, &ribmgr.nb_notifier); + fail_nbs_reg_notifier: + cdap_destroy(ribmgr.cdap); + fail_cdap_create: + connmgr_ae_fini(AEID_MGMT); + fail_connmgr_ae_init: + nbs_destroy(ribmgr.nbs); + fail_nbs_create: + return -1; } void ribmgr_fini(void) { - ribmgr_set_state(RIBMGR_SHUTDOWN); - - pthread_cancel(ribmgr.reader); - - pthread_join(ribmgr.reader, NULL); - pthread_join(ribmgr.sync, NULL); + if (ribmgr_get_state() == RIBMGR_SHUTDOWN) { + pthread_join(ribmgr.reader, NULL); + pthread_join(ribmgr.sync, NULL); + } nbs_unreg_notifier(ribmgr.nbs, &ribmgr.nb_notifier); cdap_destroy(ribmgr.cdap); - gam_destroy(ribmgr.gam); - connmgr_ae_destroy(ribmgr.ae); nbs_destroy(ribmgr.nbs); + + connmgr_ae_fini(AEID_MGMT); +} + +int ribmgr_start(void) +{ + ribmgr_set_state(RIBMGR_OPERATIONAL); + + if (pthread_create(&ribmgr.sync, NULL, sync_rib, NULL)) { + ribmgr_set_state(RIBMGR_NULL); + return -1; + } + + if (pthread_create(&ribmgr.reader, NULL, reader, NULL)) { + ribmgr_set_state(RIBMGR_SHUTDOWN); + pthread_cancel(ribmgr.reader); + return -1; + } + + return 0; +} + +void ribmgr_stop(void) +{ + if (ribmgr_get_state() == RIBMGR_OPERATIONAL) { + ribmgr_set_state(RIBMGR_SHUTDOWN); + pthread_cancel(ribmgr.reader); + } } int ribmgr_disseminate(char * path, diff --git a/src/ipcpd/normal/ribmgr.h b/src/ipcpd/normal/ribmgr.h index 7411aedd..20f87548 100644 --- a/src/ipcpd/normal/ribmgr.h +++ b/src/ipcpd/normal/ribmgr.h @@ -42,6 +42,10 @@ int ribmgr_init(void); void ribmgr_fini(void); +int ribmgr_start(void); + +void ribmgr_stop(void); + int ribmgr_disseminate(char * path, enum diss_target target, enum diss_freq freq, diff --git a/src/ipcpd/normal/routing.c b/src/ipcpd/normal/routing.c index c00ec67c..04e6fd76 100644 --- a/src/ipcpd/normal/routing.c +++ b/src/ipcpd/normal/routing.c @@ -29,36 +29,35 @@ #include "routing.h" #include "pol/link_state.h" -struct { - struct pol_routing_ops * ops; -} routing; + +struct pol_routing_ops * r_ops; int routing_init(enum pol_routing pr, struct nbs * nbs) { switch (pr) { case LINK_STATE: - routing.ops = &link_state_ops; + r_ops = &link_state_ops; break; default: log_err("Unknown routing type."); return -1; } - return routing.ops->init(nbs); + return r_ops->init(nbs); } struct routing_i * routing_i_create(struct pff * pff) { - return routing.ops->routing_i_create(pff); + return r_ops->routing_i_create(pff); } void routing_i_destroy(struct routing_i * instance) { - return routing.ops->routing_i_destroy(instance); + return r_ops->routing_i_destroy(instance); } void routing_fini(void) { - routing.ops->fini(); + r_ops->fini(); } diff --git a/src/ipcpd/normal/sdu_sched.c b/src/ipcpd/normal/sdu_sched.c index f3550d5c..10b0f02f 100644 --- a/src/ipcpd/normal/sdu_sched.c +++ b/src/ipcpd/normal/sdu_sched.c @@ -117,6 +117,8 @@ struct sdu_sched * sdu_sched_create(next_sdu_t callback) if (sdu_sched == NULL) goto fail_malloc; + assert(callback); + sdu_sched->callback = callback; for (i = 0; i < QOS_CUBE_MAX; ++i) { @@ -170,6 +172,8 @@ void sdu_sched_add(struct sdu_sched * sdu_sched, { qoscube_t qc; + assert(sdu_sched); + ipcp_flow_get_qoscube(fd, &qc); flow_set_add(sdu_sched->set[qc], fd); } @@ -179,6 +183,8 @@ void sdu_sched_del(struct sdu_sched * sdu_sched, { qoscube_t qc; + assert(sdu_sched); + ipcp_flow_get_qoscube(fd, &qc); flow_set_del(sdu_sched->set[qc], fd); } 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/dev.c b/src/lib/dev.c index 9b41e5d4..cfcfdf81 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -857,8 +857,7 @@ int flow_dealloc(int fd) if (!recv_msg->has_result) { irm_msg__free_unpacked(recv_msg, NULL); - assert(false); - return -1; + return -EIRMD; } irm_msg__free_unpacked(recv_msg, NULL); diff --git a/src/lib/ipcp_config.proto b/src/lib/ipcp_config.proto index f0d5f6eb..4ede5060 100644 --- a/src/lib/ipcp_config.proto +++ b/src/lib/ipcp_config.proto @@ -35,12 +35,10 @@ message ipcp_config_msg { optional uint32 fd_size = 4; optional bool has_ttl = 5; optional uint32 addr_auth_type = 6; - optional uint32 dt_gam_type = 7; - optional uint32 rm_gam_type = 8; - optional uint32 routing_type = 9; + optional uint32 routing_type = 7; // Config for shim UDP - optional uint32 ip_addr = 10; - optional uint32 dns_addr = 11; + optional uint32 ip_addr = 8; + optional uint32 dns_addr = 9; // Config for the shim Ethernet LLC - optional string if_name = 12; + optional string if_name = 10; } 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 4232cec1..ce17bf18 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -121,10 +121,6 @@ int irm_bootstrap_ipcp(pid_t api, config.has_ttl = conf->has_ttl; config.has_addr_auth_type = true; config.addr_auth_type = conf->addr_auth_type; - config.has_dt_gam_type = true; - config.dt_gam_type = conf->dt_gam_type; - config.has_rm_gam_type = true; - config.rm_gam_type = conf->rm_gam_type; config.has_routing_type = true; config.routing_type = conf->routing_type; dif_info.dir_hash_algo = conf->dif_info.dir_hash_algo; @@ -150,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; @@ -162,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/lib/rib.c b/src/lib/rib.c index 104dc0cc..bbe996e7 100644 --- a/src/lib/rib.c +++ b/src/lib/rib.c @@ -373,7 +373,8 @@ static void destroy_rnode(struct rnode * node) branch_hash(node->parent); } - rnode_throw_event(node, RO_DELETE); + if (node->parent != NULL) + rnode_throw_event(node->parent, RO_DELETE); list_for_each_safe(p, h, &node->subs) { struct rn_sub * s = list_entry(p, struct rn_sub, next); 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_bootstrap.c b/src/tools/irm/irm_ipcp_bootstrap.c index 264fbfd5..a4a4d326 100644 --- a/src/tools/irm/irm_ipcp_bootstrap.c +++ b/src/tools/irm/irm_ipcp_bootstrap.c @@ -48,13 +48,9 @@ #define DEFAULT_FD_SIZE 2 #define DEFAULT_DDNS 0 #define DEFAULT_ADDR_AUTH FLAT_RANDOM -#define DEFAULT_DT_GAM COMPLETE -#define DEFAULT_RM_GAM COMPLETE #define DEFAULT_ROUTING LINK_STATE #define DEFAULT_HASH_ALGO DIR_HASH_SHA3_256 #define ADDR_AUTH_FLAT "flat" -#define DT_GAM_COMPLETE "complete" -#define RM_GAM_COMPLETE "complete" #define ROUTING_LINK_STATE "link_state" static void usage(void) @@ -71,10 +67,6 @@ static void usage(void) " [fd <fd size> (default: %d)]\n" " [ttl (add time to live value in the PCI)]\n" " [addr_auth <address policy> (default: %s)]\n" - " [dt_gam <data transfer graph adjacency manager>" - " (default: %s)]\n" - " [rm_gam <rib manager graph adjacency manager>" - " (default: %s)]\n" " [routing <routing policy> (default: %s)]\n" " [hash [ALGORITHM] (default: %s)]\n" "where ALGORITHM = {" SHA3_224 " " SHA3_256 " " @@ -86,8 +78,7 @@ static void usage(void) "if TYPE == " SHIM_ETH_LLC "\n" " if_name <interface name>\n", DEFAULT_ADDR_SIZE, DEFAULT_FD_SIZE, - ADDR_AUTH_FLAT, DT_GAM_COMPLETE, RM_GAM_COMPLETE, - ROUTING_LINK_STATE, SHA3_256); + ADDR_AUTH_FLAT, ROUTING_LINK_STATE, SHA3_256); } int do_bootstrap_ipcp(int argc, char ** argv) @@ -99,8 +90,6 @@ int do_bootstrap_ipcp(int argc, char ** argv) uint8_t fd_size = DEFAULT_FD_SIZE; bool has_ttl = false; enum pol_addr_auth addr_auth_type = DEFAULT_ADDR_AUTH; - enum pol_gam dt_gam_type = DEFAULT_DT_GAM; - enum pol_gam rm_gam_type = DEFAULT_RM_GAM; enum pol_routing routing_type = DEFAULT_ROUTING; enum pol_dir_hash hash_algo = DEFAULT_HASH_ALGO; uint32_t ip_addr = 0; @@ -151,16 +140,6 @@ int do_bootstrap_ipcp(int argc, char ** argv) addr_auth_type = FLAT_RANDOM; else goto unknown_param; - } else if (matches(*argv, "dt_gam") == 0) { - if (strcmp(DT_GAM_COMPLETE, *(argv + 1)) == 0) - dt_gam_type = COMPLETE; - else - goto unknown_param; - } else if (matches(*argv, "rm_gam") == 0) { - if (strcmp(RM_GAM_COMPLETE, *(argv + 1)) == 0) - rm_gam_type = COMPLETE; - else - goto unknown_param; } else if (matches(*argv, "routing") == 0) { if (strcmp(ROUTING_LINK_STATE, *(argv + 1)) == 0) routing_type = LINK_STATE; @@ -188,8 +167,6 @@ int do_bootstrap_ipcp(int argc, char ** argv) conf.fd_size = fd_size; conf.has_ttl = has_ttl; conf.addr_auth_type = addr_auth_type; - conf.dt_gam_type = dt_gam_type; - conf.rm_gam_type = rm_gam_type; conf.routing_type = routing_type; conf.dif_info.dir_hash_algo = hash_algo; } else if (strcmp(ipcp_type, SHIM_UDP) == 0) { 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); |