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