1 %{ 2 /*- 3 * Copyright (c) 2012 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * This software was developed by Edward Tomasz Napierala under sponsorship 7 * from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $FreeBSD$ 31 */ 32 33 #include <sys/queue.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <assert.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 41 #include "ctld.h" 42 43 extern FILE *yyin; 44 extern char *yytext; 45 extern int lineno; 46 47 static struct conf *conf = NULL; 48 static struct auth_group *auth_group = NULL; 49 static struct portal_group *portal_group = NULL; 50 static struct target *target = NULL; 51 static struct lun *lun = NULL; 52 53 extern void yyerror(const char *); 54 extern int yylex(void); 55 extern void yyrestart(FILE *); 56 57 %} 58 59 %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL 60 %token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE 61 %token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER FOREIGN 62 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT 63 %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION 64 %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR 65 %token TAG TARGET TIMEOUT 66 67 %union 68 { 69 char *str; 70 } 71 72 %token <str> STR 73 74 %% 75 76 statements: 77 | 78 statements statement 79 | 80 statements statement SEMICOLON 81 ; 82 83 statement: 84 debug 85 | 86 timeout 87 | 88 maxproc 89 | 90 pidfile 91 | 92 isns_server 93 | 94 isns_period 95 | 96 isns_timeout 97 | 98 auth_group 99 | 100 portal_group 101 | 102 lun 103 | 104 target 105 ; 106 107 debug: DEBUG STR 108 { 109 uint64_t tmp; 110 111 if (expand_number($2, &tmp) != 0) { 112 yyerror("invalid numeric value"); 113 free($2); 114 return (1); 115 } 116 117 conf->conf_debug = tmp; 118 } 119 ; 120 121 timeout: TIMEOUT STR 122 { 123 uint64_t tmp; 124 125 if (expand_number($2, &tmp) != 0) { 126 yyerror("invalid numeric value"); 127 free($2); 128 return (1); 129 } 130 131 conf->conf_timeout = tmp; 132 } 133 ; 134 135 maxproc: MAXPROC STR 136 { 137 uint64_t tmp; 138 139 if (expand_number($2, &tmp) != 0) { 140 yyerror("invalid numeric value"); 141 free($2); 142 return (1); 143 } 144 145 conf->conf_maxproc = tmp; 146 } 147 ; 148 149 pidfile: PIDFILE STR 150 { 151 if (conf->conf_pidfile_path != NULL) { 152 log_warnx("pidfile specified more than once"); 153 free($2); 154 return (1); 155 } 156 conf->conf_pidfile_path = $2; 157 } 158 ; 159 160 isns_server: ISNS_SERVER STR 161 { 162 int error; 163 164 error = isns_new(conf, $2); 165 free($2); 166 if (error != 0) 167 return (1); 168 } 169 ; 170 171 isns_period: ISNS_PERIOD STR 172 { 173 uint64_t tmp; 174 175 if (expand_number($2, &tmp) != 0) { 176 yyerror("invalid numeric value"); 177 free($2); 178 return (1); 179 } 180 181 conf->conf_isns_period = tmp; 182 } 183 ; 184 185 isns_timeout: ISNS_TIMEOUT STR 186 { 187 uint64_t tmp; 188 189 if (expand_number($2, &tmp) != 0) { 190 yyerror("invalid numeric value"); 191 free($2); 192 return (1); 193 } 194 195 conf->conf_isns_timeout = tmp; 196 } 197 ; 198 199 auth_group: AUTH_GROUP auth_group_name 200 OPENING_BRACKET auth_group_entries CLOSING_BRACKET 201 { 202 auth_group = NULL; 203 } 204 ; 205 206 auth_group_name: STR 207 { 208 /* 209 * Make it possible to redefine default 210 * auth-group. but only once. 211 */ 212 if (strcmp($1, "default") == 0 && 213 conf->conf_default_ag_defined == false) { 214 auth_group = auth_group_find(conf, $1); 215 conf->conf_default_ag_defined = true; 216 } else { 217 auth_group = auth_group_new(conf, $1); 218 } 219 free($1); 220 if (auth_group == NULL) 221 return (1); 222 } 223 ; 224 225 auth_group_entries: 226 | 227 auth_group_entries auth_group_entry 228 | 229 auth_group_entries auth_group_entry SEMICOLON 230 ; 231 232 auth_group_entry: 233 auth_group_auth_type 234 | 235 auth_group_chap 236 | 237 auth_group_chap_mutual 238 | 239 auth_group_initiator_name 240 | 241 auth_group_initiator_portal 242 ; 243 244 auth_group_auth_type: AUTH_TYPE STR 245 { 246 int error; 247 248 error = auth_group_set_type(auth_group, $2); 249 free($2); 250 if (error != 0) 251 return (1); 252 } 253 ; 254 255 auth_group_chap: CHAP STR STR 256 { 257 const struct auth *ca; 258 259 ca = auth_new_chap(auth_group, $2, $3); 260 free($2); 261 free($3); 262 if (ca == NULL) 263 return (1); 264 } 265 ; 266 267 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR 268 { 269 const struct auth *ca; 270 271 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5); 272 free($2); 273 free($3); 274 free($4); 275 free($5); 276 if (ca == NULL) 277 return (1); 278 } 279 ; 280 281 auth_group_initiator_name: INITIATOR_NAME STR 282 { 283 const struct auth_name *an; 284 285 an = auth_name_new(auth_group, $2); 286 free($2); 287 if (an == NULL) 288 return (1); 289 } 290 ; 291 292 auth_group_initiator_portal: INITIATOR_PORTAL STR 293 { 294 const struct auth_portal *ap; 295 296 ap = auth_portal_new(auth_group, $2); 297 free($2); 298 if (ap == NULL) 299 return (1); 300 } 301 ; 302 303 portal_group: PORTAL_GROUP portal_group_name 304 OPENING_BRACKET portal_group_entries CLOSING_BRACKET 305 { 306 portal_group = NULL; 307 } 308 ; 309 310 portal_group_name: STR 311 { 312 /* 313 * Make it possible to redefine default 314 * portal-group. but only once. 315 */ 316 if (strcmp($1, "default") == 0 && 317 conf->conf_default_pg_defined == false) { 318 portal_group = portal_group_find(conf, $1); 319 conf->conf_default_pg_defined = true; 320 } else { 321 portal_group = portal_group_new(conf, $1); 322 } 323 free($1); 324 if (portal_group == NULL) 325 return (1); 326 } 327 ; 328 329 portal_group_entries: 330 | 331 portal_group_entries portal_group_entry 332 | 333 portal_group_entries portal_group_entry SEMICOLON 334 ; 335 336 portal_group_entry: 337 portal_group_discovery_auth_group 338 | 339 portal_group_discovery_filter 340 | 341 portal_group_foreign 342 | 343 portal_group_listen 344 | 345 portal_group_listen_iser 346 | 347 portal_group_offload 348 | 349 portal_group_option 350 | 351 portal_group_redirect 352 | 353 portal_group_tag 354 ; 355 356 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR 357 { 358 if (portal_group->pg_discovery_auth_group != NULL) { 359 log_warnx("discovery-auth-group for portal-group " 360 "\"%s\" specified more than once", 361 portal_group->pg_name); 362 return (1); 363 } 364 portal_group->pg_discovery_auth_group = 365 auth_group_find(conf, $2); 366 if (portal_group->pg_discovery_auth_group == NULL) { 367 log_warnx("unknown discovery-auth-group \"%s\" " 368 "for portal-group \"%s\"", 369 $2, portal_group->pg_name); 370 return (1); 371 } 372 free($2); 373 } 374 ; 375 376 portal_group_discovery_filter: DISCOVERY_FILTER STR 377 { 378 int error; 379 380 error = portal_group_set_filter(portal_group, $2); 381 free($2); 382 if (error != 0) 383 return (1); 384 } 385 ; 386 387 portal_group_foreign: FOREIGN 388 { 389 390 portal_group->pg_foreign = 1; 391 } 392 ; 393 394 portal_group_listen: LISTEN STR 395 { 396 int error; 397 398 error = portal_group_add_listen(portal_group, $2, false); 399 free($2); 400 if (error != 0) 401 return (1); 402 } 403 ; 404 405 portal_group_listen_iser: LISTEN_ISER STR 406 { 407 int error; 408 409 error = portal_group_add_listen(portal_group, $2, true); 410 free($2); 411 if (error != 0) 412 return (1); 413 } 414 ; 415 416 portal_group_offload: OFFLOAD STR 417 { 418 int error; 419 420 error = portal_group_set_offload(portal_group, $2); 421 free($2); 422 if (error != 0) 423 return (1); 424 } 425 ; 426 427 portal_group_option: OPTION STR STR 428 { 429 struct option *o; 430 431 o = option_new(&portal_group->pg_options, $2, $3); 432 free($2); 433 free($3); 434 if (o == NULL) 435 return (1); 436 } 437 ; 438 439 portal_group_redirect: REDIRECT STR 440 { 441 int error; 442 443 error = portal_group_set_redirection(portal_group, $2); 444 free($2); 445 if (error != 0) 446 return (1); 447 } 448 ; 449 450 portal_group_tag: TAG STR 451 { 452 uint64_t tmp; 453 454 if (expand_number($2, &tmp) != 0) { 455 yyerror("invalid numeric value"); 456 free($2); 457 return (1); 458 } 459 460 portal_group->pg_tag = tmp; 461 } 462 ; 463 464 lun: LUN lun_name 465 OPENING_BRACKET lun_entries CLOSING_BRACKET 466 { 467 lun = NULL; 468 } 469 ; 470 471 lun_name: STR 472 { 473 lun = lun_new(conf, $1); 474 free($1); 475 if (lun == NULL) 476 return (1); 477 } 478 ; 479 480 target: TARGET target_name 481 OPENING_BRACKET target_entries CLOSING_BRACKET 482 { 483 target = NULL; 484 } 485 ; 486 487 target_name: STR 488 { 489 target = target_new(conf, $1); 490 free($1); 491 if (target == NULL) 492 return (1); 493 } 494 ; 495 496 target_entries: 497 | 498 target_entries target_entry 499 | 500 target_entries target_entry SEMICOLON 501 ; 502 503 target_entry: 504 target_alias 505 | 506 target_auth_group 507 | 508 target_auth_type 509 | 510 target_chap 511 | 512 target_chap_mutual 513 | 514 target_initiator_name 515 | 516 target_initiator_portal 517 | 518 target_portal_group 519 | 520 target_port 521 | 522 target_redirect 523 | 524 target_lun 525 | 526 target_lun_ref 527 ; 528 529 target_alias: ALIAS STR 530 { 531 if (target->t_alias != NULL) { 532 log_warnx("alias for target \"%s\" " 533 "specified more than once", target->t_name); 534 return (1); 535 } 536 target->t_alias = $2; 537 } 538 ; 539 540 target_auth_group: AUTH_GROUP STR 541 { 542 if (target->t_auth_group != NULL) { 543 if (target->t_auth_group->ag_name != NULL) 544 log_warnx("auth-group for target \"%s\" " 545 "specified more than once", target->t_name); 546 else 547 log_warnx("cannot use both auth-group and explicit " 548 "authorisations for target \"%s\"", 549 target->t_name); 550 return (1); 551 } 552 target->t_auth_group = auth_group_find(conf, $2); 553 if (target->t_auth_group == NULL) { 554 log_warnx("unknown auth-group \"%s\" for target " 555 "\"%s\"", $2, target->t_name); 556 return (1); 557 } 558 free($2); 559 } 560 ; 561 562 target_auth_type: AUTH_TYPE STR 563 { 564 int error; 565 566 if (target->t_auth_group != NULL) { 567 if (target->t_auth_group->ag_name != NULL) { 568 log_warnx("cannot use both auth-group and " 569 "auth-type for target \"%s\"", 570 target->t_name); 571 return (1); 572 } 573 } else { 574 target->t_auth_group = auth_group_new(conf, NULL); 575 if (target->t_auth_group == NULL) { 576 free($2); 577 return (1); 578 } 579 target->t_auth_group->ag_target = target; 580 } 581 error = auth_group_set_type(target->t_auth_group, $2); 582 free($2); 583 if (error != 0) 584 return (1); 585 } 586 ; 587 588 target_chap: CHAP STR STR 589 { 590 const struct auth *ca; 591 592 if (target->t_auth_group != NULL) { 593 if (target->t_auth_group->ag_name != NULL) { 594 log_warnx("cannot use both auth-group and " 595 "chap for target \"%s\"", 596 target->t_name); 597 free($2); 598 free($3); 599 return (1); 600 } 601 } else { 602 target->t_auth_group = auth_group_new(conf, NULL); 603 if (target->t_auth_group == NULL) { 604 free($2); 605 free($3); 606 return (1); 607 } 608 target->t_auth_group->ag_target = target; 609 } 610 ca = auth_new_chap(target->t_auth_group, $2, $3); 611 free($2); 612 free($3); 613 if (ca == NULL) 614 return (1); 615 } 616 ; 617 618 target_chap_mutual: CHAP_MUTUAL STR STR STR STR 619 { 620 const struct auth *ca; 621 622 if (target->t_auth_group != NULL) { 623 if (target->t_auth_group->ag_name != NULL) { 624 log_warnx("cannot use both auth-group and " 625 "chap-mutual for target \"%s\"", 626 target->t_name); 627 free($2); 628 free($3); 629 free($4); 630 free($5); 631 return (1); 632 } 633 } else { 634 target->t_auth_group = auth_group_new(conf, NULL); 635 if (target->t_auth_group == NULL) { 636 free($2); 637 free($3); 638 free($4); 639 free($5); 640 return (1); 641 } 642 target->t_auth_group->ag_target = target; 643 } 644 ca = auth_new_chap_mutual(target->t_auth_group, 645 $2, $3, $4, $5); 646 free($2); 647 free($3); 648 free($4); 649 free($5); 650 if (ca == NULL) 651 return (1); 652 } 653 ; 654 655 target_initiator_name: INITIATOR_NAME STR 656 { 657 const struct auth_name *an; 658 659 if (target->t_auth_group != NULL) { 660 if (target->t_auth_group->ag_name != NULL) { 661 log_warnx("cannot use both auth-group and " 662 "initiator-name for target \"%s\"", 663 target->t_name); 664 free($2); 665 return (1); 666 } 667 } else { 668 target->t_auth_group = auth_group_new(conf, NULL); 669 if (target->t_auth_group == NULL) { 670 free($2); 671 return (1); 672 } 673 target->t_auth_group->ag_target = target; 674 } 675 an = auth_name_new(target->t_auth_group, $2); 676 free($2); 677 if (an == NULL) 678 return (1); 679 } 680 ; 681 682 target_initiator_portal: INITIATOR_PORTAL STR 683 { 684 const struct auth_portal *ap; 685 686 if (target->t_auth_group != NULL) { 687 if (target->t_auth_group->ag_name != NULL) { 688 log_warnx("cannot use both auth-group and " 689 "initiator-portal for target \"%s\"", 690 target->t_name); 691 free($2); 692 return (1); 693 } 694 } else { 695 target->t_auth_group = auth_group_new(conf, NULL); 696 if (target->t_auth_group == NULL) { 697 free($2); 698 return (1); 699 } 700 target->t_auth_group->ag_target = target; 701 } 702 ap = auth_portal_new(target->t_auth_group, $2); 703 free($2); 704 if (ap == NULL) 705 return (1); 706 } 707 ; 708 709 target_portal_group: PORTAL_GROUP STR STR 710 { 711 struct portal_group *tpg; 712 struct auth_group *tag; 713 struct port *tp; 714 715 tpg = portal_group_find(conf, $2); 716 if (tpg == NULL) { 717 log_warnx("unknown portal-group \"%s\" for target " 718 "\"%s\"", $2, target->t_name); 719 free($2); 720 free($3); 721 return (1); 722 } 723 tag = auth_group_find(conf, $3); 724 if (tag == NULL) { 725 log_warnx("unknown auth-group \"%s\" for target " 726 "\"%s\"", $3, target->t_name); 727 free($2); 728 free($3); 729 return (1); 730 } 731 tp = port_new(conf, target, tpg); 732 if (tp == NULL) { 733 log_warnx("can't link portal-group \"%s\" to target " 734 "\"%s\"", $2, target->t_name); 735 free($2); 736 return (1); 737 } 738 tp->p_auth_group = tag; 739 free($2); 740 free($3); 741 } 742 | PORTAL_GROUP STR 743 { 744 struct portal_group *tpg; 745 struct port *tp; 746 747 tpg = portal_group_find(conf, $2); 748 if (tpg == NULL) { 749 log_warnx("unknown portal-group \"%s\" for target " 750 "\"%s\"", $2, target->t_name); 751 free($2); 752 return (1); 753 } 754 tp = port_new(conf, target, tpg); 755 if (tp == NULL) { 756 log_warnx("can't link portal-group \"%s\" to target " 757 "\"%s\"", $2, target->t_name); 758 free($2); 759 return (1); 760 } 761 free($2); 762 } 763 ; 764 765 target_port: PORT STR 766 { 767 struct pport *pp; 768 struct port *tp; 769 770 pp = pport_find(conf, $2); 771 if (pp == NULL) { 772 log_warnx("unknown port \"%s\" for target \"%s\"", 773 $2, target->t_name); 774 free($2); 775 return (1); 776 } 777 if (!TAILQ_EMPTY(&pp->pp_ports)) { 778 log_warnx("can't link port \"%s\" to target \"%s\", " 779 "port already linked to some target", 780 $2, target->t_name); 781 free($2); 782 return (1); 783 } 784 tp = port_new_pp(conf, target, pp); 785 if (tp == NULL) { 786 log_warnx("can't link port \"%s\" to target \"%s\"", 787 $2, target->t_name); 788 free($2); 789 return (1); 790 } 791 free($2); 792 } 793 ; 794 795 target_redirect: REDIRECT STR 796 { 797 int error; 798 799 error = target_set_redirection(target, $2); 800 free($2); 801 if (error != 0) 802 return (1); 803 } 804 ; 805 806 target_lun: LUN lun_number 807 OPENING_BRACKET lun_entries CLOSING_BRACKET 808 { 809 lun = NULL; 810 } 811 ; 812 813 lun_number: STR 814 { 815 uint64_t tmp; 816 int ret; 817 char *name; 818 819 if (expand_number($1, &tmp) != 0) { 820 yyerror("invalid numeric value"); 821 free($1); 822 return (1); 823 } 824 825 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp); 826 if (ret <= 0) 827 log_err(1, "asprintf"); 828 lun = lun_new(conf, name); 829 if (lun == NULL) 830 return (1); 831 832 lun_set_scsiname(lun, name); 833 target->t_luns[tmp] = lun; 834 } 835 ; 836 837 target_lun_ref: LUN STR STR 838 { 839 uint64_t tmp; 840 841 if (expand_number($2, &tmp) != 0) { 842 yyerror("invalid numeric value"); 843 free($2); 844 free($3); 845 return (1); 846 } 847 free($2); 848 849 lun = lun_find(conf, $3); 850 free($3); 851 if (lun == NULL) 852 return (1); 853 854 target->t_luns[tmp] = lun; 855 } 856 ; 857 858 lun_entries: 859 | 860 lun_entries lun_entry 861 | 862 lun_entries lun_entry SEMICOLON 863 ; 864 865 lun_entry: 866 lun_backend 867 | 868 lun_blocksize 869 | 870 lun_device_id 871 | 872 lun_device_type 873 | 874 lun_ctl_lun 875 | 876 lun_option 877 | 878 lun_path 879 | 880 lun_serial 881 | 882 lun_size 883 ; 884 885 lun_backend: BACKEND STR 886 { 887 if (lun->l_backend != NULL) { 888 log_warnx("backend for lun \"%s\" " 889 "specified more than once", 890 lun->l_name); 891 free($2); 892 return (1); 893 } 894 lun_set_backend(lun, $2); 895 free($2); 896 } 897 ; 898 899 lun_blocksize: BLOCKSIZE STR 900 { 901 uint64_t tmp; 902 903 if (expand_number($2, &tmp) != 0) { 904 yyerror("invalid numeric value"); 905 free($2); 906 return (1); 907 } 908 909 if (lun->l_blocksize != 0) { 910 log_warnx("blocksize for lun \"%s\" " 911 "specified more than once", 912 lun->l_name); 913 return (1); 914 } 915 lun_set_blocksize(lun, tmp); 916 } 917 ; 918 919 lun_device_id: DEVICE_ID STR 920 { 921 if (lun->l_device_id != NULL) { 922 log_warnx("device_id for lun \"%s\" " 923 "specified more than once", 924 lun->l_name); 925 free($2); 926 return (1); 927 } 928 lun_set_device_id(lun, $2); 929 free($2); 930 } 931 ; 932 933 lun_device_type: DEVICE_TYPE STR 934 { 935 uint64_t tmp; 936 937 if (strcasecmp($2, "disk") == 0 || 938 strcasecmp($2, "direct") == 0) 939 tmp = 0; 940 else if (strcasecmp($2, "processor") == 0) 941 tmp = 3; 942 else if (strcasecmp($2, "cd") == 0 || 943 strcasecmp($2, "cdrom") == 0 || 944 strcasecmp($2, "dvd") == 0 || 945 strcasecmp($2, "dvdrom") == 0) 946 tmp = 5; 947 else if (expand_number($2, &tmp) != 0 || 948 tmp > 15) { 949 yyerror("invalid numeric value"); 950 free($2); 951 return (1); 952 } 953 954 lun_set_device_type(lun, tmp); 955 } 956 ; 957 958 lun_ctl_lun: CTL_LUN STR 959 { 960 uint64_t tmp; 961 962 if (expand_number($2, &tmp) != 0) { 963 yyerror("invalid numeric value"); 964 free($2); 965 return (1); 966 } 967 968 if (lun->l_ctl_lun >= 0) { 969 log_warnx("ctl_lun for lun \"%s\" " 970 "specified more than once", 971 lun->l_name); 972 return (1); 973 } 974 lun_set_ctl_lun(lun, tmp); 975 } 976 ; 977 978 lun_option: OPTION STR STR 979 { 980 struct option *o; 981 982 o = option_new(&lun->l_options, $2, $3); 983 free($2); 984 free($3); 985 if (o == NULL) 986 return (1); 987 } 988 ; 989 990 lun_path: PATH STR 991 { 992 if (lun->l_path != NULL) { 993 log_warnx("path for lun \"%s\" " 994 "specified more than once", 995 lun->l_name); 996 free($2); 997 return (1); 998 } 999 lun_set_path(lun, $2); 1000 free($2); 1001 } 1002 ; 1003 1004 lun_serial: SERIAL STR 1005 { 1006 if (lun->l_serial != NULL) { 1007 log_warnx("serial for lun \"%s\" " 1008 "specified more than once", 1009 lun->l_name); 1010 free($2); 1011 return (1); 1012 } 1013 lun_set_serial(lun, $2); 1014 free($2); 1015 } 1016 ; 1017 1018 lun_size: SIZE STR 1019 { 1020 uint64_t tmp; 1021 1022 if (expand_number($2, &tmp) != 0) { 1023 yyerror("invalid numeric value"); 1024 free($2); 1025 return (1); 1026 } 1027 1028 if (lun->l_size != 0) { 1029 log_warnx("size for lun \"%s\" " 1030 "specified more than once", 1031 lun->l_name); 1032 return (1); 1033 } 1034 lun_set_size(lun, tmp); 1035 } 1036 ; 1037 %% 1038 1039 void 1040 yyerror(const char *str) 1041 { 1042 1043 log_warnx("error in configuration file at line %d near '%s': %s", 1044 lineno, yytext, str); 1045 } 1046 1047 static void 1048 check_perms(const char *path) 1049 { 1050 struct stat sb; 1051 int error; 1052 1053 error = stat(path, &sb); 1054 if (error != 0) { 1055 log_warn("stat"); 1056 return; 1057 } 1058 if (sb.st_mode & S_IWOTH) { 1059 log_warnx("%s is world-writable", path); 1060 } else if (sb.st_mode & S_IROTH) { 1061 log_warnx("%s is world-readable", path); 1062 } else if (sb.st_mode & S_IXOTH) { 1063 /* 1064 * Ok, this one doesn't matter, but still do it, 1065 * just for consistency. 1066 */ 1067 log_warnx("%s is world-executable", path); 1068 } 1069 1070 /* 1071 * XXX: Should we also check for owner != 0? 1072 */ 1073 } 1074 1075 struct conf * 1076 conf_new_from_file(const char *path, struct conf *oldconf) 1077 { 1078 struct auth_group *ag; 1079 struct portal_group *pg; 1080 struct pport *pp; 1081 int error; 1082 1083 log_debugx("obtaining configuration from %s", path); 1084 1085 conf = conf_new(); 1086 1087 TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) 1088 pport_copy(pp, conf); 1089 1090 ag = auth_group_new(conf, "default"); 1091 assert(ag != NULL); 1092 1093 ag = auth_group_new(conf, "no-authentication"); 1094 assert(ag != NULL); 1095 ag->ag_type = AG_TYPE_NO_AUTHENTICATION; 1096 1097 ag = auth_group_new(conf, "no-access"); 1098 assert(ag != NULL); 1099 ag->ag_type = AG_TYPE_DENY; 1100 1101 pg = portal_group_new(conf, "default"); 1102 assert(pg != NULL); 1103 1104 yyin = fopen(path, "r"); 1105 if (yyin == NULL) { 1106 log_warn("unable to open configuration file %s", path); 1107 conf_delete(conf); 1108 return (NULL); 1109 } 1110 check_perms(path); 1111 lineno = 1; 1112 yyrestart(yyin); 1113 error = yyparse(); 1114 auth_group = NULL; 1115 portal_group = NULL; 1116 target = NULL; 1117 lun = NULL; 1118 fclose(yyin); 1119 if (error != 0) { 1120 conf_delete(conf); 1121 return (NULL); 1122 } 1123 1124 if (conf->conf_default_ag_defined == false) { 1125 log_debugx("auth-group \"default\" not defined; " 1126 "going with defaults"); 1127 ag = auth_group_find(conf, "default"); 1128 assert(ag != NULL); 1129 ag->ag_type = AG_TYPE_DENY; 1130 } 1131 1132 if (conf->conf_default_pg_defined == false) { 1133 log_debugx("portal-group \"default\" not defined; " 1134 "going with defaults"); 1135 pg = portal_group_find(conf, "default"); 1136 assert(pg != NULL); 1137 portal_group_add_listen(pg, "0.0.0.0:3260", false); 1138 portal_group_add_listen(pg, "[::]:3260", false); 1139 } 1140 1141 conf->conf_kernel_port_on = true; 1142 1143 error = conf_verify(conf); 1144 if (error != 0) { 1145 conf_delete(conf); 1146 return (NULL); 1147 } 1148 1149 return (conf); 1150 } 1151