diff options
Diffstat (limited to 'usr.sbin/ctld/uclparse.cc')
-rw-r--r-- | usr.sbin/ctld/uclparse.cc | 1279 |
1 files changed, 794 insertions, 485 deletions
diff --git a/usr.sbin/ctld/uclparse.cc b/usr.sbin/ctld/uclparse.cc index 1eb9f7736e4b..8a62636ffec6 100644 --- a/usr.sbin/ctld/uclparse.cc +++ b/usr.sbin/ctld/uclparse.cc @@ -37,297 +37,392 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <ucl.h> +#include <ucl++.h> #include <netinet/in.h> #include <netinet/ip.h> +#include <libutil++.hh> +#include <memory> + #include "conf.h" -#include "ctld.h" - -static bool uclparse_toplevel(const ucl_object_t *); -static bool uclparse_chap(const char *, const ucl_object_t *); -static bool uclparse_chap_mutual(const char *, const ucl_object_t *); -static bool uclparse_lun(const char *, const ucl_object_t *); -static bool uclparse_lun_entries(const char *, const ucl_object_t *); -static bool uclparse_auth_group(const char *, const ucl_object_t *); -static bool uclparse_portal_group(const char *, const ucl_object_t *); -static bool uclparse_target(const char *, const ucl_object_t *); -static bool uclparse_target_portal_group(const char *, const ucl_object_t *); -static bool uclparse_target_lun(const char *, const ucl_object_t *); +#include "ctld.hh" + +struct scope_exit { + using callback = void(); + scope_exit(callback *fn) : fn(fn) {} + + ~scope_exit() { fn(); } + +private: + callback *fn; +}; + +static bool uclparse_toplevel(const ucl::Ucl &); +static bool uclparse_chap(const char *, const ucl::Ucl &); +static bool uclparse_chap_mutual(const char *, const ucl::Ucl &); +static bool uclparse_lun(const char *, const ucl::Ucl &); +static bool uclparse_lun_entries(const char *, const ucl::Ucl &); +static bool uclparse_auth_group(const char *, const ucl::Ucl &); +static bool uclparse_portal_group(const char *, const ucl::Ucl &); +static bool uclparse_transport_group(const char *, const ucl::Ucl &); +static bool uclparse_controller(const char *, const ucl::Ucl &); +static bool uclparse_controller_transport_group(const char *, const ucl::Ucl &); +static bool uclparse_controller_namespace(const char *, const ucl::Ucl &); +static bool uclparse_target(const char *, const ucl::Ucl &); +static bool uclparse_target_portal_group(const char *, const ucl::Ucl &); +static bool uclparse_target_lun(const char *, const ucl::Ucl &); static bool -uclparse_chap(const char *ag_name, const ucl_object_t *obj) +uclparse_chap(const char *ag_name, const ucl::Ucl &obj) { - const ucl_object_t *user, *secret; - - user = ucl_object_find_key(obj, "user"); - if (!user || user->type != UCL_STRING) { + auto user = obj["user"]; + if (!user || user.type() != UCL_STRING) { log_warnx("chap section in auth-group \"%s\" is missing " "\"user\" string key", ag_name); return (false); } - secret = ucl_object_find_key(obj, "secret"); - if (!secret || secret->type != UCL_STRING) { + auto secret = obj["secret"]; + if (!secret || secret.type() != UCL_STRING) { log_warnx("chap section in auth-group \"%s\" is missing " "\"secret\" string key", ag_name); return (false); } return (auth_group_add_chap( - ucl_object_tostring(user), - ucl_object_tostring(secret))); + user.string_value().c_str(), + secret.string_value().c_str())); } static bool -uclparse_chap_mutual(const char *ag_name, const ucl_object_t *obj) +uclparse_chap_mutual(const char *ag_name, const ucl::Ucl &obj) { - const ucl_object_t *user, *secret, *mutual_user; - const ucl_object_t *mutual_secret; - - user = ucl_object_find_key(obj, "user"); - if (!user || user->type != UCL_STRING) { + auto user = obj["user"]; + if (!user || user.type() != UCL_STRING) { log_warnx("chap-mutual section in auth-group \"%s\" is missing " "\"user\" string key", ag_name); return (false); } - secret = ucl_object_find_key(obj, "secret"); - if (!secret || secret->type != UCL_STRING) { + auto secret = obj["secret"]; + if (!secret || secret.type() != UCL_STRING) { log_warnx("chap-mutual section in auth-group \"%s\" is missing " "\"secret\" string key", ag_name); return (false); } - mutual_user = ucl_object_find_key(obj, "mutual-user"); - if (!mutual_user || mutual_user->type != UCL_STRING) { + auto mutual_user = obj["mutual-user"]; + if (!mutual_user || mutual_user.type() != UCL_STRING) { log_warnx("chap-mutual section in auth-group \"%s\" is missing " "\"mutual-user\" string key", ag_name); return (false); } - mutual_secret = ucl_object_find_key(obj, "mutual-secret"); - if (!mutual_secret || mutual_secret->type != UCL_STRING) { + auto mutual_secret = obj["mutual-secret"]; + if (!mutual_secret || mutual_secret.type() != UCL_STRING) { log_warnx("chap-mutual section in auth-group \"%s\" is missing " "\"mutual-secret\" string key", ag_name); return (false); } return (auth_group_add_chap_mutual( - ucl_object_tostring(user), - ucl_object_tostring(secret), - ucl_object_tostring(mutual_user), - ucl_object_tostring(mutual_secret))); + user.string_value().c_str(), + secret.string_value().c_str(), + mutual_user.string_value().c_str(), + mutual_secret.string_value().c_str())); } static bool -uclparse_target_chap(const char *t_name, const ucl_object_t *obj) +uclparse_target_chap(const char *t_name, const ucl::Ucl &obj) { - const ucl_object_t *user, *secret; - - user = ucl_object_find_key(obj, "user"); - if (!user || user->type != UCL_STRING) { + auto user = obj["user"]; + if (!user || user.type() != UCL_STRING) { log_warnx("chap section in target \"%s\" is missing " "\"user\" string key", t_name); return (false); } - secret = ucl_object_find_key(obj, "secret"); - if (!secret || secret->type != UCL_STRING) { + auto secret = obj["secret"]; + if (!secret || secret.type() != UCL_STRING) { log_warnx("chap section in target \"%s\" is missing " "\"secret\" string key", t_name); return (false); } return (target_add_chap( - ucl_object_tostring(user), - ucl_object_tostring(secret))); + user.string_value().c_str(), + secret.string_value().c_str())); } static bool -uclparse_target_chap_mutual(const char *t_name, const ucl_object_t *obj) +uclparse_target_chap_mutual(const char *t_name, const ucl::Ucl &obj) { - const ucl_object_t *user, *secret, *mutual_user; - const ucl_object_t *mutual_secret; - - user = ucl_object_find_key(obj, "user"); - if (!user || user->type != UCL_STRING) { + auto user = obj["user"]; + if (!user || user.type() != UCL_STRING) { log_warnx("chap-mutual section in target \"%s\" is missing " "\"user\" string key", t_name); return (false); } - secret = ucl_object_find_key(obj, "secret"); - if (!secret || secret->type != UCL_STRING) { + auto secret = obj["secret"]; + if (!secret || secret.type() != UCL_STRING) { log_warnx("chap-mutual section in target \"%s\" is missing " "\"secret\" string key", t_name); return (false); } - mutual_user = ucl_object_find_key(obj, "mutual-user"); - if (!mutual_user || mutual_user->type != UCL_STRING) { + auto mutual_user = obj["mutual-user"]; + if (!mutual_user || mutual_user.type() != UCL_STRING) { log_warnx("chap-mutual section in target \"%s\" is missing " "\"mutual-user\" string key", t_name); return (false); } - mutual_secret = ucl_object_find_key(obj, "mutual-secret"); - if (!mutual_secret || mutual_secret->type != UCL_STRING) { + auto mutual_secret = obj["mutual-secret"]; + if (!mutual_secret || mutual_secret.type() != UCL_STRING) { log_warnx("chap-mutual section in target \"%s\" is missing " "\"mutual-secret\" string key", t_name); return (false); } return (target_add_chap_mutual( - ucl_object_tostring(user), - ucl_object_tostring(secret), - ucl_object_tostring(mutual_user), - ucl_object_tostring(mutual_secret))); + user.string_value().c_str(), + secret.string_value().c_str(), + mutual_user.string_value().c_str(), + mutual_secret.string_value().c_str())); } static bool -uclparse_target_portal_group(const char *t_name, const ucl_object_t *obj) +uclparse_target_portal_group(const char *t_name, const ucl::Ucl &obj) { - const ucl_object_t *portal_group, *auth_group; - const char *ag_name; - /* * If the value is a single string, assume it is a * portal-group name. */ - if (obj->type == UCL_STRING) - return (target_add_portal_group(ucl_object_tostring(obj), + if (obj.type() == UCL_STRING) + return (target_add_portal_group(obj.string_value().c_str(), NULL)); - if (obj->type != UCL_OBJECT) { + if (obj.type() != UCL_OBJECT) { log_warnx("portal-group section in target \"%s\" must be " "an object or string", t_name); return (false); } - portal_group = ucl_object_find_key(obj, "name"); - if (!portal_group || portal_group->type != UCL_STRING) { + auto portal_group = obj["name"]; + if (!portal_group || portal_group.type() != UCL_STRING) { log_warnx("portal-group section in target \"%s\" is missing " "\"name\" string key", t_name); return (false); } - auth_group = ucl_object_find_key(obj, "auth-group-name"); - if (auth_group != NULL) { - if (auth_group->type != UCL_STRING) { + auto auth_group = obj["auth-group-name"]; + if (auth_group) { + if (auth_group.type() != UCL_STRING) { log_warnx("\"auth-group-name\" property in " "portal-group section for target \"%s\" is not " "a string", t_name); return (false); } - ag_name = ucl_object_tostring(auth_group); - } else - ag_name = NULL; + return (target_add_portal_group( + portal_group.string_value().c_str(), + auth_group.string_value().c_str())); + } + + return (target_add_portal_group(portal_group.string_value().c_str(), + NULL)); +} + +static bool +uclparse_controller_transport_group(const char *t_name, const ucl::Ucl &obj) +{ + /* + * If the value is a single string, assume it is a + * transport-group name. + */ + if (obj.type() == UCL_STRING) + return target_add_portal_group(obj.string_value().c_str(), + nullptr); + + if (obj.type() != UCL_OBJECT) { + log_warnx("transport-group section in controller \"%s\" must " + "be an object or string", t_name); + return false; + } + + auto portal_group = obj["name"]; + if (!portal_group || portal_group.type() != UCL_STRING) { + log_warnx("transport-group section in controller \"%s\" is " + "missing \"name\" string key", t_name); + return false; + } + + auto auth_group = obj["auth-group-name"]; + if (auth_group) { + if (auth_group.type() != UCL_STRING) { + log_warnx("\"auth-group-name\" property in " + "transport-group section for controller \"%s\" is " + "not a string", t_name); + return false; + } + return target_add_portal_group( + portal_group.string_value().c_str(), + auth_group.string_value().c_str()); + } - return (target_add_portal_group(ucl_object_tostring(portal_group), - ag_name)); + return target_add_portal_group(portal_group.string_value().c_str(), + nullptr); } static bool -uclparse_target_lun(const char *t_name, const ucl_object_t *obj) +uclparse_target_lun(const char *t_name, const ucl::Ucl &obj) { - const ucl_object_t *num; - const ucl_object_t *name; - const char *key; - char *end, *lun_name; + char *end; u_int id; - bool ok; - key = ucl_object_key(obj); - if (key != NULL) { - id = strtoul(key, &end, 0); + std::string key = obj.key(); + if (!key.empty()) { + id = strtoul(key.c_str(), &end, 0); if (*end != '\0') { log_warnx("lun key \"%s\" in target \"%s\" is invalid", - key, t_name); + key.c_str(), t_name); return (false); } - if (obj->type == UCL_STRING) - return (target_add_lun(id, ucl_object_tostring(obj))); + if (obj.type() == UCL_STRING) + return (target_add_lun(id, obj.string_value().c_str())); } - if (obj->type != UCL_OBJECT) { + if (obj.type() != UCL_OBJECT) { log_warnx("lun section entries in target \"%s\" must be objects", t_name); return (false); } - if (key == NULL) { - num = ucl_object_find_key(obj, "number"); - if (num == NULL || num->type != UCL_INT) { + if (key.empty()) { + auto num = obj["number"]; + if (!num || num.type() != UCL_INT) { log_warnx("lun section in target \"%s\" is missing " "\"number\" integer property", t_name); return (false); } - id = ucl_object_toint(num); + id = num.int_value(); } - name = ucl_object_find_key(obj, "name"); - if (name == NULL) { + auto name = obj["name"]; + if (!name) { if (!target_start_lun(id)) return (false); - asprintf(&lun_name, "lun %u for target \"%s\"", id, t_name); - ok = uclparse_lun_entries(lun_name, obj); - free(lun_name); - return (ok); + scope_exit finisher(lun_finish); + std::string lun_name = + freebsd::stringf("lun %u for target \"%s\"", id, t_name); + return (uclparse_lun_entries(lun_name.c_str(), obj)); } - if (name->type != UCL_STRING) { + if (name.type() != UCL_STRING) { log_warnx("\"name\" property for lun %u for target " "\"%s\" is not a string", id, t_name); return (false); } - return (target_add_lun(id, ucl_object_tostring(name))); + return (target_add_lun(id, name.string_value().c_str())); } static bool -uclparse_toplevel(const ucl_object_t *top) +uclparse_controller_namespace(const char *t_name, const ucl::Ucl &obj) { - ucl_object_iter_t it = NULL, iter = NULL; - const ucl_object_t *obj = NULL, *child = NULL; + char *end; + u_int id; + + std::string key = obj.key(); + if (!key.empty()) { + id = strtoul(key.c_str(), &end, 0); + if (*end != '\0') { + log_warnx("namespace key \"%s\" in controller \"%s\"" + " is invalid", key.c_str(), t_name); + return false; + } + + if (obj.type() == UCL_STRING) + return controller_add_namespace(id, + obj.string_value().c_str()); + } + + if (obj.type() != UCL_OBJECT) { + log_warnx("namespace section entries in controller \"%s\"" + " must be objects", t_name); + return false; + } + + if (key.empty()) { + auto num = obj["number"]; + if (!num || num.type() != UCL_INT) { + log_warnx("namespace section in controller \"%s\" is " + "missing \"id\" integer property", t_name); + return (false); + } + id = num.int_value(); + } + + auto name = obj["name"]; + if (!name) { + if (!controller_start_namespace(id)) + return false; + + std::string lun_name = + freebsd::stringf("namespace %u for controller \"%s\"", id, + t_name); + return uclparse_lun_entries(lun_name.c_str(), obj); + } + + if (name.type() != UCL_STRING) { + log_warnx("\"name\" property for namespace %u for " + "controller \"%s\" is not a string", id, t_name); + return (false); + } + return controller_add_namespace(id, name.string_value().c_str()); +} + +static bool +uclparse_toplevel(const ucl::Ucl &top) +{ /* Pass 1 - everything except targets */ - while ((obj = ucl_iterate_object(top, &it, true))) { - const char *key = ucl_object_key(obj); + for (const auto &obj : top) { + std::string key = obj.key(); - if (strcmp(key, "debug") == 0) { - if (obj->type == UCL_INT) - conf_set_debug(ucl_object_toint(obj)); + if (key == "debug") { + if (obj.type() == UCL_INT) + conf_set_debug(obj.int_value()); else { log_warnx("\"debug\" property value is not integer"); return (false); } } - if (strcmp(key, "timeout") == 0) { - if (obj->type == UCL_INT) - conf_set_timeout(ucl_object_toint(obj)); + if (key == "timeout") { + if (obj.type() == UCL_INT) + conf_set_timeout(obj.int_value()); else { log_warnx("\"timeout\" property value is not integer"); return (false); } } - if (strcmp(key, "maxproc") == 0) { - if (obj->type == UCL_INT) - conf_set_maxproc(ucl_object_toint(obj)); + if (key == "maxproc") { + if (obj.type() == UCL_INT) + conf_set_maxproc(obj.int_value()); else { log_warnx("\"maxproc\" property value is not integer"); return (false); } } - if (strcmp(key, "pidfile") == 0) { - if (obj->type == UCL_STRING) { + if (key == "pidfile") { + if (obj.type() == UCL_STRING) { if (!conf_set_pidfile_path( - ucl_object_tostring(obj))) + obj.string_value().c_str())) return (false); } else { log_warnx("\"pidfile\" property value is not string"); @@ -335,16 +430,14 @@ uclparse_toplevel(const ucl_object_t *top) } } - if (strcmp(key, "isns-server") == 0) { - if (obj->type == UCL_ARRAY) { - iter = NULL; - while ((child = ucl_iterate_object(obj, &iter, - true))) { - if (child->type != UCL_STRING) + if (key == "isns-server") { + if (obj.type() == UCL_ARRAY) { + for (const auto &child : obj) { + if (child.type() != UCL_STRING) return (false); if (!isns_add_server( - ucl_object_tostring(child))) + child.string_value().c_str())) return (false); } } else { @@ -354,30 +447,29 @@ uclparse_toplevel(const ucl_object_t *top) } } - if (strcmp(key, "isns-period") == 0) { - if (obj->type == UCL_INT) - conf_set_isns_period(ucl_object_toint(obj)); + if (key == "isns-period") { + if (obj.type() == UCL_INT) + conf_set_isns_period(obj.int_value()); else { log_warnx("\"isns-period\" property value is not integer"); return (false); } } - if (strcmp(key, "isns-timeout") == 0) { - if (obj->type == UCL_INT) - conf_set_isns_timeout(ucl_object_toint(obj)); + if (key == "isns-timeout") { + if (obj.type() == UCL_INT) + conf_set_isns_timeout(obj.int_value()); else { log_warnx("\"isns-timeout\" property value is not integer"); return (false); } } - if (strcmp(key, "auth-group") == 0) { - if (obj->type == UCL_OBJECT) { - iter = NULL; - while ((child = ucl_iterate_object(obj, &iter, true))) { + if (key == "auth-group") { + if (obj.type() == UCL_OBJECT) { + for (const auto &child : obj) { if (!uclparse_auth_group( - ucl_object_key(child), child)) + child.key().c_str(), child)) return (false); } } else { @@ -386,12 +478,11 @@ uclparse_toplevel(const ucl_object_t *top) } } - if (strcmp(key, "portal-group") == 0) { - if (obj->type == UCL_OBJECT) { - iter = NULL; - while ((child = ucl_iterate_object(obj, &iter, true))) { + if (key == "portal-group") { + if (obj.type() == UCL_OBJECT) { + for (const auto &child : obj) { if (!uclparse_portal_group( - ucl_object_key(child), child)) + child.key().c_str(), child)) return (false); } } else { @@ -400,11 +491,23 @@ uclparse_toplevel(const ucl_object_t *top) } } - if (strcmp(key, "lun") == 0) { - if (obj->type == UCL_OBJECT) { - iter = NULL; - while ((child = ucl_iterate_object(obj, &iter, true))) { - if (!uclparse_lun(ucl_object_key(child), + if (key == "transport-group") { + if (obj.type() == UCL_OBJECT) { + for (const auto &child : obj) { + if (!uclparse_transport_group( + child.key().c_str(), child)) + return false; + } + } else { + log_warnx("\"transport-group\" section is not an object"); + return false; + } + } + + if (key == "lun") { + if (obj.type() == UCL_OBJECT) { + for (const auto &child : obj) { + if (!uclparse_lun(child.key().c_str(), child)) return (false); } @@ -416,17 +519,27 @@ uclparse_toplevel(const ucl_object_t *top) } /* Pass 2 - targets */ - it = NULL; - while ((obj = ucl_iterate_object(top, &it, true))) { - const char *key = ucl_object_key(obj); - - if (strcmp(key, "target") == 0) { - if (obj->type == UCL_OBJECT) { - iter = NULL; - while ((child = ucl_iterate_object(obj, &iter, - true))) { + for (const auto &obj : top) { + std::string key = obj.key(); + + if (key == "controller") { + if (obj.type() == UCL_OBJECT) { + for (const auto &child : obj) { + if (!uclparse_controller( + child.key().c_str(), child)) + return false; + } + } else { + log_warnx("\"controller\" section is not an object"); + return false; + } + } + + if (key == "target") { + if (obj.type() == UCL_OBJECT) { + for (const auto &child : obj) { if (!uclparse_target( - ucl_object_key(child), child)) + child.key().c_str(), child)) return (false); } } else { @@ -440,179 +553,190 @@ uclparse_toplevel(const ucl_object_t *top) } static bool -uclparse_auth_group(const char *name, const ucl_object_t *top) +uclparse_auth_group(const char *name, const ucl::Ucl &top) { - ucl_object_iter_t it = NULL, it2 = NULL; - const ucl_object_t *obj = NULL, *tmp = NULL; - const char *key; - if (!auth_group_start(name)) return (false); - while ((obj = ucl_iterate_object(top, &it, true))) { - key = ucl_object_key(obj); + scope_exit finisher(auth_group_finish); + for (const auto &obj : top) { + std::string key = obj.key(); - if (strcmp(key, "auth-type") == 0) { - const char *value = ucl_object_tostring(obj); - - if (!auth_group_set_type(value)) - goto fail; + if (key == "auth-type") { + if (!auth_group_set_type(obj.string_value().c_str())) + return false; } - if (strcmp(key, "chap") == 0) { - if (obj->type == UCL_OBJECT) { + if (key == "chap") { + if (obj.type() == UCL_OBJECT) { if (!uclparse_chap(name, obj)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - it2 = NULL; - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!uclparse_chap(name, tmp)) - goto fail; + return false; } } else { log_warnx("\"chap\" property of auth-group " "\"%s\" is not an array or object", name); - goto fail; + return false; } } - if (strcmp(key, "chap-mutual") == 0) { - if (obj->type == UCL_OBJECT) { + if (key == "chap-mutual") { + if (obj.type() == UCL_OBJECT) { if (!uclparse_chap_mutual(name, obj)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - it2 = NULL; - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!uclparse_chap_mutual(name, tmp)) - goto fail; + return false; } } else { log_warnx("\"chap-mutual\" property of " "auth-group \"%s\" is not an array or object", name); - goto fail; + return false; } } - if (strcmp(key, "initiator-name") == 0) { - if (obj->type == UCL_STRING) { - const char *value = ucl_object_tostring(obj); + if (key == "host-address") { + if (obj.type() == UCL_STRING) { + if (!auth_group_add_host_address( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { + if (!auth_group_add_host_address( + tmp.string_value().c_str())) + return false; + } + } else { + log_warnx("\"host-address\" property of " + "auth-group \"%s\" is not an array or string", + name); + return false; + } + } - if (!auth_group_add_initiator_name(value)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - it2 = NULL; - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { - const char *value = - ucl_object_tostring(tmp); + if (key == "host-nqn") { + if (obj.type() == UCL_STRING) { + if (!auth_group_add_host_nqn( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { + if (!auth_group_add_host_nqn( + tmp.string_value().c_str())) + return false; + } + } else { + log_warnx("\"host-nqn\" property of " + "auth-group \"%s\" is not an array or string", + name); + return false; + } + } + if (key == "initiator-name") { + if (obj.type() == UCL_STRING) { + if (!auth_group_add_initiator_name( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!auth_group_add_initiator_name( - value)) - goto fail; + tmp.string_value().c_str())) + return false; } } else { log_warnx("\"initiator-name\" property of " "auth-group \"%s\" is not an array or string", name); - goto fail; + return false; } } - if (strcmp(key, "initiator-portal") == 0) { - if (obj->type == UCL_STRING) { - const char *value = ucl_object_tostring(obj); - - if (!auth_group_add_initiator_portal(value)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - it2 = NULL; - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { - const char *value = - ucl_object_tostring(tmp); - + if (key == "initiator-portal") { + if (obj.type() == UCL_STRING) { + if (!auth_group_add_initiator_portal( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!auth_group_add_initiator_portal( - value)) - goto fail; + tmp.string_value().c_str())) + return false; } } else { log_warnx("\"initiator-portal\" property of " "auth-group \"%s\" is not an array or string", name); - goto fail; + return false; } } } - auth_group_finish(); return (true); -fail: - auth_group_finish(); - return (false); } static bool uclparse_dscp(const char *group_type, const char *pg_name, - const ucl_object_t *obj) + const ucl::Ucl &obj) { - const char *key; - - if ((obj->type != UCL_STRING) && (obj->type != UCL_INT)) { + if ((obj.type() != UCL_STRING) && (obj.type() != UCL_INT)) { log_warnx("\"dscp\" property of %s group \"%s\" is not a " "string or integer", group_type, pg_name); return (false); } - if (obj->type == UCL_INT) - return (portal_group_set_dscp(ucl_object_toint(obj))); + if (obj.type() == UCL_INT) + return (portal_group_set_dscp(obj.int_value())); - key = ucl_object_tostring(obj); - if (strcmp(key, "be") == 0 || strcmp(key, "cs0") == 0) + std::string key = obj.key(); + if (key == "be" || key == "cs0") portal_group_set_dscp(IPTOS_DSCP_CS0 >> 2); - else if (strcmp(key, "ef") == 0) + else if (key == "ef") portal_group_set_dscp(IPTOS_DSCP_EF >> 2); - else if (strcmp(key, "cs0") == 0) + else if (key == "cs0") portal_group_set_dscp(IPTOS_DSCP_CS0 >> 2); - else if (strcmp(key, "cs1") == 0) + else if (key == "cs1") portal_group_set_dscp(IPTOS_DSCP_CS1 >> 2); - else if (strcmp(key, "cs2") == 0) + else if (key == "cs2") portal_group_set_dscp(IPTOS_DSCP_CS2 >> 2); - else if (strcmp(key, "cs3") == 0) + else if (key == "cs3") portal_group_set_dscp(IPTOS_DSCP_CS3 >> 2); - else if (strcmp(key, "cs4") == 0) + else if (key == "cs4") portal_group_set_dscp(IPTOS_DSCP_CS4 >> 2); - else if (strcmp(key, "cs5") == 0) + else if (key == "cs5") portal_group_set_dscp(IPTOS_DSCP_CS5 >> 2); - else if (strcmp(key, "cs6") == 0) + else if (key == "cs6") portal_group_set_dscp(IPTOS_DSCP_CS6 >> 2); - else if (strcmp(key, "cs7") == 0) + else if (key == "cs7") portal_group_set_dscp(IPTOS_DSCP_CS7 >> 2); - else if (strcmp(key, "af11") == 0) + else if (key == "af11") portal_group_set_dscp(IPTOS_DSCP_AF11 >> 2); - else if (strcmp(key, "af12") == 0) + else if (key == "af12") portal_group_set_dscp(IPTOS_DSCP_AF12 >> 2); - else if (strcmp(key, "af13") == 0) + else if (key == "af13") portal_group_set_dscp(IPTOS_DSCP_AF13 >> 2); - else if (strcmp(key, "af21") == 0) + else if (key == "af21") portal_group_set_dscp(IPTOS_DSCP_AF21 >> 2); - else if (strcmp(key, "af22") == 0) + else if (key == "af22") portal_group_set_dscp(IPTOS_DSCP_AF22 >> 2); - else if (strcmp(key, "af23") == 0) + else if (key == "af23") portal_group_set_dscp(IPTOS_DSCP_AF23 >> 2); - else if (strcmp(key, "af31") == 0) + else if (key == "af31") portal_group_set_dscp(IPTOS_DSCP_AF31 >> 2); - else if (strcmp(key, "af32") == 0) + else if (key == "af32") portal_group_set_dscp(IPTOS_DSCP_AF32 >> 2); - else if (strcmp(key, "af33") == 0) + else if (key == "af33") portal_group_set_dscp(IPTOS_DSCP_AF33 >> 2); - else if (strcmp(key, "af41") == 0) + else if (key == "af41") portal_group_set_dscp(IPTOS_DSCP_AF41 >> 2); - else if (strcmp(key, "af42") == 0) + else if (key == "af42") portal_group_set_dscp(IPTOS_DSCP_AF42 >> 2); - else if (strcmp(key, "af43") == 0) + else if (key == "af43") portal_group_set_dscp(IPTOS_DSCP_AF43 >> 2); else { log_warnx("\"dscp\" property value is not a supported textual value"); @@ -623,499 +747,684 @@ uclparse_dscp(const char *group_type, const char *pg_name, static bool uclparse_pcp(const char *group_type, const char *pg_name, - const ucl_object_t *obj) + const ucl::Ucl &obj) { - if (obj->type != UCL_INT) { + if (obj.type() != UCL_INT) { log_warnx("\"pcp\" property of %s group \"%s\" is not an " "integer", group_type, pg_name); return (false); } - return (portal_group_set_pcp(ucl_object_toint(obj))); + return (portal_group_set_pcp(obj.int_value())); } static bool -uclparse_portal_group(const char *name, const ucl_object_t *top) +uclparse_portal_group(const char *name, const ucl::Ucl &top) { - ucl_object_iter_t it = NULL, it2 = NULL; - const ucl_object_t *obj = NULL, *tmp = NULL; - const char *key; - if (!portal_group_start(name)) return (false); - while ((obj = ucl_iterate_object(top, &it, true))) { - key = ucl_object_key(obj); + scope_exit finisher(portal_group_finish); + for (const auto &obj : top) { + std::string key = obj.key(); - if (strcmp(key, "discovery-auth-group") == 0) { - if (obj->type != UCL_STRING) { + if (key == "discovery-auth-group") { + if (obj.type() != UCL_STRING) { log_warnx("\"discovery-auth-group\" property " "of portal-group \"%s\" is not a string", name); - goto fail; + return false; } if (!portal_group_set_discovery_auth_group( - ucl_object_tostring(obj))) - goto fail; + obj.string_value().c_str())) + return false; } - if (strcmp(key, "discovery-filter") == 0) { - if (obj->type != UCL_STRING) { + if (key == "discovery-filter") { + if (obj.type() != UCL_STRING) { log_warnx("\"discovery-filter\" property of " "portal-group \"%s\" is not a string", name); - goto fail; + return false; } - if (!portal_group_set_filter(ucl_object_tostring(obj))) - goto fail; + if (!portal_group_set_filter( + obj.string_value().c_str())) + return false; } - if (strcmp(key, "foreign") == 0) { + if (key == "foreign") { portal_group_set_foreign(); } - if (strcmp(key, "listen") == 0) { - if (obj->type == UCL_STRING) { + if (key == "listen") { + if (obj.type() == UCL_STRING) { if (!portal_group_add_listen( - ucl_object_tostring(obj), false)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + obj.string_value().c_str(), false)) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!portal_group_add_listen( - ucl_object_tostring(tmp), + tmp.string_value().c_str(), false)) - goto fail; + return false; } } else { log_warnx("\"listen\" property of " "portal-group \"%s\" is not a string", name); - goto fail; + return false; } } - if (strcmp(key, "listen-iser") == 0) { - if (obj->type == UCL_STRING) { + if (key == "listen-iser") { + if (obj.type() == UCL_STRING) { if (!portal_group_add_listen( - ucl_object_tostring(obj), true)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + obj.string_value().c_str(), true)) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!portal_group_add_listen( - ucl_object_tostring(tmp), + tmp.string_value().c_str(), true)) - goto fail; + return false; } } else { log_warnx("\"listen\" property of " "portal-group \"%s\" is not a string", name); - goto fail; + return false; } } - if (strcmp(key, "offload") == 0) { - if (obj->type != UCL_STRING) { + if (key == "offload") { + if (obj.type() != UCL_STRING) { log_warnx("\"offload\" property of " "portal-group \"%s\" is not a string", name); - goto fail; + return false; } - if (!portal_group_set_offload(ucl_object_tostring(obj))) - goto fail; + if (!portal_group_set_offload( + obj.string_value().c_str())) + return false; } - if (strcmp(key, "redirect") == 0) { - if (obj->type != UCL_STRING) { + if (key == "redirect") { + if (obj.type() != UCL_STRING) { log_warnx("\"listen\" property of " "portal-group \"%s\" is not a string", name); - goto fail; + return false; } if (!portal_group_set_redirection( - ucl_object_tostring(obj))) - goto fail; + obj.string_value().c_str())) + return false; } - if (strcmp(key, "options") == 0) { - if (obj->type != UCL_OBJECT) { + if (key == "options") { + if (obj.type() != UCL_OBJECT) { log_warnx("\"options\" property of portal group " "\"%s\" is not an object", name); - goto fail; + return false; } - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + for (const auto &tmp : obj) { if (!portal_group_add_option( - ucl_object_key(tmp), - ucl_object_tostring_forced(tmp))) - goto fail; + tmp.key().c_str(), + tmp.forced_string_value().c_str())) + return false; } } - if (strcmp(key, "tag") == 0) { - if (obj->type != UCL_INT) { + if (key == "tag") { + if (obj.type() != UCL_INT) { log_warnx("\"tag\" property of portal group " "\"%s\" is not an integer", name); - goto fail; + return false; } - portal_group_set_tag(ucl_object_toint(obj)); + portal_group_set_tag(obj.int_value()); } - if (strcmp(key, "dscp") == 0) { + if (key == "dscp") { if (!uclparse_dscp("portal", name, obj)) - goto fail; + return false; } - if (strcmp(key, "pcp") == 0) { + if (key == "pcp") { if (!uclparse_pcp("portal", name, obj)) - goto fail; + return false; } } - portal_group_finish(); return (true); -fail: - portal_group_finish(); - return (false); } static bool -uclparse_target(const char *name, const ucl_object_t *top) +uclparse_transport_listen_obj(const char *pg_name, const ucl::Ucl &top) +{ + for (const auto &obj : top) { + std::string key = obj.key(); + + if (key.empty()) { + log_warnx("missing protocol for \"listen\" " + "property of transport-group \"%s\"", pg_name); + return false; + } + + if (key == "tcp") { + if (obj.type() == UCL_STRING) { + if (!transport_group_add_listen_tcp( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { + if (!transport_group_add_listen_tcp( + tmp.string_value().c_str())) + return false; + } + } + } else if (key == "discovery-tcp") { + if (obj.type() == UCL_STRING) { + if (!transport_group_add_listen_discovery_tcp( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { + if (!transport_group_add_listen_discovery_tcp( + tmp.string_value().c_str())) + return false; + } + } + } else { + log_warnx("invalid listen protocol \"%s\" for " + "transport-group \"%s\"", key.c_str(), pg_name); + return false; + } + } + return true; +} + +static bool +uclparse_transport_group(const char *name, const ucl::Ucl &top) +{ + if (!transport_group_start(name)) + return false; + + scope_exit finisher(portal_group_finish); + for (const auto &obj : top) { + std::string key = obj.key(); + + if (key == "discovery-auth-group") { + if (obj.type() != UCL_STRING) { + log_warnx("\"discovery-auth-group\" property " + "of transport-group \"%s\" is not a string", + name); + return false; + } + + if (!portal_group_set_discovery_auth_group( + obj.string_value().c_str())) + return false; + } + + if (key == "discovery-filter") { + if (obj.type() != UCL_STRING) { + log_warnx("\"discovery-filter\" property of " + "transport-group \"%s\" is not a string", + name); + return false; + } + + if (!portal_group_set_filter( + obj.string_value().c_str())) + return false; + } + + if (key == "listen") { + if (obj.type() != UCL_OBJECT) { + log_warnx("\"listen\" property of " + "transport-group \"%s\" is not an object", + name); + return false; + } + if (!uclparse_transport_listen_obj(name, obj)) + return false; + } + + if (key == "options") { + if (obj.type() != UCL_OBJECT) { + log_warnx("\"options\" property of transport group " + "\"%s\" is not an object", name); + return false; + } + + for (const auto &tmp : obj) { + if (!portal_group_add_option( + tmp.key().c_str(), + tmp.forced_string_value().c_str())) + return false; + } + } + + if (key == "dscp") { + if (!uclparse_dscp("transport", name, obj)) + return false; + } + + if (key == "pcp") { + if (!uclparse_pcp("transport", name, obj)) + return false; + } + } + + return true; +} + +static bool +uclparse_controller(const char *name, const ucl::Ucl &top) { - ucl_object_iter_t it = NULL, it2 = NULL; - const ucl_object_t *obj = NULL, *tmp = NULL; - const char *key; + if (!controller_start(name)) + return false; + + scope_exit finisher(target_finish); + for (const auto &obj : top) { + std::string key = obj.key(); + + if (key == "auth-group") { + if (obj.type() != UCL_STRING) { + log_warnx("\"auth-group\" property of " + "controller \"%s\" is not a string", name); + return false; + } + + if (!target_set_auth_group(obj.string_value().c_str())) + return false; + } + + if (key == "auth-type") { + if (obj.type() != UCL_STRING) { + log_warnx("\"auth-type\" property of " + "controller \"%s\" is not a string", name); + return false; + } + + if (!target_set_auth_type(obj.string_value().c_str())) + return false; + } + + if (key == "host-address") { + if (obj.type() == UCL_STRING) { + if (!controller_add_host_address( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { + if (!controller_add_host_address( + tmp.string_value().c_str())) + return false; + } + } else { + log_warnx("\"host-address\" property of " + "controller \"%s\" is not an array or " + "string", name); + return false; + } + } + + if (key == "host-nqn") { + if (obj.type() == UCL_STRING) { + if (!controller_add_host_nqn( + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { + if (!controller_add_host_nqn( + tmp.string_value().c_str())) + return false; + } + } else { + log_warnx("\"host-nqn\" property of " + "controller \"%s\" is not an array or " + "string", name); + return false; + } + } + + if (key == "transport-group") { + if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { + if (!uclparse_controller_transport_group(name, + tmp)) + return false; + } + } else { + if (!uclparse_controller_transport_group(name, + obj)) + return false; + } + } + + if (key == "namespace") { + for (const auto &tmp : obj) { + if (!uclparse_controller_namespace(name, tmp)) + return false; + } + } + } + + return true; +} +static bool +uclparse_target(const char *name, const ucl::Ucl &top) +{ if (!target_start(name)) return (false); - while ((obj = ucl_iterate_object(top, &it, true))) { - key = ucl_object_key(obj); + scope_exit finisher(target_finish); + for (const auto &obj : top) { + std::string key = obj.key(); - if (strcmp(key, "alias") == 0) { - if (obj->type != UCL_STRING) { + if (key == "alias") { + if (obj.type() != UCL_STRING) { log_warnx("\"alias\" property of target " "\"%s\" is not a string", name); - goto fail; + return false; } - if (!target_set_alias(ucl_object_tostring(obj))) - goto fail; + if (!target_set_alias(obj.string_value().c_str())) + return false; } - if (strcmp(key, "auth-group") == 0) { - if (obj->type != UCL_STRING) { + if (key == "auth-group") { + if (obj.type() != UCL_STRING) { log_warnx("\"auth-group\" property of target " "\"%s\" is not a string", name); - goto fail; + return false; } - if (!target_set_auth_group(ucl_object_tostring(obj))) - goto fail; + if (!target_set_auth_group(obj.string_value().c_str())) + return false; } - if (strcmp(key, "auth-type") == 0) { - if (obj->type != UCL_STRING) { + if (key == "auth-type") { + if (obj.type() != UCL_STRING) { log_warnx("\"auth-type\" property of target " "\"%s\" is not a string", name); - goto fail; + return false; } - if (!target_set_auth_type(ucl_object_tostring(obj))) - goto fail; + if (!target_set_auth_type(obj.string_value().c_str())) + return false; } - if (strcmp(key, "chap") == 0) { - if (obj->type == UCL_OBJECT) { + if (key == "chap") { + if (obj.type() == UCL_OBJECT) { if (!uclparse_target_chap(name, obj)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!uclparse_target_chap(name, tmp)) - goto fail; + return false; } } else { log_warnx("\"chap\" property of target " "\"%s\" is not an array or object", name); - goto fail; + return false; } } - if (strcmp(key, "chap-mutual") == 0) { - if (obj->type == UCL_OBJECT) { + if (key == "chap-mutual") { + if (obj.type() == UCL_OBJECT) { if (!uclparse_target_chap_mutual(name, obj)) - goto fail; - } else if (obj->type == UCL_ARRAY) { - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!uclparse_target_chap_mutual(name, tmp)) - goto fail; + return false; } } else { log_warnx("\"chap-mutual\" property of target " "\"%s\" is not an array or object", name); - goto fail; + return false; } } - if (strcmp(key, "initiator-name") == 0) { - if (obj->type == UCL_STRING) { + if (key == "initiator-name") { + if (obj.type() == UCL_STRING) { if (!target_add_initiator_name( - ucl_object_tostring(obj))) - goto fail; - } else if (obj->type == UCL_ARRAY) { - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!target_add_initiator_name( - ucl_object_tostring(tmp))) - goto fail; + tmp.string_value().c_str())) + return false; } } else { log_warnx("\"initiator-name\" property of " "target \"%s\" is not an array or string", name); - goto fail; + return false; } } - if (strcmp(key, "initiator-portal") == 0) { - if (obj->type == UCL_STRING) { + if (key == "initiator-portal") { + if (obj.type() == UCL_STRING) { if (!target_add_initiator_portal( - ucl_object_tostring(obj))) - goto fail; - } else if (obj->type == UCL_ARRAY) { - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + obj.string_value().c_str())) + return false; + } else if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!target_add_initiator_portal( - ucl_object_tostring(tmp))) - goto fail; + tmp.string_value().c_str())) + return false; } } else { log_warnx("\"initiator-portal\" property of " "target \"%s\" is not an array or string", name); - goto fail; + return false; } } - if (strcmp(key, "portal-group") == 0) { - if (obj->type == UCL_ARRAY) { - while ((tmp = ucl_iterate_object(obj, &it2, - true))) { + if (key == "portal-group") { + if (obj.type() == UCL_ARRAY) { + for (const auto &tmp : obj) { if (!uclparse_target_portal_group(name, tmp)) - goto fail; + return false; } } else { if (!uclparse_target_portal_group(name, obj)) - goto fail; + return false; } } - if (strcmp(key, "port") == 0) { - if (obj->type != UCL_STRING) { + if (key == "port") { + if (obj.type() != UCL_STRING) { log_warnx("\"port\" property of target " "\"%s\" is not a string", name); - goto fail; + return false; } - if (!target_set_physical_port(ucl_object_tostring(obj))) - goto fail; + if (!target_set_physical_port(obj.string_value().c_str())) + return false; } - if (strcmp(key, "redirect") == 0) { - if (obj->type != UCL_STRING) { + if (key == "redirect") { + if (obj.type() != UCL_STRING) { log_warnx("\"redirect\" property of target " "\"%s\" is not a string", name); - goto fail; + return false; } - if (!target_set_redirection(ucl_object_tostring(obj))) - goto fail; + if (!target_set_redirection(obj.string_value().c_str())) + return false; } - if (strcmp(key, "lun") == 0) { - while ((tmp = ucl_iterate_object(obj, &it2, true))) { + if (key == "lun") { + for (const auto &tmp : obj) { if (!uclparse_target_lun(name, tmp)) - goto fail; + return false; } } } - target_finish(); return (true); -fail: - target_finish(); - return (false); } static bool -uclparse_lun(const char *name, const ucl_object_t *top) +uclparse_lun(const char *name, const ucl::Ucl &top) { - char *lun_name; - bool ok; - if (!lun_start(name)) return (false); - asprintf(&lun_name, "lun \"%s\"", name); - ok = uclparse_lun_entries(lun_name, top); - free(lun_name); - return (ok); + + scope_exit finisher(lun_finish); + std::string lun_name = freebsd::stringf("lun \"%s\"", name); + return (uclparse_lun_entries(lun_name.c_str(), top)); } static bool -uclparse_lun_entries(const char *name, const ucl_object_t *top) +uclparse_lun_entries(const char *name, const ucl::Ucl &top) { - ucl_object_iter_t it = NULL, child_it = NULL; - const ucl_object_t *obj = NULL, *child = NULL; - const char *key; - - while ((obj = ucl_iterate_object(top, &it, true))) { - key = ucl_object_key(obj); + for (const auto &obj : top) { + std::string key = obj.key(); - if (strcmp(key, "backend") == 0) { - if (obj->type != UCL_STRING) { + if (key == "backend") { + if (obj.type() != UCL_STRING) { log_warnx("\"backend\" property of %s " "is not a string", name); - goto fail; + return false; } - if (!lun_set_backend(ucl_object_tostring(obj))) - goto fail; + if (!lun_set_backend(obj.string_value().c_str())) + return false; } - if (strcmp(key, "blocksize") == 0) { - if (obj->type != UCL_INT) { + if (key == "blocksize") { + if (obj.type() != UCL_INT) { log_warnx("\"blocksize\" property of %s " "is not an integer", name); - goto fail; + return false; } - if (!lun_set_blocksize(ucl_object_toint(obj))) - goto fail; + if (!lun_set_blocksize(obj.int_value())) + return false; } - if (strcmp(key, "device-id") == 0) { - if (obj->type != UCL_STRING) { + if (key == "device-id") { + if (obj.type() != UCL_STRING) { log_warnx("\"device-id\" property of %s " "is not an integer", name); - goto fail; + return false; } - if (!lun_set_device_id(ucl_object_tostring(obj))) - goto fail; + if (!lun_set_device_id(obj.string_value().c_str())) + return false; } - if (strcmp(key, "device-type") == 0) { - if (obj->type != UCL_STRING) { + if (key == "device-type") { + if (obj.type() != UCL_STRING) { log_warnx("\"device-type\" property of %s " "is not an integer", name); - goto fail; + return false; } - if (!lun_set_device_type(ucl_object_tostring(obj))) - goto fail; + if (!lun_set_device_type(obj.string_value().c_str())) + return false; } - if (strcmp(key, "ctl-lun") == 0) { - if (obj->type != UCL_INT) { + if (key == "ctl-lun") { + if (obj.type() != UCL_INT) { log_warnx("\"ctl-lun\" property of %s " "is not an integer", name); - goto fail; + return false; } - if (!lun_set_ctl_lun(ucl_object_toint(obj))) - goto fail; + if (!lun_set_ctl_lun(obj.int_value())) + return false; } - if (strcmp(key, "options") == 0) { - if (obj->type != UCL_OBJECT) { + if (key == "options") { + if (obj.type() != UCL_OBJECT) { log_warnx("\"options\" property of %s " "is not an object", name); - goto fail; + return false; } - while ((child = ucl_iterate_object(obj, &child_it, - true))) { - if (!lun_add_option(ucl_object_key(child), - ucl_object_tostring_forced(child))) - goto fail; + for (const auto &child : obj) { + if (!lun_add_option(child.key().c_str(), + child.forced_string_value().c_str())) + return false; } } - if (strcmp(key, "path") == 0) { - if (obj->type != UCL_STRING) { + if (key == "path") { + if (obj.type() != UCL_STRING) { log_warnx("\"path\" property of %s " "is not a string", name); - goto fail; + return false; } - if (!lun_set_path(ucl_object_tostring(obj))) - goto fail; + if (!lun_set_path(obj.string_value().c_str())) + return false; } - if (strcmp(key, "serial") == 0) { - if (obj->type != UCL_STRING) { + if (key == "serial") { + if (obj.type() != UCL_STRING) { log_warnx("\"serial\" property of %s " "is not a string", name); - goto fail; + return false; } - if (!lun_set_serial(ucl_object_tostring(obj))) - goto fail; + if (!lun_set_serial(obj.string_value().c_str())) + return false; } - if (strcmp(key, "size") == 0) { - if (obj->type != UCL_INT) { + if (key == "size") { + if (obj.type() != UCL_INT) { log_warnx("\"size\" property of %s " "is not an integer", name); - goto fail; + return false; } - if (!lun_set_size(ucl_object_toint(obj))) - goto fail; + if (!lun_set_size(obj.int_value())) + return false; } } - lun_finish(); return (true); -fail: - lun_finish(); - return (false); } bool uclparse_conf(const char *path) { - struct ucl_parser *parser; - ucl_object_t *top; - bool parsed; - - parser = ucl_parser_new(0); - - if (!ucl_parser_add_file(parser, path)) { - log_warn("unable to parse configuration file %s: %s", path, - ucl_parser_get_error(parser)); - ucl_parser_free(parser); + std::string err; + ucl::Ucl top = ucl::Ucl::parse_from_file(path, err); + if (!top) { + log_warnx("unable to parse configuration file %s: %s", path, + err.c_str()); return (false); } - top = ucl_parser_get_object(parser); - parsed = uclparse_toplevel(top); - ucl_object_unref(top); - ucl_parser_free(parser); + bool parsed; + try { + parsed = uclparse_toplevel(top); + } catch (std::bad_alloc &) { + log_warnx("failed to allocate memory parsing %s", path); + parsed = false; + } catch (...) { + log_warnx("unknown exception parsing %s", path); + parsed = false; + } return (parsed); } |