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