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_redirect 350 | 351 portal_group_tag 352 ; 353 354 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR 355 { 356 if (portal_group->pg_discovery_auth_group != NULL) { 357 log_warnx("discovery-auth-group for portal-group " 358 "\"%s\" specified more than once", 359 portal_group->pg_name); 360 return (1); 361 } 362 portal_group->pg_discovery_auth_group = 363 auth_group_find(conf, $2); 364 if (portal_group->pg_discovery_auth_group == NULL) { 365 log_warnx("unknown discovery-auth-group \"%s\" " 366 "for portal-group \"%s\"", 367 $2, portal_group->pg_name); 368 return (1); 369 } 370 free($2); 371 } 372 ; 373 374 portal_group_discovery_filter: DISCOVERY_FILTER STR 375 { 376 int error; 377 378 error = portal_group_set_filter(portal_group, $2); 379 free($2); 380 if (error != 0) 381 return (1); 382 } 383 ; 384 385 portal_group_foreign: FOREIGN 386 { 387 388 portal_group->pg_foreign = 1; 389 } 390 ; 391 392 portal_group_listen: LISTEN STR 393 { 394 int error; 395 396 error = portal_group_add_listen(portal_group, $2, false); 397 free($2); 398 if (error != 0) 399 return (1); 400 } 401 ; 402 403 portal_group_listen_iser: LISTEN_ISER STR 404 { 405 int error; 406 407 error = portal_group_add_listen(portal_group, $2, true); 408 free($2); 409 if (error != 0) 410 return (1); 411 } 412 ; 413 414 portal_group_offload: OFFLOAD STR 415 { 416 int error; 417 418 error = portal_group_set_offload(portal_group, $2); 419 free($2); 420 if (error != 0) 421 return (1); 422 } 423 ; 424 425 portal_group_redirect: REDIRECT STR 426 { 427 int error; 428 429 error = portal_group_set_redirection(portal_group, $2); 430 free($2); 431 if (error != 0) 432 return (1); 433 } 434 ; 435 436 portal_group_tag: TAG STR 437 { 438 uint64_t tmp; 439 440 if (expand_number($2, &tmp) != 0) { 441 yyerror("invalid numeric value"); 442 free($2); 443 return (1); 444 } 445 446 portal_group->pg_tag = tmp; 447 } 448 ; 449 450 lun: LUN lun_name 451 OPENING_BRACKET lun_entries CLOSING_BRACKET 452 { 453 lun = NULL; 454 } 455 ; 456 457 lun_name: STR 458 { 459 lun = lun_new(conf, $1); 460 free($1); 461 if (lun == NULL) 462 return (1); 463 } 464 ; 465 466 target: TARGET target_name 467 OPENING_BRACKET target_entries CLOSING_BRACKET 468 { 469 target = NULL; 470 } 471 ; 472 473 target_name: STR 474 { 475 target = target_new(conf, $1); 476 free($1); 477 if (target == NULL) 478 return (1); 479 } 480 ; 481 482 target_entries: 483 | 484 target_entries target_entry 485 | 486 target_entries target_entry SEMICOLON 487 ; 488 489 target_entry: 490 target_alias 491 | 492 target_auth_group 493 | 494 target_auth_type 495 | 496 target_chap 497 | 498 target_chap_mutual 499 | 500 target_initiator_name 501 | 502 target_initiator_portal 503 | 504 target_portal_group 505 | 506 target_port 507 | 508 target_redirect 509 | 510 target_lun 511 | 512 target_lun_ref 513 ; 514 515 target_alias: ALIAS STR 516 { 517 if (target->t_alias != NULL) { 518 log_warnx("alias for target \"%s\" " 519 "specified more than once", target->t_name); 520 return (1); 521 } 522 target->t_alias = $2; 523 } 524 ; 525 526 target_auth_group: AUTH_GROUP STR 527 { 528 if (target->t_auth_group != NULL) { 529 if (target->t_auth_group->ag_name != NULL) 530 log_warnx("auth-group for target \"%s\" " 531 "specified more than once", target->t_name); 532 else 533 log_warnx("cannot use both auth-group and explicit " 534 "authorisations for target \"%s\"", 535 target->t_name); 536 return (1); 537 } 538 target->t_auth_group = auth_group_find(conf, $2); 539 if (target->t_auth_group == NULL) { 540 log_warnx("unknown auth-group \"%s\" for target " 541 "\"%s\"", $2, target->t_name); 542 return (1); 543 } 544 free($2); 545 } 546 ; 547 548 target_auth_type: AUTH_TYPE STR 549 { 550 int error; 551 552 if (target->t_auth_group != NULL) { 553 if (target->t_auth_group->ag_name != NULL) { 554 log_warnx("cannot use both auth-group and " 555 "auth-type for target \"%s\"", 556 target->t_name); 557 return (1); 558 } 559 } else { 560 target->t_auth_group = auth_group_new(conf, NULL); 561 if (target->t_auth_group == NULL) { 562 free($2); 563 return (1); 564 } 565 target->t_auth_group->ag_target = target; 566 } 567 error = auth_group_set_type(target->t_auth_group, $2); 568 free($2); 569 if (error != 0) 570 return (1); 571 } 572 ; 573 574 target_chap: CHAP STR STR 575 { 576 const struct auth *ca; 577 578 if (target->t_auth_group != NULL) { 579 if (target->t_auth_group->ag_name != NULL) { 580 log_warnx("cannot use both auth-group and " 581 "chap for target \"%s\"", 582 target->t_name); 583 free($2); 584 free($3); 585 return (1); 586 } 587 } else { 588 target->t_auth_group = auth_group_new(conf, NULL); 589 if (target->t_auth_group == NULL) { 590 free($2); 591 free($3); 592 return (1); 593 } 594 target->t_auth_group->ag_target = target; 595 } 596 ca = auth_new_chap(target->t_auth_group, $2, $3); 597 free($2); 598 free($3); 599 if (ca == NULL) 600 return (1); 601 } 602 ; 603 604 target_chap_mutual: CHAP_MUTUAL STR STR STR STR 605 { 606 const struct auth *ca; 607 608 if (target->t_auth_group != NULL) { 609 if (target->t_auth_group->ag_name != NULL) { 610 log_warnx("cannot use both auth-group and " 611 "chap-mutual for target \"%s\"", 612 target->t_name); 613 free($2); 614 free($3); 615 free($4); 616 free($5); 617 return (1); 618 } 619 } else { 620 target->t_auth_group = auth_group_new(conf, NULL); 621 if (target->t_auth_group == NULL) { 622 free($2); 623 free($3); 624 free($4); 625 free($5); 626 return (1); 627 } 628 target->t_auth_group->ag_target = target; 629 } 630 ca = auth_new_chap_mutual(target->t_auth_group, 631 $2, $3, $4, $5); 632 free($2); 633 free($3); 634 free($4); 635 free($5); 636 if (ca == NULL) 637 return (1); 638 } 639 ; 640 641 target_initiator_name: INITIATOR_NAME STR 642 { 643 const struct auth_name *an; 644 645 if (target->t_auth_group != NULL) { 646 if (target->t_auth_group->ag_name != NULL) { 647 log_warnx("cannot use both auth-group and " 648 "initiator-name for target \"%s\"", 649 target->t_name); 650 free($2); 651 return (1); 652 } 653 } else { 654 target->t_auth_group = auth_group_new(conf, NULL); 655 if (target->t_auth_group == NULL) { 656 free($2); 657 return (1); 658 } 659 target->t_auth_group->ag_target = target; 660 } 661 an = auth_name_new(target->t_auth_group, $2); 662 free($2); 663 if (an == NULL) 664 return (1); 665 } 666 ; 667 668 target_initiator_portal: INITIATOR_PORTAL STR 669 { 670 const struct auth_portal *ap; 671 672 if (target->t_auth_group != NULL) { 673 if (target->t_auth_group->ag_name != NULL) { 674 log_warnx("cannot use both auth-group and " 675 "initiator-portal for target \"%s\"", 676 target->t_name); 677 free($2); 678 return (1); 679 } 680 } else { 681 target->t_auth_group = auth_group_new(conf, NULL); 682 if (target->t_auth_group == NULL) { 683 free($2); 684 return (1); 685 } 686 target->t_auth_group->ag_target = target; 687 } 688 ap = auth_portal_new(target->t_auth_group, $2); 689 free($2); 690 if (ap == NULL) 691 return (1); 692 } 693 ; 694 695 target_portal_group: PORTAL_GROUP STR STR 696 { 697 struct portal_group *tpg; 698 struct auth_group *tag; 699 struct port *tp; 700 701 tpg = portal_group_find(conf, $2); 702 if (tpg == NULL) { 703 log_warnx("unknown portal-group \"%s\" for target " 704 "\"%s\"", $2, target->t_name); 705 free($2); 706 free($3); 707 return (1); 708 } 709 tag = auth_group_find(conf, $3); 710 if (tag == NULL) { 711 log_warnx("unknown auth-group \"%s\" for target " 712 "\"%s\"", $3, target->t_name); 713 free($2); 714 free($3); 715 return (1); 716 } 717 tp = port_new(conf, target, tpg); 718 if (tp == NULL) { 719 log_warnx("can't link portal-group \"%s\" to target " 720 "\"%s\"", $2, target->t_name); 721 free($2); 722 return (1); 723 } 724 tp->p_auth_group = tag; 725 free($2); 726 free($3); 727 } 728 | PORTAL_GROUP STR 729 { 730 struct portal_group *tpg; 731 struct port *tp; 732 733 tpg = portal_group_find(conf, $2); 734 if (tpg == NULL) { 735 log_warnx("unknown portal-group \"%s\" for target " 736 "\"%s\"", $2, target->t_name); 737 free($2); 738 return (1); 739 } 740 tp = port_new(conf, target, tpg); 741 if (tp == NULL) { 742 log_warnx("can't link portal-group \"%s\" to target " 743 "\"%s\"", $2, target->t_name); 744 free($2); 745 return (1); 746 } 747 free($2); 748 } 749 ; 750 751 target_port: PORT STR 752 { 753 struct pport *pp; 754 struct port *tp; 755 756 pp = pport_find(conf, $2); 757 if (pp == NULL) { 758 log_warnx("unknown port \"%s\" for target \"%s\"", 759 $2, target->t_name); 760 free($2); 761 return (1); 762 } 763 if (!TAILQ_EMPTY(&pp->pp_ports)) { 764 log_warnx("can't link port \"%s\" to target \"%s\", " 765 "port already linked to some target", 766 $2, target->t_name); 767 free($2); 768 return (1); 769 } 770 tp = port_new_pp(conf, target, pp); 771 if (tp == NULL) { 772 log_warnx("can't link port \"%s\" to target \"%s\"", 773 $2, target->t_name); 774 free($2); 775 return (1); 776 } 777 free($2); 778 } 779 ; 780 781 target_redirect: REDIRECT STR 782 { 783 int error; 784 785 error = target_set_redirection(target, $2); 786 free($2); 787 if (error != 0) 788 return (1); 789 } 790 ; 791 792 target_lun: LUN lun_number 793 OPENING_BRACKET lun_entries CLOSING_BRACKET 794 { 795 lun = NULL; 796 } 797 ; 798 799 lun_number: STR 800 { 801 uint64_t tmp; 802 int ret; 803 char *name; 804 805 if (expand_number($1, &tmp) != 0) { 806 yyerror("invalid numeric value"); 807 free($1); 808 return (1); 809 } 810 811 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp); 812 if (ret <= 0) 813 log_err(1, "asprintf"); 814 lun = lun_new(conf, name); 815 if (lun == NULL) 816 return (1); 817 818 lun_set_scsiname(lun, name); 819 target->t_luns[tmp] = lun; 820 } 821 ; 822 823 target_lun_ref: LUN STR STR 824 { 825 uint64_t tmp; 826 827 if (expand_number($2, &tmp) != 0) { 828 yyerror("invalid numeric value"); 829 free($2); 830 free($3); 831 return (1); 832 } 833 free($2); 834 835 lun = lun_find(conf, $3); 836 free($3); 837 if (lun == NULL) 838 return (1); 839 840 target->t_luns[tmp] = lun; 841 } 842 ; 843 844 lun_entries: 845 | 846 lun_entries lun_entry 847 | 848 lun_entries lun_entry SEMICOLON 849 ; 850 851 lun_entry: 852 lun_backend 853 | 854 lun_blocksize 855 | 856 lun_device_id 857 | 858 lun_device_type 859 | 860 lun_ctl_lun 861 | 862 lun_option 863 | 864 lun_path 865 | 866 lun_serial 867 | 868 lun_size 869 ; 870 871 lun_backend: BACKEND STR 872 { 873 if (lun->l_backend != NULL) { 874 log_warnx("backend for lun \"%s\" " 875 "specified more than once", 876 lun->l_name); 877 free($2); 878 return (1); 879 } 880 lun_set_backend(lun, $2); 881 free($2); 882 } 883 ; 884 885 lun_blocksize: BLOCKSIZE STR 886 { 887 uint64_t tmp; 888 889 if (expand_number($2, &tmp) != 0) { 890 yyerror("invalid numeric value"); 891 free($2); 892 return (1); 893 } 894 895 if (lun->l_blocksize != 0) { 896 log_warnx("blocksize for lun \"%s\" " 897 "specified more than once", 898 lun->l_name); 899 return (1); 900 } 901 lun_set_blocksize(lun, tmp); 902 } 903 ; 904 905 lun_device_id: DEVICE_ID STR 906 { 907 if (lun->l_device_id != NULL) { 908 log_warnx("device_id for lun \"%s\" " 909 "specified more than once", 910 lun->l_name); 911 free($2); 912 return (1); 913 } 914 lun_set_device_id(lun, $2); 915 free($2); 916 } 917 ; 918 919 lun_device_type: DEVICE_TYPE STR 920 { 921 uint64_t tmp; 922 923 if (strcasecmp($2, "disk") == 0 || 924 strcasecmp($2, "direct") == 0) 925 tmp = 0; 926 else if (strcasecmp($2, "processor") == 0) 927 tmp = 3; 928 else if (strcasecmp($2, "cd") == 0 || 929 strcasecmp($2, "cdrom") == 0 || 930 strcasecmp($2, "dvd") == 0 || 931 strcasecmp($2, "dvdrom") == 0) 932 tmp = 5; 933 else if (expand_number($2, &tmp) != 0 || 934 tmp > 15) { 935 yyerror("invalid numeric value"); 936 free($2); 937 return (1); 938 } 939 940 lun_set_device_type(lun, tmp); 941 } 942 ; 943 944 lun_ctl_lun: CTL_LUN STR 945 { 946 uint64_t tmp; 947 948 if (expand_number($2, &tmp) != 0) { 949 yyerror("invalid numeric value"); 950 free($2); 951 return (1); 952 } 953 954 if (lun->l_ctl_lun >= 0) { 955 log_warnx("ctl_lun for lun \"%s\" " 956 "specified more than once", 957 lun->l_name); 958 return (1); 959 } 960 lun_set_ctl_lun(lun, tmp); 961 } 962 ; 963 964 lun_option: OPTION STR STR 965 { 966 struct lun_option *clo; 967 968 clo = lun_option_new(lun, $2, $3); 969 free($2); 970 free($3); 971 if (clo == NULL) 972 return (1); 973 } 974 ; 975 976 lun_path: PATH STR 977 { 978 if (lun->l_path != NULL) { 979 log_warnx("path for lun \"%s\" " 980 "specified more than once", 981 lun->l_name); 982 free($2); 983 return (1); 984 } 985 lun_set_path(lun, $2); 986 free($2); 987 } 988 ; 989 990 lun_serial: SERIAL STR 991 { 992 if (lun->l_serial != NULL) { 993 log_warnx("serial for lun \"%s\" " 994 "specified more than once", 995 lun->l_name); 996 free($2); 997 return (1); 998 } 999 lun_set_serial(lun, $2); 1000 free($2); 1001 } 1002 ; 1003 1004 lun_size: SIZE STR 1005 { 1006 uint64_t tmp; 1007 1008 if (expand_number($2, &tmp) != 0) { 1009 yyerror("invalid numeric value"); 1010 free($2); 1011 return (1); 1012 } 1013 1014 if (lun->l_size != 0) { 1015 log_warnx("size for lun \"%s\" " 1016 "specified more than once", 1017 lun->l_name); 1018 return (1); 1019 } 1020 lun_set_size(lun, tmp); 1021 } 1022 ; 1023 %% 1024 1025 void 1026 yyerror(const char *str) 1027 { 1028 1029 log_warnx("error in configuration file at line %d near '%s': %s", 1030 lineno, yytext, str); 1031 } 1032 1033 static void 1034 check_perms(const char *path) 1035 { 1036 struct stat sb; 1037 int error; 1038 1039 error = stat(path, &sb); 1040 if (error != 0) { 1041 log_warn("stat"); 1042 return; 1043 } 1044 if (sb.st_mode & S_IWOTH) { 1045 log_warnx("%s is world-writable", path); 1046 } else if (sb.st_mode & S_IROTH) { 1047 log_warnx("%s is world-readable", path); 1048 } else if (sb.st_mode & S_IXOTH) { 1049 /* 1050 * Ok, this one doesn't matter, but still do it, 1051 * just for consistency. 1052 */ 1053 log_warnx("%s is world-executable", path); 1054 } 1055 1056 /* 1057 * XXX: Should we also check for owner != 0? 1058 */ 1059 } 1060 1061 struct conf * 1062 conf_new_from_file(const char *path, struct conf *oldconf) 1063 { 1064 struct auth_group *ag; 1065 struct portal_group *pg; 1066 struct pport *pp; 1067 int error; 1068 1069 log_debugx("obtaining configuration from %s", path); 1070 1071 conf = conf_new(); 1072 1073 TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) 1074 pport_copy(pp, conf); 1075 1076 ag = auth_group_new(conf, "default"); 1077 assert(ag != NULL); 1078 1079 ag = auth_group_new(conf, "no-authentication"); 1080 assert(ag != NULL); 1081 ag->ag_type = AG_TYPE_NO_AUTHENTICATION; 1082 1083 ag = auth_group_new(conf, "no-access"); 1084 assert(ag != NULL); 1085 ag->ag_type = AG_TYPE_DENY; 1086 1087 pg = portal_group_new(conf, "default"); 1088 assert(pg != NULL); 1089 1090 yyin = fopen(path, "r"); 1091 if (yyin == NULL) { 1092 log_warn("unable to open configuration file %s", path); 1093 conf_delete(conf); 1094 return (NULL); 1095 } 1096 check_perms(path); 1097 lineno = 1; 1098 yyrestart(yyin); 1099 error = yyparse(); 1100 auth_group = NULL; 1101 portal_group = NULL; 1102 target = NULL; 1103 lun = NULL; 1104 fclose(yyin); 1105 if (error != 0) { 1106 conf_delete(conf); 1107 return (NULL); 1108 } 1109 1110 if (conf->conf_default_ag_defined == false) { 1111 log_debugx("auth-group \"default\" not defined; " 1112 "going with defaults"); 1113 ag = auth_group_find(conf, "default"); 1114 assert(ag != NULL); 1115 ag->ag_type = AG_TYPE_DENY; 1116 } 1117 1118 if (conf->conf_default_pg_defined == false) { 1119 log_debugx("portal-group \"default\" not defined; " 1120 "going with defaults"); 1121 pg = portal_group_find(conf, "default"); 1122 assert(pg != NULL); 1123 portal_group_add_listen(pg, "0.0.0.0:3260", false); 1124 portal_group_add_listen(pg, "[::]:3260", false); 1125 } 1126 1127 conf->conf_kernel_port_on = true; 1128 1129 error = conf_verify(conf); 1130 if (error != 0) { 1131 conf_delete(conf); 1132 return (NULL); 1133 } 1134 1135 return (conf); 1136 } 1137