]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - usr.sbin/ctld/parse.y
Document r273098, options for displaying mkimg(1) internals
[FreeBSD/releng/10.1.git] / usr.sbin / ctld / parse.y
1 %{
2 /*-
3  * Copyright (c) 2012 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by Edward Tomasz Napierala under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
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.
17  *
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
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include <sys/queue.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <assert.h>
37 #include <stdio.h>
38 #include <stdint.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include "ctld.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 int      yylex(void);
56 extern void     yyrestart(FILE *);
57
58 %}
59
60 %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
61 %token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP INITIATOR_NAME
62 %token INITIATOR_PORTAL LISTEN LISTEN_ISER LUN MAXPROC NUM OPENING_BRACKET
63 %token OPTION PATH PIDFILE PORTAL_GROUP SERIAL SIZE STR TARGET TIMEOUT
64
65 %union
66 {
67         uint64_t num;
68         char *str;
69 }
70
71 %token <num> NUM
72 %token <str> STR
73
74 %%
75
76 statements:
77         |
78         statements statement
79         ;
80
81 statement:
82         debug
83         |
84         timeout
85         |
86         maxproc
87         |
88         pidfile
89         |
90         auth_group
91         |
92         portal_group
93         |
94         target
95         ;
96
97 debug:          DEBUG NUM
98         {
99                 conf->conf_debug = $2;
100         }
101         ;
102
103 timeout:        TIMEOUT NUM
104         {
105                 conf->conf_timeout = $2;
106         }
107         ;
108
109 maxproc:        MAXPROC NUM
110         {
111                 conf->conf_maxproc = $2;
112         }
113         ;
114
115 pidfile:        PIDFILE STR
116         {
117                 if (conf->conf_pidfile_path != NULL) {
118                         log_warnx("pidfile specified more than once");
119                         free($2);
120                         return (1);
121                 }
122                 conf->conf_pidfile_path = $2;
123         }
124         ;
125
126 auth_group:     AUTH_GROUP auth_group_name
127     OPENING_BRACKET auth_group_entries CLOSING_BRACKET
128         {
129                 auth_group = NULL;
130         }
131         ;
132
133 auth_group_name:        STR
134         {
135                 /*
136                  * Make it possible to redefine default
137                  * auth-group. but only once.
138                  */
139                 if (strcmp($1, "default") == 0 &&
140                     conf->conf_default_ag_defined == false) {
141                         auth_group = auth_group_find(conf, $1);
142                         conf->conf_default_ag_defined = true;
143                 } else {
144                         auth_group = auth_group_new(conf, $1);
145                 }
146                 free($1);
147                 if (auth_group == NULL)
148                         return (1);
149         }
150         ;
151
152 auth_group_entries:
153         |
154         auth_group_entries auth_group_entry
155         ;
156
157 auth_group_entry:
158         auth_group_auth_type
159         |
160         auth_group_chap
161         |
162         auth_group_chap_mutual
163         |
164         auth_group_initiator_name
165         |
166         auth_group_initiator_portal
167         ;
168
169 auth_group_auth_type:   AUTH_TYPE STR
170         {
171                 int error;
172
173                 error = auth_group_set_type_str(auth_group, $2);
174                 free($2);
175                 if (error != 0)
176                         return (1);
177         }
178         ;
179
180 auth_group_chap:        CHAP STR STR
181         {
182                 const struct auth *ca;
183
184                 ca = auth_new_chap(auth_group, $2, $3);
185                 free($2);
186                 free($3);
187                 if (ca == NULL)
188                         return (1);
189         }
190         ;
191
192 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
193         {
194                 const struct auth *ca;
195
196                 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
197                 free($2);
198                 free($3);
199                 free($4);
200                 free($5);
201                 if (ca == NULL)
202                         return (1);
203         }
204         ;
205
206 auth_group_initiator_name:      INITIATOR_NAME STR
207         {
208                 const struct auth_name *an;
209
210                 an = auth_name_new(auth_group, $2);
211                 free($2);
212                 if (an == NULL)
213                         return (1);
214         }
215         ;
216
217 auth_group_initiator_portal:    INITIATOR_PORTAL STR
218         {
219                 const struct auth_portal *ap;
220
221                 ap = auth_portal_new(auth_group, $2);
222                 free($2);
223                 if (ap == NULL)
224                         return (1);
225         }
226         ;
227
228 portal_group:   PORTAL_GROUP portal_group_name
229     OPENING_BRACKET portal_group_entries CLOSING_BRACKET
230         {
231                 portal_group = NULL;
232         }
233         ;
234
235 portal_group_name:      STR
236         {
237                 /*
238                  * Make it possible to redefine default
239                  * portal-group. but only once.
240                  */
241                 if (strcmp($1, "default") == 0 &&
242                     conf->conf_default_pg_defined == false) {
243                         portal_group = portal_group_find(conf, $1);
244                         conf->conf_default_pg_defined = true;
245                 } else {
246                         portal_group = portal_group_new(conf, $1);
247                 }
248                 free($1);
249                 if (portal_group == NULL)
250                         return (1);
251         }
252         ;
253
254 portal_group_entries:
255         |
256         portal_group_entries portal_group_entry
257         ;
258
259 portal_group_entry:
260         portal_group_discovery_auth_group
261         |
262         portal_group_listen
263         |
264         portal_group_listen_iser
265         ;
266
267 portal_group_discovery_auth_group:      DISCOVERY_AUTH_GROUP STR
268         {
269                 if (portal_group->pg_discovery_auth_group != NULL) {
270                         log_warnx("discovery-auth-group for portal-group "
271                             "\"%s\" specified more than once",
272                             portal_group->pg_name);
273                         return (1);
274                 }
275                 portal_group->pg_discovery_auth_group =
276                     auth_group_find(conf, $2);
277                 if (portal_group->pg_discovery_auth_group == NULL) {
278                         log_warnx("unknown discovery-auth-group \"%s\" "
279                             "for portal-group \"%s\"",
280                             $2, portal_group->pg_name);
281                         return (1);
282                 }
283                 free($2);
284         }
285         ;
286
287 portal_group_listen:    LISTEN STR
288         {
289                 int error;
290
291                 error = portal_group_add_listen(portal_group, $2, false);
292                 free($2);
293                 if (error != 0)
294                         return (1);
295         }
296         ;
297
298 portal_group_listen_iser:       LISTEN_ISER STR
299         {
300                 int error;
301
302                 error = portal_group_add_listen(portal_group, $2, true);
303                 free($2);
304                 if (error != 0)
305                         return (1);
306         }
307         ;
308
309 target: TARGET target_name
310     OPENING_BRACKET target_entries CLOSING_BRACKET
311         {
312                 target = NULL;
313         }
314         ;
315
316 target_name:    STR
317         {
318                 target = target_new(conf, $1);
319                 free($1);
320                 if (target == NULL)
321                         return (1);
322         }
323         ;
324
325 target_entries:
326         |
327         target_entries target_entry
328         ;
329
330 target_entry:
331         target_alias
332         |
333         target_auth_group
334         |
335         target_auth_type
336         |
337         target_chap
338         |
339         target_chap_mutual
340         |
341         target_initiator_name
342         |
343         target_initiator_portal
344         |
345         target_portal_group
346         |
347         target_lun
348         ;
349
350 target_alias:   ALIAS STR
351         {
352                 if (target->t_alias != NULL) {
353                         log_warnx("alias for target \"%s\" "
354                             "specified more than once", target->t_name);
355                         return (1);
356                 }
357                 target->t_alias = $2;
358         }
359         ;
360
361 target_auth_group:      AUTH_GROUP STR
362         {
363                 if (target->t_auth_group != NULL) {
364                         if (target->t_auth_group->ag_name != NULL)
365                                 log_warnx("auth-group for target \"%s\" "
366                                     "specified more than once", target->t_name);
367                         else
368                                 log_warnx("cannot use both auth-group and explicit "
369                                     "authorisations for target \"%s\"",
370                                     target->t_name);
371                         return (1);
372                 }
373                 target->t_auth_group = auth_group_find(conf, $2);
374                 if (target->t_auth_group == NULL) {
375                         log_warnx("unknown auth-group \"%s\" for target "
376                             "\"%s\"", $2, target->t_name);
377                         return (1);
378                 }
379                 free($2);
380         }
381         ;
382
383 target_auth_type:       AUTH_TYPE STR
384         {
385                 int error;
386
387                 if (target->t_auth_group != NULL) {
388                         if (target->t_auth_group->ag_name != NULL) {
389                                 log_warnx("cannot use both auth-group and "
390                                     "auth-type for target \"%s\"",
391                                     target->t_name);
392                                 return (1);
393                         }
394                 } else {
395                         target->t_auth_group = auth_group_new(conf, NULL);
396                         if (target->t_auth_group == NULL) {
397                                 free($2);
398                                 return (1);
399                         }
400                         target->t_auth_group->ag_target = target;
401                 }
402                 error = auth_group_set_type_str(target->t_auth_group, $2);
403                 free($2);
404                 if (error != 0)
405                         return (1);
406         }
407         ;
408
409 target_chap:    CHAP STR STR
410         {
411                 const struct auth *ca;
412
413                 if (target->t_auth_group != NULL) {
414                         if (target->t_auth_group->ag_name != NULL) {
415                                 log_warnx("cannot use both auth-group and "
416                                     "chap for target \"%s\"",
417                                     target->t_name);
418                                 free($2);
419                                 free($3);
420                                 return (1);
421                         }
422                 } else {
423                         target->t_auth_group = auth_group_new(conf, NULL);
424                         if (target->t_auth_group == NULL) {
425                                 free($2);
426                                 free($3);
427                                 return (1);
428                         }
429                         target->t_auth_group->ag_target = target;
430                 }
431                 ca = auth_new_chap(target->t_auth_group, $2, $3);
432                 free($2);
433                 free($3);
434                 if (ca == NULL)
435                         return (1);
436         }
437         ;
438
439 target_chap_mutual:     CHAP_MUTUAL STR STR STR STR
440         {
441                 const struct auth *ca;
442
443                 if (target->t_auth_group != NULL) {
444                         if (target->t_auth_group->ag_name != NULL) {
445                                 log_warnx("cannot use both auth-group and "
446                                     "chap-mutual for target \"%s\"",
447                                     target->t_name);
448                                 free($2);
449                                 free($3);
450                                 free($4);
451                                 free($5);
452                                 return (1);
453                         }
454                 } else {
455                         target->t_auth_group = auth_group_new(conf, NULL);
456                         if (target->t_auth_group == NULL) {
457                                 free($2);
458                                 free($3);
459                                 free($4);
460                                 free($5);
461                                 return (1);
462                         }
463                         target->t_auth_group->ag_target = target;
464                 }
465                 ca = auth_new_chap_mutual(target->t_auth_group,
466                     $2, $3, $4, $5);
467                 free($2);
468                 free($3);
469                 free($4);
470                 free($5);
471                 if (ca == NULL)
472                         return (1);
473         }
474         ;
475
476 target_initiator_name:  INITIATOR_NAME STR
477         {
478                 const struct auth_name *an;
479
480                 if (target->t_auth_group != NULL) {
481                         if (target->t_auth_group->ag_name != NULL) {
482                                 log_warnx("cannot use both auth-group and "
483                                     "initiator-name for target \"%s\"",
484                                     target->t_name);
485                                 free($2);
486                                 return (1);
487                         }
488                 } else {
489                         target->t_auth_group = auth_group_new(conf, NULL);
490                         if (target->t_auth_group == NULL) {
491                                 free($2);
492                                 return (1);
493                         }
494                         target->t_auth_group->ag_target = target;
495                 }
496                 an = auth_name_new(target->t_auth_group, $2);
497                 free($2);
498                 if (an == NULL)
499                         return (1);
500         }
501         ;
502
503 target_initiator_portal:        INITIATOR_PORTAL STR
504         {
505                 const struct auth_portal *ap;
506
507                 if (target->t_auth_group != NULL) {
508                         if (target->t_auth_group->ag_name != NULL) {
509                                 log_warnx("cannot use both auth-group and "
510                                     "initiator-portal for target \"%s\"",
511                                     target->t_name);
512                                 free($2);
513                                 return (1);
514                         }
515                 } else {
516                         target->t_auth_group = auth_group_new(conf, NULL);
517                         if (target->t_auth_group == NULL) {
518                                 free($2);
519                                 return (1);
520                         }
521                         target->t_auth_group->ag_target = target;
522                 }
523                 ap = auth_portal_new(target->t_auth_group, $2);
524                 free($2);
525                 if (ap == NULL)
526                         return (1);
527         }
528         ;
529
530 target_portal_group:    PORTAL_GROUP STR
531         {
532                 if (target->t_portal_group != NULL) {
533                         log_warnx("portal-group for target \"%s\" "
534                             "specified more than once", target->t_name);
535                         free($2);
536                         return (1);
537                 }
538                 target->t_portal_group = portal_group_find(conf, $2);
539                 if (target->t_portal_group == NULL) {
540                         log_warnx("unknown portal-group \"%s\" for target "
541                             "\"%s\"", $2, target->t_name);
542                         free($2);
543                         return (1);
544                 }
545                 free($2);
546         }
547         ;
548
549 target_lun:     LUN lun_number
550     OPENING_BRACKET lun_entries CLOSING_BRACKET
551         {
552                 lun = NULL;
553         }
554         ;
555
556 lun_number:     NUM
557         {
558                 lun = lun_new(target, $1);
559                 if (lun == NULL)
560                         return (1);
561         }
562         ;
563
564 lun_entries:
565         |
566         lun_entries lun_entry
567         ;
568
569 lun_entry:
570         lun_backend
571         |
572         lun_blocksize
573         |
574         lun_device_id
575         |
576         lun_option
577         |
578         lun_path
579         |
580         lun_serial
581         |
582         lun_size
583         ;
584
585 lun_backend:    BACKEND STR
586         {
587                 if (lun->l_backend != NULL) {
588                         log_warnx("backend for lun %d, target \"%s\" "
589                             "specified more than once",
590                             lun->l_lun, target->t_name);
591                         free($2);
592                         return (1);
593                 }
594                 lun_set_backend(lun, $2);
595                 free($2);
596         }
597         ;
598
599 lun_blocksize:  BLOCKSIZE NUM
600         {
601                 if (lun->l_blocksize != 0) {
602                         log_warnx("blocksize for lun %d, target \"%s\" "
603                             "specified more than once",
604                             lun->l_lun, target->t_name);
605                         return (1);
606                 }
607                 lun_set_blocksize(lun, $2);
608         }
609         ;
610
611 lun_device_id:  DEVICE_ID STR
612         {
613                 if (lun->l_device_id != NULL) {
614                         log_warnx("device_id for lun %d, target \"%s\" "
615                             "specified more than once",
616                             lun->l_lun, target->t_name);
617                         free($2);
618                         return (1);
619                 }
620                 lun_set_device_id(lun, $2);
621                 free($2);
622         }
623         ;
624
625 lun_option:     OPTION STR STR
626         {
627                 struct lun_option *clo;
628                 
629                 clo = lun_option_new(lun, $2, $3);
630                 free($2);
631                 free($3);
632                 if (clo == NULL)
633                         return (1);
634         }
635         ;
636
637 lun_path:       PATH STR
638         {
639                 if (lun->l_path != NULL) {
640                         log_warnx("path for lun %d, target \"%s\" "
641                             "specified more than once",
642                             lun->l_lun, target->t_name);
643                         free($2);
644                         return (1);
645                 }
646                 lun_set_path(lun, $2);
647                 free($2);
648         }
649         ;
650
651 lun_serial:     SERIAL STR
652         {
653                 if (lun->l_serial != NULL) {
654                         log_warnx("serial for lun %d, target \"%s\" "
655                             "specified more than once",
656                             lun->l_lun, target->t_name);
657                         free($2);
658                         return (1);
659                 }
660                 lun_set_serial(lun, $2);
661                 free($2);
662         } |     SERIAL NUM
663         {
664                 char *str = NULL;
665
666                 if (lun->l_serial != NULL) {
667                         log_warnx("serial for lun %d, target \"%s\" "
668                             "specified more than once",
669                             lun->l_lun, target->t_name);
670                         return (1);
671                 }
672                 asprintf(&str, "%ju", $2);
673                 lun_set_serial(lun, str);
674                 free(str);
675         }
676         ;
677
678 lun_size:       SIZE NUM
679         {
680                 if (lun->l_size != 0) {
681                         log_warnx("size for lun %d, target \"%s\" "
682                             "specified more than once",
683                             lun->l_lun, target->t_name);
684                         return (1);
685                 }
686                 lun_set_size(lun, $2);
687         }
688         ;
689 %%
690
691 void
692 yyerror(const char *str)
693 {
694
695         log_warnx("error in configuration file at line %d near '%s': %s",
696             lineno, yytext, str);
697 }
698
699 static void
700 check_perms(const char *path)
701 {
702         struct stat sb;
703         int error;
704
705         error = stat(path, &sb);
706         if (error != 0) {
707                 log_warn("stat");
708                 return;
709         }
710         if (sb.st_mode & S_IWOTH) {
711                 log_warnx("%s is world-writable", path);
712         } else if (sb.st_mode & S_IROTH) {
713                 log_warnx("%s is world-readable", path);
714         } else if (sb.st_mode & S_IXOTH) {
715                 /*
716                  * Ok, this one doesn't matter, but still do it,
717                  * just for consistency.
718                  */
719                 log_warnx("%s is world-executable", path);
720         }
721
722         /*
723          * XXX: Should we also check for owner != 0?
724          */
725 }
726
727 struct conf *
728 conf_new_from_file(const char *path)
729 {
730         struct auth_group *ag;
731         struct portal_group *pg;
732         int error;
733
734         log_debugx("obtaining configuration from %s", path);
735
736         conf = conf_new();
737
738         ag = auth_group_new(conf, "default");
739         assert(ag != NULL);
740
741         ag = auth_group_new(conf, "no-authentication");
742         assert(ag != NULL);
743         ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
744
745         ag = auth_group_new(conf, "no-access");
746         assert(ag != NULL);
747         ag->ag_type = AG_TYPE_DENY;
748
749         pg = portal_group_new(conf, "default");
750         assert(pg != NULL);
751
752         yyin = fopen(path, "r");
753         if (yyin == NULL) {
754                 log_warn("unable to open configuration file %s", path);
755                 conf_delete(conf);
756                 return (NULL);
757         }
758         check_perms(path);
759         lineno = 1;
760         yyrestart(yyin);
761         error = yyparse();
762         auth_group = NULL;
763         portal_group = NULL;
764         target = NULL;
765         lun = NULL;
766         fclose(yyin);
767         if (error != 0) {
768                 conf_delete(conf);
769                 return (NULL);
770         }
771
772         if (conf->conf_default_ag_defined == false) {
773                 log_debugx("auth-group \"default\" not defined; "
774                     "going with defaults");
775                 ag = auth_group_find(conf, "default");
776                 assert(ag != NULL);
777                 ag->ag_type = AG_TYPE_DENY;
778         }
779
780         if (conf->conf_default_pg_defined == false) {
781                 log_debugx("portal-group \"default\" not defined; "
782                     "going with defaults");
783                 pg = portal_group_find(conf, "default");
784                 assert(pg != NULL);
785                 portal_group_add_listen(pg, "0.0.0.0:3260", false);
786                 portal_group_add_listen(pg, "[::]:3260", false);
787         }
788
789         conf->conf_kernel_port_on = true;
790
791         error = conf_verify(conf);
792         if (error != 0) {
793                 conf_delete(conf);
794                 return (NULL);
795         }
796
797         return (conf);
798 }