3 * Copyright (c) 2012 The FreeBSD Foundation
6 * This software was developed by Edward Tomasz Napierala under sponsorship
7 * from the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/queue.h>
34 #include <sys/types.h>
47 static struct conf *conf = NULL;
48 static struct auth_group *auth_group = NULL;
49 static struct portal_group *portal_group = NULL;
50 static struct target *target = NULL;
51 static struct lun *lun = NULL;
53 extern void yyerror(const char *);
54 extern int yylex(void);
55 extern void yyrestart(FILE *);
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 FOREIGN
62 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
63 %token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION
64 %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
65 %token TAG TARGET TIMEOUT
80 statements statement SEMICOLON
111 if (expand_number($2, &tmp) != 0) {
112 yyerror("invalid numeric value");
117 conf->conf_debug = tmp;
125 if (expand_number($2, &tmp) != 0) {
126 yyerror("invalid numeric value");
131 conf->conf_timeout = tmp;
139 if (expand_number($2, &tmp) != 0) {
140 yyerror("invalid numeric value");
145 conf->conf_maxproc = tmp;
151 if (conf->conf_pidfile_path != NULL) {
152 log_warnx("pidfile specified more than once");
156 conf->conf_pidfile_path = $2;
160 isns_server: ISNS_SERVER STR
164 error = isns_new(conf, $2);
171 isns_period: ISNS_PERIOD STR
175 if (expand_number($2, &tmp) != 0) {
176 yyerror("invalid numeric value");
181 conf->conf_isns_period = tmp;
185 isns_timeout: ISNS_TIMEOUT STR
189 if (expand_number($2, &tmp) != 0) {
190 yyerror("invalid numeric value");
195 conf->conf_isns_timeout = tmp;
199 auth_group: AUTH_GROUP auth_group_name
200 OPENING_BRACKET auth_group_entries CLOSING_BRACKET
209 * Make it possible to redefine default
210 * auth-group. but only once.
212 if (strcmp($1, "default") == 0 &&
213 conf->conf_default_ag_defined == false) {
214 auth_group = auth_group_find(conf, $1);
215 conf->conf_default_ag_defined = true;
217 auth_group = auth_group_new(conf, $1);
220 if (auth_group == NULL)
227 auth_group_entries auth_group_entry
229 auth_group_entries auth_group_entry SEMICOLON
237 auth_group_chap_mutual
239 auth_group_initiator_name
241 auth_group_initiator_portal
244 auth_group_auth_type: AUTH_TYPE STR
248 error = auth_group_set_type(auth_group, $2);
255 auth_group_chap: CHAP STR STR
257 const struct auth *ca;
259 ca = auth_new_chap(auth_group, $2, $3);
267 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
269 const struct auth *ca;
271 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
281 auth_group_initiator_name: INITIATOR_NAME STR
283 const struct auth_name *an;
285 an = auth_name_new(auth_group, $2);
292 auth_group_initiator_portal: INITIATOR_PORTAL STR
294 const struct auth_portal *ap;
296 ap = auth_portal_new(auth_group, $2);
303 portal_group: PORTAL_GROUP portal_group_name
304 OPENING_BRACKET portal_group_entries CLOSING_BRACKET
310 portal_group_name: STR
313 * Make it possible to redefine default
314 * portal-group. but only once.
316 if (strcmp($1, "default") == 0 &&
317 conf->conf_default_pg_defined == false) {
318 portal_group = portal_group_find(conf, $1);
319 conf->conf_default_pg_defined = true;
321 portal_group = portal_group_new(conf, $1);
324 if (portal_group == NULL)
329 portal_group_entries:
331 portal_group_entries portal_group_entry
333 portal_group_entries portal_group_entry SEMICOLON
337 portal_group_discovery_auth_group
339 portal_group_discovery_filter
345 portal_group_listen_iser
349 portal_group_redirect
354 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR
356 if (portal_group->pg_discovery_auth_group != NULL) {
357 log_warnx("discovery-auth-group for portal-group "
358 "\"%s\" specified more than once",
359 portal_group->pg_name);
362 portal_group->pg_discovery_auth_group =
363 auth_group_find(conf, $2);
364 if (portal_group->pg_discovery_auth_group == NULL) {
365 log_warnx("unknown discovery-auth-group \"%s\" "
366 "for portal-group \"%s\"",
367 $2, portal_group->pg_name);
374 portal_group_discovery_filter: DISCOVERY_FILTER STR
378 error = portal_group_set_filter(portal_group, $2);
385 portal_group_foreign: FOREIGN
388 portal_group->pg_foreign = 1;
392 portal_group_listen: LISTEN STR
396 error = portal_group_add_listen(portal_group, $2, false);
403 portal_group_listen_iser: LISTEN_ISER STR
407 error = portal_group_add_listen(portal_group, $2, true);
414 portal_group_option: OPTION STR STR
418 o = option_new(&portal_group->pg_options, $2, $3);
426 portal_group_redirect: REDIRECT STR
430 error = portal_group_set_redirection(portal_group, $2);
437 portal_group_tag: TAG STR
441 if (expand_number($2, &tmp) != 0) {
442 yyerror("invalid numeric value");
447 portal_group->pg_tag = tmp;
452 OPENING_BRACKET lun_entries CLOSING_BRACKET
460 lun = lun_new(conf, $1);
467 target: TARGET target_name
468 OPENING_BRACKET target_entries CLOSING_BRACKET
476 target = target_new(conf, $1);
485 target_entries target_entry
487 target_entries target_entry SEMICOLON
501 target_initiator_name
503 target_initiator_portal
516 target_alias: ALIAS STR
518 if (target->t_alias != NULL) {
519 log_warnx("alias for target \"%s\" "
520 "specified more than once", target->t_name);
523 target->t_alias = $2;
527 target_auth_group: AUTH_GROUP STR
529 if (target->t_auth_group != NULL) {
530 if (target->t_auth_group->ag_name != NULL)
531 log_warnx("auth-group for target \"%s\" "
532 "specified more than once", target->t_name);
534 log_warnx("cannot use both auth-group and explicit "
535 "authorisations for target \"%s\"",
539 target->t_auth_group = auth_group_find(conf, $2);
540 if (target->t_auth_group == NULL) {
541 log_warnx("unknown auth-group \"%s\" for target "
542 "\"%s\"", $2, target->t_name);
549 target_auth_type: AUTH_TYPE STR
553 if (target->t_auth_group != NULL) {
554 if (target->t_auth_group->ag_name != NULL) {
555 log_warnx("cannot use both auth-group and "
556 "auth-type for target \"%s\"",
561 target->t_auth_group = auth_group_new(conf, NULL);
562 if (target->t_auth_group == NULL) {
566 target->t_auth_group->ag_target = target;
568 error = auth_group_set_type(target->t_auth_group, $2);
575 target_chap: CHAP STR STR
577 const struct auth *ca;
579 if (target->t_auth_group != NULL) {
580 if (target->t_auth_group->ag_name != NULL) {
581 log_warnx("cannot use both auth-group and "
582 "chap for target \"%s\"",
589 target->t_auth_group = auth_group_new(conf, NULL);
590 if (target->t_auth_group == NULL) {
595 target->t_auth_group->ag_target = target;
597 ca = auth_new_chap(target->t_auth_group, $2, $3);
605 target_chap_mutual: CHAP_MUTUAL STR STR STR STR
607 const struct auth *ca;
609 if (target->t_auth_group != NULL) {
610 if (target->t_auth_group->ag_name != NULL) {
611 log_warnx("cannot use both auth-group and "
612 "chap-mutual for target \"%s\"",
621 target->t_auth_group = auth_group_new(conf, NULL);
622 if (target->t_auth_group == NULL) {
629 target->t_auth_group->ag_target = target;
631 ca = auth_new_chap_mutual(target->t_auth_group,
642 target_initiator_name: INITIATOR_NAME STR
644 const struct auth_name *an;
646 if (target->t_auth_group != NULL) {
647 if (target->t_auth_group->ag_name != NULL) {
648 log_warnx("cannot use both auth-group and "
649 "initiator-name for target \"%s\"",
655 target->t_auth_group = auth_group_new(conf, NULL);
656 if (target->t_auth_group == NULL) {
660 target->t_auth_group->ag_target = target;
662 an = auth_name_new(target->t_auth_group, $2);
669 target_initiator_portal: INITIATOR_PORTAL STR
671 const struct auth_portal *ap;
673 if (target->t_auth_group != NULL) {
674 if (target->t_auth_group->ag_name != NULL) {
675 log_warnx("cannot use both auth-group and "
676 "initiator-portal for target \"%s\"",
682 target->t_auth_group = auth_group_new(conf, NULL);
683 if (target->t_auth_group == NULL) {
687 target->t_auth_group->ag_target = target;
689 ap = auth_portal_new(target->t_auth_group, $2);
696 target_portal_group: PORTAL_GROUP STR STR
698 struct portal_group *tpg;
699 struct auth_group *tag;
702 tpg = portal_group_find(conf, $2);
704 log_warnx("unknown portal-group \"%s\" for target "
705 "\"%s\"", $2, target->t_name);
710 tag = auth_group_find(conf, $3);
712 log_warnx("unknown auth-group \"%s\" for target "
713 "\"%s\"", $3, target->t_name);
718 tp = port_new(conf, target, tpg);
720 log_warnx("can't link portal-group \"%s\" to target "
721 "\"%s\"", $2, target->t_name);
725 tp->p_auth_group = tag;
731 struct portal_group *tpg;
734 tpg = portal_group_find(conf, $2);
736 log_warnx("unknown portal-group \"%s\" for target "
737 "\"%s\"", $2, target->t_name);
741 tp = port_new(conf, target, tpg);
743 log_warnx("can't link portal-group \"%s\" to target "
744 "\"%s\"", $2, target->t_name);
752 target_port: PORT STR
757 pp = pport_find(conf, $2);
759 log_warnx("unknown port \"%s\" for target \"%s\"",
764 if (!TAILQ_EMPTY(&pp->pp_ports)) {
765 log_warnx("can't link port \"%s\" to target \"%s\", "
766 "port already linked to some target",
771 tp = port_new_pp(conf, target, pp);
773 log_warnx("can't link port \"%s\" to target \"%s\"",
782 target_redirect: REDIRECT STR
786 error = target_set_redirection(target, $2);
793 target_lun: LUN lun_number
794 OPENING_BRACKET lun_entries CLOSING_BRACKET
806 if (expand_number($1, &tmp) != 0) {
807 yyerror("invalid numeric value");
811 if (tmp >= MAX_LUNS) {
812 yyerror("LU number is too big");
817 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
819 log_err(1, "asprintf");
820 lun = lun_new(conf, name);
824 lun_set_scsiname(lun, name);
825 target->t_luns[tmp] = lun;
829 target_lun_ref: LUN STR STR
833 if (expand_number($2, &tmp) != 0) {
834 yyerror("invalid numeric value");
840 if (tmp >= MAX_LUNS) {
841 yyerror("LU number is too big");
846 lun = lun_find(conf, $3);
851 target->t_luns[tmp] = lun;
857 lun_entries lun_entry
859 lun_entries lun_entry SEMICOLON
882 lun_backend: BACKEND STR
884 if (lun->l_backend != NULL) {
885 log_warnx("backend for lun \"%s\" "
886 "specified more than once",
891 lun_set_backend(lun, $2);
896 lun_blocksize: BLOCKSIZE STR
900 if (expand_number($2, &tmp) != 0) {
901 yyerror("invalid numeric value");
906 if (lun->l_blocksize != 0) {
907 log_warnx("blocksize for lun \"%s\" "
908 "specified more than once",
912 lun_set_blocksize(lun, tmp);
916 lun_device_id: DEVICE_ID STR
918 if (lun->l_device_id != NULL) {
919 log_warnx("device_id for lun \"%s\" "
920 "specified more than once",
925 lun_set_device_id(lun, $2);
930 lun_device_type: DEVICE_TYPE STR
934 if (strcasecmp($2, "disk") == 0 ||
935 strcasecmp($2, "direct") == 0)
937 else if (strcasecmp($2, "processor") == 0)
939 else if (strcasecmp($2, "cd") == 0 ||
940 strcasecmp($2, "cdrom") == 0 ||
941 strcasecmp($2, "dvd") == 0 ||
942 strcasecmp($2, "dvdrom") == 0)
944 else if (expand_number($2, &tmp) != 0 ||
946 yyerror("invalid numeric value");
951 lun_set_device_type(lun, tmp);
955 lun_ctl_lun: CTL_LUN STR
959 if (expand_number($2, &tmp) != 0) {
960 yyerror("invalid numeric value");
965 if (lun->l_ctl_lun >= 0) {
966 log_warnx("ctl_lun for lun \"%s\" "
967 "specified more than once",
971 lun_set_ctl_lun(lun, tmp);
975 lun_option: OPTION STR STR
979 o = option_new(&lun->l_options, $2, $3);
989 if (lun->l_path != NULL) {
990 log_warnx("path for lun \"%s\" "
991 "specified more than once",
996 lun_set_path(lun, $2);
1001 lun_serial: SERIAL STR
1003 if (lun->l_serial != NULL) {
1004 log_warnx("serial for lun \"%s\" "
1005 "specified more than once",
1010 lun_set_serial(lun, $2);
1019 if (expand_number($2, &tmp) != 0) {
1020 yyerror("invalid numeric value");
1025 if (lun->l_size != 0) {
1026 log_warnx("size for lun \"%s\" "
1027 "specified more than once",
1031 lun_set_size(lun, tmp);
1037 yyerror(const char *str)
1040 log_warnx("error in configuration file at line %d near '%s': %s",
1041 lineno, yytext, str);
1045 check_perms(const char *path)
1050 error = stat(path, &sb);
1055 if (sb.st_mode & S_IWOTH) {
1056 log_warnx("%s is world-writable", path);
1057 } else if (sb.st_mode & S_IROTH) {
1058 log_warnx("%s is world-readable", path);
1059 } else if (sb.st_mode & S_IXOTH) {
1061 * Ok, this one doesn't matter, but still do it,
1062 * just for consistency.
1064 log_warnx("%s is world-executable", path);
1068 * XXX: Should we also check for owner != 0?
1073 conf_new_from_file(const char *path, struct conf *oldconf)
1075 struct auth_group *ag;
1076 struct portal_group *pg;
1080 log_debugx("obtaining configuration from %s", path);
1084 TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next)
1085 pport_copy(pp, conf);
1087 ag = auth_group_new(conf, "default");
1090 ag = auth_group_new(conf, "no-authentication");
1092 ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
1094 ag = auth_group_new(conf, "no-access");
1096 ag->ag_type = AG_TYPE_DENY;
1098 pg = portal_group_new(conf, "default");
1101 yyin = fopen(path, "r");
1103 log_warn("unable to open configuration file %s", path);
1112 portal_group = NULL;
1121 if (conf->conf_default_ag_defined == false) {
1122 log_debugx("auth-group \"default\" not defined; "
1123 "going with defaults");
1124 ag = auth_group_find(conf, "default");
1126 ag->ag_type = AG_TYPE_DENY;
1129 if (conf->conf_default_pg_defined == false) {
1130 log_debugx("portal-group \"default\" not defined; "
1131 "going with defaults");
1132 pg = portal_group_find(conf, "default");
1134 portal_group_add_listen(pg, "0.0.0.0:3260", false);
1135 portal_group_add_listen(pg, "[::]:3260", false);
1138 conf->conf_kernel_port_on = true;
1140 error = conf_verify(conf);