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 if (target == NULL) 623 return (1); 624 625 while ((obj = ucl_iterate_object(top, &it, true))) { 626 key = ucl_object_key(obj); 627 628 if (!strcmp(key, "alias")) { 629 if (obj->type != UCL_STRING) { 630 log_warnx("\"alias\" property of target " 631 "\"%s\" is not a string", target->t_name); 632 return (1); 633 } 634 635 target->t_alias = strdup(ucl_object_tostring(obj)); 636 } 637 638 if (!strcmp(key, "auth-group")) { 639 if (target->t_auth_group != NULL) { 640 if (target->t_auth_group->ag_name != NULL) 641 log_warnx("auth-group for target \"%s\" " 642 "specified more than once", 643 target->t_name); 644 else 645 log_warnx("cannot use both auth-group " 646 "and explicit authorisations for " 647 "target \"%s\"", target->t_name); 648 return (1); 649 } 650 target->t_auth_group = auth_group_find(conf, 651 ucl_object_tostring(obj)); 652 if (target->t_auth_group == NULL) { 653 log_warnx("unknown auth-group \"%s\" for target " 654 "\"%s\"", ucl_object_tostring(obj), 655 target->t_name); 656 return (1); 657 } 658 } 659 660 if (!strcmp(key, "auth-type")) { 661 int error; 662 663 if (target->t_auth_group != NULL) { 664 if (target->t_auth_group->ag_name != NULL) { 665 log_warnx("cannot use both auth-group and " 666 "auth-type for target \"%s\"", 667 target->t_name); 668 return (1); 669 } 670 } else { 671 target->t_auth_group = auth_group_new(conf, NULL); 672 if (target->t_auth_group == NULL) 673 return (1); 674 675 target->t_auth_group->ag_target = target; 676 } 677 error = auth_group_set_type(target->t_auth_group, 678 ucl_object_tostring(obj)); 679 if (error != 0) 680 return (1); 681 } 682 683 if (!strcmp(key, "chap")) { 684 if (uclparse_chap(target->t_auth_group, obj) != 0) 685 return (1); 686 } 687 688 if (!strcmp(key, "chap-mutual")) { 689 if (uclparse_chap_mutual(target->t_auth_group, obj) != 0) 690 return (1); 691 } 692 693 if (!strcmp(key, "initiator-name")) { 694 const struct auth_name *an; 695 696 if (target->t_auth_group != NULL) { 697 if (target->t_auth_group->ag_name != NULL) { 698 log_warnx("cannot use both auth-group and " 699 "initiator-name for target \"%s\"", 700 target->t_name); 701 return (1); 702 } 703 } else { 704 target->t_auth_group = auth_group_new(conf, NULL); 705 if (target->t_auth_group == NULL) 706 return (1); 707 708 target->t_auth_group->ag_target = target; 709 } 710 an = auth_name_new(target->t_auth_group, 711 ucl_object_tostring(obj)); 712 if (an == NULL) 713 return (1); 714 } 715 716 if (!strcmp(key, "initiator-portal")) { 717 const struct auth_portal *ap; 718 719 if (target->t_auth_group != NULL) { 720 if (target->t_auth_group->ag_name != NULL) { 721 log_warnx("cannot use both auth-group and " 722 "initiator-portal for target \"%s\"", 723 target->t_name); 724 return (1); 725 } 726 } else { 727 target->t_auth_group = auth_group_new(conf, NULL); 728 if (target->t_auth_group == NULL) 729 return (1); 730 731 target->t_auth_group->ag_target = target; 732 } 733 ap = auth_portal_new(target->t_auth_group, 734 ucl_object_tostring(obj)); 735 if (ap == NULL) 736 return (1); 737 } 738 739 if (!strcmp(key, "portal-group")) { 740 if (obj->type == UCL_OBJECT) { 741 if (uclparse_target_portal_group(target, obj) != 0) 742 return (1); 743 } 744 745 if (obj->type == UCL_ARRAY) { 746 while ((tmp = ucl_iterate_object(obj, &it2, 747 true))) { 748 if (uclparse_target_portal_group(target, 749 tmp) != 0) 750 return (1); 751 } 752 } 753 } 754 755 if (!strcmp(key, "port")) { 756 struct pport *pp; 757 struct port *tp; 758 const char *value = ucl_object_tostring(obj); 759 760 pp = pport_find(conf, value); 761 if (pp == NULL) { 762 log_warnx("unknown port \"%s\" for target \"%s\"", 763 value, target->t_name); 764 return (1); 765 } 766 if (!TAILQ_EMPTY(&pp->pp_ports)) { 767 log_warnx("can't link port \"%s\" to target \"%s\", " 768 "port already linked to some target", 769 value, target->t_name); 770 return (1); 771 } 772 tp = port_new_pp(conf, target, pp); 773 if (tp == NULL) { 774 log_warnx("can't link port \"%s\" to target \"%s\"", 775 value, target->t_name); 776 return (1); 777 } 778 } 779 780 if (!strcmp(key, "redirect")) { 781 if (obj->type != UCL_STRING) { 782 log_warnx("\"redirect\" property of target " 783 "\"%s\" is not a string", target->t_name); 784 return (1); 785 } 786 787 if (target_set_redirection(target, 788 ucl_object_tostring(obj)) != 0) 789 return (1); 790 } 791 792 if (!strcmp(key, "lun")) { 793 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 794 if (uclparse_target_lun(target, tmp) != 0) 795 return (1); 796 } 797 } 798 } 799 800 return (0); 801 } 802 803 static int 804 uclparse_lun(const char *name, const ucl_object_t *top) 805 { 806 struct lun *lun; 807 ucl_object_iter_t it = NULL, child_it = NULL; 808 const ucl_object_t *obj = NULL, *child = NULL; 809 const char *key; 810 811 lun = lun_new(conf, name); 812 if (lun == NULL) 813 return (1); 814 815 while ((obj = ucl_iterate_object(top, &it, true))) { 816 key = ucl_object_key(obj); 817 818 if (!strcmp(key, "backend")) { 819 if (obj->type != UCL_STRING) { 820 log_warnx("\"backend\" property of lun " 821 "\"%s\" is not a string", 822 lun->l_name); 823 return (1); 824 } 825 826 lun_set_backend(lun, ucl_object_tostring(obj)); 827 } 828 829 if (!strcmp(key, "blocksize")) { 830 if (obj->type != UCL_INT) { 831 log_warnx("\"blocksize\" property of lun " 832 "\"%s\" is not an integer", lun->l_name); 833 return (1); 834 } 835 836 lun_set_blocksize(lun, ucl_object_toint(obj)); 837 } 838 839 if (!strcmp(key, "device-id")) { 840 if (obj->type != UCL_STRING) { 841 log_warnx("\"device-id\" property of lun " 842 "\"%s\" is not an integer", lun->l_name); 843 return (1); 844 } 845 846 lun_set_device_id(lun, ucl_object_tostring(obj)); 847 } 848 849 if (!strcmp(key, "options")) { 850 if (obj->type != UCL_OBJECT) { 851 log_warnx("\"options\" property of lun " 852 "\"%s\" is not an object", lun->l_name); 853 return (1); 854 } 855 856 while ((child = ucl_iterate_object(obj, &child_it, 857 true))) { 858 option_new(&lun->l_options, 859 ucl_object_key(child), 860 ucl_object_tostring_forced(child)); 861 } 862 } 863 864 if (!strcmp(key, "path")) { 865 if (obj->type != UCL_STRING) { 866 log_warnx("\"path\" property of lun " 867 "\"%s\" is not a string", lun->l_name); 868 return (1); 869 } 870 871 lun_set_path(lun, ucl_object_tostring(obj)); 872 } 873 874 if (!strcmp(key, "serial")) { 875 if (obj->type != UCL_STRING) { 876 log_warnx("\"serial\" property of lun " 877 "\"%s\" is not a string", lun->l_name); 878 return (1); 879 } 880 881 lun_set_serial(lun, ucl_object_tostring(obj)); 882 } 883 884 if (!strcmp(key, "size")) { 885 if (obj->type != UCL_INT) { 886 log_warnx("\"size\" property of lun " 887 "\"%s\" is not an integer", lun->l_name); 888 return (1); 889 } 890 891 lun_set_size(lun, ucl_object_toint(obj)); 892 } 893 } 894 895 return (0); 896 } 897 898 int 899 uclparse_conf(struct conf *newconf, const char *path) 900 { 901 struct ucl_parser *parser; 902 int error; 903 904 conf = newconf; 905 parser = ucl_parser_new(0); 906 907 if (!ucl_parser_add_file(parser, path)) { 908 log_warn("unable to parse configuration file %s: %s", path, 909 ucl_parser_get_error(parser)); 910 return (1); 911 } 912 913 error = uclparse_toplevel(ucl_parser_get_object(parser)); 914 915 return (error); 916 } 917