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 (!mutual_user || mutual_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 (!mutual_secret || mutual_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 (!mutual_user || mutual_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 (!mutual_secret || mutual_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, "be") == 0 || strcmp(key, "cs0") == 0) 574 portal_group_set_dscp(IPTOS_DSCP_CS0 >> 2); 575 else if (strcmp(key, "ef") == 0) 576 portal_group_set_dscp(IPTOS_DSCP_EF >> 2); 577 else if (strcmp(key, "cs0") == 0) 578 portal_group_set_dscp(IPTOS_DSCP_CS0 >> 2); 579 else if (strcmp(key, "cs1") == 0) 580 portal_group_set_dscp(IPTOS_DSCP_CS1 >> 2); 581 else if (strcmp(key, "cs2") == 0) 582 portal_group_set_dscp(IPTOS_DSCP_CS2 >> 2); 583 else if (strcmp(key, "cs3") == 0) 584 portal_group_set_dscp(IPTOS_DSCP_CS3 >> 2); 585 else if (strcmp(key, "cs4") == 0) 586 portal_group_set_dscp(IPTOS_DSCP_CS4 >> 2); 587 else if (strcmp(key, "cs5") == 0) 588 portal_group_set_dscp(IPTOS_DSCP_CS5 >> 2); 589 else if (strcmp(key, "cs6") == 0) 590 portal_group_set_dscp(IPTOS_DSCP_CS6 >> 2); 591 else if (strcmp(key, "cs7") == 0) 592 portal_group_set_dscp(IPTOS_DSCP_CS7 >> 2); 593 else if (strcmp(key, "af11") == 0) 594 portal_group_set_dscp(IPTOS_DSCP_AF11 >> 2); 595 else if (strcmp(key, "af12") == 0) 596 portal_group_set_dscp(IPTOS_DSCP_AF12 >> 2); 597 else if (strcmp(key, "af13") == 0) 598 portal_group_set_dscp(IPTOS_DSCP_AF13 >> 2); 599 else if (strcmp(key, "af21") == 0) 600 portal_group_set_dscp(IPTOS_DSCP_AF21 >> 2); 601 else if (strcmp(key, "af22") == 0) 602 portal_group_set_dscp(IPTOS_DSCP_AF22 >> 2); 603 else if (strcmp(key, "af23") == 0) 604 portal_group_set_dscp(IPTOS_DSCP_AF23 >> 2); 605 else if (strcmp(key, "af31") == 0) 606 portal_group_set_dscp(IPTOS_DSCP_AF31 >> 2); 607 else if (strcmp(key, "af32") == 0) 608 portal_group_set_dscp(IPTOS_DSCP_AF32 >> 2); 609 else if (strcmp(key, "af33") == 0) 610 portal_group_set_dscp(IPTOS_DSCP_AF33 >> 2); 611 else if (strcmp(key, "af41") == 0) 612 portal_group_set_dscp(IPTOS_DSCP_AF41 >> 2); 613 else if (strcmp(key, "af42") == 0) 614 portal_group_set_dscp(IPTOS_DSCP_AF42 >> 2); 615 else if (strcmp(key, "af43") == 0) 616 portal_group_set_dscp(IPTOS_DSCP_AF43 >> 2); 617 else { 618 log_warnx("\"dscp\" property value is not a supported textual value"); 619 return (false); 620 } 621 return (true); 622 } 623 624 static bool 625 uclparse_pcp(const char *group_type, const char *pg_name, 626 const ucl_object_t *obj) 627 { 628 if (obj->type != UCL_INT) { 629 log_warnx("\"pcp\" property of %s group \"%s\" is not an " 630 "integer", group_type, pg_name); 631 return (false); 632 } 633 return (portal_group_set_pcp(ucl_object_toint(obj))); 634 } 635 636 static bool 637 uclparse_portal_group(const char *name, const ucl_object_t *top) 638 { 639 ucl_object_iter_t it = NULL, it2 = NULL; 640 const ucl_object_t *obj = NULL, *tmp = NULL; 641 const char *key; 642 643 if (!portal_group_start(name)) 644 return (false); 645 646 while ((obj = ucl_iterate_object(top, &it, true))) { 647 key = ucl_object_key(obj); 648 649 if (strcmp(key, "discovery-auth-group") == 0) { 650 if (obj->type != UCL_STRING) { 651 log_warnx("\"discovery-auth-group\" property " 652 "of portal-group \"%s\" is not a string", 653 name); 654 goto fail; 655 } 656 657 if (!portal_group_set_discovery_auth_group( 658 ucl_object_tostring(obj))) 659 goto fail; 660 } 661 662 if (strcmp(key, "discovery-filter") == 0) { 663 if (obj->type != UCL_STRING) { 664 log_warnx("\"discovery-filter\" property of " 665 "portal-group \"%s\" is not a string", 666 name); 667 goto fail; 668 } 669 670 if (!portal_group_set_filter(ucl_object_tostring(obj))) 671 goto fail; 672 } 673 674 if (strcmp(key, "foreign") == 0) { 675 portal_group_set_foreign(); 676 } 677 678 if (strcmp(key, "listen") == 0) { 679 if (obj->type == UCL_STRING) { 680 if (!portal_group_add_listen( 681 ucl_object_tostring(obj), false)) 682 goto fail; 683 } else if (obj->type == UCL_ARRAY) { 684 while ((tmp = ucl_iterate_object(obj, &it2, 685 true))) { 686 if (!portal_group_add_listen( 687 ucl_object_tostring(tmp), 688 false)) 689 goto fail; 690 } 691 } else { 692 log_warnx("\"listen\" property of " 693 "portal-group \"%s\" is not a string", 694 name); 695 goto fail; 696 } 697 } 698 699 if (strcmp(key, "listen-iser") == 0) { 700 if (obj->type == UCL_STRING) { 701 if (!portal_group_add_listen( 702 ucl_object_tostring(obj), true)) 703 goto fail; 704 } else if (obj->type == UCL_ARRAY) { 705 while ((tmp = ucl_iterate_object(obj, &it2, 706 true))) { 707 if (!portal_group_add_listen( 708 ucl_object_tostring(tmp), 709 true)) 710 goto fail; 711 } 712 } else { 713 log_warnx("\"listen\" property of " 714 "portal-group \"%s\" is not a string", 715 name); 716 goto fail; 717 } 718 } 719 720 if (strcmp(key, "offload") == 0) { 721 if (obj->type != UCL_STRING) { 722 log_warnx("\"offload\" property of " 723 "portal-group \"%s\" is not a string", 724 name); 725 goto fail; 726 } 727 728 if (!portal_group_set_offload(ucl_object_tostring(obj))) 729 goto fail; 730 } 731 732 if (strcmp(key, "redirect") == 0) { 733 if (obj->type != UCL_STRING) { 734 log_warnx("\"listen\" property of " 735 "portal-group \"%s\" is not a string", 736 name); 737 goto fail; 738 } 739 740 if (!portal_group_set_redirection( 741 ucl_object_tostring(obj))) 742 goto fail; 743 } 744 745 if (strcmp(key, "options") == 0) { 746 if (obj->type != UCL_OBJECT) { 747 log_warnx("\"options\" property of portal group " 748 "\"%s\" is not an object", name); 749 goto fail; 750 } 751 752 while ((tmp = ucl_iterate_object(obj, &it2, 753 true))) { 754 if (!portal_group_add_option( 755 ucl_object_key(tmp), 756 ucl_object_tostring_forced(tmp))) 757 goto fail; 758 } 759 } 760 761 if (strcmp(key, "tag") == 0) { 762 if (obj->type != UCL_INT) { 763 log_warnx("\"tag\" property of portal group " 764 "\"%s\" is not an integer", 765 name); 766 goto fail; 767 } 768 769 portal_group_set_tag(ucl_object_toint(obj)); 770 } 771 772 if (strcmp(key, "dscp") == 0) { 773 if (!uclparse_dscp("portal", name, obj)) 774 goto fail; 775 } 776 777 if (strcmp(key, "pcp") == 0) { 778 if (!uclparse_pcp("portal", name, obj)) 779 goto fail; 780 } 781 } 782 783 portal_group_finish(); 784 return (true); 785 fail: 786 portal_group_finish(); 787 return (false); 788 } 789 790 static bool 791 uclparse_target(const char *name, const ucl_object_t *top) 792 { 793 ucl_object_iter_t it = NULL, it2 = NULL; 794 const ucl_object_t *obj = NULL, *tmp = NULL; 795 const char *key; 796 797 if (!target_start(name)) 798 return (false); 799 800 while ((obj = ucl_iterate_object(top, &it, true))) { 801 key = ucl_object_key(obj); 802 803 if (strcmp(key, "alias") == 0) { 804 if (obj->type != UCL_STRING) { 805 log_warnx("\"alias\" property of target " 806 "\"%s\" is not a string", name); 807 goto fail; 808 } 809 810 if (!target_set_alias(ucl_object_tostring(obj))) 811 goto fail; 812 } 813 814 if (strcmp(key, "auth-group") == 0) { 815 if (obj->type != UCL_STRING) { 816 log_warnx("\"auth-group\" property of target " 817 "\"%s\" is not a string", name); 818 goto fail; 819 } 820 821 if (!target_set_auth_group(ucl_object_tostring(obj))) 822 goto fail; 823 } 824 825 if (strcmp(key, "auth-type") == 0) { 826 if (obj->type != UCL_STRING) { 827 log_warnx("\"auth-type\" property of target " 828 "\"%s\" is not a string", name); 829 goto fail; 830 } 831 832 if (!target_set_auth_type(ucl_object_tostring(obj))) 833 goto fail; 834 } 835 836 if (strcmp(key, "chap") == 0) { 837 if (obj->type == UCL_OBJECT) { 838 if (!uclparse_target_chap(name, obj)) 839 goto fail; 840 } else if (obj->type == UCL_ARRAY) { 841 while ((tmp = ucl_iterate_object(obj, &it2, 842 true))) { 843 if (!uclparse_target_chap(name, tmp)) 844 goto fail; 845 } 846 } else { 847 log_warnx("\"chap\" property of target " 848 "\"%s\" is not an array or object", 849 name); 850 goto fail; 851 } 852 } 853 854 if (strcmp(key, "chap-mutual") == 0) { 855 if (obj->type == UCL_OBJECT) { 856 if (!uclparse_target_chap_mutual(name, obj)) 857 goto fail; 858 } else if (obj->type == UCL_ARRAY) { 859 while ((tmp = ucl_iterate_object(obj, &it2, 860 true))) { 861 if (!uclparse_target_chap_mutual(name, 862 tmp)) 863 goto fail; 864 } 865 } else { 866 log_warnx("\"chap-mutual\" property of target " 867 "\"%s\" is not an array or object", 868 name); 869 goto fail; 870 } 871 } 872 873 if (strcmp(key, "initiator-name") == 0) { 874 if (obj->type == UCL_STRING) { 875 if (!target_add_initiator_name( 876 ucl_object_tostring(obj))) 877 goto fail; 878 } else if (obj->type == UCL_ARRAY) { 879 while ((tmp = ucl_iterate_object(obj, &it2, 880 true))) { 881 if (!target_add_initiator_name( 882 ucl_object_tostring(tmp))) 883 goto fail; 884 } 885 } else { 886 log_warnx("\"initiator-name\" property of " 887 "target \"%s\" is not an array or string", 888 name); 889 goto fail; 890 } 891 } 892 893 if (strcmp(key, "initiator-portal") == 0) { 894 if (obj->type == UCL_STRING) { 895 if (!target_add_initiator_portal( 896 ucl_object_tostring(obj))) 897 goto fail; 898 } else if (obj->type == UCL_ARRAY) { 899 while ((tmp = ucl_iterate_object(obj, &it2, 900 true))) { 901 if (!target_add_initiator_portal( 902 ucl_object_tostring(tmp))) 903 goto fail; 904 } 905 } else { 906 log_warnx("\"initiator-portal\" property of " 907 "target \"%s\" is not an array or string", 908 name); 909 goto fail; 910 } 911 } 912 913 if (strcmp(key, "portal-group") == 0) { 914 if (obj->type == UCL_ARRAY) { 915 while ((tmp = ucl_iterate_object(obj, &it2, 916 true))) { 917 if (!uclparse_target_portal_group(name, 918 tmp)) 919 goto fail; 920 } 921 } else { 922 if (!uclparse_target_portal_group(name, obj)) 923 goto fail; 924 } 925 } 926 927 if (strcmp(key, "port") == 0) { 928 if (obj->type != UCL_STRING) { 929 log_warnx("\"port\" property of target " 930 "\"%s\" is not a string", name); 931 goto fail; 932 } 933 934 if (!target_set_physical_port(ucl_object_tostring(obj))) 935 goto fail; 936 } 937 938 if (strcmp(key, "redirect") == 0) { 939 if (obj->type != UCL_STRING) { 940 log_warnx("\"redirect\" property of target " 941 "\"%s\" is not a string", name); 942 goto fail; 943 } 944 945 if (!target_set_redirection(ucl_object_tostring(obj))) 946 goto fail; 947 } 948 949 if (strcmp(key, "lun") == 0) { 950 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 951 if (!uclparse_target_lun(name, tmp)) 952 goto fail; 953 } 954 } 955 } 956 957 target_finish(); 958 return (true); 959 fail: 960 target_finish(); 961 return (false); 962 } 963 964 static bool 965 uclparse_lun(const char *name, const ucl_object_t *top) 966 { 967 char *lun_name; 968 bool ok; 969 970 if (!lun_start(name)) 971 return (false); 972 asprintf(&lun_name, "lun \"%s\"", name); 973 ok = uclparse_lun_entries(lun_name, top); 974 free(lun_name); 975 return (ok); 976 } 977 978 static bool 979 uclparse_lun_entries(const char *name, const ucl_object_t *top) 980 { 981 ucl_object_iter_t it = NULL, child_it = NULL; 982 const ucl_object_t *obj = NULL, *child = NULL; 983 const char *key; 984 985 while ((obj = ucl_iterate_object(top, &it, true))) { 986 key = ucl_object_key(obj); 987 988 if (strcmp(key, "backend") == 0) { 989 if (obj->type != UCL_STRING) { 990 log_warnx("\"backend\" property of %s " 991 "is not a string", name); 992 goto fail; 993 } 994 995 if (!lun_set_backend(ucl_object_tostring(obj))) 996 goto fail; 997 } 998 999 if (strcmp(key, "blocksize") == 0) { 1000 if (obj->type != UCL_INT) { 1001 log_warnx("\"blocksize\" property of %s " 1002 "is not an integer", name); 1003 goto fail; 1004 } 1005 1006 if (!lun_set_blocksize(ucl_object_toint(obj))) 1007 goto fail; 1008 } 1009 1010 if (strcmp(key, "device-id") == 0) { 1011 if (obj->type != UCL_STRING) { 1012 log_warnx("\"device-id\" property of %s " 1013 "is not an integer", name); 1014 goto fail; 1015 } 1016 1017 if (!lun_set_device_id(ucl_object_tostring(obj))) 1018 goto fail; 1019 } 1020 1021 if (strcmp(key, "device-type") == 0) { 1022 if (obj->type != UCL_STRING) { 1023 log_warnx("\"device-type\" property of %s " 1024 "is not an integer", name); 1025 goto fail; 1026 } 1027 1028 if (!lun_set_device_type(ucl_object_tostring(obj))) 1029 goto fail; 1030 } 1031 1032 if (strcmp(key, "ctl-lun") == 0) { 1033 if (obj->type != UCL_INT) { 1034 log_warnx("\"ctl-lun\" property of %s " 1035 "is not an integer", name); 1036 goto fail; 1037 } 1038 1039 if (!lun_set_ctl_lun(ucl_object_toint(obj))) 1040 goto fail; 1041 } 1042 1043 if (strcmp(key, "options") == 0) { 1044 if (obj->type != UCL_OBJECT) { 1045 log_warnx("\"options\" property of %s " 1046 "is not an object", name); 1047 goto fail; 1048 } 1049 1050 while ((child = ucl_iterate_object(obj, &child_it, 1051 true))) { 1052 if (!lun_add_option(ucl_object_key(child), 1053 ucl_object_tostring_forced(child))) 1054 goto fail; 1055 } 1056 } 1057 1058 if (strcmp(key, "path") == 0) { 1059 if (obj->type != UCL_STRING) { 1060 log_warnx("\"path\" property of %s " 1061 "is not a string", name); 1062 goto fail; 1063 } 1064 1065 if (!lun_set_path(ucl_object_tostring(obj))) 1066 goto fail; 1067 } 1068 1069 if (strcmp(key, "serial") == 0) { 1070 if (obj->type != UCL_STRING) { 1071 log_warnx("\"serial\" property of %s " 1072 "is not a string", name); 1073 goto fail; 1074 } 1075 1076 if (!lun_set_serial(ucl_object_tostring(obj))) 1077 goto fail; 1078 } 1079 1080 if (strcmp(key, "size") == 0) { 1081 if (obj->type != UCL_INT) { 1082 log_warnx("\"size\" property of %s " 1083 "is not an integer", name); 1084 goto fail; 1085 } 1086 1087 if (!lun_set_size(ucl_object_toint(obj))) 1088 goto fail; 1089 } 1090 } 1091 1092 lun_finish(); 1093 return (true); 1094 fail: 1095 lun_finish(); 1096 return (false); 1097 } 1098 1099 bool 1100 uclparse_conf(const char *path) 1101 { 1102 struct ucl_parser *parser; 1103 ucl_object_t *top; 1104 bool parsed; 1105 1106 parser = ucl_parser_new(0); 1107 1108 if (!ucl_parser_add_file(parser, path)) { 1109 log_warn("unable to parse configuration file %s: %s", path, 1110 ucl_parser_get_error(parser)); 1111 ucl_parser_free(parser); 1112 return (false); 1113 } 1114 1115 top = ucl_parser_get_object(parser); 1116 parsed = uclparse_toplevel(top); 1117 ucl_object_unref(top); 1118 ucl_parser_free(parser); 1119 1120 return (parsed); 1121 } 1122