2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2015 iXsystems Inc.
7 * This software was developed by Jakub Klama <jceel@FreeBSD.org>
8 * under sponsorship from iXsystems Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/queue.h>
33 #include <sys/types.h>
40 #include <netinet/in.h>
41 #include <netinet/ip.h>
45 static struct conf *conf = NULL;
47 static int uclparse_toplevel(const ucl_object_t *);
48 static int uclparse_chap(struct auth_group *, const ucl_object_t *);
49 static int uclparse_chap_mutual(struct auth_group *, const ucl_object_t *);
50 static int uclparse_lun(const char *, const ucl_object_t *);
51 static int uclparse_auth_group(const char *, const ucl_object_t *);
52 static int uclparse_portal_group(const char *, const ucl_object_t *);
53 static int uclparse_target(const char *, const ucl_object_t *);
54 static int uclparse_target_portal_group(struct target *, const ucl_object_t *);
55 static int uclparse_target_lun(struct target *, const ucl_object_t *);
58 uclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj)
60 const struct auth *ca;
61 const ucl_object_t *user, *secret;
63 user = ucl_object_find_key(obj, "user");
64 if (!user || user->type != UCL_STRING) {
65 log_warnx("chap section in auth-group \"%s\" is missing "
66 "\"user\" string key", auth_group->ag_name);
70 secret = ucl_object_find_key(obj, "secret");
71 if (!secret || secret->type != UCL_STRING) {
72 log_warnx("chap section in auth-group \"%s\" is missing "
73 "\"secret\" string key", auth_group->ag_name);
76 ca = auth_new_chap(auth_group,
77 ucl_object_tostring(user),
78 ucl_object_tostring(secret));
87 uclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj)
89 const struct auth *ca;
90 const ucl_object_t *user, *secret, *mutual_user;
91 const ucl_object_t *mutual_secret;
93 user = ucl_object_find_key(obj, "user");
94 if (!user || user->type != UCL_STRING) {
95 log_warnx("chap-mutual section in auth-group \"%s\" is missing "
96 "\"user\" string key", auth_group->ag_name);
100 secret = ucl_object_find_key(obj, "secret");
101 if (!secret || secret->type != UCL_STRING) {
102 log_warnx("chap-mutual section in auth-group \"%s\" is missing "
103 "\"secret\" string key", auth_group->ag_name);
107 mutual_user = ucl_object_find_key(obj, "mutual-user");
108 if (!user || user->type != UCL_STRING) {
109 log_warnx("chap-mutual section in auth-group \"%s\" is missing "
110 "\"mutual-user\" string key", auth_group->ag_name);
114 mutual_secret = ucl_object_find_key(obj, "mutual-secret");
115 if (!secret || secret->type != UCL_STRING) {
116 log_warnx("chap-mutual section in auth-group \"%s\" is missing "
117 "\"mutual-secret\" string key", auth_group->ag_name);
121 ca = auth_new_chap_mutual(auth_group,
122 ucl_object_tostring(user),
123 ucl_object_tostring(secret),
124 ucl_object_tostring(mutual_user),
125 ucl_object_tostring(mutual_secret));
134 uclparse_target_portal_group(struct target *target, const ucl_object_t *obj)
136 struct portal_group *tpg;
137 struct auth_group *tag = NULL;
139 const ucl_object_t *portal_group, *auth_group;
141 portal_group = ucl_object_find_key(obj, "name");
142 if (!portal_group || portal_group->type != UCL_STRING) {
143 log_warnx("portal-group section in target \"%s\" is missing "
144 "\"name\" string key", target->t_name);
148 auth_group = ucl_object_find_key(obj, "auth-group-name");
149 if (auth_group && auth_group->type != UCL_STRING) {
150 log_warnx("portal-group section in target \"%s\" is missing "
151 "\"auth-group-name\" string key", target->t_name);
156 tpg = portal_group_find(conf, ucl_object_tostring(portal_group));
158 log_warnx("unknown portal-group \"%s\" for target "
159 "\"%s\"", ucl_object_tostring(portal_group), target->t_name);
164 tag = auth_group_find(conf, ucl_object_tostring(auth_group));
166 log_warnx("unknown auth-group \"%s\" for target "
167 "\"%s\"", ucl_object_tostring(auth_group),
173 tp = port_new(conf, target, tpg);
175 log_warnx("can't link portal-group \"%s\" to target "
176 "\"%s\"", ucl_object_tostring(portal_group), target->t_name);
179 tp->p_auth_group = tag;
185 uclparse_target_lun(struct target *target, const ucl_object_t *obj)
190 if (obj->type == UCL_INT) {
193 tmp = ucl_object_toint(obj);
194 if (tmp >= MAX_LUNS) {
195 log_warnx("LU number %ju in target \"%s\" is too big",
196 tmp, target->t_name);
200 asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
201 lun = lun_new(conf, name);
205 lun_set_scsiname(lun, name);
206 target->t_luns[tmp] = lun;
210 if (obj->type == UCL_OBJECT) {
211 const ucl_object_t *num = ucl_object_find_key(obj, "number");
212 const ucl_object_t *name = ucl_object_find_key(obj, "name");
214 if (num == NULL || num->type != UCL_INT) {
215 log_warnx("lun section in target \"%s\" is missing "
216 "\"number\" integer property", target->t_name);
219 tmp = ucl_object_toint(num);
220 if (tmp >= MAX_LUNS) {
221 log_warnx("LU number %ju in target \"%s\" is too big",
222 tmp, target->t_name);
226 if (name == NULL || name->type != UCL_STRING) {
227 log_warnx("lun section in target \"%s\" is missing "
228 "\"name\" string property", target->t_name);
232 lun = lun_find(conf, ucl_object_tostring(name));
236 target->t_luns[tmp] = lun;
243 uclparse_toplevel(const ucl_object_t *top)
245 ucl_object_iter_t it = NULL, iter = NULL;
246 const ucl_object_t *obj = NULL, *child = NULL;
249 /* Pass 1 - everything except targets */
250 while ((obj = ucl_iterate_object(top, &it, true))) {
251 const char *key = ucl_object_key(obj);
253 if (!strcmp(key, "debug")) {
254 if (obj->type == UCL_INT)
255 conf->conf_debug = ucl_object_toint(obj);
257 log_warnx("\"debug\" property value is not integer");
262 if (!strcmp(key, "timeout")) {
263 if (obj->type == UCL_INT)
264 conf->conf_timeout = ucl_object_toint(obj);
266 log_warnx("\"timeout\" property value is not integer");
271 if (!strcmp(key, "maxproc")) {
272 if (obj->type == UCL_INT)
273 conf->conf_maxproc = ucl_object_toint(obj);
275 log_warnx("\"maxproc\" property value is not integer");
280 if (!strcmp(key, "pidfile")) {
281 if (obj->type == UCL_STRING)
282 conf->conf_pidfile_path = strdup(
283 ucl_object_tostring(obj));
285 log_warnx("\"pidfile\" property value is not string");
290 if (!strcmp(key, "isns-server")) {
291 if (obj->type == UCL_ARRAY) {
293 while ((child = ucl_iterate_object(obj, &iter,
295 if (child->type != UCL_STRING)
299 ucl_object_tostring(child));
305 log_warnx("\"isns-server\" property value is "
311 if (!strcmp(key, "isns-period")) {
312 if (obj->type == UCL_INT)
313 conf->conf_timeout = ucl_object_toint(obj);
315 log_warnx("\"isns-period\" property value is not integer");
320 if (!strcmp(key, "isns-timeout")) {
321 if (obj->type == UCL_INT)
322 conf->conf_timeout = ucl_object_toint(obj);
324 log_warnx("\"isns-timeout\" property value is not integer");
329 if (!strcmp(key, "auth-group")) {
330 if (obj->type == UCL_OBJECT) {
332 while ((child = ucl_iterate_object(obj, &iter, true))) {
333 uclparse_auth_group(ucl_object_key(child), child);
336 log_warnx("\"auth-group\" section is not an object");
341 if (!strcmp(key, "portal-group")) {
342 if (obj->type == UCL_OBJECT) {
344 while ((child = ucl_iterate_object(obj, &iter, true))) {
345 uclparse_portal_group(ucl_object_key(child), child);
348 log_warnx("\"portal-group\" section is not an object");
353 if (!strcmp(key, "lun")) {
354 if (obj->type == UCL_OBJECT) {
356 while ((child = ucl_iterate_object(obj, &iter, true))) {
357 uclparse_lun(ucl_object_key(child), child);
360 log_warnx("\"lun\" section is not an object");
366 /* Pass 2 - targets */
368 while ((obj = ucl_iterate_object(top, &it, true))) {
369 const char *key = ucl_object_key(obj);
371 if (!strcmp(key, "target")) {
372 if (obj->type == UCL_OBJECT) {
374 while ((child = ucl_iterate_object(obj, &iter,
376 uclparse_target(ucl_object_key(child),
380 log_warnx("\"target\" section is not an object");
390 uclparse_auth_group(const char *name, const ucl_object_t *top)
392 struct auth_group *auth_group;
393 const struct auth_name *an;
394 const struct auth_portal *ap;
395 ucl_object_iter_t it = NULL, it2 = NULL;
396 const ucl_object_t *obj = NULL, *tmp = NULL;
400 if (!strcmp(name, "default") &&
401 conf->conf_default_ag_defined == false) {
402 auth_group = auth_group_find(conf, name);
403 conf->conf_default_ag_defined = true;
405 auth_group = auth_group_new(conf, name);
408 if (auth_group == NULL)
411 while ((obj = ucl_iterate_object(top, &it, true))) {
412 key = ucl_object_key(obj);
414 if (!strcmp(key, "auth-type")) {
415 const char *value = ucl_object_tostring(obj);
417 err = auth_group_set_type(auth_group, value);
422 if (!strcmp(key, "chap")) {
423 if (obj->type != UCL_ARRAY) {
424 log_warnx("\"chap\" property of "
425 "auth-group \"%s\" is not an array",
431 while ((tmp = ucl_iterate_object(obj, &it2, true))) {
432 if (uclparse_chap(auth_group, tmp) != 0)
437 if (!strcmp(key, "chap-mutual")) {
438 if (obj->type != UCL_ARRAY) {
439 log_warnx("\"chap-mutual\" property of "
440 "auth-group \"%s\" is not an array",
446 while ((tmp = ucl_iterate_object(obj, &it2, true))) {
447 if (uclparse_chap_mutual(auth_group, tmp) != 0)
452 if (!strcmp(key, "initiator-name")) {
453 if (obj->type != UCL_ARRAY) {
454 log_warnx("\"initiator-name\" property of "
455 "auth-group \"%s\" is not an array",
461 while ((tmp = ucl_iterate_object(obj, &it2, true))) {
462 const char *value = ucl_object_tostring(tmp);
464 an = auth_name_new(auth_group, value);
470 if (!strcmp(key, "initiator-portal")) {
471 if (obj->type != UCL_ARRAY) {
472 log_warnx("\"initiator-portal\" property of "
473 "auth-group \"%s\" is not an array",
479 while ((tmp = ucl_iterate_object(obj, &it2, true))) {
480 const char *value = ucl_object_tostring(tmp);
482 ap = auth_portal_new(auth_group, value);
493 uclparse_portal_group(const char *name, const ucl_object_t *top)
495 struct portal_group *portal_group;
496 ucl_object_iter_t it = NULL, it2 = NULL;
497 const ucl_object_t *obj = NULL, *tmp = NULL;
500 if (strcmp(name, "default") == 0 &&
501 conf->conf_default_pg_defined == false) {
502 portal_group = portal_group_find(conf, name);
503 conf->conf_default_pg_defined = true;
505 portal_group = portal_group_new(conf, name);
508 if (portal_group == NULL)
511 while ((obj = ucl_iterate_object(top, &it, true))) {
512 key = ucl_object_key(obj);
514 if (!strcmp(key, "discovery-auth-group")) {
515 portal_group->pg_discovery_auth_group =
516 auth_group_find(conf, ucl_object_tostring(obj));
517 if (portal_group->pg_discovery_auth_group == NULL) {
518 log_warnx("unknown discovery-auth-group \"%s\" "
519 "for portal-group \"%s\"",
520 ucl_object_tostring(obj),
521 portal_group->pg_name);
526 if (!strcmp(key, "discovery-filter")) {
527 if (obj->type != UCL_STRING) {
528 log_warnx("\"discovery-filter\" property of "
529 "portal-group \"%s\" is not a string",
530 portal_group->pg_name);
534 if (portal_group_set_filter(portal_group,
535 ucl_object_tostring(obj)) != 0)
539 if (!strcmp(key, "listen")) {
540 if (obj->type == UCL_STRING) {
541 if (portal_group_add_listen(portal_group,
542 ucl_object_tostring(obj), false) != 0)
544 } else if (obj->type == UCL_ARRAY) {
545 while ((tmp = ucl_iterate_object(obj, &it2,
547 if (portal_group_add_listen(
549 ucl_object_tostring(tmp),
554 log_warnx("\"listen\" property of "
555 "portal-group \"%s\" is not a string",
556 portal_group->pg_name);
561 if (!strcmp(key, "listen-iser")) {
562 if (obj->type == UCL_STRING) {
563 if (portal_group_add_listen(portal_group,
564 ucl_object_tostring(obj), true) != 0)
566 } else if (obj->type == UCL_ARRAY) {
567 while ((tmp = ucl_iterate_object(obj, &it2,
569 if (portal_group_add_listen(
571 ucl_object_tostring(tmp),
576 log_warnx("\"listen\" property of "
577 "portal-group \"%s\" is not a string",
578 portal_group->pg_name);
583 if (!strcmp(key, "redirect")) {
584 if (obj->type != UCL_STRING) {
585 log_warnx("\"listen\" property of "
586 "portal-group \"%s\" is not a string",
587 portal_group->pg_name);
591 if (portal_group_set_redirection(portal_group,
592 ucl_object_tostring(obj)) != 0)
596 if (!strcmp(key, "options")) {
597 if (obj->type != UCL_OBJECT) {
598 log_warnx("\"options\" property of portal group "
599 "\"%s\" is not an object", portal_group->pg_name);
603 while ((tmp = ucl_iterate_object(obj, &it2,
605 option_new(&portal_group->pg_options,
607 ucl_object_tostring_forced(tmp));
611 if (!strcmp(key, "dscp")) {
612 if ((obj->type != UCL_STRING) && (obj->type != UCL_INT)) {
613 log_warnx("\"dscp\" property of portal group "
614 "\"%s\" is not a string or integer", portal_group->pg_name);
617 if (obj->type == UCL_INT)
618 portal_group->pg_dscp = ucl_object_toint(obj);
620 key = ucl_object_tostring(obj);
621 if (strcmp(key, "0x") == 0)
622 portal_group->pg_dscp = strtol(key + 2, NULL, 16);
623 else if (strcmp(key, "be") || strcmp(key, "cs0"))
624 portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2;
625 else if (strcmp(key, "ef"))
626 portal_group->pg_dscp = IPTOS_DSCP_EF >> 2;
627 else if (strcmp(key, "cs0"))
628 portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2;
629 else if (strcmp(key, "cs1"))
630 portal_group->pg_dscp = IPTOS_DSCP_CS1 >> 2;
631 else if (strcmp(key, "cs2"))
632 portal_group->pg_dscp = IPTOS_DSCP_CS2 >> 2;
633 else if (strcmp(key, "cs3"))
634 portal_group->pg_dscp = IPTOS_DSCP_CS3 >> 2;
635 else if (strcmp(key, "cs4"))
636 portal_group->pg_dscp = IPTOS_DSCP_CS4 >> 2;
637 else if (strcmp(key, "cs5"))
638 portal_group->pg_dscp = IPTOS_DSCP_CS5 >> 2;
639 else if (strcmp(key, "cs6"))
640 portal_group->pg_dscp = IPTOS_DSCP_CS6 >> 2;
641 else if (strcmp(key, "cs7"))
642 portal_group->pg_dscp = IPTOS_DSCP_CS7 >> 2;
643 else if (strcmp(key, "af11"))
644 portal_group->pg_dscp = IPTOS_DSCP_AF11 >> 2;
645 else if (strcmp(key, "af12"))
646 portal_group->pg_dscp = IPTOS_DSCP_AF12 >> 2;
647 else if (strcmp(key, "af13"))
648 portal_group->pg_dscp = IPTOS_DSCP_AF13 >> 2;
649 else if (strcmp(key, "af21"))
650 portal_group->pg_dscp = IPTOS_DSCP_AF21 >> 2;
651 else if (strcmp(key, "af22"))
652 portal_group->pg_dscp = IPTOS_DSCP_AF22 >> 2;
653 else if (strcmp(key, "af23"))
654 portal_group->pg_dscp = IPTOS_DSCP_AF23 >> 2;
655 else if (strcmp(key, "af31"))
656 portal_group->pg_dscp = IPTOS_DSCP_AF31 >> 2;
657 else if (strcmp(key, "af32"))
658 portal_group->pg_dscp = IPTOS_DSCP_AF32 >> 2;
659 else if (strcmp(key, "af33"))
660 portal_group->pg_dscp = IPTOS_DSCP_AF33 >> 2;
661 else if (strcmp(key, "af41"))
662 portal_group->pg_dscp = IPTOS_DSCP_AF41 >> 2;
663 else if (strcmp(key, "af42"))
664 portal_group->pg_dscp = IPTOS_DSCP_AF42 >> 2;
665 else if (strcmp(key, "af43"))
666 portal_group->pg_dscp = IPTOS_DSCP_AF43 >> 2;
668 log_warnx("\"dscp\" property value is not a supported textual value");
674 if (!strcmp(key, "pcp")) {
675 if (obj->type != UCL_INT) {
676 log_warnx("\"pcp\" property of portal group "
677 "\"%s\" is not an integer", portal_group->pg_name);
680 portal_group->pg_pcp = ucl_object_toint(obj);
681 if (!((portal_group->pg_pcp >= 0) && (portal_group->pg_pcp <= 7))) {
682 log_warnx("invalid \"pcp\" value %d, using default", portal_group->pg_pcp);
683 portal_group->pg_pcp = -1;
692 uclparse_target(const char *name, const ucl_object_t *top)
694 struct target *target;
695 ucl_object_iter_t it = NULL, it2 = NULL;
696 const ucl_object_t *obj = NULL, *tmp = NULL;
699 target = target_new(conf, name);
703 while ((obj = ucl_iterate_object(top, &it, true))) {
704 key = ucl_object_key(obj);
706 if (!strcmp(key, "alias")) {
707 if (obj->type != UCL_STRING) {
708 log_warnx("\"alias\" property of target "
709 "\"%s\" is not a string", target->t_name);
713 target->t_alias = strdup(ucl_object_tostring(obj));
716 if (!strcmp(key, "auth-group")) {
717 if (target->t_auth_group != NULL) {
718 if (target->t_auth_group->ag_name != NULL)
719 log_warnx("auth-group for target \"%s\" "
720 "specified more than once",
723 log_warnx("cannot use both auth-group "
724 "and explicit authorisations for "
725 "target \"%s\"", target->t_name);
728 target->t_auth_group = auth_group_find(conf,
729 ucl_object_tostring(obj));
730 if (target->t_auth_group == NULL) {
731 log_warnx("unknown auth-group \"%s\" for target "
732 "\"%s\"", ucl_object_tostring(obj),
738 if (!strcmp(key, "auth-type")) {
741 if (target->t_auth_group != NULL) {
742 if (target->t_auth_group->ag_name != NULL) {
743 log_warnx("cannot use both auth-group and "
744 "auth-type for target \"%s\"",
749 target->t_auth_group = auth_group_new(conf, NULL);
750 if (target->t_auth_group == NULL)
753 target->t_auth_group->ag_target = target;
755 error = auth_group_set_type(target->t_auth_group,
756 ucl_object_tostring(obj));
761 if (!strcmp(key, "chap")) {
762 if (uclparse_chap(target->t_auth_group, obj) != 0)
766 if (!strcmp(key, "chap-mutual")) {
767 if (uclparse_chap_mutual(target->t_auth_group, obj) != 0)
771 if (!strcmp(key, "initiator-name")) {
772 const struct auth_name *an;
774 if (target->t_auth_group != NULL) {
775 if (target->t_auth_group->ag_name != NULL) {
776 log_warnx("cannot use both auth-group and "
777 "initiator-name for target \"%s\"",
782 target->t_auth_group = auth_group_new(conf, NULL);
783 if (target->t_auth_group == NULL)
786 target->t_auth_group->ag_target = target;
788 an = auth_name_new(target->t_auth_group,
789 ucl_object_tostring(obj));
794 if (!strcmp(key, "initiator-portal")) {
795 const struct auth_portal *ap;
797 if (target->t_auth_group != NULL) {
798 if (target->t_auth_group->ag_name != NULL) {
799 log_warnx("cannot use both auth-group and "
800 "initiator-portal for target \"%s\"",
805 target->t_auth_group = auth_group_new(conf, NULL);
806 if (target->t_auth_group == NULL)
809 target->t_auth_group->ag_target = target;
811 ap = auth_portal_new(target->t_auth_group,
812 ucl_object_tostring(obj));
817 if (!strcmp(key, "portal-group")) {
818 if (obj->type == UCL_OBJECT) {
819 if (uclparse_target_portal_group(target, obj) != 0)
823 if (obj->type == UCL_ARRAY) {
824 while ((tmp = ucl_iterate_object(obj, &it2,
826 if (uclparse_target_portal_group(target,
833 if (!strcmp(key, "port")) {
836 const char *value = ucl_object_tostring(obj);
837 int ret, i_pp, i_vp = 0;
839 ret = sscanf(value, "ioctl/%d/%d", &i_pp, &i_vp);
841 tp = port_new_ioctl(conf, target, i_pp, i_vp);
843 log_warnx("can't create new ioctl port "
844 "for target \"%s\"", target->t_name);
851 pp = pport_find(conf, value);
853 log_warnx("unknown port \"%s\" for target \"%s\"",
854 value, target->t_name);
857 if (!TAILQ_EMPTY(&pp->pp_ports)) {
858 log_warnx("can't link port \"%s\" to target \"%s\", "
859 "port already linked to some target",
860 value, target->t_name);
863 tp = port_new_pp(conf, target, pp);
865 log_warnx("can't link port \"%s\" to target \"%s\"",
866 value, target->t_name);
871 if (!strcmp(key, "redirect")) {
872 if (obj->type != UCL_STRING) {
873 log_warnx("\"redirect\" property of target "
874 "\"%s\" is not a string", target->t_name);
878 if (target_set_redirection(target,
879 ucl_object_tostring(obj)) != 0)
883 if (!strcmp(key, "lun")) {
884 while ((tmp = ucl_iterate_object(obj, &it2, true))) {
885 if (uclparse_target_lun(target, tmp) != 0)
895 uclparse_lun(const char *name, const ucl_object_t *top)
898 ucl_object_iter_t it = NULL, child_it = NULL;
899 const ucl_object_t *obj = NULL, *child = NULL;
902 lun = lun_new(conf, name);
906 while ((obj = ucl_iterate_object(top, &it, true))) {
907 key = ucl_object_key(obj);
909 if (!strcmp(key, "backend")) {
910 if (obj->type != UCL_STRING) {
911 log_warnx("\"backend\" property of lun "
912 "\"%s\" is not a string",
917 lun_set_backend(lun, ucl_object_tostring(obj));
920 if (!strcmp(key, "blocksize")) {
921 if (obj->type != UCL_INT) {
922 log_warnx("\"blocksize\" property of lun "
923 "\"%s\" is not an integer", lun->l_name);
927 lun_set_blocksize(lun, ucl_object_toint(obj));
930 if (!strcmp(key, "device-id")) {
931 if (obj->type != UCL_STRING) {
932 log_warnx("\"device-id\" property of lun "
933 "\"%s\" is not an integer", lun->l_name);
937 lun_set_device_id(lun, ucl_object_tostring(obj));
940 if (!strcmp(key, "options")) {
941 if (obj->type != UCL_OBJECT) {
942 log_warnx("\"options\" property of lun "
943 "\"%s\" is not an object", lun->l_name);
947 while ((child = ucl_iterate_object(obj, &child_it,
949 option_new(&lun->l_options,
950 ucl_object_key(child),
951 ucl_object_tostring_forced(child));
955 if (!strcmp(key, "path")) {
956 if (obj->type != UCL_STRING) {
957 log_warnx("\"path\" property of lun "
958 "\"%s\" is not a string", lun->l_name);
962 lun_set_path(lun, ucl_object_tostring(obj));
965 if (!strcmp(key, "serial")) {
966 if (obj->type != UCL_STRING) {
967 log_warnx("\"serial\" property of lun "
968 "\"%s\" is not a string", lun->l_name);
972 lun_set_serial(lun, ucl_object_tostring(obj));
975 if (!strcmp(key, "size")) {
976 if (obj->type != UCL_INT) {
977 log_warnx("\"size\" property of lun "
978 "\"%s\" is not an integer", lun->l_name);
982 lun_set_size(lun, ucl_object_toint(obj));
990 uclparse_conf(struct conf *newconf, const char *path)
992 struct ucl_parser *parser;
997 parser = ucl_parser_new(0);
999 if (!ucl_parser_add_file(parser, path)) {
1000 log_warn("unable to parse configuration file %s: %s", path,
1001 ucl_parser_get_error(parser));
1002 ucl_parser_free(parser);
1006 top = ucl_parser_get_object(parser);
1007 error = uclparse_toplevel(top);
1008 ucl_object_unref(top);
1009 ucl_parser_free(parser);