enum: Return boolean result for enum_from_name() lookup
authorMartin Willi <martin@revosec.ch>
Fri, 16 May 2014 09:57:54 +0000 (11:57 +0200)
committerMartin Willi <martin@revosec.ch>
Fri, 16 May 2014 13:42:07 +0000 (15:42 +0200)
Handling the result for enum_from_name() is difficult, as checking for
negative return values requires a cast if the enum type is unsigned. The new
signature clearly differentiates lookup result from lookup value.

Further, this actually allows to convert real -1 enum values, which could not
be distinguished from "not-found" and the -1 return value.

This also fixes several clang warnings where enums are unsigned.

28 files changed:
scripts/hash_burn.c
src/charon-cmd/cmd/cmd_connection.c
src/conftest/hooks/add_notify.c
src/conftest/hooks/add_payload.c
src/conftest/hooks/custom_proposal.c
src/conftest/hooks/set_critical.c
src/conftest/hooks/set_length.c
src/conftest/hooks/set_reserved.c
src/conftest/hooks/unencrypted_notify.c
src/conftest/hooks/unsort_message.c
src/libcharon/plugins/coupling/coupling_validator.c
src/libcharon/plugins/eap_radius/eap_radius_forward.c
src/libcharon/plugins/load_tester/load_tester_creds.c
src/libcharon/plugins/stroke/stroke_socket.c
src/libcharon/plugins/vici/vici_query.c
src/libstrongswan/tests/suites/test_enum.c
src/libstrongswan/utils/enum.c
src/libstrongswan/utils/enum.h
src/libtls/tls_crypto.c
src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c
src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c
src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c
src/pki/commands/acert.c
src/pki/commands/issue.c
src/pki/commands/req.c
src/pki/commands/self.c
src/pki/commands/signcrl.c
src/swanctl/commands/list_certs.c

index 97eab0d..0aa9bf1 100644 (file)
@@ -43,8 +43,7 @@ int main(int argc, char *argv[])
                limit = atoi(argv[2]);
        }
 
