1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2015 iXsystems Inc. 5 * All rights reserved. 6 * 7 * This software was developed by Jakub Klama <jceel@FreeBSD.org> 8 * under sponsorship from iXsystems Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 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. 18 * 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 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/nv.h> 34 #include <sys/queue.h> 35 #include <assert.h> 36 #include <stdio.h> 37 #include <stdint.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <ucl.h> 41 #include <netinet/in.h> 42 #include <netinet/ip.h> 43 44 #include "conf.h" 45 #include "ctld.h" 46 47 static bool uclparse_toplevel(const ucl_object_t *); 48 static bool uclparse_chap(const char *, const ucl_object_t *); 49 static bool uclparse_chap_mutual(const char *, const ucl_object_t *); 50 static bool uclparse_lun(const char *, const ucl_object_t *); 51 static bool uclparse_lun_entries(const char *, const ucl_object_t *); 52 static bool uclparse_auth_group(const char *, const ucl_object_t *); 53 static bool uclparse_portal_group(const char *, const ucl_object_t *); 54 static bool uclparse_target(const char *, const ucl_object_t *); 55 static bool uclparse_target_portal_group(const char *, const ucl_object_t *); 56 static bool uclparse_target_lun(const char *, const ucl_object_t *); 57 58 static bool 59 uclparse_chap(const char *ag_name, const ucl_object_t *obj) 60 { 61 const ucl_object_t *user, *secret; 62 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", ag_name); 67 return (false); 68 } 69 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", ag_name); 74 return (false); 75 } 76 77 return (auth_group_add_chap( 78 ucl_object_tostring(user), 79 ucl_object_tostring(secret))); 80 } 81 82 static bool 83 uclparse_chap_mutual(const char *ag_name, const ucl_object_t *obj) 84 { 85 const ucl_object_t *user, *secret, *mutual_user; 86 const ucl_object_t *mutual_secret; 87 88 user = ucl_object_find_key(obj, "user"); 89 if (!user || user->type != UCL_STRING) { 90 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 91 "\"user\" string key", ag_name); 92 return (false); 93 } 94 95 secret = ucl_object_find_key(obj, "secret"); 96 if (!secret || secret->type != UCL_STRING) { 97 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 98 "\"secret\" string key", ag_name); 99 return (false); 100 } 101 102 mutual_user = ucl_object_find_key(obj, "mutual-user"); 103 if (!user || user->type != UCL_STRING) { 104 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 105 "\"mutual-user\" string key", ag_name); 106 return (false); 107 } 108 109 mutual_secret = ucl_object_find_key(obj, "mutual-secret"); 110 if (!secret || secret->type != UCL_STRING) { 111 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 112 "\"mutual-secret\" string key", ag_name); 113 return (false); 114 } 115 116 return (auth_group_add_chap_mutual( 117 ucl_object_tostring(user), 118 ucl_object_tostring(secret), 119 ucl_object_tostring(mutual_user), 120 ucl_object_tostring(mutual_secret))); 121 } 122 123 static bool 124 uclparse_target_chap(const char *t_name, const ucl_object_t *obj) 125 { 126 const ucl_object_t *user, *secret; 127 128 user = ucl_object_find_key(obj, "user"); 129 if (!user || user->type != UCL_STRING) { 130 log_warnx("chap section in target \"%s\" is missing " 131 "\"user\" string key", t_name); 132 return (false); 133 } 134 135 secret = ucl_object_find_key(obj, "secret"); 136 if (!secret || secret->type != UCL_STRING) { 137 log_warnx("chap section in target \"%s\" is missing " 138 "\"secret\" string key", t_name); 139 return (false); 140 } 141 142 return (target_add_chap( 143 ucl_object_tostring(user), 144 ucl_object_tostring(secret))); 145 } 146 147 static bool 148 uclparse_target_chap_mutual(const char *t_name, const ucl_object_t *obj) 149 { 150 const ucl_object_t *user, *secret, *mutual_user; 151 const ucl_object_t *mutual_secret; 152 153 user = ucl_object_find_key(obj, "user"); 154 if (!user || user->type != UCL_STRING) { 155 log_warnx("chap-mutual section in target \"%s\" is missing " 156 "\"user\" string key", t_name); 157 return (false); 158 } 159 160 secret = ucl_object_find_key(obj, "secret"); 161 if (!secret || secret->type != UCL_STRING) { 162 log_warnx("chap-mutual section in target \"%s\" is missing " 163 "\"secret\" string key", t_name); 164 return (false); 165 } 166 167 mutual_user = ucl_object_find_key(obj, "mutual-user"); 168 if (!user || user->type != UCL_STRING) { 169 log_warnx("chap-mutual section in target \"%s\" is missing " 170 "\"mutual-user\" string key", t_name); 171 return (false); 172 } 173 174 mutual_secret = ucl_object_find_key(obj, "mutual-secret"); 175 if (!secret || secret->type != UCL_STRING) { 176 log_warnx("chap-mutual section in target \"%s\" is missing " 177 "\"mutual-secret\" string key", t_name); 178 return (false); 179 } 180 181 return (target_add_chap_mutual( 182 ucl_object_tostring(user), 183 ucl_object_tostring(secret), 184 ucl_object_tostring(mutual_user), 185 ucl_object_tostring(mutual_secret))); 186 } 187 188 static bool 189 uclparse_target_portal_group(const char *t_name, const ucl_object_t *obj) 190 { 191 const ucl_object_t *portal_group, *auth_group; 192 const char *ag_name; 193 194 /* 195 * If the value is a single string, assume it is a 196 * portal-group name. 197 */ 198 if (obj->type == UCL_STRING) 199 return (target_add_portal_group(ucl_object_tostring(obj), 200 NULL)); 201 202 if (obj->type != UCL_OBJECT) { 203 log_warnx("portal-group section in target \"%s\" must be " 204 "an object or string", t_name); 205 return (false); 206 } 207 208 portal_group = ucl_object_find_key(obj, "name"); 209 if (!portal_group || portal_group->type != UCL_STRING) { 210 log_warnx("portal-group section in target \"%s\" is missing " 211 "\"name\" string key", t_name); 212 return (false); 213 } 214 215 auth_group = ucl_object_find_key(obj, "auth-group-name"); 216 if (auth_group != NULL) { 217 if (auth_group->type != UCL_STRING) { 218 log_warnx("\"auth-group-name\" property in " 219 "portal-group section for target \"%s\" is not " 220 "a string", t_name); 221 return (false); 222 } 223 ag_name = ucl_object_tostring(auth_group); 224 } else 225 ag_name = NULL; 226 227 return (target_add_portal_group(ucl_object_tostring(portal_group), 228 ag_name)); 229 } 230 231 static bool 232 uclparse_target_lun(const char *t_name, const ucl_object_t *obj) 233 { 234 const ucl_object_t *num; 235 const ucl_object_t *name; 236 const char *key; 237 char *end, *lun_name; 238 u_int id; 239 bool ok; 240 241 key = ucl_object_key(obj); 242 if (key != NULL) { 243 id = strtoul(key, &end, 0); 244 if (*end != '\0') { 245 log_warnx("lun key \"%s\" in target \"%s\" is invalid", 246 key, t_name); 247 return (false); 248 } 249 250 if (obj->type == UCL_STRING) 251 return (target_add_lun(id, ucl_object_tostring(obj))); 252 } 253 254 if (obj->type != UCL_OBJECT) { 255 log_warnx("lun section entries in target \"%s\" must be objects", 256 t_name); 257 return (false); 258 } 259 260 if (key == NULL) { 261 num = ucl_object_find_key(obj, "number"); 262 if (num == NULL || num->type != UCL_INT) { 263 log_warnx("lun section in target \"%s\" is missing " 264 "\"number\" integer property", t_name); 265 return (false); 266 } 267 id = ucl_object_toint(num); 268 } 269 270 name = ucl_object_find_key(obj, "name"); 271 if (name == NULL) { 272 if (!target_start_lun(id)) 273 return (false); 274 275 asprintf(&lun_name, "lun %u for target \"%s\"", id, t_name); 276 ok = uclparse_lun_entries(lun_name, obj); 277 free(lun_name); 278 return (ok); 279 } 280 281 if (name->type != UCL_STRING) { 282 log_warnx("\"name\" property for lun %u for target " 283 "\"%s\" is not a string", id, t_name); 284 return (false); 285 } 286 287 return (target_add_lun(id, ucl_object_tostring(name))); 288 } 289 290 static bool 291 uclparse_toplevel(const ucl_object_t *top) 292 { 293 ucl_object_iter_t it = NULL, iter = NULL; 294 const ucl_object_t *obj = NULL, *child = NULL; 295 296 /* Pass 1 - everything except targets */ 297 while ((obj = ucl_iterate_object(top, &it, true))) { 298 const char *key = ucl_object_key(obj); 299 300 if (strcmp(key, "debug") == 0) { 301 if (obj->type == UCL_INT) 302 conf_set_debug(ucl_object_toint(obj)); 303 else { 304 log_warnx("\"debug\" property value is not integer"); 305 return (false); 306 } 307 } 308 309 if (strcmp(key, "timeout") == 0) { 310 if (obj->type == UCL_INT) 311 conf_set_timeout(ucl_object_toint(obj)); 312 else { 313 log_warnx("\"timeout\" property value is not integer"); 314 return (false); 315 } 316 } 317 318 if (strcmp(key, "maxproc") == 0) { 319 if (obj->type == UCL_INT) 320 conf_set_maxproc(ucl_object_toint(obj)); 321 else { 322 log_warnx("\"maxproc\" property value is not integer"); 323 return (false); 324 } 325 } 326 327 if (strcmp(key, "pidfile") == 0) { 328 if (obj->type == UCL_STRING) { 329 if (!conf_set_pidfile_path( 330 ucl_object_tostring(obj))) 331 return (false); 332 } else { 333 log_warnx("\"pidfile\" property value is not string"); 334 return (false); 335 } 336 } 337 338 if (strcmp(key, "isns-server") == 0) { 339 if (obj->type == UCL_ARRAY) { 340 iter = NULL; 341 while ((child = ucl_iterate_object(obj, &iter, 342 true))) { 343 if (child->type != UCL_STRING) 344 return (false); 345 346 if (!isns_add_server( 347 ucl_object_tostring(child))) 348 return (false); 349 } 350 } else { 351 log_warnx("\"isns-server\" property value is " 352 "not an array"); 353 return (false); 354 } 355 } 356 357 if (strcmp(key, "isns-period") == 0) { 358 if (obj->type == UCL_INT) 359 conf_set_isns_period(ucl_object_toint(obj)); 360 else { 361 log_warnx("\"isns-period\" property value is not integer"); 362 return (false); 363 } 364 } 365 366 if (strcmp(key, "isns-timeout") == 0) { 367 if (obj->type == UCL_INT) 368 conf_set_isns_timeout(ucl_object_toint(obj)); 369 else { 370 log_warnx("\"isns-timeout\" property value is not integer"); 371 return (false); 372 } 373 } 374 375 if (strcmp(key, "auth-group") == 0) { 376 if (obj->type == UCL_OBJECT) { 377 iter = NULL; 378 while ((child = ucl_iterate_object(obj, &iter, true))) { 379 if (!uclparse_auth_group( 380 ucl_object_key(child), child)) 381 return (false); 382 } 383 } else { 384 log_warnx("\"auth-group\" section is not an object"); 385 return (false); 386 } 387 } 388 389 if (strcmp(key, "portal-group") == 0) { 390 if (obj->type == UCL_OBJECT) { 391 iter = NULL; 392 while ((child = ucl_iterate_object(obj, &iter, true))) { 393 if (!uclparse_portal_group( 394 ucl_object_key(child), child)) 395 return (false); 396 } 397 } else { 398 log_warnx("\"portal-group\" section is not an object"); 399 return (false); 400 } 401 } 402 403 if (strcmp(key, "lun") == 0) { 404 if (obj->type == UCL_OBJECT) { 405 iter = NULL; 406 while ((child = ucl_iterate_object(obj, &iter, true))) { 407 if (!uclparse_lun(ucl_object_key(child), 408 child)) 409 return (false); 410 } 411 } else { 412 log_warnx("\"lun\" section is not an object"); 413 return (false); 414 } 415 } 416 } 417 418 /* Pass 2 - targets */ 419 it = NULL; 420 while ((obj = ucl_iterate_object(top, &it, true))) { 421 const char *key = ucl_object_key(obj); 422 423 if (strcmp(key, "target") == 0) { 424 if (obj->type == UCL_OBJECT) { 425 iter = NULL; 426 while ((child = ucl_iterate_object(obj, &iter, 427 true))) { 428 if (!uclparse_target( 429 ucl_object_key(child), child)) 430 return (false); 431 } 432 } else { 433 log_warnx("\"target\" section is not an object"); 434 return (false); 435 } 436 } 437 } 438 439 return (true); 440 } 441 442 static bool 443 uclparse_auth_group(const char *name, const ucl_object_t *top) 444 { 445 ucl_object_iter_t it = NULL, it2 = NULL; 446 const ucl_object_t *obj = NULL, *tmp = NULL; 447 const char *key; 448 449 if (!auth_group_start(name)) 450 return (false); 451 452 while ((obj = ucl_iterate_object(top, &it, true))) { 453 key = ucl_object_key(obj); 454 455 if (strcmp(key, "auth-type") == 0) { 456 const char *value = ucl_object_tostring(obj); 457 458 if (!auth_group_set_type(value)) 459 goto fail; 460 } 461 462 if (strcmp(key, "chap") == 0) { 463 if (obj->type == UCL_OBJECT) { 464 if (!uclparse_chap(name, obj)) 465 goto fail; 466 } else if (obj->type == UCL_ARRAY) { 467 it2 = NULL; 468 while ((tmp = ucl_iterate_object(obj, &it2, 469 true))) { 470 if (!uclparse_chap(name, tmp)) 471 goto fail; 472 } 473 } else { 474 log_warnx("\"chap\" property of auth-group " 475 "\"%s\" is not an array or object", 476 name); 477 goto fail; 478 } 479 } 480 481 if (strcmp(key, "chap-mutual") == 0) { 482 if (obj->type == UCL_OBJECT) { 483 if (!uclparse_chap_mutual(name, obj)) 484 goto fail; 485 } else if (obj->type == UCL_ARRAY) { 486 it2 = NULL; 487 while ((tmp = ucl_iterate_object(obj, &it2, 488 true))) { 489 if (!uclparse_chap_mutual(name, tmp)) 490 goto fail; 491 } 492 } else { 493 log_warnx("\"chap-mutual\" property of " 494 "auth-group \"%s\" is not an array or object", 495 name); 496 goto fail; 497 } 498 } 499 500 if (strcmp(key, "initiator-name") == 0) { 501 if (obj->type == UCL_STRING) { 502 const char *value = ucl_object_tostring(obj); 503 504 if (!auth_group_add_initiator_name(value)) 505 goto fail; 506 } else if (obj->type == UCL_ARRAY) { 507 it2 = NULL; 508 while ((tmp = ucl_iterate_object(obj, &it2, 509 true))) { 510 const char *value = 511 ucl_object_tostring(tmp); 512 513 if (!auth_group_add_initiator_name( 514 value)) 515 goto fail; 516 } 517 } else { 518 log_warnx("\"initiator-name\" property of " 519 "auth-group \"%s\" is not an array or string", 520 name); 521 goto fail; 522 } 523 } 524 525 if (strcmp(key, "initiator-portal") == 0) { 526 if (obj->type == UCL_STRING) { 527 const char *value = ucl_object_tostring(obj); 528 529 if (!auth_group_add_initiator_portal(value)) 530 goto fail; 531 } else if (obj->type == UCL_ARRAY) { 532 it2 = NULL; 533 while ((tmp = ucl_iterate_object(obj, &it2, 534 true))) { 535 const char *value = 536 ucl_object_tostring(tmp); 537 538 if (!auth_group_add_initiator_portal( 539 value)) 540 goto fail; 541 } 542 } else { 543 log_warnx("\"initiator-portal\" property of " 544 "auth-group \"%s\" is not an array or string", 545 name); 546 goto fail; 547 } 548 } 549 } 550 551 auth_group_finish(); 552 return (true); 553 fail: 554 auth_group_finish(); 555 return (false); 556 } 557 558 static bool 559 uclparse_dscp(const char *group_type, const char *pg_name, 560 const ucl_object_t *obj) 561 { 562 const char *key; 563 564 if ((obj->type != UCL_STRING) && (obj->type != UCL_INT)) { 565 log_warnx("\"dscp\" property of %s group \"%s\" is not a " 566 "string or integer", group_type, pg_name); 567 return (false); 568 } 569 if (obj->type == UCL_INT) 570 return (portal_group_set_dscp(ucl_object_toint(obj))); 571 572 key = ucl_object_tostring(obj); 573 if (strcmp(key, "0x") == 0) 574 return (portal_group_set_dscp(strtol(key + 2, NULL, 16))); 575 576 if (strcmp(key, "be") == 0 || strcmp(key, "cs0") == 0) 577 portal_group_set_dscp(IPTOS_DSCP_CS0 >> 2); 578 else if (strcmp(key, "ef") == 0) 579 portal_group_set_dscp(IPTOS_DSCP_EF >> 2); 580 else if (strcmp(key, "cs0") == 0) 581 portal_group_set_dscp(IPTOS_DSCP_CS0 >> 2); 582 else if (strcmp(key, "cs1") == 0) 583 portal_group_set_dscp(IPTOS_DSCP_CS1 >> 2); 584 else if (strcmp(key, "cs2") == 0) 585 portal_group_set_dscp(IPTOS_DSCP_CS2 >> 2); 586 else if (strcmp(key, "cs3") == 0) 587 portal_group_set_dscp(IPTOS_DSCP_CS3 >> 2); 588 else if (strcmp(key, "cs4") == 0) 589 portal_group_set_dscp(IPTOS_DSCP_CS4 >> 2); 590 else if (strcmp(key, "cs5") == 0) 591 portal_group_set_dscp(IPTOS_DSCP_CS5 >> 2); 592 else if (strcmp(key, "cs6") == 0) 593 portal_group_set_dscp(IPTOS_DSCP_CS6 >> 2); 594 else if (strcmp(key, "cs7") == 0) 595 portal_group_set_dscp(IPTOS_DSCP_CS7 >> 2); 596 else if (strcmp(key, "af11") == 0) 597 portal_group_set_dscp(IPTOS_DSCP_AF11 >> 2); 598 else if (strcmp(key, "af12") == 0) 599 portal_group_set_dscp(IPTOS_DSCP_AF12 >> 2); 600 else if (strcmp(key, "af13") == 0) 601 portal_group_set_dscp(IPTOS_DSCP_AF13 >> 2); 602 else if (strcmp(key, "af21") == 0) 603 portal_group_set_dscp(IPTOS_DSCP_AF21 >> 2); 604 else if (strcmp(key, "af22") == 0) 605 portal_group_set_dscp(IPTOS_DSCP_AF22 >> 2); 606 else if (strcmp(key, "af23") == 0) 607 portal_group_set_dscp(IPTOS_DSCP_AF23 >> 2); 608 else if (strcmp(key, "af31") == 0) 609 portal_group_set_dscp(IPTOS_DSCP_AF31 >> 2); 610 else if (strcmp(key, "af32") == 0) 611 portal_group_set_dscp(IPTOS_DSCP_AF32 >> 2); 612 else if (strcmp(key, "af33") == 0) 613 portal_group_set_dscp(IPTOS_DSCP_AF33 >> 2); 614 else if (strcmp(key, "af41") == 0) 615 portal_group_set_dscp(IPTOS_DSCP_AF41 >> 2); 616 else if (strcmp(key, "af42") == 0) 617 portal_group_set_dscp(IPTOS_DSCP_AF42 >> 2); 618 else if (strcmp(key, "af43") == 0) 619 portal_group_set_dscp(IPTOS_DSCP_AF43 >> 2); 620 else { 621 log_warnx("\"dscp\" property value is not a supported textual value"); 622 return (false); 623 } 624 return (true); 625 } 626 627 static bool 628 uclparse_pcp(const char *group_type, const char *pg_name, 629 const ucl_object_t *obj) 630 { 631 if (obj->type != UCL_INT) { 632 log_warnx("\"pcp\" property of %s group \"%s\" is not an " 633 "integer", group_type, pg_name); 634 return (false); 635 } 636 return (portal_group_set_pcp(ucl_object_toint(obj))); 637 } 638 639 static bool 640 uclparse_portal_group(const char *name, const ucl_object_t *top) 641 { 642 ucl_object_iter_t it = NULL, it2 = NULL; 643 const ucl_object_t *obj = NULL, *tmp = NULL; 644 const char *key; 645 646 if (!portal_group_start(name)) 647 return (false); 648 649 while ((obj = ucl_iterate_object(top, &it, true))) { 650 key = ucl_object_key(obj); 651 652 if (strcmp(key, "discovery-auth-group") == 0) { 653 if (obj->type != UCL_STRING) { 654 log_warnx("\"discovery-auth-group\" property " 655 "of portal-group \"%s\" is not a string", 656 name); 657 goto fail; 658 } 659 660 if (!portal_group_set_discovery_auth_group( 661 ucl_object_tostring(obj))) 662 goto fail; 663 } 664 665 if (strcmp(key, "discovery-filter") == 0) { 666 if (obj->type != UCL_STRING) { 667 log_warnx("\"discovery-filter\" property of " 668 "portal-group \"%s\" is not a string", 669 name); 670 goto fail; 671 } 672 673 if (!portal_group_set_filter(ucl_object_tostring(obj))) 674 goto fail; 675 } 676 677 if (strcmp(key, "foreign") == 0) { 678 portal_group_set_foreign(); 679 } 680 681 if (strcmp(key, "listen") == 0) { 682 if (obj->type == UCL_STRING) { 683 if (!portal_group_add_listen( 684 ucl_object_tostring(obj), false)) 685 goto fail; 686 } else if (obj->type == UCL_ARRAY) { 687 while ((tmp = ucl_iterate_object(obj, &it2, 688 true))) { 689 if (!portal_group_add_listen( 690 ucl_object_tostring(tmp), 691 false)) 692 goto fail; 693 } 694 } else { 695 log_warnx("\"listen\" property of " 696 "portal-group \"%s\" is not a string", 697 name); 698 goto fail; 699 } 700 } 701 702 if (strcmp(key, "listen-iser") == 0) { 703 if (obj->type == UCL_STRING) { 704 if (!portal_group_add_listen( 705 ucl_object_tostring(obj), true)) 706 goto fail; 707 } else if (obj->type == UCL_ARRAY) { 708 while ((tmp = ucl_iterate_object(obj, &it2, 709 true))) { 710 if (!portal_group_add_listen( 711 ucl_object_tostring(tmp), 712 true)) 713 goto fail; 714 } 715 } else { 716 log_warnx("\"listen\" property of " 717 "portal-group \"%s\" is not a string", 718 name); 719 goto fail; 720 } 721 } 722 723 if (strcmp(key, "offload") == 0) { 724 if (obj->type != UCL_STRING) { 725 log_warnx("\"offload\" property of " 726 "portal-group \"%s\" is not a string", 727 name); 728 goto fail; 729 } 730 731 if (!portal_group_set_offload(ucl_object_tostring(obj))) 732 goto fail; 733 } 734 735 if (strcmp(key, "redirect") == 0) { 736 if (obj->type != UCL_STRING) { 737 log_warnx("\"listen\" property of " 738 "portal-group \"%s\" is not a string", 739 name); 740 goto fail; 741 } 742 743 if (!portal_group_set_redirection( 744 ucl_object_tostring(obj))) 745 goto fail; 746 } 747 748 if (strcmp(key, "options") == 0) { 749 if (obj->type != UCL_OBJECT) { 750 log_warnx("\"options\" property of portal group " 751 "\"%s\" is not an object", name); 752 goto fail; 753 } 754 755 while ((tmp = ucl_iterate_object(obj, &it2, 756 true))) { 757 if (!portal_group_add_option( 758 ucl_object_key(tmp), 759 ucl_object_tostring_forced(tmp))) 760 goto fail; 761 } 762 } 763 764 if (strcmp(key, "tag") == 0) { 765 if (obj->type != UCL_INT) { 766 log_warnx("\"tag\" property of portal group " 767 "\"%s\" is not an integer", 768 name); 769 goto fail; 770 } 771 772 portal_group_set_tag(ucl_object_toint(obj)); 773 } 774 775 if (strcmp(key, "dscp") == 0) { 776 if (!uclparse_dscp("portal", name, obj)) 777 goto fail; 778 } 779 780 if (strcmp(key, "pcp") == 0) { 781 if (!uclparse_pcp("portal", name, obj)) 782 goto fail; 783 } 784 } 785 786 portal_group_finish(); 787 return (true); 788 fail: 789 portal_group_finish(); 790 return (false); 791 } 792 793 static bool 794 uclparse_target(const char *name, const ucl_object_t *top) 795 { 796 ucl_object_iter_t it = NULL, it2 = NULL; 797 const ucl_object_t *obj = NULL, *tmp = NULL; 798 const char *key; 799 800 if (!target_start(name)) 801 return (false); 802 803 while ((obj = ucl_iterate_object(top, &it, true))) { 804 key = ucl_object_key(obj); 805 806 if (strcmp(key, "alias") == 0) { 807 if (obj->type != UCL_STRING) { 808 log_warnx("\"alias\" property of target " 809 "\"%s\" is not a string", name); 810 goto fail; 811 } 812 813 if (!target_set_alias(ucl_object_tostring(obj))) 814 goto fail; 815 } 816 817 if (strcmp(key, "auth-group") == 0) { 818 if (obj->type != UCL_STRING) { 819 log_warnx("\"auth-group\" property of target " 820 "\"%s\" is not a string", name); 821 goto fail; 822 } 823 824 if (!target_set_auth_group(ucl_object_tostring(obj))) 825 goto fail; 826 } 827 828 if (strcmp(key, "auth-type") == 0) { 829 if (obj->type != UCL_STRING) { 830 log_warnx("\"auth-type\" property of target " 831 "\"%s\" is not a string", name); 832 goto fail; 833 } 834 835 if (!target_set_auth_type(ucl_object_tostring(obj))) 836 goto fail; 837 } 838 839 if (strcmp(key, "chap") == 0) { 840 if (obj->type == UCL_OBJECT) { 841 if (!uclparse_target_chap(name, obj)) 842 goto fail; 843 } else if (obj->type == UCL_ARRAY) { 844 while ((tmp = ucl_iterate_object(obj, &it2, 845 true))) { 846 if (!uclparse_target_chap(name, tmp)) 847 goto fail; 848 } 849 } else { 850 log_warnx("\"chap\" property of target " 851 "\"%s\" is not an array or object", 852 name); 853 goto fail; 854 } 855 } 856 857 if (strcmp(key, "chap-mutual") == 0) { 858 if (obj->type == UCL_OBJECT) { 859 if (!uclparse_target_chap_mutual(name, obj)) 860 goto fail; 861 } else if (obj->type == UCL_ARRAY) { 862 while ((tmp = ucl_iterate_object(obj, &it2, 863 true))) { 864 if (!uclparse_target_chap_mutual(name, 865 tmp)) 866 goto fail; 867 } 868 } else { 869 log_warnx("\"chap-mutual\" property of target " 870 "\"%s\" is not an array or object", 871 name); 872 goto fail; 873 } 874 } 875 876 if (strcmp(key, "initiator-name") == 0) { 877 if (obj->type == UCL_STRING) { 878 if (!target_add_initiator_name( 879 ucl_object_tostring(obj))) 880 goto fail; 881 } else if (obj->type == UCL_ARRAY) { 882 while ((tmp = ucl_iterate_object(obj, &it2, 883 true))) { 884 if (!target_add_initiator_name( 885 ucl_object_tostring(tmp))) 886 goto fail; 887 } 888 } else { 889 log_warnx("\"initiator-name\" property of " 890 "target \"%s\" is not an array or string", 891 name); 892 goto fail; 893 } 894 } 895 896 if (strcmp(key, "initiator-portal") == 0) { 897 if (obj->type == UCL_STRING) { 898 if (!target_add_initiator_portal( 899 ucl_object_tostring(obj))) 900 goto fail; 901 } else if (obj->type == UCL_ARRAY) { 902 while ((tmp = ucl_iterate_object(obj, &it2, 903 true))) { 904 if (!target_add_initiator_portal( 905 ucl_object_tostring(tmp))) 906 goto fail; 907 } 908 } else { 909 log_warnx("\"initiator-portal\" property of " 910 "target \"%s\" is not an array or string", 911 name); 912 goto fail; 913 } 914 } 915 916 if (strcmp(key, "portal-group") == 0) { 917 if (obj->type == UCL_ARRAY) { 918 while ((tmp = ucl_iterate_object(obj, &it2, 919 true))) { 920 if (!uclparse_target_portal_group(name, 921 tmp)) 922 goto fail; 923 } 924 } else { 925 if (!uclparse_target_portal_group(name, obj)) 926 goto fail; 927 } 928 } 929 930 if (strcmp(key, "port") == 0) { 931 if (obj->type != UCL_STRING) { 932 log_warnx("\"port\" property of target " 933 "\"%s\" is not a string", name); 934 goto fail; 935 } 936 937 if (!target_set_physical_port(ucl_object_tostring(obj))) 938 goto fail; 939 } 940 941 if (strcmp(key, "redirect") == 0) { 942 if (obj->type != UCL_STRING) { 943 log_warnx("\"redirect\" property of target " 944 "\"%s\" is not a string", name); 945 goto fail; 946 } 947 948 if (!target_set_redirection(ucl_object_tostring(obj))) 949 goto fail; 950 } 951 952 if (strcmp(key, "lun") == 0) { 953 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 954 if (!uclparse_target_lun(name, tmp)) 955 goto fail; 956 } 957 } 958 } 959 960 target_finish(); 961 return (true); 962 fail: 963 target_finish(); 964 return (false); 965 } 966 967 static bool 968 uclparse_lun(const char *name, const ucl_object_t *top) 969 { 970 char *lun_name; 971 bool ok; 972 973 if (!lun_start(name)) 974 return (false); 975 asprintf(&lun_name, "lun \"%s\"", name); 976 ok = uclparse_lun_entries(lun_name, top); 977 free(lun_name); 978 return (ok); 979 } 980 981 static bool 982 uclparse_lun_entries(const char *name, const ucl_object_t *top) 983 { 984 ucl_object_iter_t it = NULL, child_it = NULL; 985 const ucl_object_t *obj = NULL, *child = NULL; 986 const char *key; 987 988 while ((obj = ucl_iterate_object(top, &it, true))) { 989 key = ucl_object_key(obj); 990 991 if (strcmp(key, "backend") == 0) { 992 if (obj->type != UCL_STRING) { 993 log_warnx("\"backend\" property of %s " 994 "is not a string", name); 995 goto fail; 996 } 997 998 if (!lun_set_backend(ucl_object_tostring(obj))) 999 goto fail; 1000 } 1001 1002 if (strcmp(key, "blocksize") == 0) { 1003 if (obj->type != UCL_INT) { 1004 log_warnx("\"blocksize\" property of %s " 1005 "is not an integer", name); 1006 goto fail; 1007 } 1008 1009 if (!lun_set_blocksize(ucl_object_toint(obj))) 1010 goto fail; 1011 } 1012 1013 if (strcmp(key, "device-id") == 0) { 1014 if (obj->type != UCL_STRING) { 1015 log_warnx("\"device-id\" property of %s " 1016 "is not an integer", name); 1017 goto fail; 1018 } 1019 1020 if (!lun_set_device_id(ucl_object_tostring(obj))) 1021 goto fail; 1022 } 1023 1024 if (strcmp(key, "device-type") == 0) { 1025 if (obj->type != UCL_STRING) { 1026 log_warnx("\"device-type\" property of %s " 1027 "is not an integer", name); 1028 goto fail; 1029 } 1030 1031 if (!lun_set_device_type(ucl_object_tostring(obj))) 1032 goto fail; 1033 } 1034 1035 if (strcmp(key, "ctl-lun") == 0) { 1036 if (obj->type != UCL_INT) { 1037 log_warnx("\"ctl-lun\" property of %s " 1038 "is not an integer", name); 1039 goto fail; 1040 } 1041 1042 if (!lun_set_ctl_lun(ucl_object_toint(obj))) 1043 goto fail; 1044 } 1045 1046 if (strcmp(key, "options") == 0) { 1047 if (obj->type != UCL_OBJECT) { 1048 log_warnx("\"options\" property of %s " 1049 "is not an object", name); 1050 goto fail; 1051 } 1052 1053 while ((child = ucl_iterate_object(obj, &child_it, 1054 true))) { 1055 if (!lun_add_option(ucl_object_key(child), 1056 ucl_object_tostring_forced(child))) 1057 goto fail; 1058 } 1059 } 1060 1061 if (strcmp(key, "path") == 0) { 1062 if (obj->type != UCL_STRING) { 1063 log_warnx("\"path\" property of %s " 1064 "is not a string", name); 1065 goto fail; 1066 } 1067 1068 if (!lun_set_path(ucl_object_tostring(obj))) 1069 goto fail; 1070 } 1071 1072 if (strcmp(key, "serial") == 0) { 1073 if (obj->type != UCL_STRING) { 1074 log_warnx("\"serial\" property of %s " 1075 "is not a string", name); 1076 goto fail; 1077 } 1078 1079 if (!lun_set_serial(ucl_object_tostring(obj))) 1080 goto fail; 1081 } 1082 1083 if (strcmp(key, "size") == 0) { 1084 if (obj->type != UCL_INT) { 1085 log_warnx("\"size\" property of %s " 1086 "is not an integer", name); 1087 goto fail; 1088 } 1089 1090 if (!lun_set_size(ucl_object_toint(obj))) 1091 goto fail; 1092 } 1093 } 1094 1095 lun_finish(); 1096 return (true); 1097 fail: 1098 lun_finish(); 1099 return (false); 1100 } 1101 1102 bool 1103 uclparse_conf(const char *path) 1104 { 1105 struct ucl_parser *parser; 1106 ucl_object_t *top; 1107 bool parsed; 1108 1109 parser = ucl_parser_new(0); 1110 1111 if (!ucl_parser_add_file(parser, path)) { 1112 log_warn("unable to parse configuration file %s: %s", path, 1113 ucl_parser_get_error(parser)); 1114 ucl_parser_free(parser); 1115 return (false); 1116 } 1117 1118 top = ucl_parser_get_object(parser); 1119 parsed = uclparse_toplevel(top); 1120 ucl_object_unref(top); 1121 ucl_parser_free(parser); 1122 1123 return (parsed); 1124 } 1125