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