-       alg = enum_from_name(hash_algorithm_short_names, argv[1]);
-       if (alg == -1)
+       if (!enum_from_name(hash_algorithm_short_names, argv[1], &alg))
        {
                fprintf(stderr, "unknown hash algorthm: %s\n", argv[1]);
                return 1;
index ac085e1..c4c8a2a 100644 (file)
@@ -460,10 +460,9 @@ static void add_ts(private_cmd_connection_t *this,
  */
 static void set_profile(private_cmd_connection_t *this, char *name)
 {
-       int profile;
+       profile_t profile;
 
-       profile = enum_from_name(profile_names, name);
-       if (profile == -1)
+       if (!enum_from_name(profile_names, name, &profile))
        {
                DBG1(DBG_CFG, "unknown connection profile: %s", name);
                exit(1);
index 9611cad..504b02a 100644 (file)
@@ -73,8 +73,7 @@ METHOD(listener_t, message, bool,
                type = atoi(this->type);
                if (!type)
                {
-                       type = enum_from_name(notify_type_names, this->type);
-                       if (type == -1)
+                       if (!enum_from_name(notify_type_names, this->type, &type))
                        {
                                DBG1(DBG_CFG, "unknown notify: '%s', skipped", this->type);
                                return TRUE;
index 2903bb2..cb5be1a 100644 (file)
@@ -77,8 +77,7 @@ METHOD(listener_t, message, bool,
                type = atoi(this->type);
                if (!type)
                {
-                       type = enum_from_name(payload_type_short_names, this->type);
-                       if (type == -1)
+                       if (!enum_from_name(payload_type_short_names, this->type, &type))
                        {
                                DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type);
                                return TRUE;
index 38d4286..6086d13 100644 (file)
@@ -79,8 +79,7 @@ static linked_list_t* load_proposals(private_custom_proposal_t *this,
                        type = strtoul(key, &end, 10);
                        if (end == key || errno)
                        {
-                               type = enum_from_name(transform_type_names, key);
-                               if (type == -1)
+                               if (!enum_from_name(transform_type_names, key, &type))
                                {
                                        DBG1(DBG_CFG, "unknown transform: '%s', skipped", key);
                                        continue;
index 8ec84e1..15c313c 100644 (file)
@@ -65,8 +65,7 @@ METHOD(listener_t, message, bool,
                        type = atoi(name);
                        if (!type)
                        {
-                               type = enum_from_name(payload_type_short_names, name);
-                               if (type == -1)
+                               if (!enum_from_name(payload_type_short_names, name, &type))
                                {
                                        DBG1(DBG_CFG, "invalid payload name '%s'", name);
                                        break;
index c1a867a..b1a1a47 100644 (file)
@@ -63,8 +63,7 @@ METHOD(listener_t, message, bool,
                type = atoi(this->type);
                if (!type)
                {
-                       type = enum_from_name(payload_type_short_names, this->type);
-                       if (type == -1)
+                       if (!enum_from_name(payload_type_short_names, this->type, &type))
                        {
                                DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type);
                                return TRUE;
index d1a4a97..5961aeb 100644 (file)
@@ -181,8 +181,7 @@ METHOD(listener_t, message, bool,
                        type = atoi(name);
                        if (!type)
                        {
-                               type = enum_from_name(payload_type_short_names, name);
-                               if (type == -1)
+                               if (!enum_from_name(payload_type_short_names, name, &type))
                                {
                                        DBG1(DBG_CFG, "invalid payload name '%s'", name);
                                        break;
index f4c3572..dae76fa 100644 (file)
@@ -68,8 +68,7 @@ METHOD(listener_t, ike_updown, bool,
                type = atoi(this->type);
                if (!type)
                {
-                       type = enum_from_name(notify_type_names, this->type);
-                       if (type == -1)
+                       if (!enum_from_name(notify_type_names, this->type, &type))
                        {
                                DBG1(DBG_CFG, "unknown notify: '%s', skipped", this->type);
                                return TRUE;
index 1b2b302..399d293 100644 (file)
@@ -69,8 +69,7 @@ METHOD(listener_t, message, bool,
                order = enumerator_create_token(this->order, ", ", " ");
                while (order->enumerate(order, &name))
                {
-                       type = enum_from_name(payload_type_short_names, name);
-                       if (type != -1)
+                       if (enum_from_name(payload_type_short_names, name, &type))
                        {
                                enumerator = list->create_enumerator(list);
                                while (enumerator->enumerate(enumerator, &payload))
index fc35462..0686e0f 100644 (file)
@@ -202,6 +202,7 @@ METHOD(coupling_validator_t, destroy, void,
 coupling_validator_t *coupling_validator_create()
 {
        private_coupling_validator_t *this;
+       hash_algorithm_t alg;
        char *path, *hash;
 
        INIT(this,
@@ -219,8 +220,13 @@ coupling_validator_t *coupling_validator_create()
 
        hash = lib->settings->get_str(lib->settings,
                                                                  "%s.plugins.coupling.hash", "sha1", lib->ns);
-       this->hasher = lib->crypto->create_hasher(lib->crypto,
-                                                       enum_from_name(hash_algorithm_short_names, hash));
+       if (!enum_from_name(hash_algorithm_short_names, hash, &alg))
+       {
+               DBG1(DBG_CFG, "unknown coupling hash algorithm: %s", hash);
+               destroy(this);
+               return NULL;
+       }
+       this->hasher = lib->crypto->create_hasher(lib->crypto, alg);
        if (!this->hasher)
        {
                DBG1(DBG_CFG, "unsupported coupling hash algorithm: %s", hash);
index 54d52a9..a41d520 100644 (file)
@@ -362,8 +362,7 @@ static linked_list_t* parse_selector(char *selector)
                        vendor = atoi(token);
                        token = pos;
                }
-               type = enum_from_name(radius_attribute_type_names, token);
-               if (type == -1)
+               if (!enum_from_name(radius_attribute_type_names, token, &type))
                {
                        type = atoi(token);
                }
index f17d41f..8fbb611 100644 (file)
@@ -465,7 +465,6 @@ load_tester_creds_t *load_tester_creds_create()
                .private = load_issuer_key(),
                .ca = load_issuer_cert(),
                .cas = linked_list_create(),
-               .digest = enum_from_name(hash_algorithm_short_names, digest),
                .psk = shared_key_create(SHARED_IKE,
                                                                 chunk_clone(chunk_create(psk, strlen(psk)))),
                .pwd = shared_key_create(SHARED_EAP,
@@ -477,7 +476,7 @@ load_tester_creds_t *load_tester_creds_create()
                this->cas->insert_last(this->cas, this->ca->get_ref(this->ca));
        }
 
-       if (this->digest == -1)
+       if (!enum_from_name(hash_algorithm_short_names, digest, &this->digest))
        {
                DBG1(DBG_CFG, "invalid load-tester digest: '%s', using sha1", digest);
                this->digest = HASH_SHA1;
@@ -487,4 +486,3 @@ load_tester_creds_t *load_tester_creds_create()
 
        return &this->public;
 }
-
index 169ff2b..553a7cd 100644 (file)
@@ -584,8 +584,7 @@ static void stroke_loglevel(private_stroke_socket_t *this,
        }
        else
        {
-               group = enum_from_name(debug_names, msg->loglevel.type);
-               if ((int)group < 0)
+               if (!enum_from_name(debug_names, msg->loglevel.type, &group))
                {
                        fprintf(out, "unknown type '%s'!\n", msg->loglevel.type);
                        return;
index f89ae01..9a8e9a4 100644 (file)
@@ -729,8 +729,7 @@ CALLBACK(list_certs, vici_message_t*,
        char *str;
 
        str = request->get_str(request, "ANY", "type");
-       type = enum_from_name(certificate_type_names, str);
-       if (type == -1)
+       if (!enum_from_name(certificate_type_names, str, &type))
        {
                b = vici_builder_create();
                return b->finalize(b);
index 512448a..b48b51c 100644 (file)
@@ -120,41 +120,50 @@ END_TEST
  */
 
 static struct {
+       bool found;
        int val;
        char *str;
 } enum_tests_cont[] = {
-       {CONT1, "CONT1"},
-       {CONT2, "CONT2"},
-       {CONT2, "CoNt2"},
-       {CONT3, "CONT3"},
-       {CONT4, "CONT4"},
-       {CONT5, "CONT5"},
-       {-1, "asdf"},
-       {-1, ""},
-       {-1, NULL},
+       {TRUE, CONT1, "CONT1"},
+       {TRUE, CONT2, "CONT2"},
+       {TRUE, CONT2, "CoNt2"},
+       {TRUE, CONT3, "CONT3"},
+       {TRUE, CONT4, "CONT4"},
+       {TRUE, CONT5, "CONT5"},
+       {FALSE, 0, "asdf"},
+       {FALSE, 0, ""},
+       {FALSE, 0, NULL},
 }, enum_tests_split[] = {
-       {SPLIT1, "SPLIT1"},
-       {SPLIT1, "split1"},
-       {SPLIT2, "SPLIT2"},
-       {SPLIT2, "SpLiT2"},
-       {SPLIT3, "SPLIT3"},
-       {SPLIT4, "SPLIT4"},
-       {SPLIT5, "SPLIT5"},
-       {-1, "asdf"},
-       {-1, ""},
-       {-1, NULL},
+       {TRUE, SPLIT1, "SPLIT1"},
+       {TRUE, SPLIT1, "split1"},
+       {TRUE, SPLIT2, "SPLIT2"},
+       {TRUE, SPLIT2, "SpLiT2"},
+       {TRUE, SPLIT3, "SPLIT3"},
+       {TRUE, SPLIT4, "SPLIT4"},
+       {TRUE, SPLIT5, "SPLIT5"},
+       {FALSE, 0, "asdf"},
+       {FALSE, 0, ""},
+       {FALSE, 0, NULL},
 };
 
 START_TEST(test_enum_from_name_cont)
 {
-       int val = enum_from_name(test_enum_cont_names, enum_tests_cont[_i].str);
+       int val = 0;
+       bool found;
+
+       found = enum_from_name(test_enum_cont_names, enum_tests_cont[_i].str, &val);
+       ck_assert(enum_tests_cont[_i].found == found);
        ck_assert_int_eq(val, enum_tests_cont[_i].val);
 }
 END_TEST
 
 START_TEST(test_enum_from_name_split)
 {
-       int val = enum_from_name(test_enum_split_names, enum_tests_split[_i].str);
+       int val = 0;
+       bool found;
+
+       found = enum_from_name(test_enum_split_names, enum_tests_split[_i].str, &val);
+       ck_assert(enum_tests_split[_i].found == found);
        ck_assert_int_eq(val, enum_tests_split[_i].val);
 }
 END_TEST
index 465121e..f96fe29 100644 (file)
@@ -40,7 +40,7 @@ char *enum_to_name(enum_name_t *e, int val)
 /**
  * See header.
  */
-int enum_from_name(enum_name_t *e, char *name)
+bool enum_from_name_as_int(enum_name_t *e, const char *name, int *val)
 {
        do
        {
@@ -50,12 +50,13 @@ int enum_from_name(enum_name_t *e, char *name)
                {
                        if (name && strcaseeq(name, e->names[i]))
                        {
-                               return e->first + i;
+                               *val = e->first + i;
+                               return TRUE;
                        }
                }
        }
        while ((e = e->next));
-       return -1;
+       return FALSE;
 }
 
 /**
index a2f97d0..a164857 100644 (file)
@@ -120,9 +120,30 @@ char *enum_to_name(enum_name_t *e, int val);
  *
  * @param e            enum names for this enum value
  * @param name name to get enum value for
- * @return             enum value, -1 if not found
+ * @├żaram valp        variable sized pointer receiving value
+ * @return             TRUE if enum name found, FALSE otherwise
  */
-int enum_from_name(enum_name_t *e, char *name);
+#define enum_from_name(e, name, valp) ({ \
+       int _val; \
+       int _found = enum_from_name_as_int(e, name, &_val); \
+       if (_found) \
+       { \
+               *(valp) = _val; \
+       } \
+       _found; })
+
+/**
+ * Convert a enum string back to its enum value, integer pointer variant.
+ *
+ * This variant takes integer pointer only, use enum_from_name() to pass
+ * enum type pointers for the result.
+ *
+ * @param e            enum names for this enum value
+ * @param name name to get enum value for
+ * @├żaram val integer pointer receiving value
+ * @return             TRUE if enum name found, FALSE otherwise
+ */
+bool enum_from_name_as_int(enum_name_t *e, const char *name, int *val);
 
 /**
  * printf hook function for enum_names_t.
index 4f67b20..2cffeb8 100644 (file)
@@ -959,8 +959,8 @@ static void filter_specific_config_suites(private_tls_crypto_t *this,
                        enumerator = enumerator_create_token(config, ",", " ");
                        while (enumerator->enumerate(enumerator, &token))
                        {
-                               suite = enum_from_name(tls_cipher_suite_names, token);
-                               if (suite == suites[i].suite)
+                               if (enum_from_name(tls_cipher_suite_names, token, &suite) &&
+                                       suite == suites[i].suite)
                                {
                                        suites[remaining++] = suites[i];
                                        break;
index 5624501..1a03158 100644 (file)
@@ -432,7 +432,7 @@ METHOD(imv_manager_t, destroy, void,
 imv_manager_t* tnc_imv_manager_create(void)
 {
        private_tnc_imv_manager_t *this;
-       recommendation_policy_t policy;
+       char *polname;
 
        INIT(this,
                .public = {
@@ -458,11 +458,12 @@ imv_manager_t* tnc_imv_manager_create(void)
                .next_imv_id = 1,
        );
 
-       policy = enum_from_name(recommendation_policy_names,
-                               lib->settings->get_str(lib->settings,
-                                       "%s.plugins.tnc-imv.recommendation_policy",
-                                       "default", lib->ns));
-       this->policy = (policy != -1) ? policy : RECOMMENDATION_POLICY_DEFAULT;
+       polname = lib->settings->get_str(lib->settings,
+                               "%s.plugins.tnc-imv.recommendation_policy", "default", lib->ns);
+       if (!enum_from_name(recommendation_policy_names, polname, &this->policy))
+       {
+               this->policy = RECOMMENDATION_POLICY_DEFAULT;
+       }
        DBG1(DBG_TNC, "TNC recommendation policy is '%N'",
                                   recommendation_policy_names, this->policy);
 
index 86b7c6a..26a6c03 100644 (file)
@@ -128,9 +128,8 @@ tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node)
        error_type_name = xmlGetProp(node, "type");
        if (error_type_name)
        {
-               this->error_type = enum_from_name(tnccs_error_type_names,
-                                                                                 error_type_name);
-               if (this->error_type == -1)
+               if (!enum_from_name(tnccs_error_type_names, error_type_name,
+                                                       &this->error_type))
                {
                        this->error_type = TNCCS_ERROR_OTHER;
                }
index fa5ce82..e373656 100644 (file)
@@ -41,7 +41,7 @@ tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
        char *error_msg, buf[BUF_LEN];
        tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
        tnccs_msg_t *msg;
-       tnccs_msg_type_t type = IMC_IMV_MSG;
+       tnccs_msg_type_t type = IMC_IMV_MSG, nametype;
 
        if (streq((char*)node->name, "IMC-IMV-Message"))
        {
@@ -103,7 +103,8 @@ tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
                                error_msg = "node is not in the TNCCS message namespace";
                                goto fatal;
                        }
-                       if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name))
+                       if (!enum_from_name(tnccs_msg_type_names, cur->name, &nametype) ||
+                               type != nametype)
                        {
                                error_msg = buf;
                                snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'",
@@ -137,4 +138,3 @@ fatal:
        errors->insert_last(errors, msg);
        return NULL;
 }
-
index d49365d..4a11c47 100644 (file)
@@ -53,8 +53,7 @@ static int acert()
                        case 'h':
                                goto usage;
                        case 'g':
-                               digest = enum_from_name(hash_algorithm_short_names, arg);
-                               if (digest == -1)
+                               if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
                                {
                                        error = "invalid --digest type";
                                        goto usage;
index d03326e..339a880 100644 (file)
@@ -106,8 +106,7 @@ static int issue()
                                }
                                continue;
                        case 'g':
-                               digest = enum_from_name(hash_algorithm_short_names, arg);
-                               if (digest == -1)
+                               if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
                                {
                                        error = "invalid --digest type";
                                        goto usage;
index 5b2c128..1dce8cb 100644 (file)
@@ -64,8 +64,7 @@ static int req()
                                }
                                continue;
                        case 'g':
-                               digest = enum_from_name(hash_algorithm_short_names, arg);
-                               if (digest == -1)
+                               if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
                                {
                                        error = "invalid --digest type";
                                        goto usage;
index a35a42b..80f5053 100644 (file)
@@ -95,8 +95,7 @@ static int self()
                                }
                                continue;
                        case 'g':
-                               digest = enum_from_name(hash_algorithm_short_names, arg);
-                               if (digest == -1)
+                               if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
                                {
                                        error = "invalid --digest type";
                                        goto usage;
index c9eebbf..3be020a 100644 (file)
@@ -142,8 +142,7 @@ static int sign_crl()
                        case 'h':
                                goto usage;
                        case 'g':
-                               digest = enum_from_name(hash_algorithm_short_names, arg);
-                               if (digest == -1)
+                               if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
                                {
                                        error = "invalid --digest type";
                                        goto usage;
index d9b7738..6d7b6a9 100644 (file)
@@ -556,10 +556,10 @@ CALLBACK(list_cb, void,
                bool has_privkey;
 
                buf = vici_find(res, &len, "data");
-               type = enum_from_name(certificate_type_names,
-                                                         vici_find_str(res, "ANY", "type"));
                has_privkey = streq(vici_find_str(res, "no", "has_privkey"), "yes");
-               if (type != -1 && type != CERT_ANY && buf)
+               if (enum_from_name(certificate_type_names,
+                                                  vici_find_str(res, "ANY", "type"), &type) &&
+                       type != CERT_ANY && buf)
                {
                        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
                                                                        BUILD_BLOB_ASN1_DER, chunk_create(buf, len),