ipsec-types: Add helper to parse interface ID
authorTobias Brunner <tobias@strongswan.org>
Tue, 12 Feb 2019 11:25:53 +0000 (12:25 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 3 Apr 2019 10:00:08 +0000 (12:00 +0200)
src/libstrongswan/ipsec/ipsec_types.c
src/libstrongswan/ipsec/ipsec_types.h
src/libstrongswan/tests/suites/test_utils.c

index 6f19cc7..aa0728b 100644 (file)
@@ -147,3 +147,44 @@ bool mark_from_string(const char *value, mark_op_t ops, mark_t *mark)
        }
        return TRUE;
 }
+
+/*
+ * See header
+ */
+bool if_id_from_string(const char *value, uint32_t *if_id)
+{
+       char *endptr;
+
+       if (!value)
+       {
+               return FALSE;
+       }
+       if (strcasepfx(value, "%unique"))
+       {
+               endptr = (char*)value + strlen("%unique");
+               if (strcasepfx(endptr, "-dir"))
+               {
+                       *if_id = IF_ID_UNIQUE_DIR;
+                       endptr += strlen("-dir");
+               }
+               else if (!*endptr)
+               {
+                       *if_id = IF_ID_UNIQUE;
+               }
+               else
+               {
+                       DBG1(DBG_APP, "invalid interface ID: %s", value);
+                       return FALSE;
+               }
+       }
+       else
+       {
+               *if_id = strtoul(value, &endptr, 0);
+       }
+       if (*endptr)
+       {
+               DBG1(DBG_APP, "invalid interface ID: %s", value);
+               return FALSE;
+       }
+       return TRUE;
+}
index 7b7bd37..6750e22 100644 (file)
@@ -240,4 +240,20 @@ enum mark_op_t {
  */
 bool mark_from_string(const char *value, mark_op_t ops, mark_t *mark);
 
+/**
+ * Special interface ID values to allocate a unique ID for each CHILD_SA/dir
+ */
+#define IF_ID_UNIQUE (0xFFFFFFFF)
+#define IF_ID_UNIQUE_DIR (0xFFFFFFFE)
+#define IF_ID_IS_UNIQUE(m) ((m) == IF_ID_UNIQUE || (m) == IF_ID_UNIQUE_DIR)
+
+/**
+ * Try to parse an interface ID from the given string.
+ *
+ * @param value                string to parse
+ * @param if_id                interface ID to fill
+ * @return                     TRUE if parsing was successful
+ */
+bool if_id_from_string(const char *value, uint32_t *if_id);
+
 #endif /** IPSEC_TYPES_H_ @}*/
index f1d46ee..976d7f4 100644 (file)
@@ -941,6 +941,49 @@ START_TEST(test_mark_from_string)
 END_TEST
 
 /*******************************************************************************
+ * if_id_from_string
+ */
+
+static struct {
+       char *s;
+       bool ok;
+       uint32_t i;
+} if_id_data[] = {
+       {NULL,                  FALSE,  0 },
+       {"",                    TRUE,   0 },
+       {"/",                   FALSE,  0 },
+       {"42",                  TRUE,   42 },
+       {"0x42",                TRUE,   0x42 },
+       {"x",                   FALSE,  0 },
+       {"42/",                 FALSE,  0 },
+       {"42/0",                FALSE,  0 },
+       {"%unique",             TRUE,   IF_ID_UNIQUE },
+       {"%unique/",    FALSE,  0},
+       {"%unique0xffffffffff", FALSE,  0},
+       {"0xffffffff",  TRUE,   IF_ID_UNIQUE},
+       {"%unique-dir", TRUE,   IF_ID_UNIQUE_DIR},
+       {"%unique-dir/",FALSE,  0},
+       {"0xfffffffe",  TRUE,   IF_ID_UNIQUE_DIR},
+       {"%unique-",    FALSE,  0},
+       {"%unique-foo", FALSE,  0},
+};
+
+START_TEST(test_if_id_from_string)
+{
+       uint32_t if_id;
+
+       if (if_id_from_string(if_id_data[_i].s, &if_id))
+       {
+               ck_assert_int_eq(if_id, if_id_data[_i].i);
+       }
+       else
+       {
+               ck_assert(!if_id_data[_i].ok);
+       }
+}
+END_TEST
+
+/*******************************************************************************
  * signature_schemes_for_key
  */
 
@@ -1087,6 +1130,10 @@ Suite *utils_suite_create()
        tcase_add_loop_test(tc, test_mark_from_string, 0, countof(mark_data));
        suite_add_tcase(s, tc);
 
+       tc = tcase_create("if_id_from_string");
+       tcase_add_loop_test(tc, test_if_id_from_string, 0, countof(if_id_data));
+       suite_add_tcase(s, tc);
+
        tc = tcase_create("signature_schemes_for_key");
        tcase_add_loop_test(tc, test_signature_schemes_for_key, 0, countof(scheme_data));
        suite_add_tcase(s, tc);