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 DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER
61 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
62 %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
63 %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
79 statements statement SEMICOLON
110 if (expand_number($2, &tmp) != 0) {
111 yyerror("invalid numeric value");
116 conf->conf_debug = tmp;
124 if (expand_number($2, &tmp) != 0) {
125 yyerror("invalid numeric value");
130 conf->conf_timeout = tmp;
138 if (expand_number($2, &tmp) != 0) {
139 yyerror("invalid numeric value");
144 conf->conf_maxproc = tmp;
150 if (conf->conf_pidfile_path != NULL) {
151 log_warnx("pidfile specified more than once");
155 conf->conf_pidfile_path = $2;
159 isns_server: ISNS_SERVER STR
163 error = isns_new(conf, $2);
170 isns_period: ISNS_PERIOD STR
174 if (expand_number($2, &tmp) != 0) {
175 yyerror("invalid numeric value");
180 conf->conf_isns_period = tmp;
184 isns_timeout: ISNS_TIMEOUT STR
188 if (expand_number($2, &tmp) != 0) {
189 yyerror("invalid numeric value");
194 conf->conf_isns_timeout = tmp;
198 auth_group: AUTH_GROUP auth_group_name
199 OPENING_BRACKET auth_group_entries CLOSING_BRACKET
208 * Make it possible to redefine default
209 * auth-group. but only once.
211 if (strcmp($1, "default") == 0 &&
212 conf->conf_default_ag_defined == false) {
213 auth_group = auth_group_find(conf, $1);
214 conf->conf_default_ag_defined = true;
216 auth_group = auth_group_new(conf, $1);
219 if (auth_group == NULL)
226 auth_group_entries auth_group_entry
228 auth_group_entries auth_group_entry SEMICOLON
236 auth_group_chap_mutual
238 auth_group_initiator_name
240 auth_group_initiator_portal
243 auth_group_auth_type: AUTH_TYPE STR
247 error = auth_group_set_type(auth_group, $2);
254 auth_group_chap: CHAP STR STR
256 const struct auth *ca;
258 ca = auth_new_chap(auth_group, $2, $3);
266 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
268 const struct auth *ca;
270 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
280 auth_group_initiator_name: INITIATOR_NAME STR
282 const struct auth_name *an;
284 an = auth_name_new(auth_group, $2);
291 auth_group_initiator_portal: INITIATOR_PORTAL STR
293 const struct auth_portal *ap;
295 ap = auth_portal_new(auth_group, $2);
302 portal_group: PORTAL_GROUP portal_group_name
303 OPENING_BRACKET portal_group_entries CLOSING_BRACKET
309 portal_group_name: STR
312 * Make it possible to redefine default
313 * portal-group. but only once.
315 if (strcmp($1, "default") == 0 &&
316 conf->conf_default_pg_defined == false) {
317 portal_group = portal_group_find(conf, $1);
318 conf->conf_default_pg_defined = true;
320 portal_group = portal_group_new(conf, $1);
323 if (portal_group == NULL)
328 portal_group_entries:
330 portal_group_entries portal_group_entry
332 portal_group_entries portal_group_entry SEMICOLON
336 portal_group_discovery_auth_group
338 portal_group_discovery_filter
342 portal_group_listen_iser
346 portal_group_redirect
349 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR
351 if (portal_group->pg_discovery_auth_group != NULL) {
352 log_warnx("discovery-auth-group for portal-group "
353 "\"%s\" specified more than once",
354 portal_group->pg_name);
357 portal_group->pg_discovery_auth_group =
358 auth_group_find(conf, $2);
359 if (portal_group->pg_discovery_auth_group == NULL) {
360 log_warnx("unknown discovery-auth-group \"%s\" "
361 "for portal-group \"%s\"",
362 $2, portal_group->pg_name);
369 portal_group_discovery_filter: DISCOVERY_FILTER STR
373 error = portal_group_set_filter(portal_group, $2);
380 portal_group_listen: LISTEN STR
384 error = portal_group_add_listen(portal_group, $2, false);
391 portal_group_listen_iser: LISTEN_ISER STR
395 error = portal_group_add_listen(portal_group, $2, true);
402 portal_group_offload: OFFLOAD STR
406 error = portal_group_set_offload(portal_group, $2);
413 portal_group_redirect: REDIRECT STR
417 error = portal_group_set_redirection(portal_group, $2);
425 OPENING_BRACKET lun_entries CLOSING_BRACKET
433 lun = lun_new(conf, $1);
440 target: TARGET target_name
441 OPENING_BRACKET target_entries CLOSING_BRACKET
449 target = target_new(conf, $1);
458 target_entries target_entry
460 target_entries target_entry SEMICOLON
474 target_initiator_name
476 target_initiator_portal
489 target_alias: ALIAS STR
491 if (target->t_alias != NULL) {
492 log_warnx("alias for target \"%s\" "
493 "specified more than once", target->t_name);
496 target->t_alias = $2;
500 target_auth_group: AUTH_GROUP STR
502 if (target->t_auth_group != NULL) {
503 if (target->t_auth_group->ag_name != NULL)
504 log_warnx("auth-group for target \"%s\" "
505 "specified more than once", target->t_name);
507 log_warnx("cannot use both auth-group and explicit "
508 "authorisations for target \"%s\"",
512 target->t_auth_group = auth_group_find(conf, $2);
513 if (target->t_auth_group == NULL) {
514 log_warnx("unknown auth-group \"%s\" for target "
515 "\"%s\"", $2, target->t_name);
522 target_auth_type: AUTH_TYPE STR
526 if (target->t_auth_group != NULL) {
527 if (target->t_auth_group->ag_name != NULL) {
528 log_warnx("cannot use both auth-group and "
529 "auth-type for target \"%s\"",
534 target->t_auth_group = auth_group_new(conf, NULL);
535 if (target->t_auth_group == NULL) {
539 target->t_auth_group->ag_target = target;
541 error = auth_group_set_type(target->t_auth_group, $2);
548 target_chap: CHAP STR STR
550 const struct auth *ca;
552 if (target->t_auth_group != NULL) {
553 if (target->t_auth_group->ag_name != NULL) {
554 log_warnx("cannot use both auth-group and "
555 "chap for target \"%s\"",
562 target->t_auth_group = auth_group_new(conf, NULL);
563 if (target->t_auth_group == NULL) {
568 target->t_auth_group->ag_target = target;
570 ca = auth_new_chap(target->t_auth_group, $2, $3);
578 target_chap_mutual: CHAP_MUTUAL STR STR STR STR
580 const struct auth *ca;
582 if (target->t_auth_group != NULL) {
583 if (target->t_auth_group->ag_name != NULL) {
584 log_warnx("cannot use both auth-group and "
585 "chap-mutual for target \"%s\"",
594 target->t_auth_group = auth_group_new(conf, NULL);
595 if (target->t_auth_group == NULL) {
602 target->t_auth_group->ag_target = target;
604 ca = auth_new_chap_mutual(target->t_auth_group,
615 target_initiator_name: INITIATOR_NAME STR
617 const struct auth_name *an;
619 if (target->t_auth_group != NULL) {
620 if (target->t_auth_group->ag_name != NULL) {
621 log_warnx("cannot use both auth-group and "
622 "initiator-name for target \"%s\"",
628 target->t_auth_group = auth_group_new(conf, NULL);
629 if (target->t_auth_group == NULL) {
633 target->t_auth_group->ag_target = target;
635 an = auth_name_new(target->t_auth_group, $2);
642 target_initiator_portal: INITIATOR_PORTAL STR
644 const struct auth_portal *ap;
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-portal 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 ap = auth_portal_new(target->t_auth_group, $2);
669 target_portal_group: PORTAL_GROUP STR STR
671 struct portal_group *tpg;
672 struct auth_group *tag;
675 tpg = portal_group_find(conf, $2);
677 log_warnx("unknown portal-group \"%s\" for target "
678 "\"%s\"", $2, target->t_name);
683 tag = auth_group_find(conf, $3);
685 log_warnx("unknown auth-group \"%s\" for target "
686 "\"%s\"", $3, target->t_name);
691 tp = port_new(conf, target, tpg);
693 log_warnx("can't link portal-group \"%s\" to target "
694 "\"%s\"", $2, target->t_name);
698 tp->p_auth_group = tag;
704 struct portal_group *tpg;
707 tpg = portal_group_find(conf, $2);
709 log_warnx("unknown portal-group \"%s\" for target "
710 "\"%s\"", $2, target->t_name);
714 tp = port_new(conf, target, tpg);
716 log_warnx("can't link portal-group \"%s\" to target "
717 "\"%s\"", $2, target->t_name);
725 target_port: PORT STR
730 pp = pport_find(conf, $2);
732 log_warnx("unknown port \"%s\" for target \"%s\"",
737 if (!TAILQ_EMPTY(&pp->pp_ports)) {
738 log_warnx("can't link port \"%s\" to target \"%s\", "
739 "port already linked to some target",
744 tp = port_new_pp(conf, target, pp);
746 log_warnx("can't link port \"%s\" to target \"%s\"",
755 target_redirect: REDIRECT STR
759 error = target_set_redirection(target, $2);
766 target_lun: LUN lun_number
767 OPENING_BRACKET lun_entries CLOSING_BRACKET
779 if (expand_number($1, &tmp) != 0) {
780 yyerror("invalid numeric value");
785 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
787 log_err(1, "asprintf");
788 lun = lun_new(conf, name);
792 lun_set_scsiname(lun, name);
793 target->t_luns[tmp] = lun;
797 target_lun_ref: LUN STR STR
801 if (expand_number($2, &tmp) != 0) {
802 yyerror("invalid numeric value");
809 lun = lun_find(conf, $3);
814 target->t_luns[tmp] = lun;
820 lun_entries lun_entry
822 lun_entries lun_entry SEMICOLON
841 lun_backend: BACKEND STR
843 if (lun->l_backend != NULL) {
844 log_warnx("backend for lun \"%s\" "
845 "specified more than once",
850 lun_set_backend(lun, $2);
855 lun_blocksize: BLOCKSIZE STR
859 if (expand_number($2, &tmp) != 0) {
860 yyerror("invalid numeric value");
865 if (lun->l_blocksize != 0) {
866 log_warnx("blocksize for lun \"%s\" "
867 "specified more than once",
871 lun_set_blocksize(lun, tmp);
875 lun_device_id: DEVICE_ID STR
877 if (lun->l_device_id != NULL) {
878 log_warnx("device_id for lun \"%s\" "
879 "specified more than once",
884 lun_set_device_id(lun, $2);
889 lun_option: OPTION STR STR
891 struct lun_option *clo;
893 clo = lun_option_new(lun, $2, $3);
903 if (lun->l_path != NULL) {
904 log_warnx("path for lun \"%s\" "
905 "specified more than once",
910 lun_set_path(lun, $2);
915 lun_serial: SERIAL STR
917 if (lun->l_serial != NULL) {
918 log_warnx("serial for lun \"%s\" "
919 "specified more than once",
924 lun_set_serial(lun, $2);
933 if (expand_number($2, &tmp) != 0) {
934 yyerror("invalid numeric value");
939 if (lun->l_size != 0) {
940 log_warnx("size for lun \"%s\" "
941 "specified more than once",
945 lun_set_size(lun, tmp);
951 yyerror(const char *str)
954 log_warnx("error in configuration file at line %d near '%s': %s",
955 lineno, yytext, str);
959 check_perms(const char *path)
964 error = stat(path, &sb);
969 if (sb.st_mode & S_IWOTH) {
970 log_warnx("%s is world-writable", path);
971 } else if (sb.st_mode & S_IROTH) {
972 log_warnx("%s is world-readable", path);
973 } else if (sb.st_mode & S_IXOTH) {
975 * Ok, this one doesn't matter, but still do it,
976 * just for consistency.
978 log_warnx("%s is world-executable", path);
982 * XXX: Should we also check for owner != 0?
987 conf_new_from_file(const char *path, struct conf *oldconf)
989 struct auth_group *ag;
990 struct portal_group *pg;
994 log_debugx("obtaining configuration from %s", path);
998 TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next)
999 pport_copy(pp, conf);
1001 ag = auth_group_new(conf, "default");
1004 ag = auth_group_new(conf, "no-authentication");
1006 ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
1008 ag = auth_group_new(conf, "no-access");
1010 ag->ag_type = AG_TYPE_DENY;
1012 pg = portal_group_new(conf, "default");
1015 yyin = fopen(path, "r");
1017 log_warn("unable to open configuration file %s", path);
1026 portal_group = NULL;
1035 if (conf->conf_default_ag_defined == false) {
1036 log_debugx("auth-group \"default\" not defined; "
1037 "going with defaults");
1038 ag = auth_group_find(conf, "default");
1040 ag->ag_type = AG_TYPE_DENY;
1043 if (conf->conf_default_pg_defined == false) {
1044 log_debugx("portal-group \"default\" not defined; "
1045 "going with defaults");
1046 pg = portal_group_find(conf, "default");
1048 portal_group_add_listen(pg, "0.0.0.0:3260", false);
1049 portal_group_add_listen(pg, "[::]:3260", false);
1052 conf->conf_kernel_port_on = true;
1054 error = conf_verify(conf);