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 772 pp = pport_find(conf, $2); 773 if (pp == NULL) { 774 log_warnx("unknown port \"%s\" for target \"%s\"", 775 $2, target->t_name); 776 free($2); 777 return (1); 778 } 779 if (!TAILQ_EMPTY(&pp->pp_ports)) { 780 log_warnx("can't link port \"%s\" to target \"%s\", " 781 "port already linked to some target", 782 $2, target->t_name); 783 free($2); 784 return (1); 785 } 786 tp = port_new_pp(conf, target, pp); 787 if (tp == NULL) { 788 log_warnx("can't link port \"%s\" to target \"%s\"", 789 $2, target->t_name); 790 free($2); 791 return (1); 792 } 793 free($2); 794 } 795 ; 796 797 target_redirect: REDIRECT STR 798 { 799 int error; 800 801 error = target_set_redirection(target, $2); 802 free($2); 803 if (error != 0) 804 return (1); 805 } 806 ; 807 808 target_lun: LUN lun_number 809 OPENING_BRACKET lun_entries CLOSING_BRACKET 810 { 811 lun = NULL; 812 } 813 ; 814 815 lun_number: STR 816 { 817 uint64_t tmp; 818 int ret; 819 char *name; 820 821 if (expand_number($1, &tmp) != 0) { 822 yyerror("invalid numeric value"); 823 free($1); 824 return (1); 825 } 826 if (tmp >= MAX_LUNS) { 827 yyerror("LU number is too big"); 828 free($1); 829 return (1); 830 } 831 832 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp); 833 if (ret <= 0) 834 log_err(1, "asprintf"); 835 lun = lun_new(conf, name); 836 if (lun == NULL) 837 return (1); 838 839 lun_set_scsiname(lun, name); 840 target->t_luns[tmp] = lun; 841 } 842 ; 843 844 target_lun_ref: LUN STR STR 845 { 846 uint64_t tmp; 847 848 if (expand_number($2, &tmp) != 0) { 849 yyerror("invalid numeric value"); 850 free($2); 851 free($3); 852 return (1); 853 } 854 free($2); 855 if (tmp >= MAX_LUNS) { 856 yyerror("LU number is too big"); 857 free($3); 858 return (1); 859 } 860 861 lun = lun_find(conf, $3); 862 free($3); 863 if (lun == NULL) 864 return (1); 865 866 target->t_luns[tmp] = lun; 867 } 868 ; 869 870 lun_entries: 871 | 872 lun_entries lun_entry 873 | 874 lun_entries lun_entry SEMICOLON 875 ; 876 877 lun_entry: 878 lun_backend 879 | 880 lun_blocksize 881 | 882 lun_device_id 883 | 884 lun_device_type 885 | 886 lun_ctl_lun 887 | 888 lun_option 889 | 890 lun_path 891 | 892 lun_serial 893 | 894 lun_size 895 ; 896 897 lun_backend: BACKEND STR 898 { 899 if (lun->l_backend != NULL) { 900 log_warnx("backend for lun \"%s\" " 901 "specified more than once", 902 lun->l_name); 903 free($2); 904 return (1); 905 } 906 lun_set_backend(lun, $2); 907 free($2); 908 } 909 ; 910 911 lun_blocksize: BLOCKSIZE STR 912 { 913 uint64_t tmp; 914 915 if (expand_number($2, &tmp) != 0) { 916 yyerror("invalid numeric value"); 917 free($2); 918 return (1); 919 } 920 921 if (lun->l_blocksize != 0) { 922 log_warnx("blocksize for lun \"%s\" " 923 "specified more than once", 924 lun->l_name); 925 return (1); 926 } 927 lun_set_blocksize(lun, tmp); 928 } 929 ; 930 931 lun_device_id: DEVICE_ID STR 932 { 933 if (lun->l_device_id != NULL) { 934 log_warnx("device_id for lun \"%s\" " 935 "specified more than once", 936 lun->l_name); 937 free($2); 938 return (1); 939 } 940 lun_set_device_id(lun, $2); 941 free($2); 942 } 943 ; 944 945 lun_device_type: DEVICE_TYPE STR 946 { 947 uint64_t tmp; 948 949 if (strcasecmp($2, "disk") == 0 || 950 strcasecmp($2, "direct") == 0) 951 tmp = 0; 952 else if (strcasecmp($2, "processor") == 0) 953 tmp = 3; 954 else if (strcasecmp($2, "cd") == 0 || 955 strcasecmp($2, "cdrom") == 0 || 956 strcasecmp($2, "dvd") == 0 || 957 strcasecmp($2, "dvdrom") == 0) 958 tmp = 5; 959 else if (expand_number($2, &tmp) != 0 || 960 tmp > 15) { 961 yyerror("invalid numeric value"); 962 free($2); 963 return (1); 964 } 965 966 lun_set_device_type(lun, tmp); 967 } 968 ; 969 970 lun_ctl_lun: CTL_LUN STR 971 { 972 uint64_t tmp; 973 974 if (expand_number($2, &tmp) != 0) { 975 yyerror("invalid numeric value"); 976 free($2); 977 return (1); 978 } 979 980 if (lun->l_ctl_lun >= 0) { 981 log_warnx("ctl_lun for lun \"%s\" " 982 "specified more than once", 983 lun->l_name); 984 return (1); 985 } 986 lun_set_ctl_lun(lun, tmp); 987 } 988 ; 989 990 lun_option: OPTION STR STR 991 { 992 struct option *o; 993 994 o = option_new(&lun->l_options, $2, $3); 995 free($2); 996 free($3); 997 if (o == NULL) 998 return (1); 999 } 1000 ; 1001 1002 lun_path: PATH STR 1003 { 1004 if (lun->l_path != NULL) { 1005 log_warnx("path for lun \"%s\" " 1006 "specified more than once", 1007 lun->l_name); 1008 free($2); 1009 return (1); 1010 } 1011 lun_set_path(lun, $2); 1012 free($2); 1013 } 1014 ; 1015 1016 lun_serial: SERIAL STR 1017 { 1018 if (lun->l_serial != NULL) { 1019 log_warnx("serial for lun \"%s\" " 1020 "specified more than once", 1021 lun->l_name); 1022 free($2); 1023 return (1); 1024 } 1025 lun_set_serial(lun, $2); 1026 free($2); 1027 } 1028 ; 1029 1030 lun_size: SIZE STR 1031 { 1032 uint64_t tmp; 1033 1034 if (expand_number($2, &tmp) != 0) { 1035 yyerror("invalid numeric value"); 1036 free($2); 1037 return (1); 1038 } 1039 1040 if (lun->l_size != 0) { 1041 log_warnx("size for lun \"%s\" " 1042 "specified more than once", 1043 lun->l_name); 1044 return (1); 1045 } 1046 lun_set_size(lun, tmp); 1047 } 1048 ; 1049 %% 1050 1051 void 1052 yyerror(const char *str) 1053 { 1054 1055 log_warnx("error in configuration file at line %d near '%s': %s", 1056 lineno, yytext, str); 1057 } 1058 1059 int 1060 parse_conf(struct conf *newconf, const char *path) 1061 { 1062 int error; 1063 1064 conf = newconf; 1065 yyin = fopen(path, "r"); 1066 if (yyin == NULL) { 1067 log_warn("unable to open configuration file %s", path); 1068 return (1); 1069 } 1070 1071 lineno = 1; 1072 yyrestart(yyin); 1073 error = yyparse(); 1074 auth_group = NULL; 1075 portal_group = NULL; 1076 target = NULL; 1077 lun = NULL; 1078 fclose(yyin); 1079 1080 return (error); 1081 } 1082