]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ctld/parse.y
Update nvi to 2.1.3 which fixes the data corruption when locale conversion
[FreeBSD/FreeBSD.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 DISCOVERY_FILTER
62 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
63 %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
64 %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
65 %token TARGET TIMEOUT 
66
67 %union
68 {
69         char *str;
70 }
71
72 %token <str> STR
73
74 %%
75
76 statements:
77         |
78         statements statement
79         |
80         statements statement SEMICOLON
81         ;
82
83 statement:
84         debug
85         |
86         timeout
87         |
88         maxproc
89         |
90         pidfile
91         |
92         isns_server
93         |
94         isns_period
95         |
96         isns_timeout
97         |
98         auth_group
99         |
100         portal_group
101         |
102         lun
103         |
104         target
105         ;
106
107 debug:          DEBUG STR
108         {
109                 uint64_t tmp;
110
111                 if (expand_number($2, &tmp) != 0) {
112                         yyerror("invalid numeric value");
113                         free($2);
114                         return (1);
115                 }
116                         
117                 conf->conf_debug = tmp;
118         }
119         ;
120
121 timeout:        TIMEOUT STR
122         {
123                 uint64_t tmp;
124
125                 if (expand_number($2, &tmp) != 0) {
126                         yyerror("invalid numeric value");
127                         free($2);
128                         return (1);
129                 }
130
131                 conf->conf_timeout = tmp;
132         }
133         ;
134
135 maxproc:        MAXPROC STR
136         {
137                 uint64_t tmp;
138
139                 if (expand_number($2, &tmp) != 0) {
140                         yyerror("invalid numeric value");
141                         free($2);
142                         return (1);
143                 }
144
145                 conf->conf_maxproc = tmp;
146         }
147         ;
148
149 pidfile:        PIDFILE STR
150         {
151                 if (conf->conf_pidfile_path != NULL) {
152                         log_warnx("pidfile specified more than once");
153                         free($2);
154                         return (1);
155                 }
156                 conf->conf_pidfile_path = $2;
157         }
158         ;
159
160 isns_server:    ISNS_SERVER STR
161         {
162                 int error;
163
164                 error = isns_new(conf, $2);
165                 free($2);
166                 if (error != 0)
167                         return (1);
168         }
169         ;
170
171 isns_period:    ISNS_PERIOD STR
172         {
173                 uint64_t tmp;
174
175                 if (expand_number($2, &tmp) != 0) {
176                         yyerror("invalid numeric value");
177                         free($2);
178                         return (1);
179                 }
180
181                 conf->conf_isns_period = tmp;
182         }
183         ;
184
185 isns_timeout:   ISNS_TIMEOUT STR
186         {
187                 uint64_t tmp;
188
189                 if (expand_number($2, &tmp) != 0) {
190                         yyerror("invalid numeric value");
191                         free($2);
192                         return (1);
193                 }
194
195                 conf->conf_isns_timeout = tmp;
196         }
197         ;
198
199 auth_group:     AUTH_GROUP auth_group_name
200     OPENING_BRACKET auth_group_entries CLOSING_BRACKET
201         {
202                 auth_group = NULL;
203         }
204         ;
205
206 auth_group_name:        STR
207         {
208                 /*
209                  * Make it possible to redefine default
210                  * auth-group. but only once.
211                  */
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;
216                 } else {
217                         auth_group = auth_group_new(conf, $1);
218                 }
219                 free($1);
220                 if (auth_group == NULL)
221                         return (1);
222         }
223         ;
224
225 auth_group_entries:
226         |
227         auth_group_entries auth_group_entry
228         |
229         auth_group_entries auth_group_entry SEMICOLON
230         ;
231
232 auth_group_entry:
233         auth_group_auth_type
234         |
235         auth_group_chap
236         |
237         auth_group_chap_mutual
238         |
239         auth_group_initiator_name
240         |
241         auth_group_initiator_portal
242         ;
243
244 auth_group_auth_type:   AUTH_TYPE STR
245         {
246                 int error;
247
248                 error = auth_group_set_type(auth_group, $2);
249                 free($2);
250                 if (error != 0)
251                         return (1);
252         }
253         ;
254
255 auth_group_chap:        CHAP STR STR
256         {
257                 const struct auth *ca;
258
259                 ca = auth_new_chap(auth_group, $2, $3);
260                 free($2);
261                 free($3);
262                 if (ca == NULL)
263                         return (1);
264         }
265         ;
266
267 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
268         {
269                 const struct auth *ca;
270
271                 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
272                 free($2);
273                 free($3);
274                 free($4);
275                 free($5);
276                 if (ca == NULL)
277                         return (1);
278         }
279         ;
280
281 auth_group_initiator_name:      INITIATOR_NAME STR
282         {
283                 const struct auth_name *an;
284
285                 an = auth_name_new(auth_group, $2);
286                 free($2);
287                 if (an == NULL)
288                         return (1);
289         }
290         ;
291
292 auth_group_initiator_portal:    INITIATOR_PORTAL STR
293         {
294                 const struct auth_portal *ap;
295
296                 ap = auth_portal_new(auth_group, $2);
297                 free($2);
298                 if (ap == NULL)
299                         return (1);
300         }
301         ;
302
303 portal_group:   PORTAL_GROUP portal_group_name
304     OPENING_BRACKET portal_group_entries CLOSING_BRACKET
305         {
306                 portal_group = NULL;
307         }
308         ;
309
310 portal_group_name:      STR
311         {
312                 /*
313                  * Make it possible to redefine default
314                  * portal-group. but only once.
315                  */
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;
320                 } else {
321                         portal_group = portal_group_new(conf, $1);
322                 }
323                 free($1);
324                 if (portal_group == NULL)
325                         return (1);
326         }
327         ;
328
329 portal_group_entries:
330         |
331         portal_group_entries portal_group_entry
332         |
333         portal_group_entries portal_group_entry SEMICOLON
334         ;
335
336 portal_group_entry:
337         portal_group_discovery_auth_group
338         |
339         portal_group_discovery_filter
340         |
341         portal_group_listen
342         |
343         portal_group_listen_iser
344         |
345         portal_group_offload
346         |
347         portal_group_redirect
348         ;
349
350 portal_group_discovery_auth_group:      DISCOVERY_AUTH_GROUP STR
351         {
352                 if (portal_group->pg_discovery_auth_group != NULL) {
353                         log_warnx("discovery-auth-group for portal-group "
354                             "\"%s\" specified more than once",
355                             portal_group->pg_name);
356                         return (1);
357                 }
358                 portal_group->pg_discovery_auth_group =
359                     auth_group_find(conf, $2);
360                 if (portal_group->pg_discovery_auth_group == NULL) {
361                         log_warnx("unknown discovery-auth-group \"%s\" "
362                             "for portal-group \"%s\"",
363                             $2, portal_group->pg_name);
364                         return (1);
365                 }
366                 free($2);
367         }
368         ;
369
370 portal_group_discovery_filter:  DISCOVERY_FILTER STR
371         {
372                 int error;
373
374                 error = portal_group_set_filter(portal_group, $2);
375                 free($2);
376                 if (error != 0)
377                         return (1);
378         }
379         ;
380
381 portal_group_listen:    LISTEN STR
382         {
383                 int error;
384
385                 error = portal_group_add_listen(portal_group, $2, false);
386                 free($2);
387                 if (error != 0)
388                         return (1);
389         }
390         ;
391
392 portal_group_listen_iser:       LISTEN_ISER STR
393         {
394                 int error;
395
396                 error = portal_group_add_listen(portal_group, $2, true);
397                 free($2);
398                 if (error != 0)
399                         return (1);
400         }
401         ;
402
403 portal_group_offload:   OFFLOAD STR
404         {
405                 int error;
406
407                 error = portal_group_set_offload(portal_group, $2);
408                 free($2);
409                 if (error != 0)
410                         return (1);
411         }
412         ;
413
414 portal_group_redirect:  REDIRECT STR
415         {
416                 int error;
417
418                 error = portal_group_set_redirection(portal_group, $2);
419                 free($2);
420                 if (error != 0)
421                         return (1);
422         }
423         ;
424
425 lun:    LUN lun_name
426     OPENING_BRACKET lun_entries CLOSING_BRACKET
427         {
428                 lun = NULL;
429         }
430         ;
431
432 lun_name:       STR
433         {
434                 lun = lun_new(conf, $1);
435                 free($1);
436                 if (lun == NULL)
437                         return (1);
438         }
439         ;
440
441 target: TARGET target_name
442     OPENING_BRACKET target_entries CLOSING_BRACKET
443         {
444                 target = NULL;
445         }
446         ;
447
448 target_name:    STR
449         {
450                 target = target_new(conf, $1);
451                 free($1);
452                 if (target == NULL)
453                         return (1);
454         }
455         ;
456
457 target_entries:
458         |
459         target_entries target_entry
460         |
461         target_entries target_entry SEMICOLON
462         ;
463
464 target_entry:
465         target_alias
466         |
467         target_auth_group
468         |
469         target_auth_type
470         |
471         target_chap
472         |
473         target_chap_mutual
474         |
475         target_initiator_name
476         |
477         target_initiator_portal
478         |
479         target_portal_group
480         |
481         target_port
482         |
483         target_redirect
484         |
485         target_lun
486         |
487         target_lun_ref
488         ;
489
490 target_alias:   ALIAS STR
491         {
492                 if (target->t_alias != NULL) {
493                         log_warnx("alias for target \"%s\" "
494                             "specified more than once", target->t_name);
495                         return (1);
496                 }
497                 target->t_alias = $2;
498         }
499         ;
500
501 target_auth_group:      AUTH_GROUP STR
502         {
503                 if (target->t_auth_group != NULL) {
504                         if (target->t_auth_group->ag_name != NULL)
505                                 log_warnx("auth-group for target \"%s\" "
506                                     "specified more than once", target->t_name);
507                         else
508                                 log_warnx("cannot use both auth-group and explicit "
509                                     "authorisations for target \"%s\"",
510                                     target->t_name);
511                         return (1);
512                 }
513                 target->t_auth_group = auth_group_find(conf, $2);
514                 if (target->t_auth_group == NULL) {
515                         log_warnx("unknown auth-group \"%s\" for target "
516                             "\"%s\"", $2, target->t_name);
517                         return (1);
518                 }
519                 free($2);
520         }
521         ;
522
523 target_auth_type:       AUTH_TYPE STR
524         {
525                 int error;
526
527                 if (target->t_auth_group != NULL) {
528                         if (target->t_auth_group->ag_name != NULL) {
529                                 log_warnx("cannot use both auth-group and "
530                                     "auth-type for target \"%s\"",
531                                     target->t_name);
532                                 return (1);
533                         }
534                 } else {
535                         target->t_auth_group = auth_group_new(conf, NULL);
536                         if (target->t_auth_group == NULL) {
537                                 free($2);
538                                 return (1);
539                         }
540                         target->t_auth_group->ag_target = target;
541                 }
542                 error = auth_group_set_type(target->t_auth_group, $2);
543                 free($2);
544                 if (error != 0)
545                         return (1);
546         }
547         ;
548
549 target_chap:    CHAP STR STR
550         {
551                 const struct auth *ca;
552
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                                     "chap for target \"%s\"",
557                                     target->t_name);
558                                 free($2);
559                                 free($3);
560                                 return (1);
561                         }
562                 } else {
563                         target->t_auth_group = auth_group_new(conf, NULL);
564                         if (target->t_auth_group == NULL) {
565                                 free($2);
566                                 free($3);
567                                 return (1);
568                         }
569                         target->t_auth_group->ag_target = target;
570                 }
571                 ca = auth_new_chap(target->t_auth_group, $2, $3);
572                 free($2);
573                 free($3);
574                 if (ca == NULL)
575                         return (1);
576         }
577         ;
578
579 target_chap_mutual:     CHAP_MUTUAL STR STR STR STR
580         {
581                 const struct auth *ca;
582
583                 if (target->t_auth_group != NULL) {
584                         if (target->t_auth_group->ag_name != NULL) {
585                                 log_warnx("cannot use both auth-group and "
586                                     "chap-mutual for target \"%s\"",
587                                     target->t_name);
588                                 free($2);
589                                 free($3);
590                                 free($4);
591                                 free($5);
592                                 return (1);
593                         }
594                 } else {
595                         target->t_auth_group = auth_group_new(conf, NULL);
596                         if (target->t_auth_group == NULL) {
597                                 free($2);
598                                 free($3);
599                                 free($4);
600                                 free($5);
601                                 return (1);
602                         }
603                         target->t_auth_group->ag_target = target;
604                 }
605                 ca = auth_new_chap_mutual(target->t_auth_group,
606                     $2, $3, $4, $5);
607                 free($2);
608                 free($3);
609                 free($4);
610                 free($5);
611                 if (ca == NULL)
612                         return (1);
613         }
614         ;
615
616 target_initiator_name:  INITIATOR_NAME STR
617         {
618                 const struct auth_name *an;
619
620                 if (target->t_auth_group != NULL) {
621                         if (target->t_auth_group->ag_name != NULL) {
622                                 log_warnx("cannot use both auth-group and "
623                                     "initiator-name for target \"%s\"",
624                                     target->t_name);
625                                 free($2);
626                                 return (1);
627                         }
628                 } else {
629                         target->t_auth_group = auth_group_new(conf, NULL);
630                         if (target->t_auth_group == NULL) {
631                                 free($2);
632                                 return (1);
633                         }
634                         target->t_auth_group->ag_target = target;
635                 }
636                 an = auth_name_new(target->t_auth_group, $2);
637                 free($2);
638                 if (an == NULL)
639                         return (1);
640         }
641         ;
642
643 target_initiator_portal:        INITIATOR_PORTAL STR
644         {
645                 const struct auth_portal *ap;
646
647                 if (target->t_auth_group != NULL) {
648                         if (target->t_auth_group->ag_name != NULL) {
649                                 log_warnx("cannot use both auth-group and "
650                                     "initiator-portal for target \"%s\"",
651                                     target->t_name);
652                                 free($2);
653                                 return (1);
654                         }
655                 } else {
656                         target->t_auth_group = auth_group_new(conf, NULL);
657                         if (target->t_auth_group == NULL) {
658                                 free($2);
659                                 return (1);
660                         }
661                         target->t_auth_group->ag_target = target;
662                 }
663                 ap = auth_portal_new(target->t_auth_group, $2);
664                 free($2);
665                 if (ap == NULL)
666                         return (1);
667         }
668         ;
669
670 target_portal_group:    PORTAL_GROUP STR STR
671         {
672                 struct portal_group *tpg;
673                 struct auth_group *tag;
674                 struct port *tp;
675
676                 tpg = portal_group_find(conf, $2);
677                 if (tpg == NULL) {
678                         log_warnx("unknown portal-group \"%s\" for target "
679                             "\"%s\"", $2, target->t_name);
680                         free($2);
681                         free($3);
682                         return (1);
683                 }
684                 tag = auth_group_find(conf, $3);
685                 if (tag == NULL) {
686                         log_warnx("unknown auth-group \"%s\" for target "
687                             "\"%s\"", $3, target->t_name);
688                         free($2);
689                         free($3);
690                         return (1);
691                 }
692                 tp = port_new(conf, target, tpg);
693                 if (tp == NULL) {
694                         log_warnx("can't link portal-group \"%s\" to target "
695                             "\"%s\"", $2, target->t_name);
696                         free($2);
697                         return (1);
698                 }
699                 tp->p_auth_group = tag;
700                 free($2);
701                 free($3);
702         }
703         |               PORTAL_GROUP STR
704         {
705                 struct portal_group *tpg;
706                 struct port *tp;
707
708                 tpg = portal_group_find(conf, $2);
709                 if (tpg == NULL) {
710                         log_warnx("unknown portal-group \"%s\" for target "
711                             "\"%s\"", $2, target->t_name);
712                         free($2);
713                         return (1);
714                 }
715                 tp = port_new(conf, target, tpg);
716                 if (tp == NULL) {
717                         log_warnx("can't link portal-group \"%s\" to target "
718                             "\"%s\"", $2, target->t_name);
719                         free($2);
720                         return (1);
721                 }
722                 free($2);
723         }
724         ;
725
726 target_port:    PORT STR
727         {
728                 struct pport *pp;
729                 struct port *tp;
730
731                 pp = pport_find(conf, $2);
732                 if (pp == NULL) {
733                         log_warnx("unknown port \"%s\" for target \"%s\"",
734                             $2, target->t_name);
735                         free($2);
736                         return (1);
737                 }
738                 if (!TAILQ_EMPTY(&pp->pp_ports)) {
739                         log_warnx("can't link port \"%s\" to target \"%s\", "
740                             "port already linked to some target",
741                             $2, target->t_name);
742                         free($2);
743                         return (1);
744                 }
745                 tp = port_new_pp(conf, target, pp);
746                 if (tp == NULL) {
747                         log_warnx("can't link port \"%s\" to target \"%s\"",
748                             $2, target->t_name);
749                         free($2);
750                         return (1);
751                 }
752                 free($2);
753         }
754         ;
755
756 target_redirect:        REDIRECT STR
757         {
758                 int error;
759
760                 error = target_set_redirection(target, $2);
761                 free($2);
762                 if (error != 0)
763                         return (1);
764         }
765         ;
766
767 target_lun:     LUN lun_number
768     OPENING_BRACKET lun_entries CLOSING_BRACKET
769         {
770                 lun = NULL;
771         }
772         ;
773
774 lun_number:     STR
775         {
776                 uint64_t tmp;
777                 int ret;
778                 char *name;
779
780                 if (expand_number($1, &tmp) != 0) {
781                         yyerror("invalid numeric value");
782                         free($1);
783                         return (1);
784                 }
785
786                 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
787                 if (ret <= 0)
788                         log_err(1, "asprintf");
789                 lun = lun_new(conf, name);
790                 if (lun == NULL)
791                         return (1);
792
793                 lun_set_scsiname(lun, name);
794                 target->t_luns[tmp] = lun;
795         }
796         ;
797
798 target_lun_ref: LUN STR STR
799         {
800                 uint64_t tmp;
801
802                 if (expand_number($2, &tmp) != 0) {
803                         yyerror("invalid numeric value");
804                         free($2);
805                         free($3);
806                         return (1);
807                 }
808                 free($2);
809
810                 lun = lun_find(conf, $3);
811                 free($3);
812                 if (lun == NULL)
813                         return (1);
814
815                 target->t_luns[tmp] = lun;
816         }
817         ;
818
819 lun_entries:
820         |
821         lun_entries lun_entry
822         |
823         lun_entries lun_entry SEMICOLON
824         ;
825
826 lun_entry:
827         lun_backend
828         |
829         lun_blocksize
830         |
831         lun_device_id
832         |
833         lun_option
834         |
835         lun_path
836         |
837         lun_serial
838         |
839         lun_size
840         ;
841
842 lun_backend:    BACKEND STR
843         {
844                 if (lun->l_backend != NULL) {
845                         log_warnx("backend for lun \"%s\" "
846                             "specified more than once",
847                             lun->l_name);
848                         free($2);
849                         return (1);
850                 }
851                 lun_set_backend(lun, $2);
852                 free($2);
853         }
854         ;
855
856 lun_blocksize:  BLOCKSIZE STR
857         {
858                 uint64_t tmp;
859
860                 if (expand_number($2, &tmp) != 0) {
861                         yyerror("invalid numeric value");
862                         free($2);
863                         return (1);
864                 }
865
866                 if (lun->l_blocksize != 0) {
867                         log_warnx("blocksize for lun \"%s\" "
868                             "specified more than once",
869                             lun->l_name);
870                         return (1);
871                 }
872                 lun_set_blocksize(lun, tmp);
873         }
874         ;
875
876 lun_device_id:  DEVICE_ID STR
877         {
878                 if (lun->l_device_id != NULL) {
879                         log_warnx("device_id for lun \"%s\" "
880                             "specified more than once",
881                             lun->l_name);
882                         free($2);
883                         return (1);
884                 }
885                 lun_set_device_id(lun, $2);
886                 free($2);
887         }
888         ;
889
890 lun_option:     OPTION STR STR
891         {
892                 struct lun_option *clo;
893
894                 clo = lun_option_new(lun, $2, $3);
895                 free($2);
896                 free($3);
897                 if (clo == NULL)
898                         return (1);
899         }
900         ;
901
902 lun_path:       PATH STR
903         {
904                 if (lun->l_path != NULL) {
905                         log_warnx("path for lun \"%s\" "
906                             "specified more than once",
907                             lun->l_name);
908                         free($2);
909                         return (1);
910                 }
911                 lun_set_path(lun, $2);
912                 free($2);
913         }
914         ;
915
916 lun_serial:     SERIAL STR
917         {
918                 if (lun->l_serial != NULL) {
919                         log_warnx("serial for lun \"%s\" "
920                             "specified more than once",
921                             lun->l_name);
922                         free($2);
923                         return (1);
924                 }
925                 lun_set_serial(lun, $2);
926                 free($2);
927         }
928         ;
929
930 lun_size:       SIZE STR
931         {
932                 uint64_t tmp;
933
934                 if (expand_number($2, &tmp) != 0) {
935                         yyerror("invalid numeric value");
936                         free($2);
937                         return (1);
938                 }
939
940                 if (lun->l_size != 0) {
941                         log_warnx("size for lun \"%s\" "
942                             "specified more than once",
943                             lun->l_name);
944                         return (1);
945                 }
946                 lun_set_size(lun, tmp);
947         }
948         ;
949 %%
950
951 void
952 yyerror(const char *str)
953 {
954
955         log_warnx("error in configuration file at line %d near '%s': %s",
956             lineno, yytext, str);
957 }
958
959 static void
960 check_perms(const char *path)
961 {
962         struct stat sb;
963         int error;
964
965         error = stat(path, &sb);
966         if (error != 0) {
967                 log_warn("stat");
968                 return;
969         }
970         if (sb.st_mode & S_IWOTH) {
971                 log_warnx("%s is world-writable", path);
972         } else if (sb.st_mode & S_IROTH) {
973                 log_warnx("%s is world-readable", path);
974         } else if (sb.st_mode & S_IXOTH) {
975                 /*
976                  * Ok, this one doesn't matter, but still do it,
977                  * just for consistency.
978                  */
979                 log_warnx("%s is world-executable", path);
980         }
981
982         /*
983          * XXX: Should we also check for owner != 0?
984          */
985 }
986
987 struct conf *
988 conf_new_from_file(const char *path, struct conf *oldconf)
989 {
990         struct auth_group *ag;
991         struct portal_group *pg;
992         struct pport *pp;
993         int error;
994
995         log_debugx("obtaining configuration from %s", path);
996
997         conf = conf_new();
998
999         TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next)
1000                 pport_copy(pp, conf);
1001
1002         ag = auth_group_new(conf, "default");
1003         assert(ag != NULL);
1004
1005         ag = auth_group_new(conf, "no-authentication");
1006         assert(ag != NULL);
1007         ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
1008
1009         ag = auth_group_new(conf, "no-access");
1010         assert(ag != NULL);
1011         ag->ag_type = AG_TYPE_DENY;
1012
1013         pg = portal_group_new(conf, "default");
1014         assert(pg != NULL);
1015
1016         yyin = fopen(path, "r");
1017         if (yyin == NULL) {
1018                 log_warn("unable to open configuration file %s", path);
1019                 conf_delete(conf);
1020                 return (NULL);
1021         }
1022         check_perms(path);
1023         lineno = 1;
1024         yyrestart(yyin);
1025         error = yyparse();
1026         auth_group = NULL;
1027         portal_group = NULL;
1028         target = NULL;
1029         lun = NULL;
1030         fclose(yyin);
1031         if (error != 0) {
1032                 conf_delete(conf);
1033                 return (NULL);
1034         }
1035
1036         if (conf->conf_default_ag_defined == false) {
1037                 log_debugx("auth-group \"default\" not defined; "
1038                     "going with defaults");
1039                 ag = auth_group_find(conf, "default");
1040                 assert(ag != NULL);
1041                 ag->ag_type = AG_TYPE_DENY;
1042         }
1043
1044         if (conf->conf_default_pg_defined == false) {
1045                 log_debugx("portal-group \"default\" not defined; "
1046                     "going with defaults");
1047                 pg = portal_group_find(conf, "default");
1048                 assert(pg != NULL);
1049                 portal_group_add_listen(pg, "0.0.0.0:3260", false);
1050                 portal_group_add_listen(pg, "[::]:3260", false);
1051         }
1052
1053         conf->conf_kernel_port_on = true;
1054
1055         error = conf_verify(conf);
1056         if (error != 0) {
1057                 conf_delete(conf);
1058                 return (NULL);
1059         }
1060
1061         return (conf);
1062 }