1 %{
2 /*-
3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 *
5 * Copyright (c) 2012 The FreeBSD Foundation
6 * All rights reserved.
7 *
8 * This software was developed by Edward Tomasz Napierala under sponsorship
9 * from the FreeBSD Foundation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD$
33 */
34
35 #include <sys/queue.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <assert.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "ctld.h"
44
45 extern FILE *yyin;
46 extern char *yytext;
47 extern int lineno;
48
49 static struct conf *conf = NULL;
50 static struct auth_group *auth_group = NULL;
51 static struct portal_group *portal_group = NULL;
52 static struct target *target = NULL;
53 static struct lun *lun = NULL;
54
55 extern void yyerror(const char *);
56 extern int yylex(void);
57 extern void yyrestart(FILE *);
58
59 %}
60
61 %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
62 %token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE
63 %token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER FOREIGN
64 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
65 %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
66 %token PATH PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
67 %token TAG TARGET TIMEOUT
68
69 %union
70 {
71 char *str;
72 }
73
74 %token <str> STR
75
76 %%
77
78 statements:
79 |
80 statements statement
81 |
82 statements statement SEMICOLON
83 ;
84
85 statement:
86 debug
87 |
88 timeout
89 |
90 maxproc
91 |
92 pidfile
93 |
94 isns_server
95 |
96 isns_period
97 |
98 isns_timeout
99 |
100 auth_group
101 |
102 portal_group
103 |
104 lun
105 |
106 target
107 ;
108
109 debug: DEBUG STR
110 {
111 uint64_t tmp;
112
113 if (expand_number($2, &tmp) != 0) {
114 yyerror("invalid numeric value");
115 free($2);
116 return (1);
117 }
118
119 conf->conf_debug = tmp;
120 }
121 ;
122
123 timeout: TIMEOUT STR
124 {
125 uint64_t tmp;
126
127 if (expand_number($2, &tmp) != 0) {
128 yyerror("invalid numeric value");
129 free($2);
130 return (1);
131 }
132
133 conf->conf_timeout = tmp;
134 }
135 ;
136
137 maxproc: MAXPROC STR
138 {
139 uint64_t tmp;
140
141 if (expand_number($2, &tmp) != 0) {
142 yyerror("invalid numeric value");
143 free($2);
144 return (1);
145 }
146
147 conf->conf_maxproc = tmp;
148 }
149 ;
150
151 pidfile: PIDFILE STR
152 {
153 if (conf->conf_pidfile_path != NULL) {
154 log_warnx("pidfile specified more than once");
155 free($2);
156 return (1);
157 }
158 conf->conf_pidfile_path = $2;
159 }
160 ;
161
162 isns_server: ISNS_SERVER STR
163 {
164 int error;
165
166 error = isns_new(conf, $2);
167 free($2);
168 if (error != 0)
169 return (1);
170 }
171 ;
172
173 isns_period: ISNS_PERIOD STR
174 {
175 uint64_t tmp;
176
177 if (expand_number($2, &tmp) != 0) {
178 yyerror("invalid numeric value");
179 free($2);
180 return (1);
181 }
182
183 conf->conf_isns_period = tmp;
184 }
185 ;
186
187 isns_timeout: ISNS_TIMEOUT STR
188 {
189 uint64_t tmp;
190
191 if (expand_number($2, &tmp) != 0) {
192 yyerror("invalid numeric value");
193 free($2);
194 return (1);
195 }
196
197 conf->conf_isns_timeout = tmp;
198 }
199 ;
200
201 auth_group: AUTH_GROUP auth_group_name
202 OPENING_BRACKET auth_group_entries CLOSING_BRACKET
203 {
204 auth_group = NULL;
205 }
206 ;
207
208 auth_group_name: STR
209 {
210 /*
211 * Make it possible to redefine default
212 * auth-group. but only once.
213 */
214 if (strcmp($1, "default") == 0 &&
215 conf->conf_default_ag_defined == false) {
216 auth_group = auth_group_find(conf, $1);
217 conf->conf_default_ag_defined = true;
218 } else {
219 auth_group = auth_group_new(conf, $1);
220 }
221 free($1);
222 if (auth_group == NULL)
223 return (1);
224 }
225 ;
226
227 auth_group_entries:
228 |
229 auth_group_entries auth_group_entry
230 |
231 auth_group_entries auth_group_entry SEMICOLON
232 ;
233
234 auth_group_entry:
235 auth_group_auth_type
236 |
237 auth_group_chap
238 |
239 auth_group_chap_mutual
240 |
241 auth_group_initiator_name
242 |
243 auth_group_initiator_portal
244 ;
245
246 auth_group_auth_type: AUTH_TYPE STR
247 {
248 int error;
249
250 error = auth_group_set_type(auth_group, $2);
251 free($2);
252 if (error != 0)
253 return (1);
254 }
255 ;
256
257 auth_group_chap: CHAP STR STR
258 {
259 const struct auth *ca;
260
261 ca = auth_new_chap(auth_group, $2, $3);
262 free($2);
263 free($3);
264 if (ca == NULL)
265 return (1);
266 }
267 ;
268
269 auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
270 {
271 const struct auth *ca;
272
273 ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
274 free($2);
275 free($3);
276 free($4);
277 free($5);
278 if (ca == NULL)
279 return (1);
280 }
281 ;
282
283 auth_group_initiator_name: INITIATOR_NAME STR
284 {
285 const struct auth_name *an;
286
287 an = auth_name_new(auth_group, $2);
288 free($2);
289 if (an == NULL)
290 return (1);
291 }
292 ;
293
294 auth_group_initiator_portal: INITIATOR_PORTAL STR
295 {
296 const struct auth_portal *ap;
297
298 ap = auth_portal_new(auth_group, $2);
299 free($2);
300 if (ap == NULL)
301 return (1);
302 }
303 ;
304
305 portal_group: PORTAL_GROUP portal_group_name
306 OPENING_BRACKET portal_group_entries CLOSING_BRACKET
307 {
308 portal_group = NULL;
309 }
310 ;
311
312 portal_group_name: STR
313 {
314 /*
315 * Make it possible to redefine default
316 * portal-group. but only once.
317 */
318 if (strcmp($1, "default") == 0 &&
319 conf->conf_default_pg_defined == false) {
320 portal_group = portal_group_find(conf, $1);
321 conf->conf_default_pg_defined = true;
322 } else {
323 portal_group = portal_group_new(conf, $1);
324 }
325 free($1);
326 if (portal_group == NULL)
327 return (1);
328 }
329 ;
330
331 portal_group_entries:
332 |
333 portal_group_entries portal_group_entry
334 |
335 portal_group_entries portal_group_entry SEMICOLON
336 ;
337
338 portal_group_entry:
339 portal_group_discovery_auth_group
340 |
341 portal_group_discovery_filter
342 |
343 portal_group_foreign
344 |
345 portal_group_listen
346 |
347 portal_group_listen_iser
348 |
349 portal_group_offload
350 |
351 portal_group_option
352 |
353 portal_group_redirect
354 |
355 portal_group_tag
356 ;
357
358 portal_group_discovery_auth_group: DISCOVERY_AUTH_GROUP STR
359 {
360 if (portal_group->pg_discovery_auth_group != NULL) {
361 log_warnx("discovery-auth-group for portal-group "
362 "\"%s\" specified more than once",
363 portal_group->pg_name);
364 return (1);
365 }
366 portal_group->pg_discovery_auth_group =
367 auth_group_find(conf, $2);
368 if (portal_group->pg_discovery_auth_group == NULL) {
369 log_warnx("unknown discovery-auth-group \"%s\" "
370 "for portal-group \"%s\"",
371 $2, portal_group->pg_name);
372 return (1);
373 }
374 free($2);
375 }
376 ;
377
378 portal_group_discovery_filter: DISCOVERY_FILTER STR
379 {
380 int error;
381
382 error = portal_group_set_filter(portal_group, $2);
383 free($2);
384 if (error != 0)
385 return (1);
386 }
387 ;
388
389 portal_group_foreign: FOREIGN
390 {
391
392 portal_group->pg_foreign = 1;
393 }
394 ;
395
396 portal_group_listen: LISTEN STR
397 {
398 int error;
399
400 error = portal_group_add_listen(portal_group, $2, false);
401 free($2);
402 if (error != 0)
403 return (1);
404 }
405 ;
406
407 portal_group_listen_iser: LISTEN_ISER STR
408 {
409 int error;
410
411 error = portal_group_add_listen(portal_group, $2, true);
412 free($2);
413 if (error != 0)
414 return (1);
415 }
416 ;
417
418 portal_group_offload: OFFLOAD STR
419 {
420 int error;
421
422 error = portal_group_set_offload(portal_group, $2);
423 free($2);
424 if (error != 0)
425 return (1);
426 }
427 ;
428
429 portal_group_option: OPTION STR STR
430 {
431 struct option *o;
432
433 o = option_new(&portal_group->pg_options, $2, $3);
434 free($2);
435 free($3);
436 if (o == NULL)
437 return (1);
438 }
439 ;
440
441 portal_group_redirect: REDIRECT STR
442 {
443 int error;
444
445 error = portal_group_set_redirection(portal_group, $2);
446 free($2);
447 if (error != 0)
448 return (1);
449 }
450 ;
451
452 portal_group_tag: TAG STR
453 {
454 uint64_t tmp;
455
456 if (expand_number($2, &tmp) != 0) {
457 yyerror("invalid numeric value");
458 free($2);
459 return (1);
460 }
461
462 portal_group->pg_tag = tmp;
463 }
464 ;
465
466 lun: LUN lun_name
467 OPENING_BRACKET lun_entries CLOSING_BRACKET
468 {
469 lun = NULL;
470 }
471 ;
472
473 lun_name: STR
474 {
475 lun = lun_new(conf, $1);
476 free($1);
477 if (lun == NULL)
478 return (1);
479 }
480 ;
481
482 target: TARGET target_name
483 OPENING_BRACKET target_entries CLOSING_BRACKET
484 {
485 target = NULL;
486 }
487 ;
488
489 target_name: STR
490 {
491 target = target_new(conf, $1);
492 free($1);
493 if (target == NULL)
494 return (1);
495 }
496 ;
497
498 target_entries:
499 |
500 target_entries target_entry
501 |
502 target_entries target_entry SEMICOLON
503 ;
504
505 target_entry:
506 target_alias
507 |
508 target_auth_group
509 |
510 target_auth_type
511 |
512 target_chap
513 |
514 target_chap_mutual
515 |
516 target_initiator_name
517 |
518 target_initiator_portal
519 |
520 target_portal_group
521 |
522 target_port
523 |
524 target_redirect
525 |
526 target_lun
527 |
528 target_lun_ref
529 ;
530
531 target_alias: ALIAS STR
532 {
533 if (target->t_alias != NULL) {
534 log_warnx("alias for target \"%s\" "
535 "specified more than once", target->t_name);
536 return (1);
537 }
538 target->t_alias = $2;
539 }
540 ;
541
542 target_auth_group: AUTH_GROUP STR
543 {
544 if (target->t_auth_group != NULL) {
545 if (target->t_auth_group->ag_name != NULL)
546 log_warnx("auth-group for target \"%s\" "
547 "specified more than once", target->t_name);
548 else
549 log_warnx("cannot use both auth-group and explicit "
550 "authorisations for target \"%s\"",
551 target->t_name);
552 return (1);
553 }
554 target->t_auth_group = auth_group_find(conf, $2);
555 if (target->t_auth_group == NULL) {
556 log_warnx("unknown auth-group \"%s\" for target "
557 "\"%s\"", $2, target->t_name);
558 return (1);
559 }
560 free($2);
561 }
562 ;
563
564 target_auth_type: AUTH_TYPE STR
565 {
566 int error;
567
568 if (target->t_auth_group != NULL) {
569 if (target->t_auth_group->ag_name != NULL) {
570 log_warnx("cannot use both auth-group and "
571 "auth-type for target \"%s\"",
572 target->t_name);
573 return (1);
574 }
575 } else {
576 target->t_auth_group = auth_group_new(conf, NULL);
577 if (target->t_auth_group == NULL) {
578 free($2);
579 return (1);
580 }
581 target->t_auth_group->ag_target = target;
582 }
583 error = auth_group_set_type(target->t_auth_group, $2);
584 free($2);
585 if (error != 0)
586 return (1);
587 }
588 ;
589
590 target_chap: CHAP STR STR
591 {
592 const struct auth *ca;
593
594 if (target->t_auth_group != NULL) {
595 if (target->t_auth_group->ag_name != NULL) {
596 log_warnx("cannot use both auth-group and "
597 "chap for target \"%s\"",
598 target->t_name);
599 free($2);
600 free($3);
601 return (1);
602 }
603 } else {
604 target->t_auth_group = auth_group_new(conf, NULL);
605 if (target->t_auth_group == NULL) {
606 free($2);
607 free($3);
608 return (1);
609 }
610 target->t_auth_group->ag_target = target;
611 }
612 ca = auth_new_chap(target->t_auth_group, $2, $3);
613 free($2);
614 free($3);
615 if (ca == NULL)
616 return (1);
617 }
618 ;
619
620 target_chap_mutual: CHAP_MUTUAL STR STR STR STR
621 {
622 const struct auth *ca;
623
624 if (target->t_auth_group != NULL) {
625 if (target->t_auth_group->ag_name != NULL) {
626 log_warnx("cannot use both auth-group and "
627 "chap-mutual for target \"%s\"",
628 target->t_name);
629 free($2);
630 free($3);
631 free($4);
632 free($5);
633 return (1);
634 }
635 } else {
636 target->t_auth_group = auth_group_new(conf, NULL);
637 if (target->t_auth_group == NULL) {
638 free($2);
639 free($3);
640 free($4);
641 free($5);
642 return (1);
643 }
644 target->t_auth_group->ag_target = target;
645 }
646 ca = auth_new_chap_mutual(target->t_auth_group,
647 $2, $3, $4, $5);
648 free($2);
649 free($3);
650 free($4);
651 free($5);
652 if (ca == NULL)
653 return (1);
654 }
655 ;
656
657 target_initiator_name: INITIATOR_NAME STR
658 {
659 const struct auth_name *an;
660
661 if (target->t_auth_group != NULL) {
662 if (target->t_auth_group->ag_name != NULL) {
663 log_warnx("cannot use both auth-group and "
664 "initiator-name for target \"%s\"",
665 target->t_name);
666 free($2);
667 return (1);
668 }
669 } else {
670 target->t_auth_group = auth_group_new(conf, NULL);
671 if (target->t_auth_group == NULL) {
672 free($2);
673 return (1);
674 }
675 target->t_auth_group->ag_target = target;
676 }
677 an = auth_name_new(target->t_auth_group, $2);
678 free($2);
679 if (an == NULL)
680 return (1);
681 }
682 ;
683
684 target_initiator_portal: INITIATOR_PORTAL STR
685 {
686 const struct auth_portal *ap;
687
688 if (target->t_auth_group != NULL) {
689 if (target->t_auth_group->ag_name != NULL) {
690 log_warnx("cannot use both auth-group and "
691 "initiator-portal for target \"%s\"",
692 target->t_name);
693 free($2);
694 return (1);
695 }
696 } else {
697 target->t_auth_group = auth_group_new(conf, NULL);
698 if (target->t_auth_group == NULL) {
699 free($2);
700 return (1);
701 }
702 target->t_auth_group->ag_target = target;
703 }
704 ap = auth_portal_new(target->t_auth_group, $2);
705 free($2);
706 if (ap == NULL)
707 return (1);
708 }
709 ;
710
711 target_portal_group: PORTAL_GROUP STR STR
712 {
713 struct portal_group *tpg;
714 struct auth_group *tag;
715 struct port *tp;
716
717 tpg = portal_group_find(conf, $2);
718 if (tpg == NULL) {
719 log_warnx("unknown portal-group \"%s\" for target "
720 "\"%s\"", $2, target->t_name);
721 free($2);
722 free($3);
723 return (1);
724 }
725 tag = auth_group_find(conf, $3);
726 if (tag == NULL) {
727 log_warnx("unknown auth-group \"%s\" for target "
728 "\"%s\"", $3, target->t_name);
729 free($2);
730 free($3);
731 return (1);
732 }
733 tp = port_new(conf, target, tpg);
734 if (tp == NULL) {
735 log_warnx("can't link portal-group \"%s\" to target "
736 "\"%s\"", $2, target->t_name);
737 free($2);
738 return (1);
739 }
740 tp->p_auth_group = tag;
741 free($2);
742 free($3);
743 }
744 | PORTAL_GROUP STR
745 {
746 struct portal_group *tpg;
747 struct port *tp;
748
749 tpg = portal_group_find(conf, $2);
750 if (tpg == NULL) {
751 log_warnx("unknown portal-group \"%s\" for target "
752 "\"%s\"", $2, target->t_name);
753 free($2);
754 return (1);
755 }
756 tp = port_new(conf, target, tpg);
757 if (tp == NULL) {
758 log_warnx("can't link portal-group \"%s\" to target "
759 "\"%s\"", $2, target->t_name);
760 free($2);
761 return (1);
762 }
763 free($2);
764 }
765 ;
766
767 target_port: PORT STR
768 {
769 struct pport *pp;
770 struct port *tp;
771 int ret, i_pp, i_vp = 0;
772
773 ret = sscanf($2, "ioctl/%d/%d", &i_pp, &i_vp);
774 if (ret > 0) {
775 tp = port_new_ioctl(conf, target, i_pp, i_vp);
776 if (tp == NULL) {
777 log_warnx("can't create new ioctl port for "
778 "target \"%s\"", target->t_name);
779 free($2);
780 return (1);
781 }
782 } else {
783 pp = pport_find(conf, $2);
784 if (pp == NULL) {
785 log_warnx("unknown port \"%s\" for target \"%s\"",
786 $2, target->t_name);
787 free($2);
788 return (1);
789 }
790 if (!TAILQ_EMPTY(&pp->pp_ports)) {
791 log_warnx("can't link port \"%s\" to target \"%s\", "
792 "port already linked to some target",
793 $2, target->t_name);
794 free($2);
795 return (1);
796 }
797 tp = port_new_pp(conf, target, pp);
798 if (tp == NULL) {
799 log_warnx("can't link port \"%s\" to target \"%s\"",
800 $2, target->t_name);
801 free($2);
802 return (1);
803 }
804 }
805
806 free($2);
807 }
808 ;
809
810 target_redirect: REDIRECT STR
811 {
812 int error;
813
814 error = target_set_redirection(target, $2);
815 free($2);
816 if (error != 0)
817 return (1);
818 }
819 ;
820
821 target_lun: LUN lun_number
822 OPENING_BRACKET lun_entries CLOSING_BRACKET
823 {
824 lun = NULL;
825 }
826 ;
827
828 lun_number: STR
829 {
830 uint64_t tmp;
831 int ret;
832 char *name;
833
834 if (expand_number($1, &tmp) != 0) {
835 yyerror("invalid numeric value");
836 free($1);
837 return (1);
838 }
839 if (tmp >= MAX_LUNS) {
840 yyerror("LU number is too big");
841 free($1);
842 return (1);
843 }
844
845 ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
846 if (ret <= 0)
847 log_err(1, "asprintf");
848 lun = lun_new(conf, name);
849 if (lun == NULL)
850 return (1);
851
852 lun_set_scsiname(lun, name);
853 target->t_luns[tmp] = lun;
854 }
855 ;
856
857 target_lun_ref: LUN STR STR
858 {
859 uint64_t tmp;
860
861 if (expand_number($2, &tmp) != 0) {
862 yyerror("invalid numeric value");
863 free($2);
864 free($3);
865 return (1);
866 }
867 free($2);
868 if (tmp >= MAX_LUNS) {
869 yyerror("LU number is too big");
870 free($3);
871 return (1);
872 }
873
874 lun = lun_find(conf, $3);
875 free($3);
876 if (lun == NULL)
877 return (1);
878
879 target->t_luns[tmp] = lun;
880 }
881 ;
882
883 lun_entries:
884 |
885 lun_entries lun_entry
886 |
887 lun_entries lun_entry SEMICOLON
888 ;
889
890 lun_entry:
891 lun_backend
892 |
893 lun_blocksize
894 |
895 lun_device_id
896 |
897 lun_device_type
898 |
899 lun_ctl_lun
900 |
901 lun_option
902 |
903 lun_path
904 |
905 lun_serial
906 |
907 lun_size
908 ;
909
910 lun_backend: BACKEND STR
911 {
912 if (lun->l_backend != NULL) {
913 log_warnx("backend for lun \"%s\" "
914 "specified more than once",
915 lun->l_name);
916 free($2);
917 return (1);
918 }
919 lun_set_backend(lun, $2);
920 free($2);
921 }
922 ;
923
924 lun_blocksize: BLOCKSIZE STR
925 {
926 uint64_t tmp;
927
928 if (expand_number($2, &tmp) != 0) {
929 yyerror("invalid numeric value");
930 free($2);
931 return (1);
932 }
933
934 if (lun->l_blocksize != 0) {
935 log_warnx("blocksize for lun \"%s\" "
936 "specified more than once",
937 lun->l_name);
938 return (1);
939 }
940 lun_set_blocksize(lun, tmp);
941 }
942 ;
943
944 lun_device_id: DEVICE_ID STR
945 {
946 if (lun->l_device_id != NULL) {
947 log_warnx("device_id for lun \"%s\" "
948 "specified more than once",
949 lun->l_name);
950 free($2);
951 return (1);
952 }
953 lun_set_device_id(lun, $2);
954 free($2);
955 }
956 ;
957
958 lun_device_type: DEVICE_TYPE STR
959 {
960 uint64_t tmp;
961
962 if (strcasecmp($2, "disk") == 0 ||
963 strcasecmp($2, "direct") == 0)
964 tmp = 0;
965 else if (strcasecmp($2, "processor") == 0)
966 tmp = 3;
967 else if (strcasecmp($2, "cd") == 0 ||
968 strcasecmp($2, "cdrom") == 0 ||
969 strcasecmp($2, "dvd") == 0 ||
970 strcasecmp($2, "dvdrom") == 0)
971 tmp = 5;
972 else if (expand_number($2, &tmp) != 0 ||
973 tmp > 15) {
974 yyerror("invalid numeric value");
975 free($2);
976 return (1);
977 }
978
979 lun_set_device_type(lun, tmp);
980 }
981 ;
982
983 lun_ctl_lun: CTL_LUN STR
984 {
985 uint64_t tmp;
986
987 if (expand_number($2, &tmp) != 0) {
988 yyerror("invalid numeric value");
989 free($2);
990 return (1);
991 }
992
993 if (lun->l_ctl_lun >= 0) {
994 log_warnx("ctl_lun for lun \"%s\" "
995 "specified more than once",
996 lun->l_name);
997 return (1);
998 }
999 lun_set_ctl_lun(lun, tmp);
1000 }
1001 ;
1002
1003 lun_option: OPTION STR STR
1004 {
1005 struct option *o;
1006
1007 o = option_new(&lun->l_options, $2, $3);
1008 free($2);
1009 free($3);
1010 if (o == NULL)
1011 return (1);
1012 }
1013 ;
1014
1015 lun_path: PATH STR
1016 {
1017 if (lun->l_path != NULL) {
1018 log_warnx("path for lun \"%s\" "
1019 "specified more than once",
1020 lun->l_name);
1021 free($2);
1022 return (1);
1023 }
1024 lun_set_path(lun, $2);
1025 free($2);
1026 }
1027 ;
1028
1029 lun_serial: SERIAL STR
1030 {
1031 if (lun->l_serial != NULL) {
1032 log_warnx("serial for lun \"%s\" "
1033 "specified more than once",
1034 lun->l_name);
1035 free($2);
1036 return (1);
1037 }
1038 lun_set_serial(lun, $2);
1039 free($2);
1040 }
1041 ;
1042
1043 lun_size: SIZE STR
1044 {
1045 uint64_t tmp;
1046
1047 if (expand_number($2, &tmp) != 0) {
1048 yyerror("invalid numeric value");
1049 free($2);
1050 return (1);
1051 }
1052
1053 if (lun->l_size != 0) {
1054 log_warnx("size for lun \"%s\" "
1055 "specified more than once",
1056 lun->l_name);
1057 return (1);
1058 }
1059 lun_set_size(lun, tmp);
1060 }
1061 ;
1062 %%
1063
1064 void
1065 yyerror(const char *str)
1066 {
1067
1068 log_warnx("error in configuration file at line %d near '%s': %s",
1069 lineno, yytext, str);
1070 }
1071
1072 int
parse_conf(struct conf * newconf,const char * path)1073 parse_conf(struct conf *newconf, const char *path)
1074 {
1075 int error;
1076
1077 conf = newconf;
1078 yyin = fopen(path, "r");
1079 if (yyin == NULL) {
1080 log_warn("unable to open configuration file %s", path);
1081 return (1);
1082 }
1083
1084 lineno = 1;
1085 yyrestart(yyin);
1086 error = yyparse();
1087 auth_group = NULL;
1088 portal_group = NULL;
1089 target = NULL;
1090 lun = NULL;
1091 fclose(yyin);
1092
1093 return (error);
1094 }
1095