3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * Copyright (c) 2012 The FreeBSD Foundation
7 * This software was developed by Edward Tomasz Napierala under sponsorship
8 * from the FreeBSD Foundation.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
34 #include <sys/queue.h>
35 #include <sys/types.h>
43 #include <netinet/in.h>
44 #include <netinet/ip.h>
50 static struct conf *conf = NULL;
51 static struct auth_group *auth_group = NULL;
52 static struct portal_group *portal_group = NULL;
53 static struct target *target = NULL;
54 static struct lun *lun = NULL;
56 extern void yyerror(const char *);
57 extern int yylex(void);
58 extern void yyrestart(FILE *);
62 %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
63 %token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE
64 %token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER DSCP FOREIGN
65 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
66 %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
67 %token PATH PCP PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL
68 %token SIZE STR TAG TARGET TIMEOUT
69 %token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
70 %token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7
85 statements statement SEMICOLON
116 if (expand_number($2, &tmp) != 0) {
117 yyerror("invalid numeric value");
122 conf->conf_debug = tmp;
130 if (expand_number($2, &tmp) != 0) {
131 yyerror("invalid numeric value");
136 conf->conf_timeout = tmp;
144 if (expand_number($2, &tmp) != 0) {
145 yyerror("invalid numeric value");
150 conf->conf_maxproc = tmp;
156 if (conf->conf_pidfile_path != NULL) {
157 log_warnx("pidfile specified more than once");
161 conf->conf_pidfile_path = $2;
165 isns_server: ISNS_SERVER STR
169 error = isns_new(conf, $2);
176 isns_period: ISNS_PERIOD STR
180 if (expand_number($2, &tmp) != 0) {
181 yyerror("invalid numeric value");
186 conf->conf_isns_period = tmp;
190 isns_timeout: ISNS_TIMEOUT STR
194 if (expand_number($2, &tmp) != 0) {
195 yyerror("invalid numeric value");
200 conf->conf_isns_timeout = tmp;
204 auth_group: AUTH_GROUP auth_group_name
205 OPENING_BRACKET auth_group_entries CLOSING_BRACKET
214 * Make it possible to redefine default
215 * auth-group. but only once.
217 if (strcmp($1, "default") == 0 &&
218 conf->conf_default_ag_defined == false) {
219 auth_group = auth_group_find(conf, $1);
220 conf->conf_default_ag_defined = true;
222 auth_group = auth_group_new(conf, $1);
225 if (auth_group == NULL)
232 auth_group_entries auth_group_entry
234 auth_group_entries auth_group_entry SEMICOLON
242 auth_group_chap_mutual
244 auth_group_initiator_name
246 auth_group_initiator_portal
249 auth_group_auth_type: AUTH_TYPE STR
253 error = auth_group_set_type(auth_group, $2);
260 auth_group_chap: CHAP STR STR
262 const struct auth *ca;
264 ca = auth_new_chap(auth_group, $2, $3);
272 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
274 const struct auth *ca;
276 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
286 auth_group_initiator_name: INITIATOR_NAME STR
288 const struct auth_name *an;
290 an = auth_name_new(auth_group, $2);
297 auth_group_initiator_portal: INITIATOR_PORTAL STR
299 const struct auth_portal *ap;
301 ap = auth_portal_new(auth_group, $2);
308 portal_group: PORTAL_GROUP portal_group_name
309 OPENING_BRACKET portal_group_entries CLOSING_BRACKET
315 portal_group_name: STR
318 * Make it possible to redefine default
319 * portal-group. but only once.
321 if (strcmp($1, "default") == 0 &&
322 conf->conf_default_pg_defined == false) {
323 portal_group = portal_group_find(conf, $1);
324 conf->conf_default_pg_defined = true;
326 portal_group = portal_group_new(conf, $1);
329 if (portal_group == NULL)
334 portal_group_entries:
336 portal_group_entries portal_group_entry
338 portal_group_entries portal_group_entry SEMICOLON
342 portal_group_discovery_auth_group
344 portal_group_discovery_filter
350 portal_group_listen_iser
356 portal_group_redirect
365 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR
367 if (portal_group->pg_discovery_auth_group != NULL) {
368 log_warnx("discovery-auth-group for portal-group "
369 "\"%s\" specified more than once",
370 portal_group->pg_name);
373 portal_group->pg_discovery_auth_group =
374 auth_group_find(conf, $2);
375 if (portal_group->pg_discovery_auth_group == NULL) {
376 log_warnx("unknown discovery-auth-group \"%s\" "
377 "for portal-group \"%s\"",
378 $2, portal_group->pg_name);
385 portal_group_discovery_filter: DISCOVERY_FILTER STR
389 error = portal_group_set_filter(portal_group, $2);
396 portal_group_foreign: FOREIGN
399 portal_group->pg_foreign = 1;
403 portal_group_listen: LISTEN STR
407 error = portal_group_add_listen(portal_group, $2, false);
414 portal_group_listen_iser: LISTEN_ISER STR
418 error = portal_group_add_listen(portal_group, $2, true);
425 portal_group_offload: OFFLOAD STR
429 error = portal_group_set_offload(portal_group, $2);
436 portal_group_option: OPTION STR STR
440 o = option_new(&portal_group->pg_options, $2, $3);
448 portal_group_redirect: REDIRECT STR
452 error = portal_group_set_redirection(portal_group, $2);
459 portal_group_tag: TAG STR
463 if (expand_number($2, &tmp) != 0) {
464 yyerror("invalid numeric value");
469 portal_group->pg_tag = tmp;
478 if (strcmp($2, "0x") == 0) {
479 tmp = strtol($2 + 2, NULL, 16);
480 } else if (expand_number($2, &tmp) != 0) {
481 yyerror("invalid numeric value");
486 yyerror("invalid dscp value");
490 portal_group->pg_dscp = tmp;
492 | DSCP BE { portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2 ; }
493 | DSCP EF { portal_group->pg_dscp = IPTOS_DSCP_EF >> 2 ; }
494 | DSCP CS0 { portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2 ; }
495 | DSCP CS1 { portal_group->pg_dscp = IPTOS_DSCP_CS1 >> 2 ; }
496 | DSCP CS2 { portal_group->pg_dscp = IPTOS_DSCP_CS2 >> 2 ; }
497 | DSCP CS3 { portal_group->pg_dscp = IPTOS_DSCP_CS3 >> 2 ; }
498 | DSCP CS4 { portal_group->pg_dscp = IPTOS_DSCP_CS4 >> 2 ; }
499 | DSCP CS5 { portal_group->pg_dscp = IPTOS_DSCP_CS5 >> 2 ; }
500 | DSCP CS6 { portal_group->pg_dscp = IPTOS_DSCP_CS6 >> 2 ; }
501 | DSCP CS7 { portal_group->pg_dscp = IPTOS_DSCP_CS7 >> 2 ; }
502 | DSCP AF11 { portal_group->pg_dscp = IPTOS_DSCP_AF11 >> 2 ; }
503 | DSCP AF12 { portal_group->pg_dscp = IPTOS_DSCP_AF12 >> 2 ; }
504 | DSCP AF13 { portal_group->pg_dscp = IPTOS_DSCP_AF13 >> 2 ; }
505 | DSCP AF21 { portal_group->pg_dscp = IPTOS_DSCP_AF21 >> 2 ; }
506 | DSCP AF22 { portal_group->pg_dscp = IPTOS_DSCP_AF22 >> 2 ; }
507 | DSCP AF23 { portal_group->pg_dscp = IPTOS_DSCP_AF23 >> 2 ; }
508 | DSCP AF31 { portal_group->pg_dscp = IPTOS_DSCP_AF31 >> 2 ; }
509 | DSCP AF32 { portal_group->pg_dscp = IPTOS_DSCP_AF32 >> 2 ; }
510 | DSCP AF33 { portal_group->pg_dscp = IPTOS_DSCP_AF33 >> 2 ; }
511 | DSCP AF41 { portal_group->pg_dscp = IPTOS_DSCP_AF41 >> 2 ; }
512 | DSCP AF42 { portal_group->pg_dscp = IPTOS_DSCP_AF42 >> 2 ; }
513 | DSCP AF43 { portal_group->pg_dscp = IPTOS_DSCP_AF43 >> 2 ; }
516 portal_group_pcp: PCP STR
520 if (expand_number($2, &tmp) != 0) {
521 yyerror("invalid numeric value");
525 if (!((tmp >= 0) && (tmp <= 7))) {
526 yyerror("invalid pcp value");
531 portal_group->pg_pcp = tmp;
536 OPENING_BRACKET lun_entries CLOSING_BRACKET
544 lun = lun_new(conf, $1);
551 target: TARGET target_name
552 OPENING_BRACKET target_entries CLOSING_BRACKET
560 target = target_new(conf, $1);
569 target_entries target_entry
571 target_entries target_entry SEMICOLON
585 target_initiator_name
587 target_initiator_portal
600 target_alias: ALIAS STR
602 if (target->t_alias != NULL) {
603 log_warnx("alias for target \"%s\" "
604 "specified more than once", target->t_name);
607 target->t_alias = $2;
611 target_auth_group: AUTH_GROUP STR
613 if (target->t_auth_group != NULL) {
614 if (target->t_auth_group->ag_name != NULL)
615 log_warnx("auth-group for target \"%s\" "
616 "specified more than once", target->t_name);
618 log_warnx("cannot use both auth-group and explicit "
619 "authorisations for target \"%s\"",
623 target->t_auth_group = auth_group_find(conf, $2);
624 if (target->t_auth_group == NULL) {
625 log_warnx("unknown auth-group \"%s\" for target "
626 "\"%s\"", $2, target->t_name);
633 target_auth_type: AUTH_TYPE STR
637 if (target->t_auth_group != NULL) {
638 if (target->t_auth_group->ag_name != NULL) {
639 log_warnx("cannot use both auth-group and "
640 "auth-type for target \"%s\"",
645 target->t_auth_group = auth_group_new(conf, NULL);
646 if (target->t_auth_group == NULL) {
650 target->t_auth_group->ag_target = target;
652 error = auth_group_set_type(target->t_auth_group, $2);
659 target_chap: CHAP STR STR
661 const struct auth *ca;
663 if (target->t_auth_group != NULL) {
664 if (target->t_auth_group->ag_name != NULL) {
665 log_warnx("cannot use both auth-group and "
666 "chap for target \"%s\"",
673 target->t_auth_group = auth_group_new(conf, NULL);
674 if (target->t_auth_group == NULL) {
679 target->t_auth_group->ag_target = target;
681 ca = auth_new_chap(target->t_auth_group, $2, $3);
689 target_chap_mutual: CHAP_MUTUAL STR STR STR STR
691 const struct auth *ca;
693 if (target->t_auth_group != NULL) {
694 if (target->t_auth_group->ag_name != NULL) {
695 log_warnx("cannot use both auth-group and "
696 "chap-mutual for target \"%s\"",
705 target->t_auth_group = auth_group_new(conf, NULL);
706 if (target->t_auth_group == NULL) {
713 target->t_auth_group->ag_target = target;
715 ca = auth_new_chap_mutual(target->t_auth_group,
726 target_initiator_name: INITIATOR_NAME STR
728 const struct auth_name *an;
730 if (target->t_auth_group != NULL) {
731 if (target->t_auth_group->ag_name != NULL) {
732 log_warnx("cannot use both auth-group and "
733 "initiator-name for target \"%s\"",
739 target->t_auth_group = auth_group_new(conf, NULL);
740 if (target->t_auth_group == NULL) {
744 target->t_auth_group->ag_target = target;
746 an = auth_name_new(target->t_auth_group, $2);
753 target_initiator_portal: INITIATOR_PORTAL STR
755 const struct auth_portal *ap;
757 if (target->t_auth_group != NULL) {
758 if (target->t_auth_group->ag_name != NULL) {
759 log_warnx("cannot use both auth-group and "
760 "initiator-portal for target \"%s\"",
766 target->t_auth_group = auth_group_new(conf, NULL);
767 if (target->t_auth_group == NULL) {
771 target->t_auth_group->ag_target = target;
773 ap = auth_portal_new(target->t_auth_group, $2);
780 target_portal_group: PORTAL_GROUP STR STR
782 struct portal_group *tpg;
783 struct auth_group *tag;
786 tpg = portal_group_find(conf, $2);
788 log_warnx("unknown portal-group \"%s\" for target "
789 "\"%s\"", $2, target->t_name);
794 tag = auth_group_find(conf, $3);
796 log_warnx("unknown auth-group \"%s\" for target "
797 "\"%s\"", $3, target->t_name);
802 tp = port_new(conf, target, tpg);
804 log_warnx("can't link portal-group \"%s\" to target "
805 "\"%s\"", $2, target->t_name);
809 tp->p_auth_group = tag;
815 struct portal_group *tpg;
818 tpg = portal_group_find(conf, $2);
820 log_warnx("unknown portal-group \"%s\" for target "
821 "\"%s\"", $2, target->t_name);
825 tp = port_new(conf, target, tpg);
827 log_warnx("can't link portal-group \"%s\" to target "
828 "\"%s\"", $2, target->t_name);
836 target_port: PORT STR
840 int ret, i_pp, i_vp = 0;
842 ret = sscanf($2, "ioctl/%d/%d", &i_pp, &i_vp);
844 tp = port_new_ioctl(conf, target, i_pp, i_vp);
846 log_warnx("can't create new ioctl port for "
847 "target \"%s\"", target->t_name);
852 pp = pport_find(conf, $2);
854 log_warnx("unknown port \"%s\" for target \"%s\"",
859 if (!TAILQ_EMPTY(&pp->pp_ports)) {
860 log_warnx("can't link port \"%s\" to target \"%s\", "
861 "port already linked to some target",
866 tp = port_new_pp(conf, target, pp);
868 log_warnx("can't link port \"%s\" to target \"%s\"",
879 target_redirect: REDIRECT STR
883 error = target_set_redirection(target, $2);
890 target_lun: LUN lun_number
891 OPENING_BRACKET lun_entries CLOSING_BRACKET
903 if (expand_number($1, &tmp) != 0) {
904 yyerror("invalid numeric value");
908 if (tmp >= MAX_LUNS) {
909 yyerror("LU number is too big");
914 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
916 log_err(1, "asprintf");
917 lun = lun_new(conf, name);
921 lun_set_scsiname(lun, name);
922 target->t_luns[tmp] = lun;
926 target_lun_ref: LUN STR STR
930 if (expand_number($2, &tmp) != 0) {
931 yyerror("invalid numeric value");
937 if (tmp >= MAX_LUNS) {
938 yyerror("LU number is too big");
943 lun = lun_find(conf, $3);
948 target->t_luns[tmp] = lun;
954 lun_entries lun_entry
956 lun_entries lun_entry SEMICOLON
979 lun_backend: BACKEND STR
981 if (lun->l_backend != NULL) {
982 log_warnx("backend for lun \"%s\" "
983 "specified more than once",
988 lun_set_backend(lun, $2);
993 lun_blocksize: BLOCKSIZE STR
997 if (expand_number($2, &tmp) != 0) {
998 yyerror("invalid numeric value");
1003 if (lun->l_blocksize != 0) {
1004 log_warnx("blocksize for lun \"%s\" "
1005 "specified more than once",
1009 lun_set_blocksize(lun, tmp);
1013 lun_device_id: DEVICE_ID STR
1015 if (lun->l_device_id != NULL) {
1016 log_warnx("device_id for lun \"%s\" "
1017 "specified more than once",
1022 lun_set_device_id(lun, $2);
1027 lun_device_type: DEVICE_TYPE STR
1031 if (strcasecmp($2, "disk") == 0 ||
1032 strcasecmp($2, "direct") == 0)
1034 else if (strcasecmp($2, "processor") == 0)
1036 else if (strcasecmp($2, "cd") == 0 ||
1037 strcasecmp($2, "cdrom") == 0 ||
1038 strcasecmp($2, "dvd") == 0 ||
1039 strcasecmp($2, "dvdrom") == 0)
1041 else if (expand_number($2, &tmp) != 0 ||
1043 yyerror("invalid numeric value");
1048 lun_set_device_type(lun, tmp);
1052 lun_ctl_lun: CTL_LUN STR
1056 if (expand_number($2, &tmp) != 0) {
1057 yyerror("invalid numeric value");
1062 if (lun->l_ctl_lun >= 0) {
1063 log_warnx("ctl_lun for lun \"%s\" "
1064 "specified more than once",
1068 lun_set_ctl_lun(lun, tmp);
1072 lun_option: OPTION STR STR
1076 o = option_new(&lun->l_options, $2, $3);
1086 if (lun->l_path != NULL) {
1087 log_warnx("path for lun \"%s\" "
1088 "specified more than once",
1093 lun_set_path(lun, $2);
1098 lun_serial: SERIAL STR
1100 if (lun->l_serial != NULL) {
1101 log_warnx("serial for lun \"%s\" "
1102 "specified more than once",
1107 lun_set_serial(lun, $2);
1116 if (expand_number($2, &tmp) != 0) {
1117 yyerror("invalid numeric value");
1122 if (lun->l_size != 0) {
1123 log_warnx("size for lun \"%s\" "
1124 "specified more than once",
1128 lun_set_size(lun, tmp);
1134 yyerror(const char *str)
1137 log_warnx("error in configuration file at line %d near '%s': %s",
1138 lineno, yytext, str);
1142 parse_conf(struct conf *newconf, const char *path)
1147 yyin = fopen(path, "r");
1149 log_warn("unable to open configuration file %s", path);
1157 portal_group = NULL;