3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * Copyright (c) 2012 The FreeBSD Foundation
8 * This software was developed by Edward Tomasz Napierala under sponsorship
9 * from the FreeBSD Foundation.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
35 #include <sys/queue.h>
36 #include <sys/types.h>
44 #include <netinet/in.h>
45 #include <netinet/ip.h>
51 static struct conf *conf = NULL;
52 static struct auth_group *auth_group = NULL;
53 static struct portal_group *portal_group = NULL;
54 static struct target *target = NULL;
55 static struct lun *lun = NULL;
57 extern void yyerror(const char *);
58 extern int yylex(void);
59 extern void yyrestart(FILE *);
63 %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
64 %token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE
65 %token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER DSCP FOREIGN
66 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
67 %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
68 %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
69 %token TAG TARGET TIMEOUT
70 %token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
71 %token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7
86 statements statement SEMICOLON
117 if (expand_number($2, &tmp) != 0) {
118 yyerror("invalid numeric value");
123 conf->conf_debug = tmp;
131 if (expand_number($2, &tmp) != 0) {
132 yyerror("invalid numeric value");
137 conf->conf_timeout = tmp;
145 if (expand_number($2, &tmp) != 0) {
146 yyerror("invalid numeric value");
151 conf->conf_maxproc = tmp;
157 if (conf->conf_pidfile_path != NULL) {
158 log_warnx("pidfile specified more than once");
162 conf->conf_pidfile_path = $2;
166 isns_server: ISNS_SERVER STR
170 error = isns_new(conf, $2);
177 isns_period: ISNS_PERIOD STR
181 if (expand_number($2, &tmp) != 0) {
182 yyerror("invalid numeric value");
187 conf->conf_isns_period = tmp;
191 isns_timeout: ISNS_TIMEOUT STR
195 if (expand_number($2, &tmp) != 0) {
196 yyerror("invalid numeric value");
201 conf->conf_isns_timeout = tmp;
205 auth_group: AUTH_GROUP auth_group_name
206 OPENING_BRACKET auth_group_entries CLOSING_BRACKET
215 * Make it possible to redefine default
216 * auth-group. but only once.
218 if (strcmp($1, "default") == 0 &&
219 conf->conf_default_ag_defined == false) {
220 auth_group = auth_group_find(conf, $1);
221 conf->conf_default_ag_defined = true;
223 auth_group = auth_group_new(conf, $1);
226 if (auth_group == NULL)
233 auth_group_entries auth_group_entry
235 auth_group_entries auth_group_entry SEMICOLON
243 auth_group_chap_mutual
245 auth_group_initiator_name
247 auth_group_initiator_portal
250 auth_group_auth_type: AUTH_TYPE STR
254 error = auth_group_set_type(auth_group, $2);
261 auth_group_chap: CHAP STR STR
263 const struct auth *ca;
265 ca = auth_new_chap(auth_group, $2, $3);
273 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
275 const struct auth *ca;
277 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
287 auth_group_initiator_name: INITIATOR_NAME STR
289 const struct auth_name *an;
291 an = auth_name_new(auth_group, $2);
298 auth_group_initiator_portal: INITIATOR_PORTAL STR
300 const struct auth_portal *ap;
302 ap = auth_portal_new(auth_group, $2);
309 portal_group: PORTAL_GROUP portal_group_name
310 OPENING_BRACKET portal_group_entries CLOSING_BRACKET
316 portal_group_name: STR
319 * Make it possible to redefine default
320 * portal-group. but only once.
322 if (strcmp($1, "default") == 0 &&
323 conf->conf_default_pg_defined == false) {
324 portal_group = portal_group_find(conf, $1);
325 conf->conf_default_pg_defined = true;
327 portal_group = portal_group_new(conf, $1);
330 if (portal_group == NULL)
335 portal_group_entries:
337 portal_group_entries portal_group_entry
339 portal_group_entries portal_group_entry SEMICOLON
343 portal_group_discovery_auth_group
345 portal_group_discovery_filter
351 portal_group_listen_iser
357 portal_group_redirect
364 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR
366 if (portal_group->pg_discovery_auth_group != NULL) {
367 log_warnx("discovery-auth-group for portal-group "
368 "\"%s\" specified more than once",
369 portal_group->pg_name);
372 portal_group->pg_discovery_auth_group =
373 auth_group_find(conf, $2);
374 if (portal_group->pg_discovery_auth_group == NULL) {
375 log_warnx("unknown discovery-auth-group \"%s\" "
376 "for portal-group \"%s\"",
377 $2, portal_group->pg_name);
384 portal_group_discovery_filter: DISCOVERY_FILTER STR
388 error = portal_group_set_filter(portal_group, $2);
395 portal_group_foreign: FOREIGN
398 portal_group->pg_foreign = 1;
402 portal_group_listen: LISTEN STR
406 error = portal_group_add_listen(portal_group, $2, false);
413 portal_group_listen_iser: LISTEN_ISER STR
417 error = portal_group_add_listen(portal_group, $2, true);
424 portal_group_offload: OFFLOAD STR
428 error = portal_group_set_offload(portal_group, $2);
435 portal_group_option: OPTION STR STR
439 o = option_new(&portal_group->pg_options, $2, $3);
447 portal_group_redirect: REDIRECT STR
451 error = portal_group_set_redirection(portal_group, $2);
458 portal_group_tag: TAG STR
462 if (expand_number($2, &tmp) != 0) {
463 yyerror("invalid numeric value");
468 portal_group->pg_tag = tmp;
477 if (strcmp($2, "0x") == 0) {
478 tmp = strtol($2 + 2, NULL, 16);
479 } else if (expand_number($2, &tmp) != 0) {
480 yyerror("invalid numeric value");
485 yyerror("invalid dscp value");
489 portal_group->pg_dscp = tmp;
491 | DSCP BE { portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2 ; }
492 | DSCP EF { portal_group->pg_dscp = IPTOS_DSCP_EF >> 2 ; }
493 | DSCP CS0 { portal_group->pg_dscp = IPTOS_DSCP_CS0 >> 2 ; }
494 | DSCP CS1 { portal_group->pg_dscp = IPTOS_DSCP_CS1 >> 2 ; }
495 | DSCP CS2 { portal_group->pg_dscp = IPTOS_DSCP_CS2 >> 2 ; }
496 | DSCP CS3 { portal_group->pg_dscp = IPTOS_DSCP_CS3 >> 2 ; }
497 | DSCP CS4 { portal_group->pg_dscp = IPTOS_DSCP_CS4 >> 2 ; }
498 | DSCP CS5 { portal_group->pg_dscp = IPTOS_DSCP_CS5 >> 2 ; }
499 | DSCP CS6 { portal_group->pg_dscp = IPTOS_DSCP_CS6 >> 2 ; }
500 | DSCP CS7 { portal_group->pg_dscp = IPTOS_DSCP_CS7 >> 2 ; }
501 | DSCP AF11 { portal_group->pg_dscp = IPTOS_DSCP_AF11 >> 2 ; }
502 | DSCP AF12 { portal_group->pg_dscp = IPTOS_DSCP_AF12 >> 2 ; }
503 | DSCP AF13 { portal_group->pg_dscp = IPTOS_DSCP_AF13 >> 2 ; }
504 | DSCP AF21 { portal_group->pg_dscp = IPTOS_DSCP_AF21 >> 2 ; }
505 | DSCP AF22 { portal_group->pg_dscp = IPTOS_DSCP_AF22 >> 2 ; }
506 | DSCP AF23 { portal_group->pg_dscp = IPTOS_DSCP_AF23 >> 2 ; }
507 | DSCP AF31 { portal_group->pg_dscp = IPTOS_DSCP_AF31 >> 2 ; }
508 | DSCP AF32 { portal_group->pg_dscp = IPTOS_DSCP_AF32 >> 2 ; }
509 | DSCP AF33 { portal_group->pg_dscp = IPTOS_DSCP_AF33 >> 2 ; }
510 | DSCP AF41 { portal_group->pg_dscp = IPTOS_DSCP_AF41 >> 2 ; }
511 | DSCP AF42 { portal_group->pg_dscp = IPTOS_DSCP_AF42 >> 2 ; }
512 | DSCP AF43 { portal_group->pg_dscp = IPTOS_DSCP_AF43 >> 2 ; }
517 OPENING_BRACKET lun_entries CLOSING_BRACKET
525 lun = lun_new(conf, $1);
532 target: TARGET target_name
533 OPENING_BRACKET target_entries CLOSING_BRACKET
541 target = target_new(conf, $1);
550 target_entries target_entry
552 target_entries target_entry SEMICOLON
566 target_initiator_name
568 target_initiator_portal
581 target_alias: ALIAS STR
583 if (target->t_alias != NULL) {
584 log_warnx("alias for target \"%s\" "
585 "specified more than once", target->t_name);
588 target->t_alias = $2;
592 target_auth_group: AUTH_GROUP STR
594 if (target->t_auth_group != NULL) {
595 if (target->t_auth_group->ag_name != NULL)
596 log_warnx("auth-group for target \"%s\" "
597 "specified more than once", target->t_name);
599 log_warnx("cannot use both auth-group and explicit "
600 "authorisations for target \"%s\"",
604 target->t_auth_group = auth_group_find(conf, $2);
605 if (target->t_auth_group == NULL) {
606 log_warnx("unknown auth-group \"%s\" for target "
607 "\"%s\"", $2, target->t_name);
614 target_auth_type: AUTH_TYPE STR
618 if (target->t_auth_group != NULL) {
619 if (target->t_auth_group->ag_name != NULL) {
620 log_warnx("cannot use both auth-group and "
621 "auth-type for target \"%s\"",
626 target->t_auth_group = auth_group_new(conf, NULL);
627 if (target->t_auth_group == NULL) {
631 target->t_auth_group->ag_target = target;
633 error = auth_group_set_type(target->t_auth_group, $2);
640 target_chap: CHAP STR STR
642 const struct auth *ca;
644 if (target->t_auth_group != NULL) {
645 if (target->t_auth_group->ag_name != NULL) {
646 log_warnx("cannot use both auth-group and "
647 "chap for target \"%s\"",
654 target->t_auth_group = auth_group_new(conf, NULL);
655 if (target->t_auth_group == NULL) {
660 target->t_auth_group->ag_target = target;
662 ca = auth_new_chap(target->t_auth_group, $2, $3);
670 target_chap_mutual: CHAP_MUTUAL STR STR STR STR
672 const struct auth *ca;
674 if (target->t_auth_group != NULL) {
675 if (target->t_auth_group->ag_name != NULL) {
676 log_warnx("cannot use both auth-group and "
677 "chap-mutual for target \"%s\"",
686 target->t_auth_group = auth_group_new(conf, NULL);
687 if (target->t_auth_group == NULL) {
694 target->t_auth_group->ag_target = target;
696 ca = auth_new_chap_mutual(target->t_auth_group,
707 target_initiator_name: INITIATOR_NAME STR
709 const struct auth_name *an;
711 if (target->t_auth_group != NULL) {
712 if (target->t_auth_group->ag_name != NULL) {
713 log_warnx("cannot use both auth-group and "
714 "initiator-name for target \"%s\"",
720 target->t_auth_group = auth_group_new(conf, NULL);
721 if (target->t_auth_group == NULL) {
725 target->t_auth_group->ag_target = target;
727 an = auth_name_new(target->t_auth_group, $2);
734 target_initiator_portal: INITIATOR_PORTAL STR
736 const struct auth_portal *ap;
738 if (target->t_auth_group != NULL) {
739 if (target->t_auth_group->ag_name != NULL) {
740 log_warnx("cannot use both auth-group and "
741 "initiator-portal for target \"%s\"",
747 target->t_auth_group = auth_group_new(conf, NULL);
748 if (target->t_auth_group == NULL) {
752 target->t_auth_group->ag_target = target;
754 ap = auth_portal_new(target->t_auth_group, $2);
761 target_portal_group: PORTAL_GROUP STR STR
763 struct portal_group *tpg;
764 struct auth_group *tag;
767 tpg = portal_group_find(conf, $2);
769 log_warnx("unknown portal-group \"%s\" for target "
770 "\"%s\"", $2, target->t_name);
775 tag = auth_group_find(conf, $3);
777 log_warnx("unknown auth-group \"%s\" for target "
778 "\"%s\"", $3, target->t_name);
783 tp = port_new(conf, target, tpg);
785 log_warnx("can't link portal-group \"%s\" to target "
786 "\"%s\"", $2, target->t_name);
790 tp->p_auth_group = tag;
796 struct portal_group *tpg;
799 tpg = portal_group_find(conf, $2);
801 log_warnx("unknown portal-group \"%s\" for target "
802 "\"%s\"", $2, target->t_name);
806 tp = port_new(conf, target, tpg);
808 log_warnx("can't link portal-group \"%s\" to target "
809 "\"%s\"", $2, target->t_name);
817 target_port: PORT STR
821 int ret, i_pp, i_vp = 0;
823 ret = sscanf($2, "ioctl/%d/%d", &i_pp, &i_vp);
825 tp = port_new_ioctl(conf, target, i_pp, i_vp);
827 log_warnx("can't create new ioctl port for "
828 "target \"%s\"", target->t_name);
833 pp = pport_find(conf, $2);
835 log_warnx("unknown port \"%s\" for target \"%s\"",
840 if (!TAILQ_EMPTY(&pp->pp_ports)) {
841 log_warnx("can't link port \"%s\" to target \"%s\", "
842 "port already linked to some target",
847 tp = port_new_pp(conf, target, pp);
849 log_warnx("can't link port \"%s\" to target \"%s\"",
860 target_redirect: REDIRECT STR
864 error = target_set_redirection(target, $2);
871 target_lun: LUN lun_number
872 OPENING_BRACKET lun_entries CLOSING_BRACKET
884 if (expand_number($1, &tmp) != 0) {
885 yyerror("invalid numeric value");
889 if (tmp >= MAX_LUNS) {
890 yyerror("LU number is too big");
895 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
897 log_err(1, "asprintf");
898 lun = lun_new(conf, name);
902 lun_set_scsiname(lun, name);
903 target->t_luns[tmp] = lun;
907 target_lun_ref: LUN STR STR
911 if (expand_number($2, &tmp) != 0) {
912 yyerror("invalid numeric value");
918 if (tmp >= MAX_LUNS) {
919 yyerror("LU number is too big");
924 lun = lun_find(conf, $3);
929 target->t_luns[tmp] = lun;
935 lun_entries lun_entry
937 lun_entries lun_entry SEMICOLON
960 lun_backend: BACKEND STR
962 if (lun->l_backend != NULL) {
963 log_warnx("backend for lun \"%s\" "
964 "specified more than once",
969 lun_set_backend(lun, $2);
974 lun_blocksize: BLOCKSIZE STR
978 if (expand_number($2, &tmp) != 0) {
979 yyerror("invalid numeric value");
984 if (lun->l_blocksize != 0) {
985 log_warnx("blocksize for lun \"%s\" "
986 "specified more than once",
990 lun_set_blocksize(lun, tmp);
994 lun_device_id: DEVICE_ID STR
996 if (lun->l_device_id != NULL) {
997 log_warnx("device_id for lun \"%s\" "
998 "specified more than once",
1003 lun_set_device_id(lun, $2);
1008 lun_device_type: DEVICE_TYPE STR
1012 if (strcasecmp($2, "disk") == 0 ||
1013 strcasecmp($2, "direct") == 0)
1015 else if (strcasecmp($2, "processor") == 0)
1017 else if (strcasecmp($2, "cd") == 0 ||
1018 strcasecmp($2, "cdrom") == 0 ||
1019 strcasecmp($2, "dvd") == 0 ||
1020 strcasecmp($2, "dvdrom") == 0)
1022 else if (expand_number($2, &tmp) != 0 ||
1024 yyerror("invalid numeric value");
1029 lun_set_device_type(lun, tmp);
1033 lun_ctl_lun: CTL_LUN STR
1037 if (expand_number($2, &tmp) != 0) {
1038 yyerror("invalid numeric value");
1043 if (lun->l_ctl_lun >= 0) {
1044 log_warnx("ctl_lun for lun \"%s\" "
1045 "specified more than once",
1049 lun_set_ctl_lun(lun, tmp);
1053 lun_option: OPTION STR STR
1057 o = option_new(&lun->l_options, $2, $3);
1067 if (lun->l_path != NULL) {
1068 log_warnx("path for lun \"%s\" "
1069 "specified more than once",
1074 lun_set_path(lun, $2);
1079 lun_serial: SERIAL STR
1081 if (lun->l_serial != NULL) {
1082 log_warnx("serial for lun \"%s\" "
1083 "specified more than once",
1088 lun_set_serial(lun, $2);
1097 if (expand_number($2, &tmp) != 0) {
1098 yyerror("invalid numeric value");
1103 if (lun->l_size != 0) {
1104 log_warnx("size for lun \"%s\" "
1105 "specified more than once",
1109 lun_set_size(lun, tmp);
1115 yyerror(const char *str)
1118 log_warnx("error in configuration file at line %d near '%s': %s",
1119 lineno, yytext, str);
1123 parse_conf(struct conf *newconf, const char *path)
1128 yyin = fopen(path, "r");
1130 log_warn("unable to open configuration file %s", path);
1138 portal_group = NULL;