From a76b638a370cd0cdd087ec780e6b1f8d18bac66d Mon Sep 17 00:00:00 2001
From: Sander Vrijders <sander.vrijders@intec.ugent.be>
Date: Sun, 29 May 2016 20:25:41 +0200
Subject: irmd: Add wildcarding of DIF names

This adds wildcarding of DIF names so that application developers can
for instance specify home.* to specify all home DIFs.
---
 src/irmd/CMakeLists.txt |   1 +
 src/irmd/main.c         | 116 +++++++++++++++++++++---------------------------
 src/irmd/utils.c        |  70 +++++++++++++++++++++++++++++
 src/irmd/utils.h        |  27 +++++++++++
 4 files changed, 149 insertions(+), 65 deletions(-)
 create mode 100644 src/irmd/utils.c
 create mode 100644 src/irmd/utils.h

(limited to 'src/irmd')

diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt
index b7e3cde4..75d65ba3 100644
--- a/src/irmd/CMakeLists.txt
+++ b/src/irmd/CMakeLists.txt
@@ -7,6 +7,7 @@ include_directories(${CMAKE_BINARY_DIR}/include)
 set(SOURCE_FILES
         # Add source files here
         main.c
+        utils.c
 )
 
 add_executable (irmd ${SOURCE_FILES})
diff --git a/src/irmd/main.c b/src/irmd/main.c
index b84c3327..03f9a3c2 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -38,6 +38,8 @@
 #include <ouroboros/qos.h>
 #include <ouroboros/rw_lock.h>
 
+#include "utils.h"
+
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <signal.h>
@@ -47,9 +49,6 @@
 #include <limits.h>
 #include <pthread.h>
 
-/* FIXME: this smells like part of namespace management */
-#define ALL_DIFS "*"
-
 #ifndef IRMD_MAX_FLOWS
   #define IRMD_MAX_FLOWS 4096
 #endif
@@ -229,7 +228,12 @@ static instance_name_t * get_ipcp_by_name(char * ap_name)
         return NULL;
 }
 
-static instance_name_t * get_ipcp_by_dif_name(char * dif_name)
+/*
+ * FIXME: this just returns the first IPCP that
+ * matches the requested DIF name for now
+ */
+static instance_name_t * get_ipcp_by_dst_name(char * dst_name,
+                                              char * dif_name)
 {
         struct list_head * pos = NULL;
 
@@ -240,22 +244,13 @@ static instance_name_t * get_ipcp_by_dif_name(char * dif_name)
                 if (e->dif_name == NULL)
                         continue;
 
-                if (strcmp(dif_name, e->dif_name) == 0)
+                if (dif_name != NULL) {
+                        if (wildcard_match(dif_name, e->dif_name) == 0) {
+                                return e->api;
+                        }
+                } else {
                         return e->api;
-        }
-
-        return NULL;
-}
-
-/* FIXME: this just returns the first IPCP for now */
-static instance_name_t * get_ipcp_by_dst_name(char * dst_name)
-{
-        struct list_head * pos = NULL;
-
-        list_for_each(pos, &instance->ipcps) {
-                struct ipcp_entry * e =
-                        list_entry(pos, struct ipcp_entry, next);
-                return e->api;
+                }
         }
 
         return NULL;
@@ -470,10 +465,10 @@ static int destroy_ipcp(instance_name_t * api)
                 struct ipcp_entry * tmp =
                         list_entry(pos, struct ipcp_entry, next);
 
-                if (instance_name_cmp(api, tmp->api) == 0)
+                if (instance_name_cmp(api, tmp->api) == 0) {
                         list_del(&tmp->next);
-
-                ipcp_entry_destroy(tmp);
+                        ipcp_entry_destroy(tmp);
+                }
         }
 
         rw_lock_unlock(&instance->reg_lock);
