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: releng/10.3/usr.sbin/ctld/parse.y 291387 2015-11-27 15:19:36Z 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 812 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp); 813 if (ret <= 0) 814 log_err(1, "asprintf"); 815 lun = lun_new(conf, name); 816 if (lun == NULL) 817 return (1); 818 819 lun_set_scsiname(lun, name); 820 target->t_luns[tmp] = lun; 821 } 822 ; 823 824target_lun_ref: LUN STR STR 825 { 826 uint64_t tmp; 827 828 if (expand_number($2, &tmp) != 0) { 829 yyerror("invalid numeric value"); 830 free($2); 831 free($3); 832 return (1); 833 } 834 free($2); 835 836 lun = lun_find(conf, $3); 837 free($3); 838 if (lun == NULL) 839 return (1); 840 841 target->t_luns[tmp] = lun; 842 } 843 ; 844 845lun_entries: 846 | 847 lun_entries lun_entry 848 | 849 lun_entries lun_entry SEMICOLON 850 ; 851 852lun_entry: 853 lun_backend 854 | 855 lun_blocksize 856 | 857 lun_device_id 858 | 859 lun_device_type 860 | 861 lun_ctl_lun 862 | 863 lun_option 864 | 865 lun_path 866 | 867 lun_serial 868 | 869 lun_size 870 ; 871 872lun_backend: BACKEND STR 873 { 874 if (lun->l_backend != NULL) { 875 log_warnx("backend for lun \"%s\" " 876 "specified more than once", 877 lun->l_name); 878 free($2); 879 return (1); 880 } 881 lun_set_backend(lun, $2); 882 free($2); 883 } 884 ; 885 886lun_blocksize: BLOCKSIZE STR 887 { 888 uint64_t tmp; 889 890 if (expand_number($2, &tmp) != 0) { 891 yyerror("invalid numeric value"); 892 free($2); 893 return (1); 894 } 895 896 if (lun->l_blocksize != 0) { 897 log_warnx("blocksize for lun \"%s\" " 898 "specified more than once", 899 lun->l_name); 900 return (1); 901 } 902 lun_set_blocksize(lun, tmp); 903 } 904 ; 905 906lun_device_id: DEVICE_ID STR 907 { 908 if (lun->l_device_id != NULL) { 909 log_warnx("device_id for lun \"%s\" " 910 "specified more than once", 911 lun->l_name); 912 free($2); 913 return (1); 914 } 915 lun_set_device_id(lun, $2); 916 free($2); 917 } 918 ; 919 920lun_device_type: DEVICE_TYPE STR 921 { 922 uint64_t tmp; 923 924 if (strcasecmp($2, "disk") == 0 || 925 strcasecmp($2, "direct") == 0) 926 tmp = 0; 927 else if (strcasecmp($2, "processor") == 0) 928 tmp = 3; 929 else if (strcasecmp($2, "cd") == 0 || 930 strcasecmp($2, "cdrom") == 0 || 931 strcasecmp($2, "dvd") == 0 || 932 strcasecmp($2, "dvdrom") == 0) 933 tmp = 5; 934 else if (expand_number($2, &tmp) != 0 || 935 tmp > 15) { 936 yyerror("invalid numeric value"); 937 free($2); 938 return (1); 939 } 940 941 lun_set_device_type(lun, tmp); 942 } 943 ; 944 945lun_ctl_lun: CTL_LUN STR 946 { 947 uint64_t tmp; 948 949 if (expand_number($2, &tmp) != 0) { 950 yyerror("invalid numeric value"); 951 free($2); 952 return (1); 953 } 954 955 if (lun->l_ctl_lun >= 0) { 956 log_warnx("ctl_lun for lun \"%s\" " 957 "specified more than once", 958 lun->l_name); 959 return (1); 960 } 961 lun_set_ctl_lun(lun, tmp); 962 } 963 ; 964 965lun_option: OPTION STR STR 966 { 967 struct option *o; 968 969 o = option_new(&lun->l_options, $2, $3); 970 free($2); 971 free($3); 972 if (o == NULL) 973 return (1); 974 } 975 ; 976 977lun_path: PATH STR 978 { 979 if (lun->l_path != NULL) { 980 log_warnx("path for lun \"%s\" " 981 "specified more than once", 982 lun->l_name); 983 free($2); 984 return (1); 985 } 986 lun_set_path(lun, $2); 987 free($2); 988 } 989 ; 990 991lun_serial: SERIAL STR 992 { 993 if (lun->l_serial != NULL) { 994 log_warnx("serial for lun \"%s\" " 995 "specified more than once", 996 lun->l_name); 997 free($2); 998 return (1); 999 } 1000 lun_set_serial(lun, $2); 1001 free($2); 1002 } 1003 ; 1004 1005lun_size: SIZE STR 1006 { 1007 uint64_t tmp; 1008 1009 if (expand_number($2, &tmp) != 0) { 1010 yyerror("invalid numeric value"); 1011 free($2); 1012 return (1); 1013 } 1014 1015 if (lun->l_size != 0) { 1016 log_warnx("size for lun \"%s\" " 1017 "specified more than once", 1018 lun->l_name); 1019 return (1); 1020 } 1021 lun_set_size(lun, tmp); 1022 } 1023 ; 1024%% 1025 1026void 1027yyerror(const char *str) 1028{ 1029 1030 log_warnx("error in configuration file at line %d near '%s': %s", 1031 lineno, yytext, str); 1032} 1033 1034static void 1035check_perms(const char *path) 1036{ 1037 struct stat sb; 1038 int error; 1039 1040 error = stat(path, &sb); 1041 if (error != 0) { 1042 log_warn("stat"); 1043 return; 1044 } 1045 if (sb.st_mode & S_IWOTH) { 1046 log_warnx("%s is world-writable", path); 1047 } else if (sb.st_mode & S_IROTH) { 1048 log_warnx("%s is world-readable", path); 1049 } else if (sb.st_mode & S_IXOTH) { 1050 /* 1051 * Ok, this one doesn't matter, but still do it, 1052 * just for consistency. 1053 */ 1054 log_warnx("%s is world-executable", path); 1055 } 1056 1057 /* 1058 * XXX: Should we also check for owner != 0? 1059 */ 1060} 1061 1062struct conf * 1063conf_new_from_file(const char *path, struct conf *oldconf) 1064{ 1065 struct auth_group *ag; 1066 struct portal_group *pg; 1067 struct pport *pp; 1068 int error; 1069 1070 log_debugx("obtaining configuration from %s", path); 1071 1072 conf = conf_new(); 1073 1074 TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) 1075 pport_copy(pp, conf); 1076 1077 ag = auth_group_new(conf, "default"); 1078 assert(ag != NULL); 1079 1080 ag = auth_group_new(conf, "no-authentication"); 1081 assert(ag != NULL); 1082 ag->ag_type = AG_TYPE_NO_AUTHENTICATION; 1083 1084 ag = auth_group_new(conf, "no-access"); 1085 assert(ag != NULL); 1086 ag->ag_type = AG_TYPE_DENY; 1087 1088 pg = portal_group_new(conf, "default"); 1089 assert(pg != NULL); 1090 1091 yyin = fopen(path, "r"); 1092 if (yyin == NULL) { 1093 log_warn("unable to open configuration file %s", path); 1094 conf_delete(conf); 1095 return (NULL); 1096 } 1097 check_perms(path); 1098 lineno = 1; 1099 yyrestart(yyin); 1100 error = yyparse(); 1101 auth_group = NULL; 1102 portal_group = NULL; 1103 target = NULL; 1104 lun = NULL; 1105 fclose(yyin); 1106 if (error != 0) { 1107 conf_delete(conf); 1108 return (NULL); 1109 } 1110 1111 if (conf->conf_default_ag_defined == false) { 1112 log_debugx("auth-group \"default\" not defined; " 1113 "going with defaults"); 1114 ag = auth_group_find(conf, "default"); 1115 assert(ag != NULL); 1116 ag->ag_type = AG_TYPE_DENY; 1117 } 1118 1119 if (conf->conf_default_pg_defined == false) { 1120 log_debugx("portal-group \"default\" not defined; " 1121 "going with defaults"); 1122 pg = portal_group_find(conf, "default"); 1123 assert(pg != NULL); 1124 portal_group_add_listen(pg, "0.0.0.0:3260", false); 1125 portal_group_add_listen(pg, "[::]:3260", false); 1126 } 1127 1128 conf->conf_kernel_port_on = true; 1129 1130 error = conf_verify(conf); 1131 if (error != 0) { 1132 conf_delete(conf); 1133 return (NULL); 1134 } 1135 1136 return (conf); 1137} 1138