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 uint64_t tmp; 187 188 if (obj->type == UCL_INT) { 189 char *name; 190 191 tmp = ucl_object_toint(obj); 192 if (tmp >= MAX_LUNS) { 193 log_warnx("LU number %ju in target \"%s\" is too big", 194 tmp, target->t_name); 195 return (1); 196 } 197 198 asprintf(&name, "%s,lun,%ju", target->t_name, tmp); 199 lun = lun_new(conf, name); 200 if (lun == NULL) 201 return (1); 202 203 lun_set_scsiname(lun, name); 204 target->t_luns[tmp] = lun; 205 return (0); 206 } 207 208 if (obj->type == UCL_OBJECT) { 209 const ucl_object_t *num = ucl_object_find_key(obj, "number"); 210 const ucl_object_t *name = ucl_object_find_key(obj, "name"); 211 212 if (num == NULL || num->type != UCL_INT) { 213 log_warnx("lun section in target \"%s\" is missing " 214 "\"number\" integer property", target->t_name); 215 return (1); 216 } 217 tmp = ucl_object_toint(num); 218 if (tmp >= MAX_LUNS) { 219 log_warnx("LU number %ju in target \"%s\" is too big", 220 tmp, target->t_name); 221 return (1); 222 } 223 224 if (name == NULL || name->type != UCL_STRING) { 225 log_warnx("lun section in target \"%s\" is missing " 226 "\"name\" string property", target->t_name); 227 return (1); 228 } 229 230 lun = lun_find(conf, ucl_object_tostring(name)); 231 if (lun == NULL) 232 return (1); 233 234 target->t_luns[tmp] = lun; 235 } 236 237 return (0); 238 } 239 240 static int 241 uclparse_toplevel(const ucl_object_t *top) 242 { 243 ucl_object_iter_t it = NULL, iter = NULL; 244 const ucl_object_t *obj = NULL, *child = NULL; 245 int err = 0; 246 247 /* Pass 1 - everything except targets */ 248 while ((obj = ucl_iterate_object(top, &it, true))) { 249 const char *key = ucl_object_key(obj); 250 251 if (!strcmp(key, "debug")) { 252 if (obj->type == UCL_INT) 253 conf->conf_debug = ucl_object_toint(obj); 254 else { 255 log_warnx("\"debug\" property value is not integer"); 256 return (1); 257 } 258 } 259 260 if (!strcmp(key, "timeout")) { 261 if (obj->type == UCL_INT) 262 conf->conf_timeout = ucl_object_toint(obj); 263 else { 264 log_warnx("\"timeout\" property value is not integer"); 265 return (1); 266 } 267 } 268 269 if (!strcmp(key, "maxproc")) { 270 if (obj->type == UCL_INT) 271 conf->conf_maxproc = ucl_object_toint(obj); 272 else { 273 log_warnx("\"maxproc\" property value is not integer"); 274 return (1); 275 } 276 } 277 278 if (!strcmp(key, "pidfile")) { 279 if (obj->type == UCL_STRING) 280 conf->conf_pidfile_path = strdup( 281 ucl_object_tostring(obj)); 282 else { 283 log_warnx("\"pidfile\" property value is not string"); 284 return (1); 285 } 286 } 287 288 if (!strcmp(key, "isns-server")) { 289 if (obj->type == UCL_ARRAY) { 290 iter = NULL; 291 while ((child = ucl_iterate_object(obj, &iter, 292 true))) { 293 if (child->type != UCL_STRING) 294 return (1); 295 296 err = isns_new(conf, 297 ucl_object_tostring(child)); 298 if (err != 0) { 299 return (1); 300 } 301 } 302 } else { 303 log_warnx("\"isns-server\" property value is " 304 "not an array"); 305 return (1); 306 } 307 } 308 309 if (!strcmp(key, "isns-period")) { 310 if (obj->type == UCL_INT) 311 conf->conf_timeout = ucl_object_toint(obj); 312 else { 313 log_warnx("\"isns-period\" property value is not integer"); 314 return (1); 315 } 316 } 317 318 if (!strcmp(key, "isns-timeout")) { 319 if (obj->type == UCL_INT) 320 conf->conf_timeout = ucl_object_toint(obj); 321 else { 322 log_warnx("\"isns-timeout\" property value is not integer"); 323 return (1); 324 } 325 } 326 327 if (!strcmp(key, "auth-group")) { 328 if (obj->type == UCL_OBJECT) { 329 iter = NULL; 330 while ((child = ucl_iterate_object(obj, &iter, true))) { 331 uclparse_auth_group(ucl_object_key(child), child); 332 } 333 } else { 334 log_warnx("\"auth-group\" section is not an object"); 335 return (1); 336 } 337 } 338 339 if (!strcmp(key, "portal-group")) { 340 if (obj->type == UCL_OBJECT) { 341 iter = NULL; 342 while ((child = ucl_iterate_object(obj, &iter, true))) { 343 uclparse_portal_group(ucl_object_key(child), child); 344 } 345 } else { 346 log_warnx("\"portal-group\" section is not an object"); 347 return (1); 348 } 349 } 350 351 if (!strcmp(key, "lun")) { 352 if (obj->type == UCL_OBJECT) { 353 iter = NULL; 354 while ((child = ucl_iterate_object(obj, &iter, true))) { 355 uclparse_lun(ucl_object_key(child), child); 356 } 357 } else { 358 log_warnx("\"lun\" section is not an object"); 359 return (1); 360 } 361 } 362 } 363 364 /* Pass 2 - targets */ 365 it = NULL; 366 while ((obj = ucl_iterate_object(top, &it, true))) { 367 const char *key = ucl_object_key(obj); 368 369 if (!strcmp(key, "target")) { 370 if (obj->type == UCL_OBJECT) { 371 iter = NULL; 372 while ((child = ucl_iterate_object(obj, &iter, 373 true))) { 374 uclparse_target(ucl_object_key(child), 375 child); 376 } 377 } else { 378 log_warnx("\"target\" section is not an object"); 379 return (1); 380 } 381 } 382 } 383 384 return (0); 385 } 386 387 static int 388 uclparse_auth_group(const char *name, const ucl_object_t *top) 389 { 390 struct auth_group *auth_group; 391 const struct auth_name *an; 392 const struct auth_portal *ap; 393 ucl_object_iter_t it = NULL, it2 = NULL; 394 const ucl_object_t *obj = NULL, *tmp = NULL; 395 const char *key; 396 int err; 397 398 if (!strcmp(name, "default") && 399 conf->conf_default_ag_defined == false) { 400 auth_group = auth_group_find(conf, name); 401 conf->conf_default_ag_defined = true; 402 } else { 403 auth_group = auth_group_new(conf, name); 404 } 405 406 if (auth_group == NULL) 407 return (1); 408 409 while ((obj = ucl_iterate_object(top, &it, true))) { 410 key = ucl_object_key(obj); 411 412 if (!strcmp(key, "auth-type")) { 413 const char *value = ucl_object_tostring(obj); 414 415 err = auth_group_set_type(auth_group, value); 416 if (err) 417 return (1); 418 } 419 420 if (!strcmp(key, "chap")) { 421 if (obj->type != UCL_ARRAY) { 422 log_warnx("\"chap\" property of " 423 "auth-group \"%s\" is not an array", 424 name); 425 return (1); 426 } 427 428 it2 = NULL; 429 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 430 if (uclparse_chap(auth_group, tmp) != 0) 431 return (1); 432 } 433 } 434 435 if (!strcmp(key, "chap-mutual")) { 436 if (obj->type != UCL_ARRAY) { 437 log_warnx("\"chap-mutual\" property of " 438 "auth-group \"%s\" is not an array", 439 name); 440 return (1); 441 } 442 443 it2 = NULL; 444 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 445 if (uclparse_chap_mutual(auth_group, tmp) != 0) 446 return (1); 447 } 448 } 449 450 if (!strcmp(key, "initiator-name")) { 451 if (obj->type != UCL_ARRAY) { 452 log_warnx("\"initiator-name\" property of " 453 "auth-group \"%s\" is not an array", 454 name); 455 return (1); 456 } 457 458 it2 = NULL; 459 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 460 const char *value = ucl_object_tostring(tmp); 461 462 an = auth_name_new(auth_group, value); 463 if (an == NULL) 464 return (1); 465 } 466 } 467 468 if (!strcmp(key, "initiator-portal")) { 469 if (obj->type != UCL_ARRAY) { 470 log_warnx("\"initiator-portal\" property of " 471 "auth-group \"%s\" is not an array", 472 name); 473 return (1); 474 } 475 476 it2 = NULL; 477 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 478 const char *value = ucl_object_tostring(tmp); 479 480 ap = auth_portal_new(auth_group, value); 481 if (ap == NULL) 482 return (1); 483 } 484 } 485 } 486 487 return (0); 488 } 489 490 static int 491 uclparse_portal_group(const char *name, const ucl_object_t *top) 492 { 493 struct portal_group *portal_group; 494 ucl_object_iter_t it = NULL, it2 = NULL; 495 const ucl_object_t *obj = NULL, *tmp = NULL; 496 const char *key; 497 498 if (strcmp(name, "default") == 0 && 499 conf->conf_default_pg_defined == false) { 500 portal_group = portal_group_find(conf, name); 501 conf->conf_default_pg_defined = true; 502 } else { 503 portal_group = portal_group_new(conf, name); 504 } 505 506 if (portal_group == NULL) 507 return (1); 508 509 while ((obj = ucl_iterate_object(top, &it, true))) { 510 key = ucl_object_key(obj); 511 512 if (!strcmp(key, "discovery-auth-group")) { 513 portal_group->pg_discovery_auth_group = 514 auth_group_find(conf, ucl_object_tostring(obj)); 515 if (portal_group->pg_discovery_auth_group == NULL) { 516 log_warnx("unknown discovery-auth-group \"%s\" " 517 "for portal-group \"%s\"", 518 ucl_object_tostring(obj), 519 portal_group->pg_name); 520 return (1); 521 } 522 } 523 524 if (!strcmp(key, "discovery-filter")) { 525 if (obj->type != UCL_STRING) { 526 log_warnx("\"discovery-filter\" property of " 527 "portal-group \"%s\" is not a string", 528 portal_group->pg_name); 529 return (1); 530 } 531 532 if (portal_group_set_filter(portal_group, 533 ucl_object_tostring(obj)) != 0) 534 return (1); 535 } 536 537 if (!strcmp(key, "listen")) { 538 if (obj->type == UCL_STRING) { 539 if (portal_group_add_listen(portal_group, 540 ucl_object_tostring(obj), false) != 0) 541 return (1); 542 } else if (obj->type == UCL_ARRAY) { 543 while ((tmp = ucl_iterate_object(obj, &it2, 544 true))) { 545 if (portal_group_add_listen( 546 portal_group, 547 ucl_object_tostring(tmp), 548 false) != 0) 549 return (1); 550 } 551 } else { 552 log_warnx("\"listen\" property of " 553 "portal-group \"%s\" is not a string", 554 portal_group->pg_name); 555 return (1); 556 } 557 } 558 559 if (!strcmp(key, "listen-iser")) { 560 if (obj->type == UCL_STRING) { 561 if (portal_group_add_listen(portal_group, 562 ucl_object_tostring(obj), true) != 0) 563 return (1); 564 } else if (obj->type == UCL_ARRAY) { 565 while ((tmp = ucl_iterate_object(obj, &it2, 566 true))) { 567 if (portal_group_add_listen( 568 portal_group, 569 ucl_object_tostring(tmp), 570 true) != 0) 571 return (1); 572 } 573 } else { 574 log_warnx("\"listen\" property of " 575 "portal-group \"%s\" is not a string", 576 portal_group->pg_name); 577 return (1); 578 } 579 } 580 581 if (!strcmp(key, "redirect")) { 582 if (obj->type != UCL_STRING) { 583 log_warnx("\"listen\" property of " 584 "portal-group \"%s\" is not a string", 585 portal_group->pg_name); 586 return (1); 587 } 588 589 if (portal_group_set_redirection(portal_group, 590 ucl_object_tostring(obj)) != 0) 591 return (1); 592 } 593 594 if (!strcmp(key, "options")) { 595 if (obj->type != UCL_OBJECT) { 596 log_warnx("\"options\" property of portal group " 597 "\"%s\" is not an object", portal_group->pg_name); 598 return (1); 599 } 600 601 while ((tmp = ucl_iterate_object(obj, &it2, 602 true))) { 603 option_new(&portal_group->pg_options, 604 ucl_object_key(tmp), 605 ucl_object_tostring_forced(tmp)); 606 } 607 } 608 } 609 610 return (0); 611 } 612 613 static int 614 uclparse_target(const char *name, const ucl_object_t *top) 615 { 616 struct target *target; 617 ucl_object_iter_t it = NULL, it2 = NULL; 618 const ucl_object_t *obj = NULL, *tmp = NULL; 619 const char *key; 620 621 target = target_new(conf, name); 622 623 while ((obj = ucl_iterate_object(top, &it, true))) { 624 key = ucl_object_key(obj); 625 626 if (!strcmp(key, "alias")) { 627 if (obj->type != UCL_STRING) { 628 log_warnx("\"alias\" property of target " 629 "\"%s\" is not a string", target->t_name); 630 return (1); 631 } 632 633 target->t_alias = strdup(ucl_object_tostring(obj)); 634 } 635 636 if (!strcmp(key, "auth-group")) { 637 if (target->t_auth_group != NULL) { 638 if (target->t_auth_group->ag_name != NULL) 639 log_warnx("auth-group for target \"%s\" " 640 "specified more than once", 641 target->t_name); 642 else 643 log_warnx("cannot use both auth-group " 644 "and explicit authorisations for " 645 "target \"%s\"", target->t_name); 646 return (1); 647 } 648 target->t_auth_group = auth_group_find(conf, 649 ucl_object_tostring(obj)); 650 if (target->t_auth_group == NULL) { 651 log_warnx("unknown auth-group \"%s\" for target " 652 "\"%s\"", ucl_object_tostring(obj), 653 target->t_name); 654 return (1); 655 } 656 } 657 658 if (!strcmp(key, "auth-type")) { 659 int error; 660 661 if (target->t_auth_group != NULL) { 662 if (target->t_auth_group->ag_name != NULL) { 663 log_warnx("cannot use both auth-group and " 664 "auth-type for target \"%s\"", 665 target->t_name); 666 return (1); 667 } 668 } else { 669 target->t_auth_group = auth_group_new(conf, NULL); 670 if (target->t_auth_group == NULL) 671 return (1); 672 673 target->t_auth_group->ag_target = target; 674 } 675 error = auth_group_set_type(target->t_auth_group, 676 ucl_object_tostring(obj)); 677 if (error != 0) 678 return (1); 679 } 680 681 if (!strcmp(key, "chap")) { 682 if (uclparse_chap(target->t_auth_group, obj) != 0) 683 return (1); 684 } 685 686 if (!strcmp(key, "chap-mutual")) { 687 if (uclparse_chap_mutual(target->t_auth_group, obj) != 0) 688 return (1); 689 } 690 691 if (!strcmp(key, "initiator-name")) { 692 const struct auth_name *an; 693 694 if (target->t_auth_group != NULL) { 695 if (target->t_auth_group->ag_name != NULL) { 696 log_warnx("cannot use both auth-group and " 697 "initiator-name for target \"%s\"", 698 target->t_name); 699 return (1); 700 } 701 } else { 702 target->t_auth_group = auth_group_new(conf, NULL); 703 if (target->t_auth_group == NULL) 704 return (1); 705 706 target->t_auth_group->ag_target = target; 707 } 708 an = auth_name_new(target->t_auth_group, 709 ucl_object_tostring(obj)); 710 if (an == NULL) 711 return (1); 712 } 713 714 if (!strcmp(key, "initiator-portal")) { 715 const struct auth_portal *ap; 716 717 if (target->t_auth_group != NULL) { 718 if (target->t_auth_group->ag_name != NULL) { 719 log_warnx("cannot use both auth-group and " 720 "initiator-portal for target \"%s\"", 721 target->t_name); 722 return (1); 723 } 724 } else { 725 target->t_auth_group = auth_group_new(conf, NULL); 726 if (target->t_auth_group == NULL) 727 return (1); 728 729 target->t_auth_group->ag_target = target; 730 } 731 ap = auth_portal_new(target->t_auth_group, 732 ucl_object_tostring(obj)); 733 if (ap == NULL) 734 return (1); 735 } 736 737 if (!strcmp(key, "portal-group")) { 738 if (obj->type == UCL_OBJECT) { 739 if (uclparse_target_portal_group(target, obj) != 0) 740 return (1); 741 } 742 743 if (obj->type == UCL_ARRAY) { 744 while ((tmp = ucl_iterate_object(obj, &it2, 745 true))) { 746 if (uclparse_target_portal_group(target, 747 tmp) != 0) 748 return (1); 749 } 750 } 751 } 752 753 if (!strcmp(key, "port")) { 754 struct pport *pp; 755 struct port *tp; 756 const char *value = ucl_object_tostring(obj); 757 758 pp = pport_find(conf, value); 759 if (pp == NULL) { 760 log_warnx("unknown port \"%s\" for target \"%s\"", 761 value, target->t_name); 762 return (1); 763 } 764 if (!TAILQ_EMPTY(&pp->pp_ports)) { 765 log_warnx("can't link port \"%s\" to target \"%s\", " 766 "port already linked to some target", 767 value, target->t_name); 768 return (1); 769 } 770 tp = port_new_pp(conf, target, pp); 771 if (tp == NULL) { 772 log_warnx("can't link port \"%s\" to target \"%s\"", 773 value, target->t_name); 774 return (1); 775 } 776 } 777 778 if (!strcmp(key, "redirect")) { 779 if (obj->type != UCL_STRING) { 780 log_warnx("\"redirect\" property of target " 781 "\"%s\" is not a string", target->t_name); 782 return (1); 783 } 784 785 if (target_set_redirection(target, 786 ucl_object_tostring(obj)) != 0) 787 return (1); 788 } 789 790 if (!strcmp(key, "lun")) { 791 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 792 if (uclparse_target_lun(target, tmp) != 0) 793 return (1); 794 } 795 } 796 } 797 798 return (0); 799 } 800 801 static int 802 uclparse_lun(const char *name, const ucl_object_t *top) 803 { 804 struct lun *lun; 805 ucl_object_iter_t it = NULL, child_it = NULL; 806 const ucl_object_t *obj = NULL, *child = NULL; 807 const char *key; 808 809 lun = lun_new(conf, name); 810 811 while ((obj = ucl_iterate_object(top, &it, true))) { 812 key = ucl_object_key(obj); 813 814 if (!strcmp(key, "backend")) { 815 if (obj->type != UCL_STRING) { 816 log_warnx("\"backend\" property of lun " 817 "\"%s\" is not a string", 818 lun->l_name); 819 return (1); 820 } 821 822 lun_set_backend(lun, ucl_object_tostring(obj)); 823 } 824 825 if (!strcmp(key, "blocksize")) { 826 if (obj->type != UCL_INT) { 827 log_warnx("\"blocksize\" property of lun " 828 "\"%s\" is not an integer", lun->l_name); 829 return (1); 830 } 831 832 lun_set_blocksize(lun, ucl_object_toint(obj)); 833 } 834 835 if (!strcmp(key, "device-id")) { 836 if (obj->type != UCL_STRING) { 837 log_warnx("\"device-id\" property of lun " 838 "\"%s\" is not an integer", lun->l_name); 839 return (1); 840 } 841 842 lun_set_device_id(lun, ucl_object_tostring(obj)); 843 } 844 845 if (!strcmp(key, "options")) { 846 if (obj->type != UCL_OBJECT) { 847 log_warnx("\"options\" property of lun " 848 "\"%s\" is not an object", lun->l_name); 849 return (1); 850 } 851 852 while ((child = ucl_iterate_object(obj, &child_it, 853 true))) { 854 option_new(&lun->l_options, 855 ucl_object_key(child), 856 ucl_object_tostring_forced(child)); 857 } 858 } 859 860 if (!strcmp(key, "path")) { 861 if (obj->type != UCL_STRING) { 862 log_warnx("\"path\" property of lun " 863 "\"%s\" is not a string", lun->l_name); 864 return (1); 865 } 866 867 lun_set_path(lun, ucl_object_tostring(obj)); 868 } 869 870 if (!strcmp(key, "serial")) { 871 if (obj->type != UCL_STRING) { 872 log_warnx("\"serial\" property of lun " 873 "\"%s\" is not a string", lun->l_name); 874 return (1); 875 } 876 877 lun_set_serial(lun, ucl_object_tostring(obj)); 878 } 879 880 if (!strcmp(key, "size")) { 881 if (obj->type != UCL_INT) { 882 log_warnx("\"size\" property of lun " 883 "\"%s\" is not an integer", lun->l_name); 884 return (1); 885 } 886 887 lun_set_size(lun, ucl_object_toint(obj)); 888 } 889 } 890 891 return (0); 892 } 893 894 int 895 uclparse_conf(struct conf *newconf, const char *path) 896 { 897 struct ucl_parser *parser; 898 int error; 899 900 conf = newconf; 901 parser = ucl_parser_new(0); 902 903 if (!ucl_parser_add_file(parser, path)) { 904 log_warn("unable to parse configuration file %s: %s", path, 905 ucl_parser_get_error(parser)); 906 return (1); 907 } 908 909 error = uclparse_toplevel(ucl_parser_get_object(parser)); 910 911 return (error); 912 } 913