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