@@ -649,7 +644,6 @@ static int ap_reg(char *  ap_name,
         struct reg_name_entry * rne = NULL;
 
         instance_name_t * api   = NULL;
-        instance_name_t * ipcpi = NULL;
 
         rw_lock_rdlock(&instance->state_lock);
         rw_lock_wrlock(&instance->reg_lock);
@@ -689,31 +683,22 @@ static int ap_reg(char *  ap_name,
          * contains a single instance only
          */
 
-        if (strcmp(difs[0], ALL_DIFS) == 0) {
-                list_for_each(pos, &instance->ipcps) {
-                        struct ipcp_entry * e =
-                                list_entry(pos, struct ipcp_entry, next);
+        list_for_each(pos, &instance->ipcps) {
+                struct ipcp_entry * e =
+                        list_entry(pos, struct ipcp_entry, next);
 
-                        if (ipcp_name_reg(e->api->id, ap_name)) {
-                                LOG_ERR("Could not register %s in DIF %s.",
-                                        api->name, e->dif_name);
-                        } else {
-                                ++ret;
-                        }
-                }
-        } else {
-                for (i = 0; i < len; ++i) {
-                        ipcpi = get_ipcp_by_dif_name(difs[i]);
-                        if (ipcpi == NULL) {
-                                LOG_ERR("%s: No such DIF.", difs[i]);
-                                continue;
-                        }
+                if (e->dif_name == NULL)
+                        continue;
 
-                        if (ipcp_name_reg(ipcpi->id, api->name)) {
-                                LOG_ERR("Could not register %s in DIF %s.",
-                                        api->name, difs[i]);
-                        } else {
-                                ++ret;
+                for (i = 0; i < len; ++i) {
+                        if (wildcard_match(difs[i], e->dif_name) == 0) {
+                                if (ipcp_name_reg(e->api->id, ap_name)) {
+                                        LOG_ERR("Could not register "
+                                                "%s in DIF %s.",
+                                                api->name, e->dif_name);
+                                } else {
+                                        ++ret;
+                                }
                         }
                 }
         }
@@ -768,23 +753,21 @@ static int ap_unreg(char *  ap_name,
                 return 0;
         }
 
-        if (strcmp(difs[0], ALL_DIFS) == 0) {
-                  list_for_each(pos, &instance->ipcps) {
-                        struct ipcp_entry * e =
-                                list_entry(pos, struct ipcp_entry, next);
+        list_for_each(pos, &instance->ipcps) {
+                struct ipcp_entry * e =
+                        list_entry(pos, struct ipcp_entry, next);
+
+                if (e->dif_name == NULL)
+                        continue;
 
-                        if (ipcp_name_unreg(e->api->id, rne->name)) {
-                                LOG_ERR("Could not unregister %s in DIF %s.",
-                                        rne->name, e->dif_name);
-                                --ret;
-                        }
-                }
-        } else {
                 for (i = 0; i < len; ++i) {
-                        if (ipcp_name_unreg(ap_id, rne->name)) {
-                                LOG_ERR("Could not unregister %s in DIF %s.",
-                                        rne->name, difs[i]);
-                                --ret;
+                        if (wildcard_match(difs[i], e->dif_name) == 0) {
+                                if (ipcp_name_unreg(e->api->id, rne->name)) {
+                                        LOG_ERR("Could not unregister "
+                                                "%s in DIF %s.",
+                                                rne->name, e->dif_name);
+                                        --ret;
+                                }
                         }
                 }
         }
@@ -942,6 +925,7 @@ static struct port_map_entry * flow_alloc(pid_t  pid,
 {
         struct port_map_entry * pme;
         instance_name_t * ipcp;
+        char * dif_name = NULL;
 
         /* FIXME: Map qos_spec to qos_cube */
 
@@ -957,12 +941,14 @@ static struct port_map_entry * flow_alloc(pid_t  pid,
         rw_lock_rdlock(&instance->state_lock);
         rw_lock_rdlock(&instance->reg_lock);
 
-        ipcp = get_ipcp_by_dst_name(dst_name);
+        if (qos != NULL)
+                dif_name = qos->dif_name;
 
+        ipcp = get_ipcp_by_dst_name(dst_name, dif_name);
         if (ipcp == NULL) {
                 rw_lock_unlock(&instance->reg_lock);
                 rw_lock_unlock(&instance->state_lock);
-                LOG_DBG("unknown ipcp");
+                LOG_DBG("Unknown DIF name.");
                 return NULL;
         }
 
@@ -970,7 +956,7 @@ static struct port_map_entry * flow_alloc(pid_t  pid,
         rw_lock_wrlock(&instance->flows_lock);
 
         pme->port_id = bmp_allocate(instance->port_ids);
-        pme->n_1_pid = get_ipcp_by_dst_name(dst_name)->id;
+        pme->n_1_pid = ipcp->id;
 
         list_add(&pme->next, &instance->port_map);
 
@@ -1227,7 +1213,7 @@ static int flow_dealloc_ipcp(int port_id)
         return 0;
 }
 
-static void irm_destroy(struct irm *  irm)
+static void irm_destroy(struct irm * irm)
 {
         struct list_head * h;
         struct list_head * t;
diff --git a/src/irmd/utils.c b/src/irmd/utils.c
new file mode 100644
index 00000000..9cc1dd2f
--- /dev/null
+++ b/src/irmd/utils.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * wildcard_match is based on the fnmatch function from POSIX.2.
+ * Implementation based on that one from FreeBSD.
+ */
+
+int wildcard_match(const char * pattern, const char * string)
+{
+        char c;
+
+        /* For loop? Why not Zoidberg? */
+        for (;;) {
+                switch (c = *pattern++) {
+                case '\0':
+                        return (*string == '\0' ? 0 : -1);
+                case '*':
+                        c = *pattern;
+
+                        if (c == '\0')
+                                return 0;
+
+                        /* General case, use recursion. */
+                        while ((c = *string) != '\0') {
+                                if (!wildcard_match(pattern, string))
+                                        return 0;
+                                ++string;
+                        }
+                        return -1;
+                default:
+                        if (c != *string)
+                                return -1;
+                        string++;
+                        break;
+                }
+        }
+}
diff --git a/src/irmd/utils.h b/src/irmd/utils.h
new file mode 100644
index 00000000..aa8a38f1
--- /dev/null
+++ b/src/irmd/utils.h
@@ -0,0 +1,27 @@
+/*
+ * Ouroboros - Copyright (C) 2016
+ *
+ * Utils of the IPC Resource Manager
+ *
+ *    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.
+ */
+
+/*
+ * Checks whether the string argument matches the pattern argument,
+ * which is a wildcard pattern.
+ */
+int wildcard_match(const char * pattern, const char * string);
-- 
cgit v1.2.3