1 %{ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause 4 * 5 * Copyright (c) 2012 The FreeBSD Foundation 6 * 7 * This software was developed by Edward Tomasz Napierala under sponsorship 8 * from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/queue.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <assert.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "ctld.h" 41 #include <netinet/in.h> 42 #include <netinet/ip.h> 43 44 extern FILE *yyin; 45 extern char *yytext; 46 extern int lineno; 47 48 static struct conf *conf = NULL; 49 static struct auth_group *auth_group = NULL; 50 static struct portal_group *portal_group = NULL; 51 static struct target *target = NULL; 52 static struct lun *lun = NULL; 53 54 extern void yyerror(const char *); 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 DSCP 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 PCP PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL 65 %token SIZE STR TAG TARGET TIMEOUT 66 %token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43 67 %token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7 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 portal_group_dscp 358 | 359 portal_group_pcp 360 ; 361 362 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR 363 { 364 if (portal_group->pg_discovery_auth_group != NULL) { 365 log_warnx("discovery-auth-group for portal-group " 366 "\"%s\" specified more than once", 367 portal_group->pg_name); 368 return (1); 369 } 370 portal_group->pg_discovery_auth_group = 371 auth_group_find(conf, $2); 372 if (portal_group->pg_discovery_auth_group == NULL) { 373 log_warnx("unknown discovery-auth-group \"%s\" " 374 "for portal-group \"%s\"", 375 $2, portal_group->pg_name); 376 return (1); 377 } 378 free($2); 379 } 380 ; 381 382 portal_group_discovery_filter: DISCOVERY_FILTER STR 383 { 384 int error; 385 386 error = portal_group_set_filter(portal_group, $2); 387 free($2); 388 if (error != 0) 389 return (1); 390 } 391 ; 392 393 portal_group_foreign: FOREIGN 394 { 395 396 portal_group->pg_foreign = 1; 397 } 398 ; 399 400 portal_group_listen: LISTEN STR 401 { 402 int error; 403 404 error = portal_group_add_listen(portal_group, $2, false); 405 free($2); 406 if (error != 0) 407 return (1); 408 } 409 ; 410 411 portal_group_listen_iser: LISTEN_ISER STR 412 { 413 int error; 414 415 error = portal_group_add_listen(portal_group, $2, true); 416 free($2); 417 if (error != 0) 418 return (1); 419 } 420 ; 421 422 portal_group_offload: OFFLOAD STR 423 { 424 int error; 425 426 error = portal_group_set_offload(portal_group, $2); 427 free($2); 428 if (error != 0) 429 return (1); 430 } 431 ; 432 433 portal_group_option: OPTION STR STR 434 { 435 struct option *o; 436 437 o = option_new(&portal_group->pg_options, $2, $3); 438 free($2); 439 free($3); 440 if (o == NULL) 441 return (1); 442 } 443 ; 444 445 portal_group_redirect: REDIRECT STR 446 { 447 int error; 448 449 error = portal_group_set_redirection(portal_group, $2); 450 free($2); 451 if (error != 0) 452 return (1); 453 } 454 ; 455 456 portal_group_tag: TAG STR 457 { 458 uint64_t tmp; 459 460 if (expand_number($2, &tmp) != 0) { 461 yyerror("invalid numeric value"); 462 free($2); 463 return (1); 464 } 465 466 portal_group->pg_tag = tmp; 467 } 468 ; 469 470 portal_group_dscp 471 : DSCP STR 472 { 473 uint64_t tmp; 474 475 if (strcmp($2, "0x") == 0) { 476 tmp = strtol($2 + 2, NULL, 16); 477 } else if (expand_number($2, &tmp) != 0) { 478 yyerror("invalid numeric value"); 479 free($2); 480 return(1); 481 } 482 if (tmp >= 0x40) { 483 yyerror("invalid dscp value"); 484 return(1); 485 } 486 487 portal_group->pg_dscp = tmp; 488 } 489 | DSCP BE { portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2 ; } 490 | DSCP EF { portal_group->pg_dscp = IPTOS_DSCP_EF >> 2 ; } 491 | DSCP CS0 { portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2 ; } 492 | DSCP CS1 { portal_group->pg_dscp = IPTOS_DSCP_CS1 >> 2 ; } 493 | DSCP CS2 { portal_group->pg_dscp = IPTOS_DSCP_CS2 >> 2 ; } 494 | DSCP CS3 { portal_group->pg_dscp = IPTOS_DSCP_CS3 >> 2 ; } 495 | DSCP CS4 { portal_group->pg_dscp = IPTOS_DSCP_CS4 >> 2 ; } 496 | DSCP CS5 { portal_group->pg_dscp = IPTOS_DSCP_CS5 >> 2 ; } 497 | DSCP CS6 { portal_group->pg_dscp = IPTOS_DSCP_CS6 >> 2 ; } 498 | DSCP CS7 { portal_group->pg_dscp = IPTOS_DSCP_CS7 >> 2 ; } 499 | DSCP AF11 { portal_group->pg_dscp = IPTOS_DSCP_AF11 >> 2 ; } 500 | DSCP AF12 { portal_group->pg_dscp = IPTOS_DSCP_AF12 >> 2 ; } 501 | DSCP AF13 { portal_group->pg_dscp = IPTOS_DSCP_AF13 >> 2 ; } 502 | DSCP AF21 { portal_group->pg_dscp = IPTOS_DSCP_AF21 >> 2 ; } 503 | DSCP AF22 { portal_group->pg_dscp = IPTOS_DSCP_AF22 >> 2 ; } 504 | DSCP AF23 { portal_group->pg_dscp = IPTOS_DSCP_AF23 >> 2 ; } 505 | DSCP AF31 { portal_group->pg_dscp = IPTOS_DSCP_AF31 >> 2 ; } 506 | DSCP AF32 { portal_group->pg_dscp = IPTOS_DSCP_AF32 >> 2 ; } 507 | DSCP AF33 { portal_group->pg_dscp = IPTOS_DSCP_AF33 >> 2 ; } 508 | DSCP AF41 { portal_group->pg_dscp = IPTOS_DSCP_AF41 >> 2 ; } 509 | DSCP AF42 { portal_group->pg_dscp = IPTOS_DSCP_AF42 >> 2 ; } 510 | DSCP AF43 { portal_group->pg_dscp = IPTOS_DSCP_AF43 >> 2 ; } 511 ; 512 513 portal_group_pcp: PCP STR 514 { 515 uint64_t tmp; 516 517 if (expand_number($2, &tmp) != 0) { 518 yyerror("invalid numeric value"); 519 free($2); 520 return (1); 521 } 522 if (tmp > 7) { 523 yyerror("invalid pcp value"); 524 free($2); 525 return (1); 526 } 527 528 portal_group->pg_pcp = tmp; 529 } 530 ; 531 532 lun: LUN lun_name 533 OPENING_BRACKET lun_entries CLOSING_BRACKET 534 { 535 lun = NULL; 536 } 537 ; 538 539 lun_name: STR 540 { 541 lun = lun_new(conf, $1); 542 free($1); 543 if (lun == NULL) 544 return (1); 545 } 546 ; 547 548 target: TARGET target_name 549 OPENING_BRACKET target_entries CLOSING_BRACKET 550 { 551 target = NULL; 552 } 553 ; 554 555 target_name: STR 556 { 557 target = target_new(conf, $1); 558 free($1); 559 if (target == NULL) 560 return (1); 561 } 562 ; 563 564 target_entries: 565 | 566 target_entries target_entry 567 | 568 target_entries target_entry SEMICOLON 569 ; 570 571 target_entry: 572 target_alias 573 | 574 target_auth_group 575 | 576 target_auth_type 577 | 578 target_chap 579 | 580 target_chap_mutual 581 | 582 target_initiator_name 583 | 584 target_initiator_portal 585 | 586 target_portal_group 587 | 588 target_port 589 | 590 target_redirect 591 | 592 target_lun 593 | 594 target_lun_ref 595 ; 596 597 target_alias: ALIAS STR 598 { 599 if (target->t_alias != NULL) { 600 log_warnx("alias for target \"%s\" " 601 "specified more than once", target->t_name); 602 return (1); 603 } 604 target->t_alias = $2; 605 } 606 ; 607 608 target_auth_group: AUTH_GROUP STR 609 { 610 if (target->t_auth_group != NULL) { 611 if (target->t_auth_group->ag_name != NULL) 612 log_warnx("auth-group for target \"%s\" " 613 "specified more than once", target->t_name); 614 else 615 log_warnx("cannot use both auth-group and explicit " 616 "authorisations for target \"%s\"", 617 target->t_name); 618 return (1); 619 } 620 target->t_auth_group = auth_group_find(conf, $2); 621 if (target->t_auth_group == NULL) { 622 log_warnx("unknown auth-group \"%s\" for target " 623 "\"%s\"", $2, target->t_name); 624 return (1); 625 } 626 free($2); 627 } 628 ; 629 630 target_auth_type: AUTH_TYPE STR 631 { 632 int error; 633 634 if (target->t_auth_group != NULL) { 635 if (target->t_auth_group->ag_name != NULL) { 636 log_warnx("cannot use both auth-group and " 637 "auth-type for target \"%s\"", 638 target->t_name); 639 return (1); 640 } 641 } else { 642 target->t_auth_group = auth_group_new(conf, NULL); 643 if (target->t_auth_group == NULL) { 644 free($2); 645 return (1); 646 } 647 target->t_auth_group->ag_target = target; 648 } 649 error = auth_group_set_type(target->t_auth_group, $2); 650 free($2); 651 if (error != 0) 652 return (1); 653 } 654 ; 655 656 target_chap: CHAP STR STR 657 { 658 const struct auth *ca; 659 660 if (target->t_auth_group != NULL) { 661 if (target->t_auth_group->ag_name != NULL) { 662 log_warnx("cannot use both auth-group and " 663 "chap for target \"%s\"", 664 target->t_name); 665 free($2); 666 free($3); 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 free($3); 674 return (1); 675 } 676 target->t_auth_group->ag_target = target; 677 } 678 ca = auth_new_chap(target->t_auth_group, $2, $3); 679 free($2); 680 free($3); 681 if (ca == NULL) 682 return (1); 683 } 684 ; 685 686 target_chap_mutual: CHAP_MUTUAL STR STR STR STR 687 { 688 const struct auth *ca; 689 690 if (target->t_auth_group != NULL) { 691 if (target->t_auth_group->ag_name != NULL) { 692 log_warnx("cannot use both auth-group and " 693 "chap-mutual for target \"%s\"", 694 target->t_name); 695 free($2); 696 free($3); 697 free($4); 698 free($5); 699 return (1); 700 } 701 } else { 702 target->t_auth_group = auth_group_new(conf, NULL); 703 if (target->t_auth_group == NULL) { 704 free($2); 705 free($3); 706 free($4); 707 free($5); 708 return (1); 709 } 710 target->t_auth_group->ag_target = target; 711 } 712 ca = auth_new_chap_mutual(target->t_auth_group, 713 $2, $3, $4, $5); 714 free($2); 715 free($3); 716 free($4); 717 free($5); 718 if (ca == NULL) 719 return (1); 720 } 721 ; 722 723 target_initiator_name: INITIATOR_NAME STR 724 { 725 const struct auth_name *an; 726 727 if (target->t_auth_group != NULL) { 728 if (target->t_auth_group->ag_name != NULL) { 729 log_warnx("cannot use both auth-group and " 730 "initiator-name for target \"%s\"", 731 target->t_name); 732 free($2); 733 return (1); 734 } 735 } else { 736 target->t_auth_group = auth_group_new(conf, NULL); 737 if (target->t_auth_group == NULL) { 738 free($2); 739 return (1); 740 } 741 target->t_auth_group->ag_target = target; 742 } 743 an = auth_name_new(target->t_auth_group, $2); 744 free($2); 745 if (an == NULL) 746 return (1); 747 } 748 ; 749 750 target_initiator_portal: INITIATOR_PORTAL STR 751 { 752 const struct auth_portal *ap; 753 754 if (target->t_auth_group != NULL) { 755 if (target->t_auth_group->ag_name != NULL) { 756 log_warnx("cannot use both auth-group and " 757 "initiator-portal for target \"%s\"", 758 target->t_name); 759 free($2); 760 return (1); 761 } 762 } else { 763 target->t_auth_group = auth_group_new(conf, NULL); 764 if (target->t_auth_group == NULL) { 765 free($2); 766 return (1); 767 } 768 target->t_auth_group->ag_target = target; 769 } 770 ap = auth_portal_new(target->t_auth_group, $2); 771 free($2); 772 if (ap == NULL) 773 return (1); 774 } 775 ; 776 777 target_portal_group: PORTAL_GROUP STR STR 778 { 779 struct portal_group *tpg; 780 struct auth_group *tag; 781 struct port *tp; 782 783 tpg = portal_group_find(conf, $2); 784 if (tpg == NULL) { 785 log_warnx("unknown portal-group \"%s\" for target " 786 "\"%s\"", $2, target->t_name); 787 free($2); 788 free($3); 789 return (1); 790 } 791 tag = auth_group_find(conf, $3); 792 if (tag == NULL) { 793 log_warnx("unknown auth-group \"%s\" for target " 794 "\"%s\"", $3, target->t_name); 795 free($2); 796 free($3); 797 return (1); 798 } 799 tp = port_new(conf, target, tpg); 800 if (tp == NULL) { 801 log_warnx("can't link portal-group \"%s\" to target " 802 "\"%s\"", $2, target->t_name); 803 free($2); 804 return (1); 805 } 806 tp->p_auth_group = tag; 807 free($2); 808 free($3); 809 } 810 | PORTAL_GROUP STR 811 { 812 struct portal_group *tpg; 813 struct port *tp; 814 815 tpg = portal_group_find(conf, $2); 816 if (tpg == NULL) { 817 log_warnx("unknown portal-group \"%s\" for target " 818 "\"%s\"", $2, target->t_name); 819 free($2); 820 return (1); 821 } 822 tp = port_new(conf, target, tpg); 823 if (tp == NULL) { 824 log_warnx("can't link portal-group \"%s\" to target " 825 "\"%s\"", $2, target->t_name); 826 free($2); 827 return (1); 828 } 829 free($2); 830 } 831 ; 832 833 target_port: PORT STR 834 { 835 struct pport *pp; 836 struct port *tp; 837 int ret, i_pp, i_vp = 0; 838 839 ret = sscanf($2, "ioctl/%d/%d", &i_pp, &i_vp); 840 if (ret > 0) { 841 tp = port_new_ioctl(conf, target, i_pp, i_vp); 842 if (tp == NULL) { 843 log_warnx("can't create new ioctl port for " 844 "target \"%s\"", target->t_name); 845 free($2); 846 return (1); 847 } 848 } else { 849 pp = pport_find(conf, $2); 850 if (pp == NULL) { 851 log_warnx("unknown port \"%s\" for target \"%s\"", 852 $2, target->t_name); 853 free($2); 854 return (1); 855 } 856 if (!TAILQ_EMPTY(&pp->pp_ports)) { 857 log_warnx("can't link port \"%s\" to target \"%s\", " 858 "port already linked to some target", 859 $2, target->t_name); 860 free($2); 861 return (1); 862 } 863 tp = port_new_pp(conf, target, pp); 864 if (tp == NULL) { 865 log_warnx("can't link port \"%s\" to target \"%s\"", 866 $2, target->t_name); 867 free($2); 868 return (1); 869 } 870 } 871 872 free($2); 873 } 874 ; 875 876 target_redirect: REDIRECT STR 877 { 878 int error; 879 880 error = target_set_redirection(target, $2); 881 free($2); 882 if (error != 0) 883 return (1); 884 } 885 ; 886 887 target_lun: LUN lun_number 888 OPENING_BRACKET lun_entries CLOSING_BRACKET 889 { 890 lun = NULL; 891 } 892 ; 893 894 lun_number: STR 895 { 896 uint64_t tmp; 897 int ret; 898 char *name; 899 900 if (expand_number($1, &tmp) != 0) { 901 yyerror("invalid numeric value"); 902 free($1); 903 return (1); 904 } 905 if (tmp >= MAX_LUNS) { 906 yyerror("LU number is too big"); 907 free($1); 908 return (1); 909 } 910 911 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp); 912 if (ret <= 0) 913 log_err(1, "asprintf"); 914 lun = lun_new(conf, name); 915 if (lun == NULL) 916 return (1); 917 918 lun_set_scsiname(lun, name); 919 target->t_luns[tmp] = lun; 920 } 921 ; 922 923 target_lun_ref: LUN STR STR 924 { 925 uint64_t tmp; 926 927 if (expand_number($2, &tmp) != 0) { 928 yyerror("invalid numeric value"); 929 free($2); 930 free($3); 931 return (1); 932 } 933 free($2); 934 if (tmp >= MAX_LUNS) { 935 yyerror("LU number is too big"); 936 free($3); 937 return (1); 938 } 939 940 lun = lun_find(conf, $3); 941 free($3); 942 if (lun == NULL) 943 return (1); 944 945 target->t_luns[tmp] = lun; 946 } 947 ; 948 949 lun_entries: 950 | 951 lun_entries lun_entry 952 | 953 lun_entries lun_entry SEMICOLON 954 ; 955 956 lun_entry: 957 lun_backend 958 | 959 lun_blocksize 960 | 961 lun_device_id 962 | 963 lun_device_type 964 | 965 lun_ctl_lun 966 | 967 lun_option 968 | 969 lun_path 970 | 971 lun_serial 972 | 973 lun_size 974 ; 975 976 lun_backend: BACKEND STR 977 { 978 if (lun->l_backend != NULL) { 979 log_warnx("backend for lun \"%s\" " 980 "specified more than once", 981 lun->l_name); 982 free($2); 983 return (1); 984 } 985 lun_set_backend(lun, $2); 986 free($2); 987 } 988 ; 989 990 lun_blocksize: BLOCKSIZE STR 991 { 992 uint64_t tmp; 993 994 if (expand_number($2, &tmp) != 0) { 995 yyerror("invalid numeric value"); 996 free($2); 997 return (1); 998 } 999 1000 if (lun->l_blocksize != 0) { 1001 log_warnx("blocksize for lun \"%s\" " 1002 "specified more than once", 1003 lun->l_name); 1004 return (1); 1005 } 1006 lun_set_blocksize(lun, tmp); 1007 } 1008 ; 1009 1010 lun_device_id: DEVICE_ID STR 1011 { 1012 if (lun->l_device_id != NULL) { 1013 log_warnx("device_id for lun \"%s\" " 1014 "specified more than once", 1015 lun->l_name); 1016 free($2); 1017 return (1); 1018 } 1019 lun_set_device_id(lun, $2); 1020 free($2); 1021 } 1022 ; 1023 1024 lun_device_type: DEVICE_TYPE STR 1025 { 1026 uint64_t tmp; 1027 1028 if (strcasecmp($2, "disk") == 0 || 1029 strcasecmp($2, "direct") == 0) 1030 tmp = 0; 1031 else if (strcasecmp($2, "processor") == 0) 1032 tmp = 3; 1033 else if (strcasecmp($2, "cd") == 0 || 1034 strcasecmp($2, "cdrom") == 0 || 1035 strcasecmp($2, "dvd") == 0 || 1036 strcasecmp($2, "dvdrom") == 0) 1037 tmp = 5; 1038 else if (expand_number($2, &tmp) != 0 || 1039 tmp > 15) { 1040 yyerror("invalid numeric value"); 1041 free($2); 1042 return (1); 1043 } 1044 1045 lun_set_device_type(lun, tmp); 1046 } 1047 ; 1048 1049 lun_ctl_lun: CTL_LUN STR 1050 { 1051 uint64_t tmp; 1052 1053 if (expand_number($2, &tmp) != 0) { 1054 yyerror("invalid numeric value"); 1055 free($2); 1056 return (1); 1057 } 1058 1059 if (lun->l_ctl_lun >= 0) { 1060 log_warnx("ctl_lun for lun \"%s\" " 1061 "specified more than once", 1062 lun->l_name); 1063 return (1); 1064 } 1065 lun_set_ctl_lun(lun, tmp); 1066 } 1067 ; 1068 1069 lun_option: OPTION STR STR 1070 { 1071 struct option *o; 1072 1073 o = option_new(&lun->l_options, $2, $3); 1074 free($2); 1075 free($3); 1076 if (o == NULL) 1077 return (1); 1078 } 1079 ; 1080 1081 lun_path: PATH STR 1082 { 1083 if (lun->l_path != NULL) { 1084 log_warnx("path for lun \"%s\" " 1085 "specified more than once", 1086 lun->l_name); 1087 free($2); 1088 return (1); 1089 } 1090 lun_set_path(lun, $2); 1091 free($2); 1092 } 1093 ; 1094 1095 lun_serial: SERIAL STR 1096 { 1097 if (lun->l_serial != NULL) { 1098 log_warnx("serial for lun \"%s\" " 1099 "specified more than once", 1100 lun->l_name); 1101 free($2); 1102 return (1); 1103 } 1104 lun_set_serial(lun, $2); 1105 free($2); 1106 } 1107 ; 1108 1109 lun_size: SIZE STR 1110 { 1111 uint64_t tmp; 1112 1113 if (expand_number($2, &tmp) != 0) { 1114 yyerror("invalid numeric value"); 1115 free($2); 1116 return (1); 1117 } 1118 1119 if (lun->l_size != 0) { 1120 log_warnx("size for lun \"%s\" " 1121 "specified more than once", 1122 lun->l_name); 1123 return (1); 1124 } 1125 lun_set_size(lun, tmp); 1126 } 1127 ; 1128 %% 1129 1130 void 1131 yyerror(const char *str) 1132 { 1133 1134 log_warnx("error in configuration file at line %d near '%s': %s", 1135 lineno, yytext, str); 1136 } 1137 1138 int 1139 parse_conf(struct conf *newconf, const char *path) 1140 { 1141 int error; 1142 1143 conf = newconf; 1144 yyin = fopen(path, "r"); 1145 if (yyin == NULL) { 1146 log_warn("unable to open configuration file %s", path); 1147 return (1); 1148 } 1149 1150 lineno = 1; 1151 yyrestart(yyin); 1152 error = yyparse(); 1153 auth_group = NULL; 1154 portal_group = NULL; 1155 target = NULL; 1156 lun = NULL; 1157 fclose(yyin); 1158 1159 return (error); 1160 } 1161