1 /*- 2 * Copyright (c) 2015 iXsystems Inc. 3 * All rights reserved. 4 * 5 * This software was developed by Jakub Klama <jceel@FreeBSD.org> 6 * under sponsorship from iXsystems Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/queue.h> 33 #include <sys/types.h> 34 #include <assert.h> 35 #include <stdio.h> 36 #include <stdint.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <ucl.h> 40 41 #include "ctld.h" 42 43 static struct conf *conf = NULL; 44 45 static int uclparse_toplevel(const ucl_object_t *); 46 static int uclparse_chap(struct auth_group *, const ucl_object_t *); 47 static int uclparse_chap_mutual(struct auth_group *, const ucl_object_t *); 48 static int uclparse_lun(const char *, const ucl_object_t *); 49 static int uclparse_auth_group(const char *, const ucl_object_t *); 50 static int uclparse_portal_group(const char *, const ucl_object_t *); 51 static int uclparse_target(const char *, const ucl_object_t *); 52 static int uclparse_target_portal_group(struct target *, const ucl_object_t *); 53 static int uclparse_target_lun(struct target *, const ucl_object_t *); 54 55 static int 56 uclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj) 57 { 58 const struct auth *ca; 59 const ucl_object_t *user, *secret; 60 61 user = ucl_object_find_key(obj, "user"); 62 if (!user || user->type != UCL_STRING) { 63 log_warnx("chap section in auth-group \"%s\" is missing " 64 "\"user\" string key", auth_group->ag_name); 65 return (1); 66 } 67 68 secret = ucl_object_find_key(obj, "secret"); 69 if (!secret || secret->type != UCL_STRING) { 70 log_warnx("chap section in auth-group \"%s\" is missing " 71 "\"secret\" string key", auth_group->ag_name); 72 } 73 74 ca = auth_new_chap(auth_group, 75 ucl_object_tostring(user), 76 ucl_object_tostring(secret)); 77 78 if (ca == NULL) 79 return (1); 80 81 return (0); 82 } 83 84 static int 85 uclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj) 86 { 87 const struct auth *ca; 88 const ucl_object_t *user, *secret, *mutual_user; 89 const ucl_object_t *mutual_secret; 90 91 user = ucl_object_find_key(obj, "user"); 92 if (!user || user->type != UCL_STRING) { 93 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 94 "\"user\" string key", auth_group->ag_name); 95 return (1); 96 } 97 98 secret = ucl_object_find_key(obj, "secret"); 99 if (!secret || secret->type != UCL_STRING) { 100 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 101 "\"secret\" string key", auth_group->ag_name); 102 return (1); 103 } 104 105 mutual_user = ucl_object_find_key(obj, "mutual-user"); 106 if (!user || user->type != UCL_STRING) { 107 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 108 "\"mutual-user\" string key", auth_group->ag_name); 109 return (1); 110 } 111 112 mutual_secret = ucl_object_find_key(obj, "mutual-secret"); 113 if (!secret || secret->type != UCL_STRING) { 114 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 115 "\"mutual-secret\" string key", auth_group->ag_name); 116 return (1); 117 } 118 119 ca = auth_new_chap_mutual(auth_group, 120 ucl_object_tostring(user), 121 ucl_object_tostring(secret), 122 ucl_object_tostring(mutual_user), 123 ucl_object_tostring(mutual_secret)); 124 125 if (ca == NULL) 126 return (1); 127 128 return (0); 129 } 130 131 static int 132 uclparse_target_portal_group(struct target *target, const ucl_object_t *obj) 133 { 134 struct portal_group *tpg; 135 struct auth_group *tag = NULL; 136 struct port *tp; 137 const ucl_object_t *portal_group, *auth_group; 138 139 portal_group = ucl_object_find_key(obj, "name"); 140 if (!portal_group || portal_group->type != UCL_STRING) { 141 log_warnx("portal-group section in target \"%s\" is missing " 142 "\"name\" string key", target->t_name); 143 return (1); 144 } 145 146 auth_group = ucl_object_find_key(obj, "auth-group-name"); 147 if (auth_group && auth_group->type != UCL_STRING) { 148 log_warnx("portal-group section in target \"%s\" is missing " 149 "\"auth-group-name\" string key", target->t_name); 150 return (1); 151 } 152 153 154 tpg = portal_group_find(conf, ucl_object_tostring(portal_group)); 155 if (tpg == NULL) { 156 log_warnx("unknown portal-group \"%s\" for target " 157 "\"%s\"", ucl_object_tostring(portal_group), target->t_name); 158 return (1); 159 } 160 161 if (auth_group) { 162 tag = auth_group_find(conf, ucl_object_tostring(auth_group)); 163 if (tag == NULL) { 164 log_warnx("unknown auth-group \"%s\" for target " 165 "\"%s\"", ucl_object_tostring(auth_group), 166 target->t_name); 167 return (1); 168 } 169 } 170 171 tp = port_new(conf, target, tpg); 172 if (tp == NULL) { 173 log_warnx("can't link portal-group \"%s\" to target " 174 "\"%s\"", ucl_object_tostring(portal_group), target->t_name); 175 return (1); 176 } 177 tp->p_auth_group = tag; 178 179 return (0); 180 } 181 182 static int 183 uclparse_target_lun(struct target *target, const ucl_object_t *obj) 184 { 185 struct lun *lun; 186 187 if (obj->type == UCL_INT) { 188 char *name; 189 190 asprintf(&name, "%s,lun,%ju", target->t_name, 191 ucl_object_toint(obj)); 192 lun = lun_new(conf, name); 193 if (lun == NULL) 194 return (1); 195 196 lun_set_scsiname(lun, name); 197 target->t_luns[ucl_object_toint(obj)] = lun; 198 return (0); 199 } 200 201 if (obj->type == UCL_OBJECT) { 202 const ucl_object_t *num = ucl_object_find_key(obj, "number"); 203 const ucl_object_t *name = ucl_object_find_key(obj, "name"); 204 205 if (num == NULL || num->type != UCL_INT) { 206 log_warnx("lun section in target \"%s\" is missing " 207 "\"number\" integer property", target->t_name); 208 return (1); 209 } 210 211 if (name == NULL || name->type != UCL_STRING) { 212 log_warnx("lun section in target \"%s\" is missing " 213 "\"name\" string property", target->t_name); 214 return (1); 215 } 216 217 lun = lun_find(conf, ucl_object_tostring(name)); 218 if (lun == NULL) 219 return (1); 220 221 target->t_luns[ucl_object_toint(num)] = lun; 222 } 223 224 return (0); 225 } 226 227 static int 228 uclparse_toplevel(const ucl_object_t *top) 229 { 230 ucl_object_iter_t it = NULL, iter = NULL; 231 const ucl_object_t *obj = NULL, *child = NULL; 232 int err = 0; 233 234 /* Pass 1 - everything except targets */ 235 while ((obj = ucl_iterate_object(top, &it, true))) { 236 const char *key = ucl_object_key(obj); 237 238 if (!strcmp(key, "debug")) { 239 if (obj->type == UCL_INT) 240 conf->conf_debug = ucl_object_toint(obj); 241 else { 242 log_warnx("\"debug\" property value is not integer"); 243 return (1); 244 } 245 } 246 247 if (!strcmp(key, "timeout")) { 248 if (obj->type == UCL_INT) 249 conf->conf_timeout = ucl_object_toint(obj); 250 else { 251 log_warnx("\"timeout\" property value is not integer"); 252 return (1); 253 } 254 } 255 256 if (!strcmp(key, "maxproc")) { 257 if (obj->type == UCL_INT) 258 conf->conf_maxproc = ucl_object_toint(obj); 259 else { 260 log_warnx("\"maxproc\" property value is not integer"); 261 return (1); 262 } 263 } 264 265 if (!strcmp(key, "pidfile")) { 266 if (obj->type == UCL_STRING) 267 conf->conf_pidfile_path = strdup( 268 ucl_object_tostring(obj)); 269 else { 270 log_warnx("\"pidfile\" property value is not string"); 271 return (1); 272 } 273 } 274 275 if (!strcmp(key, "isns-server")) { 276 if (obj->type == UCL_ARRAY) { 277 iter = NULL; 278 while ((child = ucl_iterate_object(obj, &iter, 279 true))) { 280 if (child->type != UCL_STRING) 281 return (1); 282 283 err = isns_new(conf, 284 ucl_object_tostring(child)); 285 if (err != 0) { 286 return (1); 287 } 288 } 289 } else { 290 log_warnx("\"isns-server\" property value is " 291 "not an array"); 292 return (1); 293 } 294 } 295 296 if (!strcmp(key, "isns-period")) { 297 if (obj->type == UCL_INT) 298 conf->conf_timeout = ucl_object_toint(obj); 299 else { 300 log_warnx("\"isns-period\" property value is not integer"); 301 return (1); 302 } 303 } 304 305 if (!strcmp(key, "isns-timeout")) { 306 if (obj->type == UCL_INT) 307 conf->conf_timeout = ucl_object_toint(obj); 308 else { 309 log_warnx("\"isns-timeout\" property value is not integer"); 310 return (1); 311 } 312 } 313 314 if (!strcmp(key, "auth-group")) { 315 if (obj->type == UCL_OBJECT) { 316 iter = NULL; 317 while ((child = ucl_iterate_object(obj, &iter, true))) { 318 uclparse_auth_group(ucl_object_key(child), child); 319 } 320 } else { 321 log_warnx("\"auth-group\" section is not an object"); 322 return (1); 323 } 324 } 325 326 if (!strcmp(key, "portal-group")) { 327 if (obj->type == UCL_OBJECT) { 328 iter = NULL; 329 while ((child = ucl_iterate_object(obj, &iter, true))) { 330 uclparse_portal_group(ucl_object_key(child), child); 331 } 332 } else { 333 log_warnx("\"portal-group\" section is not an object"); 334 return (1); 335 } 336 } 337 338 if (!strcmp(key, "lun")) { 339 if (obj->type == UCL_OBJECT) { 340 iter = NULL; 341 while ((child = ucl_iterate_object(obj, &iter, true))) { 342 uclparse_lun(ucl_object_key(child), child); 343 } 344 } else { 345 log_warnx("\"lun\" section is not an object"); 346 return (1); 347 } 348 } 349 } 350 351 /* Pass 2 - targets */ 352 it = NULL; 353 while ((obj = ucl_iterate_object(top, &it, true))) { 354 const char *key = ucl_object_key(obj); 355 356 if (!strcmp(key, "target")) { 357 if (obj->type == UCL_OBJECT) { 358 iter = NULL; 359 while ((child = ucl_iterate_object(obj, &iter, 360 true))) { 361 uclparse_target(ucl_object_key(child), 362 child); 363 } 364 } else { 365 log_warnx("\"target\" section is not an object"); 366 return (1); 367 } 368 } 369 } 370 371 return (0); 372 } 373 374 static int 375 uclparse_auth_group(const char *name, const ucl_object_t *top) 376 { 377 struct auth_group *auth_group; 378 const struct auth_name *an; 379 const struct auth_portal *ap; 380 ucl_object_iter_t it = NULL, it2 = NULL; 381 const ucl_object_t *obj = NULL, *tmp = NULL; 382 const char *key; 383 int err; 384 385 if (!strcmp(name, "default") && 386 conf->conf_default_ag_defined == false) { 387 auth_group = auth_group_find(conf, name); 388 conf->conf_default_ag_defined = true; 389 } else { 390 auth_group = auth_group_new(conf, name); 391 } 392 393 if (auth_group == NULL) 394 return (1); 395 396 while ((obj = ucl_iterate_object(top, &it, true))) { 397 key = ucl_object_key(obj); 398 399 if (!strcmp(key, "auth-type")) { 400 const char *value = ucl_object_tostring(obj); 401 402 err = auth_group_set_type(auth_group, value); 403 if (err) 404 return (1); 405 } 406 407 if (!strcmp(key, "chap")) { 408 if (obj->type != UCL_ARRAY) { 409 log_warnx("\"chap\" property of " 410 "auth-group \"%s\" is not an array", 411 name); 412 return (1); 413 } 414 415 it2 = NULL; 416 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 417 if (uclparse_chap(auth_group, tmp) != 0) 418 return (1); 419 } 420 } 421 422 if (!strcmp(key, "chap-mutual")) { 423 if (obj->type != UCL_ARRAY) { 424 log_warnx("\"chap-mutual\" property of " 425 "auth-group \"%s\" is not an array", 426 name); 427 return (1); 428 } 429 430 it2 = NULL; 431 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 432 if (uclparse_chap_mutual(auth_group, tmp) != 0) 433 return (1); 434 } 435 } 436 437 if (!strcmp(key, "initiator-name")) { 438 if (obj->type != UCL_ARRAY) { 439 log_warnx("\"initiator-name\" property of " 440 "auth-group \"%s\" is not an array", 441 name); 442 return (1); 443 } 444 445 it2 = NULL; 446 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 447 const char *value = ucl_object_tostring(tmp); 448 449 an = auth_name_new(auth_group, value); 450 if (an == NULL) 451 return (1); 452 } 453 } 454 455 if (!strcmp(key, "initiator-portal")) { 456 if (obj->type != UCL_ARRAY) { 457 log_warnx("\"initiator-portal\" property of " 458 "auth-group \"%s\" is not an array", 459 name); 460 return (1); 461 } 462 463 it2 = NULL; 464 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 465 const char *value = ucl_object_tostring(tmp); 466 467 ap = auth_portal_new(auth_group, value); 468 if (ap == NULL) 469 return (1); 470 } 471 } 472 } 473 474 return (0); 475 } 476 477 static int 478 uclparse_portal_group(const char *name, const ucl_object_t *top) 479 { 480 struct portal_group *portal_group; 481 ucl_object_iter_t it = NULL, it2 = NULL; 482 const ucl_object_t *obj = NULL, *tmp = NULL; 483 const char *key; 484 485 if (strcmp(name, "default") == 0 && 486 conf->conf_default_pg_defined == false) { 487 portal_group = portal_group_find(conf, name); 488 conf->conf_default_pg_defined = true; 489 } else { 490 portal_group = portal_group_new(conf, name); 491 } 492 493 if (portal_group == NULL) 494 return (1); 495 496 while ((obj = ucl_iterate_object(top, &it, true))) { 497 key = ucl_object_key(obj); 498 499 if (!strcmp(key, "discovery-auth-group")) { 500 portal_group->pg_discovery_auth_group = 501 auth_group_find(conf, ucl_object_tostring(obj)); 502 if (portal_group->pg_discovery_auth_group == NULL) { 503 log_warnx("unknown discovery-auth-group \"%s\" " 504 "for portal-group \"%s\"", 505 ucl_object_tostring(obj), 506 portal_group->pg_name); 507 return (1); 508 } 509 } 510 511 if (!strcmp(key, "discovery-filter")) { 512 if (obj->type != UCL_STRING) { 513 log_warnx("\"discovery-filter\" property of " 514 "portal-group \"%s\" is not a string", 515 portal_group->pg_name); 516 return (1); 517 } 518 519 if (portal_group_set_filter(portal_group, 520 ucl_object_tostring(obj)) != 0) 521 return (1); 522 } 523 524 if (!strcmp(key, "listen")) { 525 if (obj->type == UCL_STRING) { 526 if (portal_group_add_listen(portal_group, 527 ucl_object_tostring(obj), false) != 0) 528 return (1); 529 } else if (obj->type == UCL_ARRAY) { 530 while ((tmp = ucl_iterate_object(obj, &it2, 531 true))) { 532 if (portal_group_add_listen( 533 portal_group, 534 ucl_object_tostring(tmp), 535 false) != 0) 536 return (1); 537 } 538 } else { 539 log_warnx("\"listen\" property of " 540 "portal-group \"%s\" is not a string", 541 portal_group->pg_name); 542 return (1); 543 } 544 } 545 546 if (!strcmp(key, "listen-iser")) { 547 if (obj->type == UCL_STRING) { 548 if (portal_group_add_listen(portal_group, 549 ucl_object_tostring(obj), true) != 0) 550 return (1); 551 } else if (obj->type == UCL_ARRAY) { 552 while ((tmp = ucl_iterate_object(obj, &it2, 553 true))) { 554 if (portal_group_add_listen( 555 portal_group, 556 ucl_object_tostring(tmp), 557 true) != 0) 558 return (1); 559 } 560 } else { 561 log_warnx("\"listen\" property of " 562 "portal-group \"%s\" is not a string", 563 portal_group->pg_name); 564 return (1); 565 } 566 } 567 568 if (!strcmp(key, "redirect")) { 569 if (obj->type != UCL_STRING) { 570 log_warnx("\"listen\" property of " 571 "portal-group \"%s\" is not a string", 572 portal_group->pg_name); 573 return (1); 574 } 575 576 if (portal_group_set_redirection(portal_group, 577 ucl_object_tostring(obj)) != 0) 578 return (1); 579 } 580 581 if (!strcmp(key, "options")) { 582 if (obj->type != UCL_OBJECT) { 583 log_warnx("\"options\" property of portal group " 584 "\"%s\" is not an object", portal_group->pg_name); 585 return (1); 586 } 587 588 while ((tmp = ucl_iterate_object(obj, &it2, 589 true))) { 590 option_new(&portal_group->pg_options, 591 ucl_object_key(tmp), 592 ucl_object_tostring_forced(tmp)); 593 } 594 } 595 } 596 597 return (0); 598 } 599 600 static int 601 uclparse_target(const char *name, const ucl_object_t *top) 602 { 603 struct target *target; 604 ucl_object_iter_t it = NULL, it2 = NULL; 605 const ucl_object_t *obj = NULL, *tmp = NULL; 606 const char *key; 607 608 target = target_new(conf, name); 609 610 while ((obj = ucl_iterate_object(top, &it, true))) { 611 key = ucl_object_key(obj); 612 613 if (!strcmp(key, "alias")) { 614 if (obj->type != UCL_STRING) { 615 log_warnx("\"alias\" property of target " 616 "\"%s\" is not a string", target->t_name); 617 return (1); 618 } 619 620 target->t_alias = strdup(ucl_object_tostring(obj)); 621 } 622 623 if (!strcmp(key, "auth-group")) { 624 if (target->t_auth_group != NULL) { 625 if (target->t_auth_group->ag_name != NULL) 626 log_warnx("auth-group for target \"%s\" " 627 "specified more than once", 628 target->t_name); 629 else 630 log_warnx("cannot use both auth-group " 631 "and explicit authorisations for " 632 "target \"%s\"", target->t_name); 633 return (1); 634 } 635 target->t_auth_group = auth_group_find(conf, 636 ucl_object_tostring(obj)); 637 if (target->t_auth_group == NULL) { 638 log_warnx("unknown auth-group \"%s\" for target " 639 "\"%s\"", ucl_object_tostring(obj), 640 target->t_name); 641 return (1); 642 } 643 } 644 645 if (!strcmp(key, "auth-type")) { 646 int error; 647 648 if (target->t_auth_group != NULL) { 649 if (target->t_auth_group->ag_name != NULL) { 650 log_warnx("cannot use both auth-group and " 651 "auth-type for target \"%s\"", 652 target->t_name); 653 return (1); 654 } 655 } else { 656 target->t_auth_group = auth_group_new(conf, NULL); 657 if (target->t_auth_group == NULL) 658 return (1); 659 660 target->t_auth_group->ag_target = target; 661 } 662 error = auth_group_set_type(target->t_auth_group, 663 ucl_object_tostring(obj)); 664 if (error != 0) 665 return (1); 666 } 667 668 if (!strcmp(key, "chap")) { 669 if (uclparse_chap(target->t_auth_group, obj) != 0) 670 return (1); 671 } 672 673 if (!strcmp(key, "chap-mutual")) { 674 if (uclparse_chap_mutual(target->t_auth_group, obj) != 0) 675 return (1); 676 } 677 678 if (!strcmp(key, "initiator-name")) { 679 const struct auth_name *an; 680 681 if (target->t_auth_group != NULL) { 682 if (target->t_auth_group->ag_name != NULL) { 683 log_warnx("cannot use both auth-group and " 684 "initiator-name for target \"%s\"", 685 target->t_name); 686 return (1); 687 } 688 } else { 689 target->t_auth_group = auth_group_new(conf, NULL); 690 if (target->t_auth_group == NULL) 691 return (1); 692 693 target->t_auth_group->ag_target = target; 694 } 695 an = auth_name_new(target->t_auth_group, 696 ucl_object_tostring(obj)); 697 if (an == NULL) 698 return (1); 699 } 700 701 if (!strcmp(key, "initiator-portal")) { 702 const struct auth_portal *ap; 703 704 if (target->t_auth_group != NULL) { 705 if (target->t_auth_group->ag_name != NULL) { 706 log_warnx("cannot use both auth-group and " 707 "initiator-portal for target \"%s\"", 708 target->t_name); 709 return (1); 710 } 711 } else { 712 target->t_auth_group = auth_group_new(conf, NULL); 713 if (target->t_auth_group == NULL) 714 return (1); 715 716 target->t_auth_group->ag_target = target; 717 } 718 ap = auth_portal_new(target->t_auth_group, 719 ucl_object_tostring(obj)); 720 if (ap == NULL) 721 return (1); 722 } 723 724 if (!strcmp(key, "portal-group")) { 725 if (obj->type == UCL_OBJECT) { 726 if (uclparse_target_portal_group(target, obj) != 0) 727 return (1); 728 } 729 730 if (obj->type == UCL_ARRAY) { 731 while ((tmp = ucl_iterate_object(obj, &it2, 732 true))) { 733 if (uclparse_target_portal_group(target, 734 tmp) != 0) 735 return (1); 736 } 737 } 738 } 739 740 if (!strcmp(key, "port")) { 741 struct pport *pp; 742 struct port *tp; 743 const char *value = ucl_object_tostring(obj); 744 745 pp = pport_find(conf, value); 746 if (pp == NULL) { 747 log_warnx("unknown port \"%s\" for target \"%s\"", 748 value, target->t_name); 749 return (1); 750 } 751 if (!TAILQ_EMPTY(&pp->pp_ports)) { 752 log_warnx("can't link port \"%s\" to target \"%s\", " 753 "port already linked to some target", 754 value, target->t_name); 755 return (1); 756 } 757 tp = port_new_pp(conf, target, pp); 758 if (tp == NULL) { 759 log_warnx("can't link port \"%s\" to target \"%s\"", 760 value, target->t_name); 761 return (1); 762 } 763 } 764 765 if (!strcmp(key, "redirect")) { 766 if (obj->type != UCL_STRING) { 767 log_warnx("\"redirect\" property of target " 768 "\"%s\" is not a string", target->t_name); 769 return (1); 770 } 771 772 if (target_set_redirection(target, 773 ucl_object_tostring(obj)) != 0) 774 return (1); 775 } 776 777 if (!strcmp(key, "lun")) { 778 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 779 if (uclparse_target_lun(target, tmp) != 0) 780 return (1); 781 } 782 } 783 } 784 785 return (0); 786 } 787 788 static int 789 uclparse_lun(const char *name, const ucl_object_t *top) 790 { 791 struct lun *lun; 792 ucl_object_iter_t it = NULL, child_it = NULL; 793 const ucl_object_t *obj = NULL, *child = NULL; 794 const char *key; 795 796 lun = lun_new(conf, name); 797 798 while ((obj = ucl_iterate_object(top, &it, true))) { 799 key = ucl_object_key(obj); 800 801 if (!strcmp(key, "backend")) { 802 if (obj->type != UCL_STRING) { 803 log_warnx("\"backend\" property of lun " 804 "\"%s\" is not a string", 805 lun->l_name); 806 return (1); 807 } 808 809 lun_set_backend(lun, ucl_object_tostring(obj)); 810 } 811 812 if (!strcmp(key, "blocksize")) { 813 if (obj->type != UCL_INT) { 814 log_warnx("\"blocksize\" property of lun " 815 "\"%s\" is not an integer", lun->l_name); 816 return (1); 817 } 818 819 lun_set_blocksize(lun, ucl_object_toint(obj)); 820 } 821 822 if (!strcmp(key, "device-id")) { 823 if (obj->type != UCL_STRING) { 824 log_warnx("\"device-id\" property of lun " 825 "\"%s\" is not an integer", lun->l_name); 826 return (1); 827 } 828 829 lun_set_device_id(lun, ucl_object_tostring(obj)); 830 } 831 832 if (!strcmp(key, "options")) { 833 if (obj->type != UCL_OBJECT) { 834 log_warnx("\"options\" property of lun " 835 "\"%s\" is not an object", lun->l_name); 836 return (1); 837 } 838 839 while ((child = ucl_iterate_object(obj, &child_it, 840 true))) { 841 option_new(&lun->l_options, 842 ucl_object_key(child), 843 ucl_object_tostring_forced(child)); 844 } 845 } 846 847 if (!strcmp(key, "path")) { 848 if (obj->type != UCL_STRING) { 849 log_warnx("\"path\" property of lun " 850 "\"%s\" is not a string", lun->l_name); 851 return (1); 852 } 853 854 lun_set_path(lun, ucl_object_tostring(obj)); 855 } 856 857 if (!strcmp(key, "serial")) { 858 if (obj->type != UCL_STRING) { 859 log_warnx("\"serial\" property of lun " 860 "\"%s\" is not a string", lun->l_name); 861 return (1); 862 } 863 864 lun_set_serial(lun, ucl_object_tostring(obj)); 865 } 866 867 if (!strcmp(key, "size")) { 868 if (obj->type != UCL_INT) { 869 log_warnx("\"size\" property of lun " 870 "\"%s\" is not an integer", lun->l_name); 871 return (1); 872 } 873 874 lun_set_size(lun, ucl_object_toint(obj)); 875 } 876 } 877 878 return (0); 879 } 880 881 int 882 uclparse_conf(struct conf *newconf, const char *path) 883 { 884 struct ucl_parser *parser; 885 int error; 886 887 conf = newconf; 888 parser = ucl_parser_new(0); 889 890 if (!ucl_parser_add_file(parser, path)) { 891 log_warn("unable to parse configuration file %s: %s", path, 892 ucl_parser_get_error(parser)); 893 return (1); 894 } 895 896 error = uclparse_toplevel(ucl_parser_get_object(parser)); 897 898 return (error); 899 } 900