From 85b3822a4cc121dcb3d87937c2a44395d8887ae3 Mon Sep 17 00:00:00 2001
From: Sander Vrijders <sander.vrijders@intec.ugent.be>
Date: Fri, 2 Dec 2016 15:22:52 +0100
Subject: ipcpd: normal: Provide directory for registered names

This adds a directory to the normal IPCP that maps names on IPCP
addresses.
---
 src/ipcpd/normal/CMakeLists.txt |   1 +
 src/ipcpd/normal/addr_auth.h    |   6 +-
 src/ipcpd/normal/crc32.h        |   6 +-
 src/ipcpd/normal/dir.c          | 215 ++++++++++++++++++++++++++++++++++++++++
 src/ipcpd/normal/dir.h          |  38 +++++++
 src/ipcpd/normal/dt_const.h     |   6 +-
 src/ipcpd/normal/fmgr.c         |  69 +++++++++----
 src/ipcpd/normal/fmgr.h         |   6 +-
 src/ipcpd/normal/frct.h         |   6 +-
 src/ipcpd/normal/main.c         |  55 ++--------
 src/ipcpd/normal/pol/flat.h     |   6 +-
 src/ipcpd/normal/ribmgr.c       |  79 ++++++++++++++-
 src/ipcpd/normal/ribmgr.h       |   6 +-
 src/ipcpd/normal/ro.h           |  11 +-
 src/ipcpd/normal/shm_pci.h      |   6 +-
 15 files changed, 421 insertions(+), 95 deletions(-)
 create mode 100644 src/ipcpd/normal/dir.c
 create mode 100644 src/ipcpd/normal/dir.h

(limited to 'src/ipcpd')

