1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 * $FreeBSD$ 32 */ 33 34 #include <sys/queue.h> 35 #include <sys/types.h> 36 #include <assert.h> 37 #include <stdio.h> 38 #include <stdint.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <ucl.h> 42 #include <netinet/in.h> 43 #include <netinet/ip.h> 44 45 #include "ctld.h" 46 47 static struct conf *conf = NULL; 48 49 static int uclparse_toplevel(const ucl_object_t *); 50 static int uclparse_chap(struct auth_group *, const ucl_object_t *); 51 static int uclparse_chap_mutual(struct auth_group *, const ucl_object_t *); 52 static int uclparse_lun(const char *, const ucl_object_t *); 53 static int uclparse_auth_group(const char *, const ucl_object_t *); 54 static int uclparse_portal_group(const char *, const ucl_object_t *); 55 static int uclparse_target(const char *, const ucl_object_t *); 56 static int uclparse_target_portal_group(struct target *, const ucl_object_t *); 57 static int uclparse_target_lun(struct target *, const ucl_object_t *); 58 59 static int 60 uclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj) 61 { 62 const struct auth *ca; 63 const ucl_object_t *user, *secret; 64 65 user = ucl_object_find_key(obj, "user"); 66 if (!user || user->type != UCL_STRING) { 67 log_warnx("chap section in auth-group \"%s\" is missing " 68 "\"user\" string key", auth_group->ag_name); 69 return (1); 70 } 71 72 secret = ucl_object_find_key(obj, "secret"); 73 if (!secret || secret->type != UCL_STRING) { 74 log_warnx("chap section in auth-group \"%s\" is missing " 75 "\"secret\" string key", auth_group->ag_name); 76 } 77 78 ca = auth_new_chap(auth_group, 79 ucl_object_tostring(user), 80 ucl_object_tostring(secret)); 81 82 if (ca == NULL) 83 return (1); 84 85 return (0); 86 } 87 88 static int 89 uclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj) 90 { 91 const struct auth *ca; 92 const ucl_object_t *user, *secret, *mutual_user; 93 const ucl_object_t *mutual_secret; 94 95 user = ucl_object_find_key(obj, "user"); 96 if (!user || user->type != UCL_STRING) { 97 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 98 "\"user\" string key", auth_group->ag_name); 99 return (1); 100 } 101 102 secret = ucl_object_find_key(obj, "secret"); 103 if (!secret || secret->type != UCL_STRING) { 104 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 105 "\"secret\" string key", auth_group->ag_name); 106 return (1); 107 } 108 109 mutual_user = ucl_object_find_key(obj, "mutual-user"); 110 if (!user || user->type != UCL_STRING) { 111 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 112 "\"mutual-user\" string key", auth_group->ag_name); 113 return (1); 114 } 115 116 mutual_secret = ucl_object_find_key(obj, "mutual-secret"); 117 if (!secret || secret->type != UCL_STRING) { 118 log_warnx("chap-mutual section in auth-group \"%s\" is missing " 119 "\"mutual-secret\" string key", auth_group->ag_name); 120 return (1); 121 } 122 123 ca = auth_new_chap_mutual(auth_group, 124 ucl_object_tostring(user), 125 ucl_object_tostring(secret), 126 ucl_object_tostring(mutual_user), 127 ucl_object_tostring(mutual_secret)); 128 129 if (ca == NULL) 130 return (1); 131 132 return (0); 133 } 134 135 static int 136 uclparse_target_portal_group(struct target *target, const ucl_object_t *obj) 137 { 138 struct portal_group *tpg; 139 struct auth_group *tag = NULL; 140 struct port *tp; 141 const ucl_object_t *portal_group, *auth_group; 142 143 portal_group = ucl_object_find_key(obj, "name"); 144 if (!portal_group || portal_group->type != UCL_STRING) { 145 log_warnx("portal-group section in target \"%s\" is missing " 146 "\"name\" string key", target->t_name); 147 return (1); 148 } 149 150 auth_group = ucl_object_find_key(obj, "auth-group-name"); 151 if (auth_group && auth_group->type != UCL_STRING) { 152 log_warnx("portal-group section in target \"%s\" is missing " 153 "\"auth-group-name\" string key", target->t_name); 154 return (1); 155 } 156 157 158 tpg = portal_group_find(conf, ucl_object_tostring(portal_group)); 159 if (tpg == NULL) { 160 log_warnx("unknown portal-group \"%s\" for target " 161 "\"%s\"", ucl_object_tostring(portal_group), target->t_name); 162 return (1); 163 } 164 165 if (auth_group) { 166 tag = auth_group_find(conf, ucl_object_tostring(auth_group)); 167 if (tag == NULL) { 168 log_warnx("unknown auth-group \"%s\" for target " 169 "\"%s\"", ucl_object_tostring(auth_group), 170 target->t_name); 171 return (1); 172 } 173 } 174 175 tp = port_new(conf, target, tpg); 176 if (tp == NULL) { 177 log_warnx("can't link portal-group \"%s\" to target " 178 "\"%s\"", ucl_object_tostring(portal_group), target->t_name); 179 return (1); 180 } 181 tp->p_auth_group = tag; 182 183 return (0); 184 } 185 186 static int 187 uclparse_target_lun(struct target *target, const ucl_object_t *obj) 188 { 189 struct lun *lun; 190 uint64_t tmp; 191 192 if (obj->type == UCL_INT) { 193 char *name; 194 195 tmp = ucl_object_toint(obj); 196 if (tmp >= MAX_LUNS) { 197 log_warnx("LU number %ju in target \"%s\" is too big", 198 tmp, target->t_name); 199 return (1); 200 } 201 202 asprintf(&name, "%s,lun,%ju", target->t_name, tmp); 203 lun = lun_new(conf, name); 204 if (lun == NULL) 205 return (1); 206 207 lun_set_scsiname(lun, name); 208 target->t_luns[tmp] = lun; 209 return (0); 210 } 211 212 if (obj->type == UCL_OBJECT) { 213 const ucl_object_t *num = ucl_object_find_key(obj, "number"); 214 const ucl_object_t *name = ucl_object_find_key(obj, "name"); 215 216 if (num == NULL || num->type != UCL_INT) { 217 log_warnx("lun section in target \"%s\" is missing " 218 "\"number\" integer property", target->t_name); 219 return (1); 220 } 221 tmp = ucl_object_toint(num); 222 if (tmp >= MAX_LUNS) { 223 log_warnx("LU number %ju in target \"%s\" is too big", 224 tmp, target->t_name); 225 return (1); 226 } 227 228 if (name == NULL || name->type != UCL_STRING) { 229 log_warnx("lun section in target \"%s\" is missing " 230 "\"name\" string property", target->t_name); 231 return (1); 232 } 233 234 lun = lun_find(conf, ucl_object_tostring(name)); 235 if (lun == NULL) 236 return (1); 237 238 target->t_luns[tmp] = lun; 239 } 240 241 return (0); 242 } 243 244 static int 245 uclparse_toplevel(const ucl_object_t *top) 246 { 247 ucl_object_iter_t it = NULL, iter = NULL; 248 const ucl_object_t *obj = NULL, *child = NULL; 249 int err = 0; 250 251 /* Pass 1 - everything except targets */ 252 while ((obj = ucl_iterate_object(top, &it, true))) { 253 const char *key = ucl_object_key(obj); 254 255 if (!strcmp(key, "debug")) { 256 if (obj->type == UCL_INT) 257 conf->conf_debug = ucl_object_toint(obj); 258 else { 259 log_warnx("\"debug\" property value is not integer"); 260 return (1); 261 } 262 } 263 264 if (!strcmp(key, "timeout")) { 265 if (obj->type == UCL_INT) 266 conf->conf_timeout = ucl_object_toint(obj); 267 else { 268 log_warnx("\"timeout\" property value is not integer"); 269 return (1); 270 } 271 } 272 273 if (!strcmp(key, "maxproc")) { 274 if (obj->type == UCL_INT) 275 conf->conf_maxproc = ucl_object_toint(obj); 276 else { 277 log_warnx("\"maxproc\" property value is not integer"); 278 return (1); 279 } 280 } 281 282 if (!strcmp(key, "pidfile")) { 283 if (obj->type == UCL_STRING) 284 conf->conf_pidfile_path = strdup( 285 ucl_object_tostring(obj)); 286 else { 287 log_warnx("\"pidfile\" property value is not string"); 288 return (1); 289 } 290 } 291 292 if (!strcmp(key, "isns-server")) { 293 if (obj->type == UCL_ARRAY) { 294 iter = NULL; 295 while ((child = ucl_iterate_object(obj, &iter, 296 true))) { 297 if (child->type != UCL_STRING) 298 return (1); 299 300 err = isns_new(conf, 301 ucl_object_tostring(child)); 302 if (err != 0) { 303 return (1); 304 } 305 } 306 } else { 307 log_warnx("\"isns-server\" property value is " 308 "not an array"); 309 return (1); 310 } 311 } 312 313 if (!strcmp(key, "isns-period")) { 314 if (obj->type == UCL_INT) 315 conf->conf_timeout = ucl_object_toint(obj); 316 else { 317 log_warnx("\"isns-period\" property value is not integer"); 318 return (1); 319 } 320 } 321 322 if (!strcmp(key, "isns-timeout")) { 323 if (obj->type == UCL_INT) 324 conf->conf_timeout = ucl_object_toint(obj); 325 else { 326 log_warnx("\"isns-timeout\" property value is not integer"); 327 return (1); 328 } 329 } 330 331 if (!strcmp(key, "auth-group")) { 332 if (obj->type == UCL_OBJECT) { 333 iter = NULL; 334 while ((child = ucl_iterate_object(obj, &iter, true))) { 335 uclparse_auth_group(ucl_object_key(child), child); 336 } 337 } else { 338 log_warnx("\"auth-group\" section is not an object"); 339 return (1); 340 } 341 } 342 343 if (!strcmp(key, "portal-group")) { 344 if (obj->type == UCL_OBJECT) { 345 iter = NULL; 346 while ((child = ucl_iterate_object(obj, &iter, true))) { 347 uclparse_portal_group(ucl_object_key(child), child); 348 } 349 } else { 350 log_warnx("\"portal-group\" section is not an object"); 351 return (1); 352 } 353 } 354 355 if (!strcmp(key, "lun")) { 356 if (obj->type == UCL_OBJECT) { 357 iter = NULL; 358 while ((child = ucl_iterate_object(obj, &iter, true))) { 359 uclparse_lun(ucl_object_key(child), child); 360 } 361 } else { 362 log_warnx("\"lun\" section is not an object"); 363 return (1); 364 } 365 } 366 } 367 368 /* Pass 2 - targets */ 369 it = NULL; 370 while ((obj = ucl_iterate_object(top, &it, true))) { 371 const char *key = ucl_object_key(obj); 372 373 if (!strcmp(key, "target")) { 374 if (obj->type == UCL_OBJECT) { 375 iter = NULL; 376 while ((child = ucl_iterate_object(obj, &iter, 377 true))) { 378 uclparse_target(ucl_object_key(child), 379 child); 380 } 381 } else { 382 log_warnx("\"target\" section is not an object"); 383 return (1); 384 } 385 } 386 } 387 388 return (0); 389 } 390 391 static int 392 uclparse_auth_group(const char *name, const ucl_object_t *top) 393 { 394 struct auth_group *auth_group; 395 const struct auth_name *an; 396 const struct auth_portal *ap; 397 ucl_object_iter_t it = NULL, it2 = NULL; 398 const ucl_object_t *obj = NULL, *tmp = NULL; 399 const char *key; 400 int err; 401 402 if (!strcmp(name, "default") && 403 conf->conf_default_ag_defined == false) { 404 auth_group = auth_group_find(conf, name); 405 conf->conf_default_ag_defined = true; 406 } else { 407 auth_group = auth_group_new(conf, name); 408 } 409 410 if (auth_group == NULL) 411 return (1); 412 413 while ((obj = ucl_iterate_object(top, &it, true))) { 414 key = ucl_object_key(obj); 415 416 if (!strcmp(key, "auth-type")) { 417 const char *value = ucl_object_tostring(obj); 418 419 err = auth_group_set_type(auth_group, value); 420 if (err) 421 return (1); 422 } 423 424 if (!strcmp(key, "chap")) { 425 if (obj->type != UCL_ARRAY) { 426 log_warnx("\"chap\" property of " 427 "auth-group \"%s\" is not an array", 428 name); 429 return (1); 430 } 431 432 it2 = NULL; 433 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 434 if (uclparse_chap(auth_group, tmp) != 0) 435 return (1); 436 } 437 } 438 439 if (!strcmp(key, "chap-mutual")) { 440 if (obj->type != UCL_ARRAY) { 441 log_warnx("\"chap-mutual\" property of " 442 "auth-group \"%s\" is not an array", 443 name); 444 return (1); 445 } 446 447 it2 = NULL; 448 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 449 if (uclparse_chap_mutual(auth_group, tmp) != 0) 450 return (1); 451 } 452 } 453 454 if (!strcmp(key, "initiator-name")) { 455 if (obj->type != UCL_ARRAY) { 456 log_warnx("\"initiator-name\" property of " 457 "auth-group \"%s\" is not an array", 458 name); 459 return (1); 460 } 461 462 it2 = NULL; 463 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 464 const char *value = ucl_object_tostring(tmp); 465 466 an = auth_name_new(auth_group, value); 467 if (an == NULL) 468 return (1); 469 } 470 } 471 472 if (!strcmp(key, "initiator-portal")) { 473 if (obj->type != UCL_ARRAY) { 474 log_warnx("\"initiator-portal\" property of " 475 "auth-group \"%s\" is not an array", 476 name); 477 return (1); 478 } 479 480 it2 = NULL; 481 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 482 const char *value = ucl_object_tostring(tmp); 483 484 ap = auth_portal_new(auth_group, value); 485 if (ap == NULL) 486 return (1); 487 } 488 } 489 } 490 491 return (0); 492 } 493 494 static int 495 uclparse_portal_group(const char *name, const ucl_object_t *top) 496 { 497 struct portal_group *portal_group; 498 ucl_object_iter_t it = NULL, it2 = NULL; 499 const ucl_object_t *obj = NULL, *tmp = NULL; 500 const char *key; 501 502 if (strcmp(name, "default") == 0 && 503 conf->conf_default_pg_defined == false) { 504 portal_group = portal_group_find(conf, name); 505 conf->conf_default_pg_defined = true; 506 } else { 507 portal_group = portal_group_new(conf, name); 508 } 509 510 if (portal_group == NULL) 511 return (1); 512 513 while ((obj = ucl_iterate_object(top, &it, true))) { 514 key = ucl_object_key(obj); 515 516 if (!strcmp(key, "discovery-auth-group")) { 517 portal_group->pg_discovery_auth_group = 518 auth_group_find(conf, ucl_object_tostring(obj)); 519 if (portal_group->pg_discovery_auth_group == NULL) { 520 log_warnx("unknown discovery-auth-group \"%s\" " 521 "for portal-group \"%s\"", 522 ucl_object_tostring(obj), 523 portal_group->pg_name); 524 return (1); 525 } 526 } 527 528 if (!strcmp(key, "discovery-filter")) { 529 if (obj->type != UCL_STRING) { 530 log_warnx("\"discovery-filter\" property of " 531 "portal-group \"%s\" is not a string", 532 portal_group->pg_name); 533 return (1); 534 } 535 536 if (portal_group_set_filter(portal_group, 537 ucl_object_tostring(obj)) != 0) 538 return (1); 539 } 540 541 if (!strcmp(key, "listen")) { 542 if (obj->type == UCL_STRING) { 543 if (portal_group_add_listen(portal_group, 544 ucl_object_tostring(obj), false) != 0) 545 return (1); 546 } else if (obj->type == UCL_ARRAY) { 547 while ((tmp = ucl_iterate_object(obj, &it2, 548 true))) { 549 if (portal_group_add_listen( 550 portal_group, 551 ucl_object_tostring(tmp), 552 false) != 0) 553 return (1); 554 } 555 } else { 556 log_warnx("\"listen\" property of " 557 "portal-group \"%s\" is not a string", 558 portal_group->pg_name); 559 return (1); 560 } 561 } 562 563 if (!strcmp(key, "listen-iser")) { 564 if (obj->type == UCL_STRING) { 565 if (portal_group_add_listen(portal_group, 566 ucl_object_tostring(obj), true) != 0) 567 return (1); 568 } else if (obj->type == UCL_ARRAY) { 569 while ((tmp = ucl_iterate_object(obj, &it2, 570 true))) { 571 if (portal_group_add_listen( 572 portal_group, 573 ucl_object_tostring(tmp), 574 true) != 0) 575 return (1); 576 } 577 } else { 578 log_warnx("\"listen\" property of " 579 "portal-group \"%s\" is not a string", 580 portal_group->pg_name); 581 return (1); 582 } 583 } 584 585 if (!strcmp(key, "redirect")) { 586 if (obj->type != UCL_STRING) { 587 log_warnx("\"listen\" property of " 588 "portal-group \"%s\" is not a string", 589 portal_group->pg_name); 590 return (1); 591 } 592 593 if (portal_group_set_redirection(portal_group, 594 ucl_object_tostring(obj)) != 0) 595 return (1); 596 } 597 598 if (!strcmp(key, "options")) { 599 if (obj->type != UCL_OBJECT) { 600 log_warnx("\"options\" property of portal group " 601 "\"%s\" is not an object", portal_group->pg_name); 602 return (1); 603 } 604 605 while ((tmp = ucl_iterate_object(obj, &it2, 606 true))) { 607 option_new(&portal_group->pg_options, 608 ucl_object_key(tmp), 609 ucl_object_tostring_forced(tmp)); 610 } 611 } 612 613 if (!strcmp(key, "dscp")) { 614 if ((obj->type != UCL_STRING) && (obj->type != UCL_INT)) { 615 log_warnx("\"dscp\" property of portal group " 616 "\"%s\" is not a string or integer", portal_group->pg_name); 617 return(1); 618 } 619 if (obj->type == UCL_INT) 620 portal_group->pg_dscp = ucl_object_toint(obj); 621 else { 622 key = ucl_object_tostring(obj); 623 if (strcmp(key, "0x") == 0) 624 portal_group->pg_dscp = strtol(key + 2, NULL, 16); 625 else if (strcmp(key, "be") || strcmp(key, "cs0")) 626 portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2; 627 else if (strcmp(key, "ef")) 628 portal_group->pg_dscp = IPTOS_DSCP_EF >> 2; 629 else if (strcmp(key, "cs0")) 630 portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2; 631 else if (strcmp(key, "cs1")) 632 portal_group->pg_dscp = IPTOS_DSCP_CS1 >> 2; 633 else if (strcmp(key, "cs2")) 634 portal_group->pg_dscp = IPTOS_DSCP_CS2 >> 2; 635 else if (strcmp(key, "cs3")) 636 portal_group->pg_dscp = IPTOS_DSCP_CS3 >> 2; 637 else if (strcmp(key, "cs4")) 638 portal_group->pg_dscp = IPTOS_DSCP_CS4 >> 2; 639 else if (strcmp(key, "cs5")) 640 portal_group->pg_dscp = IPTOS_DSCP_CS5 >> 2; 641 else if (strcmp(key, "cs6")) 642 portal_group->pg_dscp = IPTOS_DSCP_CS6 >> 2; 643 else if (strcmp(key, "cs7")) 644 portal_group->pg_dscp = IPTOS_DSCP_CS7 >> 2; 645 else if (strcmp(key, "af11")) 646 portal_group->pg_dscp = IPTOS_DSCP_AF11 >> 2; 647 else if (strcmp(key, "af12")) 648 portal_group->pg_dscp = IPTOS_DSCP_AF12 >> 2; 649 else if (strcmp(key, "af13")) 650 portal_group->pg_dscp = IPTOS_DSCP_AF13 >> 2; 651 else if (strcmp(key, "af21")) 652 portal_group->pg_dscp = IPTOS_DSCP_AF21 >> 2; 653 else if (strcmp(key, "af22")) 654 portal_group->pg_dscp = IPTOS_DSCP_AF22 >> 2; 655 else if (strcmp(key, "af23")) 656 portal_group->pg_dscp = IPTOS_DSCP_AF23 >> 2; 657 else if (strcmp(key, "af31")) 658 portal_group->pg_dscp = IPTOS_DSCP_AF31 >> 2; 659 else if (strcmp(key, "af32")) 660 portal_group->pg_dscp = IPTOS_DSCP_AF32 >> 2; 661 else if (strcmp(key, "af33")) 662 portal_group->pg_dscp = IPTOS_DSCP_AF33 >> 2; 663 else if (strcmp(key, "af41")) 664 portal_group->pg_dscp = IPTOS_DSCP_AF41 >> 2; 665 else if (strcmp(key, "af42")) 666 portal_group->pg_dscp = IPTOS_DSCP_AF42 >> 2; 667 else if (strcmp(key, "af43")) 668 portal_group->pg_dscp = IPTOS_DSCP_AF43 >> 2; 669 else { 670 log_warnx("\"dscp\" property value is not a supported textual value"); 671 return (1); 672 } 673 } 674 } 675 } 676 677 return (0); 678 } 679 680 static int 681 uclparse_target(const char *name, const ucl_object_t *top) 682 { 683 struct target *target; 684 ucl_object_iter_t it = NULL, it2 = NULL; 685 const ucl_object_t *obj = NULL, *tmp = NULL; 686 const char *key; 687 688 target = target_new(conf, name); 689 if (target == NULL) 690 return (1); 691 692 while ((obj = ucl_iterate_object(top, &it, true))) { 693 key = ucl_object_key(obj); 694 695 if (!strcmp(key, "alias")) { 696 if (obj->type != UCL_STRING) { 697 log_warnx("\"alias\" property of target " 698 "\"%s\" is not a string", target->t_name); 699 return (1); 700 } 701 702 target->t_alias = strdup(ucl_object_tostring(obj)); 703 } 704 705 if (!strcmp(key, "auth-group")) { 706 if (target->t_auth_group != NULL) { 707 if (target->t_auth_group->ag_name != NULL) 708 log_warnx("auth-group for target \"%s\" " 709 "specified more than once", 710 target->t_name); 711 else 712 log_warnx("cannot use both auth-group " 713 "and explicit authorisations for " 714 "target \"%s\"", target->t_name); 715 return (1); 716 } 717 target->t_auth_group = auth_group_find(conf, 718 ucl_object_tostring(obj)); 719 if (target->t_auth_group == NULL) { 720 log_warnx("unknown auth-group \"%s\" for target " 721 "\"%s\"", ucl_object_tostring(obj), 722 target->t_name); 723 return (1); 724 } 725 } 726 727 if (!strcmp(key, "auth-type")) { 728 int error; 729 730 if (target->t_auth_group != NULL) { 731 if (target->t_auth_group->ag_name != NULL) { 732 log_warnx("cannot use both auth-group and " 733 "auth-type for target \"%s\"", 734 target->t_name); 735 return (1); 736 } 737 } else { 738 target->t_auth_group = auth_group_new(conf, NULL); 739 if (target->t_auth_group == NULL) 740 return (1); 741 742 target->t_auth_group->ag_target = target; 743 } 744 error = auth_group_set_type(target->t_auth_group, 745 ucl_object_tostring(obj)); 746 if (error != 0) 747 return (1); 748 } 749 750 if (!strcmp(key, "chap")) { 751 if (uclparse_chap(target->t_auth_group, obj) != 0) 752 return (1); 753 } 754 755 if (!strcmp(key, "chap-mutual")) { 756 if (uclparse_chap_mutual(target->t_auth_group, obj) != 0) 757 return (1); 758 } 759 760 if (!strcmp(key, "initiator-name")) { 761 const struct auth_name *an; 762 763 if (target->t_auth_group != NULL) { 764 if (target->t_auth_group->ag_name != NULL) { 765 log_warnx("cannot use both auth-group and " 766 "initiator-name for target \"%s\"", 767 target->t_name); 768 return (1); 769 } 770 } else { 771 target->t_auth_group = auth_group_new(conf, NULL); 772 if (target->t_auth_group == NULL) 773 return (1); 774 775 target->t_auth_group->ag_target = target; 776 } 777 an = auth_name_new(target->t_auth_group, 778 ucl_object_tostring(obj)); 779 if (an == NULL) 780 return (1); 781 } 782 783 if (!strcmp(key, "initiator-portal")) { 784 const struct auth_portal *ap; 785 786 if (target->t_auth_group != NULL) { 787 if (target->t_auth_group->ag_name != NULL) { 788 log_warnx("cannot use both auth-group and " 789 "initiator-portal for target \"%s\"", 790 target->t_name); 791 return (1); 792 } 793 } else { 794 target->t_auth_group = auth_group_new(conf, NULL); 795 if (target->t_auth_group == NULL) 796 return (1); 797 798 target->t_auth_group->ag_target = target; 799 } 800 ap = auth_portal_new(target->t_auth_group, 801 ucl_object_tostring(obj)); 802 if (ap == NULL) 803 return (1); 804 } 805 806 if (!strcmp(key, "portal-group")) { 807 if (obj->type == UCL_OBJECT) { 808 if (uclparse_target_portal_group(target, obj) != 0) 809 return (1); 810 } 811 812 if (obj->type == UCL_ARRAY) { 813 while ((tmp = ucl_iterate_object(obj, &it2, 814 true))) { 815 if (uclparse_target_portal_group(target, 816 tmp) != 0) 817 return (1); 818 } 819 } 820 } 821 822 if (!strcmp(key, "port")) { 823 struct pport *pp; 824 struct port *tp; 825 const char *value = ucl_object_tostring(obj); 826 int ret, i_pp, i_vp = 0; 827 828 ret = sscanf(value, "ioctl/%d/%d", &i_pp, &i_vp); 829 if (ret > 0) { 830 tp = port_new_ioctl(conf, target, i_pp, i_vp); 831 if (tp == NULL) { 832 log_warnx("can't create new ioctl port " 833 "for target \"%s\"", target->t_name); 834 return (1); 835 } 836 837 return (0); 838 } 839 840 pp = pport_find(conf, value); 841 if (pp == NULL) { 842 log_warnx("unknown port \"%s\" for target \"%s\"", 843 value, target->t_name); 844 return (1); 845 } 846 if (!TAILQ_EMPTY(&pp->pp_ports)) { 847 log_warnx("can't link port \"%s\" to target \"%s\", " 848 "port already linked to some target", 849 value, target->t_name); 850 return (1); 851 } 852 tp = port_new_pp(conf, target, pp); 853 if (tp == NULL) { 854 log_warnx("can't link port \"%s\" to target \"%s\"", 855 value, target->t_name); 856 return (1); 857 } 858 } 859 860 if (!strcmp(key, "redirect")) { 861 if (obj->type != UCL_STRING) { 862 log_warnx("\"redirect\" property of target " 863 "\"%s\" is not a string", target->t_name); 864 return (1); 865 } 866 867 if (target_set_redirection(target, 868 ucl_object_tostring(obj)) != 0) 869 return (1); 870 } 871 872 if (!strcmp(key, "lun")) { 873 while ((tmp = ucl_iterate_object(obj, &it2, true))) { 874 if (uclparse_target_lun(target, tmp) != 0) 875 return (1); 876 } 877 } 878 } 879 880 return (0); 881 } 882 883 static int 884 uclparse_lun(const char *name, const ucl_object_t *top) 885 { 886 struct lun *lun; 887 ucl_object_iter_t it = NULL, child_it = NULL; 888 const ucl_object_t *obj = NULL, *child = NULL; 889 const char *key; 890 891 lun = lun_new(conf, name); 892 if (lun == NULL) 893 return (1); 894 895 while ((obj = ucl_iterate_object(top, &it, true))) { 896 key = ucl_object_key(obj); 897 898 if (!strcmp(key, "backend")) { 899 if (obj->type != UCL_STRING) { 900 log_warnx("\"backend\" property of lun " 901 "\"%s\" is not a string", 902 lun->l_name); 903 return (1); 904 } 905 906 lun_set_backend(lun, ucl_object_tostring(obj)); 907 } 908 909 if (!strcmp(key, "blocksize")) { 910 if (obj->type != UCL_INT) { 911 log_warnx("\"blocksize\" property of lun " 912 "\"%s\" is not an integer", lun->l_name); 913 return (1); 914 } 915 916 lun_set_blocksize(lun, ucl_object_toint(obj)); 917 } 918 919 if (!strcmp(key, "device-id")) { 920 if (obj->type != UCL_STRING) { 921 log_warnx("\"device-id\" property of lun " 922 "\"%s\" is not an integer", lun->l_name); 923 return (1); 924 } 925 926 lun_set_device_id(lun, ucl_object_tostring(obj)); 927 } 928 929 if (!strcmp(key, "options")) { 930 if (obj->type != UCL_OBJECT) { 931 log_warnx("\"options\" property of lun " 932 "\"%s\" is not an object", lun->l_name); 933 return (1); 934 } 935 936 while ((child = ucl_iterate_object(obj, &child_it, 937 true))) { 938 option_new(&lun->l_options, 939 ucl_object_key(child), 940 ucl_object_tostring_forced(child)); 941 } 942 } 943 944 if (!strcmp(key, "path")) { 945 if (obj->type != UCL_STRING) { 946 log_warnx("\"path\" property of lun " 947 "\"%s\" is not a string", lun->l_name); 948 return (1); 949 } 950 951 lun_set_path(lun, ucl_object_tostring(obj)); 952 } 953 954 if (!strcmp(key, "serial")) { 955 if (obj->type != UCL_STRING) { 956 log_warnx("\"serial\" property of lun " 957 "\"%s\" is not a string", lun->l_name); 958 return (1); 959 } 960 961 lun_set_serial(lun, ucl_object_tostring(obj)); 962 } 963 964 if (!strcmp(key, "size")) { 965 if (obj->type != UCL_INT) { 966 log_warnx("\"size\" property of lun " 967 "\"%s\" is not an integer", lun->l_name); 968 return (1); 969 } 970 971 lun_set_size(lun, ucl_object_toint(obj)); 972 } 973 } 974 975 return (0); 976 } 977 978 int 979 uclparse_conf(struct conf *newconf, const char *path) 980 { 981 struct ucl_parser *parser; 982 ucl_object_t *top; 983 int error; 984 985 conf = newconf; 986 parser = ucl_parser_new(0); 987 988 if (!ucl_parser_add_file(parser, path)) { 989 log_warn("unable to parse configuration file %s: %s", path, 990 ucl_parser_get_error(parser)); 991 ucl_parser_free(parser); 992 return (1); 993 } 994 995 top = ucl_parser_get_object(parser); 996 error = uclparse_toplevel(top); 997 ucl_object_unref(top); 998 ucl_parser_free(parser); 999 1000 return (error); 1001 } 1002