diff --git a/src/ipcpd/normal/CMakeLists.txt b/src/ipcpd/normal/CMakeLists.txt
index ca7e1ae2..e61c226d 100644
--- a/src/ipcpd/normal/CMakeLists.txt
+++ b/src/ipcpd/normal/CMakeLists.txt
@@ -27,6 +27,7 @@ set(SOURCE_FILES
   addr_auth.c
   cdap_request.c
   crc32.c
+  dir.c
   fmgr.c
   frct.c
   main.c
diff --git a/src/ipcpd/normal/addr_auth.h b/src/ipcpd/normal/addr_auth.h
index 6881dd55..73ff9aa4 100644
--- a/src/ipcpd/normal/addr_auth.h
+++ b/src/ipcpd/normal/addr_auth.h
@@ -20,8 +20,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_ADDR_AUTH
-#define OUROBOROS_ADDR_AUTH
+#ifndef OUROBOROS_IPCPD_NORMAL_ADDR_AUTH_H
+#define OUROBOROS_IPCPD_NORMAL_ADDR_AUTH_H
 
 #include <ouroboros/irm_config.h>
 
@@ -36,4 +36,4 @@ struct addr_auth * addr_auth_create(enum pol_addr_auth type);
 
 int                addr_auth_destroy(struct addr_auth * instance);
 
-#endif /* OUROBOROS_ADDR_AUTH */
+#endif /* OUROBOROS_IPCPD_NORMAL_ADDR_AUTH_H */
diff --git a/src/ipcpd/normal/crc32.h b/src/ipcpd/normal/crc32.h
index f22bbc19..a7a01818 100644
--- a/src/ipcpd/normal/crc32.h
+++ b/src/ipcpd/normal/crc32.h
@@ -20,11 +20,11 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_IPCP_CRC32_H
-#define OUROBOROS_IPCP_CRC32_H
+#ifndef OUROBOROS_IPCPD_NORMAL_CRC32_H
+#define OUROBOROS_IPCPD_NORMAL_CRC32_H
 
 #include <stdint.h>
 
 void crc32(uint32_t * crc, const uint8_t * buf, size_t len);
 
-#endif /* OUROBOROS_IPCP_CRC32_H */
+#endif /* OUROBOROS_IPCPD_NORMAL_CRC32_H */
diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c
new file mode 100644
index 00000000..2b3742d9
--- /dev/null
+++ b/src/ipcpd/normal/dir.c
@@ -0,0 +1,215 @@
+/*
+ * Ouroboros - Copyright (C) 2016
+ *
+ * DIF directory
+ *
+ *    Sander Vrijders <sander.vrijders@intec.ugent.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define OUROBOROS_PREFIX "directory"
+
+#include <ouroboros/config.h>
+#include <ouroboros/logs.h>
+#include <ouroboros/errno.h>
+
+#include "dir.h"
+#include "ipcp.h"
+#include "ro.h"
+#include "path.h"
+#include "ribmgr.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+char * create_path(char * name)
+{
+        char * path;
+
+        path = pathname_create(RO_DIR);
+        if (path == NULL)
+                return NULL;
+
+        path = pathname_append(path, name);
+        if (path == NULL) {
+                pathname_destroy(path);
+                return NULL;
+        }
+
+        return path;
+}
+
+int dir_init(void)
+{
+        char * path;
+        struct ro_attr attr;
+
+        ro_attr_init(&attr);
+        attr.enrol_sync = true;
+        attr.recv_set = ALL_MEMBERS;
+
+        path = pathname_create(RO_DIR);
+        if (path == NULL)
+                return -1;
+
+        if (ro_create(path, &attr, NULL, 0)) {
+                pathname_destroy(path);
+                LOG_ERR("Failed to create RIB object.");
+                return -1;
+        }
+
+        pathname_destroy(path);
+
+        return 0;
+}
+
+int dir_fini(void)
+{
+        char * path;
+
+        path = pathname_create(RO_DIR);
+        if (path == NULL)
+                return -1;
+
+        ro_delete(path);
+        pathname_destroy(path);
+
+        return 0;
+}
+
+int dir_name_reg(char * name)
+{
+        struct ro_attr attr;
+        char * path;
+        uint64_t * addr;
+
+        pthread_rwlock_rdlock(&ipcpi.state_lock);
+
+        if (ipcp_get_state() != IPCP_RUNNING) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                LOG_ERR("IPCP is not in RUNNING state.");
+                return -1;
+        }
+
+        ro_attr_init(&attr);
+        attr.enrol_sync = true;
+        attr.recv_set = ALL_MEMBERS;
+
+        path = create_path(name);
+        if (path == NULL) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                return -ENOMEM;
+        }
+
+        addr = malloc(sizeof(*addr));
+        if (addr == NULL) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                pathname_destroy(path);
+                return -ENOMEM;
+        }
+        *addr = ribmgr_address();
+
+        if (ro_create(path, &attr, (uint8_t *) addr, sizeof(*addr))) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                pathname_destroy(path);
+                LOG_ERR("Failed to create RIB object.");
+                return -1;
+        }
+
+        pthread_rwlock_unlock(&ipcpi.state_lock);
+
+        LOG_DBG("Registered %s.", name);
+        pathname_destroy(path);
+
+        return 0;
+}
+
+int dir_name_unreg(char * name)
+{
+        char * path;
+
+        pthread_rwlock_rdlock(&ipcpi.state_lock);
+
+        if (ipcp_get_state() != IPCP_RUNNING) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                LOG_ERR("IPCP is not in RUNNING state.");
+                return -1;
+        }
+
+        path = create_path(name);
+        if (path == NULL) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                return -ENOMEM;
+        }
+
+        if (ro_delete(path)) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                pathname_destroy(path);
+                LOG_ERR("No such RIB object exists.");
+                return -1;
+        }
+
+        pthread_rwlock_unlock(&ipcpi.state_lock);
+
+        pathname_destroy(path);
+
+        return 0;
+}
+
+int dir_name_query(char * name)
+{
+        char * path;
+        int ret = -1;
+        uint8_t * ro_data;
+        uint64_t addr;
+        struct dt_const * dtc;
+
+        pthread_rwlock_rdlock(&ipcpi.state_lock);
+
+        if (ipcp_get_state() != IPCP_RUNNING) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                return -1;
+        }
+
+        path = create_path(name);
+        if (path == NULL) {
+                pthread_rwlock_unlock(&ipcpi.state_lock);
+                return -1;
+        }
+
+        if (ro_exists(path)) {
+                if (ro_read(path, &ro_data) < 0) {
+                        pathname_destroy(path);
+                        return -1;
+                }
+                addr = *((uint64_t *) ro_data);
+                free(ro_data);
+
+                dtc = ribmgr_dt_const();
+                if (dtc == NULL) {
+                        pathname_destroy(path);
+                        return -1;
+                }
+
+                ret = (addr == ribmgr_address()) ? -1 : 0;
+        }
+
+        pthread_rwlock_unlock(&ipcpi.state_lock);
+
+        pathname_destroy(path);
+
+        return ret;
+}
diff --git a/src/ipcpd/normal/dir.h b/src/ipcpd/normal/dir.h
new file mode 100644
index 00000000..9b27feb4
--- /dev/null
+++ b/src/ipcpd/normal/dir.h
@@ -0,0 +1,38 @@
+/*
+ * Ouroboros - Copyright (C) 2016
+ *
+ * DIF directory
+ *
+ *    Sander Vrijders <sander.vrijders@intec.ugent.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef OUROBOROS_IPCPD_NORMAL_DIR_H
+#define OUROBOROS_IPCPD_NORMAL_DIR_H
+
+#define RO_DIR "directory"
+
+int dir_init(void);
+
+int dir_fini(void);
+
+int dir_name_reg(char * name);
+
+int dir_name_unreg(char * name);
+
+int dir_name_query(char * name);
+
+#endif /* OUROBOROS_IPCPD_NORMAL_DIR_H */
diff --git a/src/ipcpd/normal/dt_const.h b/src/ipcpd/normal/dt_const.h
index eda66838..a45991f1 100644
--- a/src/ipcpd/normal/dt_const.h
+++ b/src/ipcpd/normal/dt_const.h
@@ -21,8 +21,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef IPCP_DT_CONST_H
-#define IPCP_DT_CONST_H
+#ifndef OUROBOROS_IPCPD_NORMAL_DT_CONST_H
+#define OUROBOROS_IPCPD_NORMAL_DT_CONST_H
 
 #include <stdint.h>
 #include <stdbool.h>
@@ -38,4 +38,4 @@ struct dt_const {
         uint32_t max_pdu_size;
 };
 
-#endif /* IPCP_DT_CONST_H */
+#endif /* OUROBOROS_IPCPD_NORMAL_DT_CONST_H */
diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c
index 35217283..82163aef 100644
--- a/src/ipcpd/normal/fmgr.c
+++ b/src/ipcpd/normal/fmgr.c
@@ -40,6 +40,9 @@
 #include "frct.h"
 #include "ipcp.h"
 #include "shm_pci.h"
+#include "dir.h"
+#include "path.h"
+#include "ro.h"
 
 #include "flow_alloc.pb-c.h"
 typedef FlowAllocMsg flow_alloc_msg_t;
@@ -273,19 +276,22 @@ void * fmgr_nm1_sdu_reader(void * o)
                         if (pci->dst_addr != ribmgr_address()) {
                                 LOG_DBG("PDU needs to be forwarded.");
 
-                                if (pci->ttl == 0) {
-                                        LOG_DBG("TTL was zero.");
-                                        ipcp_flow_del(sdb);
-                                        free(pci);
-                                        continue;
+                                if (ribmgr_dt_const()->has_ttl) {
+                                        if (pci->ttl == 0) {
+                                                LOG_DBG("TTL was zero.");
+                                                ipcp_flow_del(sdb);
+                                                free(pci);
+                                                continue;
+                                        }
+
+                                        if (shm_pci_dec_ttl(sdb)) {
+                                                LOG_ERR("Failed to dec TTL.");
+                                                ipcp_flow_del(sdb);
+                                                free(pci);
+                                                continue;
+                                        }
                                 }
 
-                                if (shm_pci_dec_ttl(sdb)) {
-                                        LOG_ERR("Failed to decrease TTL.");
-                                        ipcp_flow_del(sdb);
-                                        free(pci);
-                                        continue;
-                                }
                                 /*
                                  * FIXME: Dropping for now, since
                                  * we don't have a PFF yet
@@ -401,14 +407,16 @@ int fmgr_fini()
 }
 
 int fmgr_np1_alloc(int           fd,
-                    char *        dst_ap_name,
-                    char *        src_ae_name,
-                    enum qos_cube qos)
+                   char *        dst_ap_name,
+                   char *        src_ae_name,
+                   enum qos_cube qos)
 {
         cep_id_t cep_id;
-        uint32_t address = 0;
         buffer_t buf;
         flow_alloc_msg_t msg = FLOW_ALLOC_MSG__INIT;
+        char * path;
+        uint8_t * ro_data;
+        uint64_t addr;
 
         pthread_rwlock_rdlock(&ipcpi.state_lock);
 
@@ -420,7 +428,23 @@ int fmgr_np1_alloc(int           fd,
 
         pthread_rwlock_unlock(&ipcpi.state_lock);
 
-        /* FIXME: Obtain correct address here from DIF NSM */
+        path = pathname_create(RO_DIR);
+        if (path == NULL)
+                return -1;
+
+        path = pathname_append(path, dst_ap_name);
+        if (path == NULL) {
+                pathname_destroy(path);
+                return -1;
+        }
+
+        if (ro_read(path, &ro_data) < 0) {
+                pathname_destroy(path);
+                return -1;
+        }
+        addr = *((uint64_t *) ro_data);
+
+        pathname_destroy(path);
 
         msg.code = FLOW_ALLOC_CODE__FLOW_REQ;
         msg.dst_name = dst_ap_name;
@@ -429,24 +453,31 @@ int fmgr_np1_alloc(int           fd,
         msg.has_qos_cube = true;
 
         buf.len = flow_alloc_msg__get_packed_size(&msg);
-        if (buf.len == 0)
+        if (buf.len == 0) {
+                free(ro_data);
                 return -1;
+        }
 
         buf.data = malloc(buf.len);
-        if (buf.data == NULL)
+        if (buf.data == NULL) {
+                free(ro_data);
                 return -1;
+        }
 
         flow_alloc_msg__pack(&msg, buf.data);
 
         pthread_rwlock_wrlock(&fmgr.np1_flows_lock);
 
-        cep_id = frct_i_create(address, &buf, qos);
+        cep_id = frct_i_create(addr, &buf, qos);
         if (cep_id == INVALID_CEP_ID) {
+                free(ro_data);
                 free(buf.data);
                 pthread_rwlock_unlock(&fmgr.np1_flows_lock);
                 return -1;
         }
 
+        free(ro_data);
+
         if (add_np1_fd(fd, cep_id, qos)) {
                 pthread_rwlock_unlock(&fmgr.np1_flows_lock);
                 return -1;
diff --git a/src/ipcpd/normal/fmgr.h b/src/ipcpd/normal/fmgr.h
index faa8a0e4..73c62440 100644
--- a/src/ipcpd/normal/fmgr.h
+++ b/src/ipcpd/normal/fmgr.h
@@ -20,8 +20,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_IPCP_FMGR_H
-#define OUROBOROS_IPCP_FMGR_H
+#ifndef OUROBOROS_IPCPD_NORMAL_FMGR_H
+#define OUROBOROS_IPCPD_NORMAL_FMGR_H
 
 #include <ouroboros/shared.h>
 
@@ -65,4 +65,4 @@ int fmgr_nm1_write_sdu(struct pci *         pci,
 int fmgr_nm1_write_buf(struct pci * pci,
                        buffer_t *   buf);
 
-#endif
+#endif /* OUROBOROS_IPCPD_NORMAL_FMGR_H */
diff --git a/src/ipcpd/normal/frct.h b/src/ipcpd/normal/frct.h
index 572c1f61..6025abec 100644
--- a/src/ipcpd/normal/frct.h
+++ b/src/ipcpd/normal/frct.h
@@ -20,8 +20,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_IPCP_FRCT_H
-#define OUROBOROS_IPCP_FRCT_H
+#ifndef OUROBOROS_IPCPD_NORMAL_FRCT_H
+#define OUROBOROS_IPCPD_NORMAL_FRCT_H
 
 #include <ouroboros/shared.h>
 #include <ouroboros/utils.h>
@@ -51,4 +51,4 @@ int         frct_i_write_sdu(cep_id_t             id,
 int         frct_nm1_post_sdu(struct pci *         pci,
                               struct shm_du_buff * sdb);
 
-#endif
+#endif /* OUROBOROS_IPCPD_NORMAL_FRCT_H */
diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c
index 810fbca5..64138838 100644
--- a/src/ipcpd/normal/main.c
+++ b/src/ipcpd/normal/main.c
@@ -32,6 +32,7 @@
 #include "ribmgr.h"
 #include "ipcp.h"
 #include "frct.h"
+#include "dir.h"
 
 #include <stdbool.h>
 #include <signal.h>
@@ -68,51 +69,6 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c)
         }
 }
 
-static int normal_ipcp_name_reg(char * name)
-{
-        pthread_rwlock_rdlock(&ipcpi.state_lock);
-
-        if (ipcp_data_reg_add_entry(ipcpi.data, name)) {
-                pthread_rwlock_unlock(&ipcpi.state_lock);
-                LOG_ERR("Failed to add %s to local registry.", name);
-                return -1;
-        }
-
-        pthread_rwlock_unlock(&ipcpi.state_lock);
-
-        LOG_DBG("Registered %s.", name);
-
-        return 0;
-}
-
-static int normal_ipcp_name_unreg(char * name)
-{
-        pthread_rwlock_rdlock(&ipcpi.state_lock);
-
-        ipcp_data_reg_del_entry(ipcpi.data, name);
-
-        pthread_rwlock_unlock(&ipcpi.state_lock);
-
-        return 0;
-}
-
-static int normal_ipcp_name_query(char * name)
-{
-        LOG_MISSING;
-
-        /*
-         * NOTE: For the moment we just return -1,
-         * for testing purposes we may return zero here
-         * for certain names.
-         */
-
-        /* FIXME: Here for testing purposes */
-        if (strcmp(name, "normal.app") == 0)
-                return 0;
-
-        return -1;
-}
-
 static int normal_ipcp_enroll(char * dif_name)
 {
         struct timespec timeout = {(ENROLL_TIMEOUT / 1000),
@@ -206,9 +162,9 @@ static int normal_ipcp_bootstrap(struct dif_config * conf)
 static struct ipcp_ops normal_ops = {
         .ipcp_bootstrap       = normal_ipcp_bootstrap,
         .ipcp_enroll          = normal_ipcp_enroll,
-        .ipcp_name_reg        = normal_ipcp_name_reg,
-        .ipcp_name_unreg      = normal_ipcp_name_unreg,
-        .ipcp_name_query      = normal_ipcp_name_query,
+        .ipcp_name_reg        = dir_name_reg,
+        .ipcp_name_unreg      = dir_name_unreg,
+        .ipcp_name_query      = dir_name_query,
         .ipcp_flow_alloc      = fmgr_np1_alloc,
         .ipcp_flow_alloc_resp = fmgr_np1_alloc_resp,
         .ipcp_flow_dealloc    = fmgr_np1_dealloc
@@ -292,6 +248,9 @@ int main(int argc, char * argv[])
         if (frct_fini())
                 LOG_ERR("Failed to finalize FRCT.");
 
+        if (dir_fini())
+                LOG_ERR("Failed to finalize directory.");
+
         close_logfile();
 
         ap_fini();
diff --git a/src/ipcpd/normal/pol/flat.h b/src/ipcpd/normal/pol/flat.h
index 51cb511b..a488eb35 100644
--- a/src/ipcpd/normal/pol/flat.h
+++ b/src/ipcpd/normal/pol/flat.h
@@ -20,11 +20,11 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_FLAT
-#define OUROBOROS_FLAT
+#ifndef OUROBOROS_IPCPD_NORMAL_FLAT_H
+#define OUROBOROS_IPCPD_NORMAL_FLAT_H
 
 int      flat_init(void);
 int      flat_fini(void);
 uint64_t flat_address(void);
 
-#endif /* OUROBOROS_FLAT */
+#endif /* OUROBOROS_IPCPD_NORMAL_FLAT_H */
diff --git a/src/ipcpd/normal/ribmgr.c b/src/ipcpd/normal/ribmgr.c
index 3e305ffe..127eb9f2 100644
--- a/src/ipcpd/normal/ribmgr.c
+++ b/src/ipcpd/normal/ribmgr.c
@@ -45,6 +45,7 @@
 #include "cdap_request.h"
 #include "ro.h"
 #include "path.h"
+#include "dir.h"
 
 #include "static_info.pb-c.h"
 typedef StaticInfoMsg static_info_msg_t;
@@ -1269,8 +1270,17 @@ int ribmgr_bootstrap(struct dif_config * conf)
                 return -1;
         }
 
+        if (dir_init()) {
+                LOG_ERR("Failed to init directory");
+                ribmgr_ro_delete(RIBMGR_PREFIX STAT_INFO);
+                addr_auth_destroy(rib.addr_auth);
+                ribmgr_ro_delete(RIBMGR_PREFIX);
+                return -1;
+        }
+
         if (frct_init()) {
                 LOG_ERR("Failed to initialize FRCT.");
+                dir_fini();
                 ribmgr_ro_delete(RIBMGR_PREFIX STAT_INFO);
                 addr_auth_destroy(rib.addr_auth);
                 ribmgr_ro_delete(RIBMGR_PREFIX);
@@ -1412,7 +1422,6 @@ int ro_create(const char *     name,
         node = ribmgr_ro_create(name, *attr, data, len);
         if (node == NULL) {
                 pthread_mutex_unlock(&rib.ro_lock);
-                LOG_ERR("Failed to create RO.");
                 return -1;
         }
 
@@ -1563,6 +1572,74 @@ ssize_t ro_read(const char * name,
         return len;
 }
 
+ssize_t ro_children(const char * name,
+                    char ***     children)
+{
+        struct rnode * node;
+        struct rnode * child;
+        ssize_t len = 0;
+        int i = 0;
+
+        assert(name);
+        assert(children);
+
+        pthread_mutex_lock(&rib.ro_lock);
+
+        node = find_rnode_by_name(name);
+        if (node == NULL) {
+                pthread_mutex_unlock(&rib.ro_lock);
+                return -1;
+        }
+
+        child = node->child;
+        while (child != NULL) {
+                len++;
+                child = child->sibling;
+        }
+        child = node->child;
+
+        **children = malloc(len);
+        if (**children == NULL) {
+                pthread_mutex_unlock(&rib.ro_lock);
+                return -1;
+        }
+
+        for (i = 0; i < len; i++) {
+                (*children)[i] = strdup(child->name);
+                if ((*children)[i] == NULL) {
+                        while (i >= 0) {
+                                free((*children)[i]);
+                                i--;
+                        }
+                        free(**children);
+                        pthread_mutex_unlock(&rib.ro_lock);
+                        return -1;
+                }
+                child = child->sibling;
+        }
+
+        pthread_mutex_unlock(&rib.ro_lock);
+
+        return len;
+}
+
+bool ro_exists(const char * name)
+{
+        struct rnode * node;
+        bool found;
+
+        assert(name);
+
+        pthread_mutex_lock(&rib.ro_lock);
+
+        node = find_rnode_by_name(name);
+        found = (node == NULL) ? false : true;
+
+        pthread_mutex_unlock(&rib.ro_lock);
+
+        return found;
+}
+
 int ro_subscribe(const char *        name,
                  struct ro_sub_ops * ops)
 {
diff --git a/src/ipcpd/normal/ribmgr.h b/src/ipcpd/normal/ribmgr.h
index b76ff3bd..5594751f 100644
--- a/src/ipcpd/normal/ribmgr.h
+++ b/src/ipcpd/normal/ribmgr.h
@@ -20,8 +20,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_IPCP_RIBMGR_H
-#define OUROBOROS_IPCP_RIBMGR_H
+#ifndef OUROBOROS_IPCPD_NORMAL_RIBMGR_H
+#define OUROBOROS_IPCPD_NORMAL_RIBMGR_H
 
 #include <ouroboros/irm_config.h>
 #include <ouroboros/utils.h>
@@ -46,4 +46,4 @@ struct dt_const * ribmgr_dt_const(void);
 
 uint64_t          ribmgr_address(void);
 
-#endif
+#endif /* OUROBOROS_IPCPD_NORMAL_RIBMGR_H */
diff --git a/src/ipcpd/normal/ro.h b/src/ipcpd/normal/ro.h
index 278c9213..99ea81f1 100644
--- a/src/ipcpd/normal/ro.h
+++ b/src/ipcpd/normal/ro.h
@@ -20,8 +20,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_IPCP_RO_H
-#define OUROBOROS_IPCP_RO_H
+#ifndef OUROBOROS_IPCPD_NORMAL_RO_H
+#define OUROBOROS_IPCPD_NORMAL_RO_H
 
 enum ro_recv_set {
         NO_SYNC = 0,
@@ -54,6 +54,11 @@ int          ro_write(const char * name,
 ssize_t      ro_read(const char * name,
                      uint8_t **   data);
 
+ssize_t      ro_children(const char * name,
+                         char ***     children);
+
+bool         ro_exists(const char * name);
+
 /* Callback passes ownership of the data */
 struct ro_sub_ops {
         void (* ro_created)(const char * name,
@@ -71,4 +76,4 @@ int          ro_subscribe(const char *        name,
 
 int          ro_unsubscribe(int sid);
 
-#endif
+#endif /* OUROBOROS_IPCPD_NORMAL_RO_H */
diff --git a/src/ipcpd/normal/shm_pci.h b/src/ipcpd/normal/shm_pci.h
index 6e955d84..53931139 100644
--- a/src/ipcpd/normal/shm_pci.h
+++ b/src/ipcpd/normal/shm_pci.h
@@ -21,8 +21,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef OUROBOROS_IPCP_SHM_PCI_H
-#define OUROBOROS_IPCP_SHM_PCI_H
+#ifndef OUROBOROS_IPCPD_NORMAL_SHM_PCI_H
+#define OUROBOROS_IPCPD_NORMAL_SHM_PCI_H
 
 #include <ouroboros/shm_rdrbuff.h>
 #include <ouroboros/utils.h>
@@ -61,4 +61,4 @@ int          shm_pci_shrink(struct shm_du_buff * sdb);
 
 int          shm_pci_dec_ttl(struct shm_du_buff * sdb);
 
-#endif /* OUROBOROS_IPCP_SHM_PCI_H */
+#endif /* OUROBOROS_IPCPD_NORMAL_SHM_PCI_H */
-- 
cgit v1.2.3