xref: /freebsd/usr.sbin/ctld/parse.y (revision ffc5ee0f57d56459df93f4107b9835ae78a546b5)
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 CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE
58 %token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER DSCP FOREIGN
59 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
60 %token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
61 %token PATH PCP PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL
62 %token SIZE STR TAG TARGET TIMEOUT
63 %token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
64 %token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7
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 		free($2);
116 
117 		conf_set_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 		free($2);
131 
132 		conf_set_timeout(tmp);
133 	}
134 	;
135 
136 maxproc:	MAXPROC STR
137 	{
138 		uint64_t tmp;
139 
140 		if (expand_number($2, &tmp) != 0) {
141 			yyerror("invalid numeric value");
142 			free($2);
143 			return (1);
144 		}
145 		free($2);
146 
147 		conf_set_maxproc(tmp);
148 	}
149 	;
150 
151 pidfile:	PIDFILE STR
152 	{
153 		bool ok;
154 
155 		ok = conf_set_pidfile_path($2);
156 		free($2);
157 		if (!ok)
158 			return (1);
159 	}
160 	;
161 
162 isns_server:	ISNS_SERVER STR
163 	{
164 		bool ok;
165 
166 		ok = isns_add_server($2);
167 		free($2);
168 		if (!ok)
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 		free($2);
183 
184 		conf_set_isns_period(tmp);
185 	}
186 	;
187 
188 isns_timeout:	ISNS_TIMEOUT STR
189 	{
190 		uint64_t tmp;
191 
192 		if (expand_number($2, &tmp) != 0) {
193 			yyerror("invalid numeric value");
194 			free($2);
195 			return (1);
196 		}
197 		free($2);
198 
199 		conf_set_isns_timeout(tmp);
200 	}
201 	;
202 
203 auth_group:	AUTH_GROUP auth_group_name
204     OPENING_BRACKET auth_group_entries CLOSING_BRACKET
205 	{
206 		auth_group_finish();
207 	}
208 	;
209 
210 auth_group_name:	STR
211 	{
212 		bool ok;
213 
214 		ok = auth_group_start($1);
215 		free($1);
216 		if (!ok)
217 			return (1);
218 	}
219 	;
220 
221 auth_group_entries:
222 	|
223 	auth_group_entries auth_group_entry
224 	|
225 	auth_group_entries auth_group_entry SEMICOLON
226 	;
227 
228 auth_group_entry:
229 	auth_group_auth_type
230 	|
231 	auth_group_chap
232 	|
233 	auth_group_chap_mutual
234 	|
235 	auth_group_initiator_name
236 	|
237 	auth_group_initiator_portal
238 	;
239 
240 auth_group_auth_type:	AUTH_TYPE STR
241 	{
242 		bool ok;
243 
244 		ok = auth_group_set_type($2);
245 		free($2);
246 		if (!ok)
247 			return (1);
248 	}
249 	;
250 
251 auth_group_chap:	CHAP STR STR
252 	{
253 		bool ok;
254 
255 		ok = auth_group_add_chap($2, $3);
256 		free($2);
257 		free($3);
258 		if (!ok)
259 			return (1);
260 	}
261 	;
262 
263 auth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
264 	{
265 		bool ok;
266 
267 		ok = auth_group_add_chap_mutual($2, $3, $4, $5);
268 		free($2);
269 		free($3);
270 		free($4);
271 		free($5);
272 		if (!ok)
273 			return (1);
274 	}
275 	;
276 
277 auth_group_initiator_name:	INITIATOR_NAME STR
278 	{
279 		bool ok;
280 
281 		ok = auth_group_add_initiator_name($2);
282 		free($2);
283 		if (!ok)
284 			return (1);
285 	}
286 	;
287 
288 auth_group_initiator_portal:	INITIATOR_PORTAL STR
289 	{
290 		bool ok;
291 
292 		ok = auth_group_add_initiator_portal($2);
293 		free($2);
294 		if (!ok)
295 			return (1);
296 	}
297 	;
298 
299 portal_group:	PORTAL_GROUP portal_group_name
300     OPENING_BRACKET portal_group_entries CLOSING_BRACKET
301 	{
302 		portal_group_finish();
303 	}
304 	;
305 
306 portal_group_name:	STR
307 	{
308 		bool ok;
309 
310 		ok = portal_group_start($1);
311 		free($1);
312 		if (!ok)
313 			return (1);
314 	}
315 	;
316 
317 portal_group_entries:
318 	|
319 	portal_group_entries portal_group_entry
320 	|
321 	portal_group_entries portal_group_entry SEMICOLON
322 	;
323 
324 portal_group_entry:
325 	portal_group_discovery_auth_group
326 	|
327 	portal_group_discovery_filter
328 	|
329 	portal_group_foreign
330 	|
331 	portal_group_listen
332 	|
333 	portal_group_listen_iser
334 	|
335 	portal_group_offload
336 	|
337 	portal_group_option
338 	|
339 	portal_group_redirect
340 	|
341 	portal_group_tag
342 	|
343 	portal_group_dscp
344 	|
345 	portal_group_pcp
346 	;
347 
348 portal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
349 	{
350 		bool ok;
351 
352 		ok = portal_group_set_discovery_auth_group($2);
353 		free($2);
354 		if (!ok)
355 			return (1);
356 	}
357 	;
358 
359 portal_group_discovery_filter:	DISCOVERY_FILTER STR
360 	{
361 		bool ok;
362 
363 		ok = portal_group_set_filter($2);
364 		free($2);
365 		if (!ok)
366 			return (1);
367 	}
368 	;
369 
370 portal_group_foreign:	FOREIGN
371 	{
372 
373 		portal_group_set_foreign();
374 	}
375 	;
376 
377 portal_group_listen:	LISTEN STR
378 	{
379 		bool ok;
380 
381 		ok = portal_group_add_listen($2, false);
382 		free($2);
383 		if (!ok)
384 			return (1);
385 	}
386 	;
387 
388 portal_group_listen_iser:	LISTEN_ISER STR
389 	{
390 		bool ok;
391 
392 		ok = portal_group_add_listen($2, true);
393 		free($2);
394 		if (!ok)
395 			return (1);
396 	}
397 	;
398 
399 portal_group_offload:	OFFLOAD STR
400 	{
401 		bool ok;
402 
403 		ok = portal_group_set_offload($2);
404 		free($2);
405 		if (!ok)
406 			return (1);
407 	}
408 	;
409 
410 portal_group_option:	OPTION STR STR
411 	{
412 		bool ok;
413 
414 		ok = portal_group_add_option($2, $3);
415 		free($2);
416 		free($3);
417 		if (!ok)
418 			return (1);
419 	}
420 	;
421 
422 portal_group_redirect:	REDIRECT STR
423 	{
424 		bool ok;
425 
426 		ok = portal_group_set_redirection($2);
427 		free($2);
428 		if (!ok)
429 			return (1);
430 	}
431 	;
432 
433 portal_group_tag:	TAG STR
434 	{
435 		uint64_t tmp;
436 
437 		if (expand_number($2, &tmp) != 0) {
438 			yyerror("invalid numeric value");
439 			free($2);
440 			return (1);
441 		}
442 		free($2);
443 
444 		portal_group_set_tag(tmp);
445 	}
446 	;
447 
448 portal_group_dscp
449 : DSCP STR
450 	{
451 		uint64_t tmp;
452 
453 		if (strcmp($2, "0x") == 0) {
454 			tmp = strtol($2 + 2, NULL, 16);
455 		} else if (expand_number($2, &tmp) != 0) {
456 			yyerror("invalid numeric value");
457 			free($2);
458 			return (1);
459 		}
460 		free($2);
461 
462 		if (!portal_group_set_dscp(tmp))
463 			return (1);
464 	}
465 | DSCP BE	{ portal_group_set_dscp(IPTOS_DSCP_CS0  >> 2); }
466 | DSCP EF	{ portal_group_set_dscp(IPTOS_DSCP_EF   >> 2); }
467 | DSCP CS0	{ portal_group_set_dscp(IPTOS_DSCP_CS0  >> 2); }
468 | DSCP CS1	{ portal_group_set_dscp(IPTOS_DSCP_CS1  >> 2); }
469 | DSCP CS2	{ portal_group_set_dscp(IPTOS_DSCP_CS2  >> 2); }
470 | DSCP CS3	{ portal_group_set_dscp(IPTOS_DSCP_CS3  >> 2); }
471 | DSCP CS4	{ portal_group_set_dscp(IPTOS_DSCP_CS4  >> 2); }
472 | DSCP CS5	{ portal_group_set_dscp(IPTOS_DSCP_CS5  >> 2); }
473 | DSCP CS6	{ portal_group_set_dscp(IPTOS_DSCP_CS6  >> 2); }
474 | DSCP CS7	{ portal_group_set_dscp(IPTOS_DSCP_CS7  >> 2); }
475 | DSCP AF11	{ portal_group_set_dscp(IPTOS_DSCP_AF11 >> 2); }
476 | DSCP AF12	{ portal_group_set_dscp(IPTOS_DSCP_AF12 >> 2); }
477 | DSCP AF13	{ portal_group_set_dscp(IPTOS_DSCP_AF13 >> 2); }
478 | DSCP AF21	{ portal_group_set_dscp(IPTOS_DSCP_AF21 >> 2); }
479 | DSCP AF22	{ portal_group_set_dscp(IPTOS_DSCP_AF22 >> 2); }
480 | DSCP AF23	{ portal_group_set_dscp(IPTOS_DSCP_AF23 >> 2); }
481 | DSCP AF31	{ portal_group_set_dscp(IPTOS_DSCP_AF31 >> 2); }
482 | DSCP AF32	{ portal_group_set_dscp(IPTOS_DSCP_AF32 >> 2); }
483 | DSCP AF33	{ portal_group_set_dscp(IPTOS_DSCP_AF33 >> 2); }
484 | DSCP AF41	{ portal_group_set_dscp(IPTOS_DSCP_AF41 >> 2); }
485 | DSCP AF42	{ portal_group_set_dscp(IPTOS_DSCP_AF42 >> 2); }
486 | DSCP AF43	{ portal_group_set_dscp(IPTOS_DSCP_AF43 >> 2); }
487 	;
488 
489 portal_group_pcp:	PCP STR
490 	{
491 		uint64_t tmp;
492 
493 		if (expand_number($2, &tmp) != 0) {
494 			yyerror("invalid numeric value");
495 			free($2);
496 			return (1);
497 		}
498 		free($2);
499 
500 		if (!portal_group_set_pcp(tmp))
501 			return (1);
502 	}
503 	;
504 
505 lun:	LUN lun_name
506     OPENING_BRACKET lun_entries CLOSING_BRACKET
507 	{
508 		lun_finish();
509 	}
510 	;
511 
512 lun_name:	STR
513 	{
514 		bool ok;
515 
516 		ok = lun_start($1);
517 		free($1);
518 		if (!ok)
519 			return (1);
520 	}
521 	;
522 
523 target:	TARGET target_name
524     OPENING_BRACKET target_entries CLOSING_BRACKET
525 	{
526 		target_finish();
527 	}
528 	;
529 
530 target_name:	STR
531 	{
532 		bool ok;
533 
534 		ok = target_start($1);
535 		free($1);
536 		if (!ok)
537 			return (1);
538 	}
539 	;
540 
541 target_entries:
542 	|
543 	target_entries target_entry
544 	|
545 	target_entries target_entry SEMICOLON
546 	;
547 
548 target_entry:
549 	target_alias
550 	|
551 	target_auth_group
552 	|
553 	target_auth_type
554 	|
555 	target_chap
556 	|
557 	target_chap_mutual
558 	|
559 	target_initiator_name
560 	|
561 	target_initiator_portal
562 	|
563 	target_portal_group
564 	|
565 	target_port
566 	|
567 	target_redirect
568 	|
569 	target_lun
570 	|
571 	target_lun_ref
572 	;
573 
574 target_alias:	ALIAS STR
575 	{
576 		bool ok;
577 
578 		ok = target_set_alias($2);
579 		free($2);
580 		if (!ok)
581 			return (1);
582 	}
583 	;
584 
585 target_auth_group:	AUTH_GROUP STR
586 	{
587 		bool ok;
588 
589 		ok = target_set_auth_group($2);
590 		free($2);
591 		if (!ok)
592 			return (1);
593 	}
594 	;
595 
596 target_auth_type:	AUTH_TYPE STR
597 	{
598 		bool ok;
599 
600 		ok = target_set_auth_type($2);
601 		free($2);
602 		if (!ok)
603 			return (1);
604 	}
605 	;
606 
607 target_chap:	CHAP STR STR
608 	{
609 		bool ok;
610 
611 		ok = target_add_chap($2, $3);
612 		free($2);
613 		free($3);
614 		if (!ok)
615 			return (1);
616 	}
617 	;
618 
619 target_chap_mutual:	CHAP_MUTUAL STR STR STR STR
620 	{
621 		bool ok;
622 
623 		ok = target_add_chap_mutual($2, $3, $4, $5);
624 		free($2);
625 		free($3);
626 		free($4);
627 		free($5);
628 		if (!ok)
629 			return (1);
630 	}
631 	;
632 
633 target_initiator_name:	INITIATOR_NAME STR
634 	{
635 		bool ok;
636 
637 		ok = target_add_initiator_name($2);
638 		free($2);
639 		if (!ok)
640 			return (1);
641 	}
642 	;
643 
644 target_initiator_portal:	INITIATOR_PORTAL STR
645 	{
646 		bool ok;
647 
648 		ok = target_add_initiator_portal($2);
649 		free($2);
650 		if (!ok)
651 			return (1);
652 	}
653 	;
654 
655 target_portal_group:	PORTAL_GROUP STR STR
656 	{
657 		bool ok;
658 
659 		ok = target_add_portal_group($2, $3);
660 		free($2);
661 		free($3);
662 		if (!ok)
663 			return (1);
664 	}
665 	|		PORTAL_GROUP STR
666 	{
667 		bool ok;
668 
669 		ok = target_add_portal_group($2, NULL);
670 		free($2);
671 		if (!ok)
672 			return (1);
673 	}
674 	;
675 
676 target_port:	PORT STR
677 	{
678 		bool ok;
679 
680 		ok = target_set_physical_port($2);
681 		free($2);
682 		if (!ok)
683 			return (1);
684 	}
685 	;
686 
687 target_redirect:	REDIRECT STR
688 	{
689 		bool ok;
690 
691 		ok = target_set_redirection($2);
692 		free($2);
693 		if (!ok)
694 			return (1);
695 	}
696 	;
697 
698 target_lun:	LUN lun_number
699     OPENING_BRACKET lun_entries CLOSING_BRACKET
700 	{
701 		lun_finish();
702 	}
703 	;
704 
705 lun_number:	STR
706 	{
707 		uint64_t tmp;
708 
709 		if (expand_number($1, &tmp) != 0) {
710 			yyerror("invalid numeric value");
711 			free($1);
712 			return (1);
713 		}
714 		free($1);
715 
716 		if (!target_start_lun(tmp))
717 			return (1);
718 	}
719 	;
720 
721 target_lun_ref:	LUN STR STR
722 	{
723 		uint64_t tmp;
724 		bool ok;
725 
726 		if (expand_number($2, &tmp) != 0) {
727 			yyerror("invalid numeric value");
728 			free($2);
729 			free($3);
730 			return (1);
731 		}
732 		free($2);
733 
734 		ok = target_add_lun(tmp, $3);
735 		free($3);
736 		if (!ok)
737 			return (1);
738 	}
739 	;
740 
741 lun_entries:
742 	|
743 	lun_entries lun_entry
744 	|
745 	lun_entries lun_entry SEMICOLON
746 	;
747 
748 lun_entry:
749 	lun_backend
750 	|
751 	lun_blocksize
752 	|
753 	lun_device_id
754 	|
755 	lun_device_type
756 	|
757 	lun_ctl_lun
758 	|
759 	lun_option
760 	|
761 	lun_path
762 	|
763 	lun_serial
764 	|
765 	lun_size
766 	;
767 
768 lun_backend:	BACKEND STR
769 	{
770 		bool ok;
771 
772 		ok = lun_set_backend($2);
773 		free($2);
774 		if (!ok)
775 			return (1);
776 	}
777 	;
778 
779 lun_blocksize:	BLOCKSIZE STR
780 	{
781 		uint64_t tmp;
782 
783 		if (expand_number($2, &tmp) != 0) {
784 			yyerror("invalid numeric value");
785 			free($2);
786 			return (1);
787 		}
788 		free($2);
789 
790 		if (!lun_set_blocksize(tmp))
791 			return (1);
792 	}
793 	;
794 
795 lun_device_id:	DEVICE_ID STR
796 	{
797 		bool ok;
798 
799 		ok = lun_set_device_id($2);
800 		free($2);
801 		if (!ok)
802 			return (1);
803 	}
804 	;
805 
806 lun_device_type:	DEVICE_TYPE STR
807 	{
808 		bool ok;
809 
810 		ok = lun_set_device_type($2);
811 		free($2);
812 		if (!ok)
813 			return (1);
814 	}
815 	;
816 
817 lun_ctl_lun:	CTL_LUN STR
818 	{
819 		uint64_t tmp;
820 
821 		if (expand_number($2, &tmp) != 0) {
822 			yyerror("invalid numeric value");
823 			free($2);
824 			return (1);
825 		}
826 		free($2);
827 
828 		if (!lun_set_ctl_lun(tmp))
829 			return (1);
830 	}
831 	;
832 
833 lun_option:	OPTION STR STR
834 	{
835 		bool ok;
836 
837 		ok = lun_add_option($2, $3);
838 		free($2);
839 		free($3);
840 		if (!ok)
841 			return (1);
842 	}
843 	;
844 
845 lun_path:	PATH STR
846 	{
847 		bool ok;
848 
849 		ok = lun_set_path($2);
850 		free($2);
851 		if (!ok)
852 			return (1);
853 	}
854 	;
855 
856 lun_serial:	SERIAL STR
857 	{
858 		bool ok;
859 
860 		ok = lun_set_serial($2);
861 		free($2);
862 		if (!ok)
863 			return (1);
864 	}
865 	;
866 
867 lun_size:	SIZE STR
868 	{
869 		uint64_t tmp;
870 
871 		if (expand_number($2, &tmp) != 0) {
872 			yyerror("invalid numeric value");
873 			free($2);
874 			return (1);
875 		}
876 		free($2);
877 
878 		if (!lun_set_size(tmp))
879 			return (1);
880 	}
881 	;
882 %%
883 
884 void
885 yyerror(const char *str)
886 {
887 
888 	log_warnx("error in configuration file at line %d near '%s': %s",
889 	    lineno, yytext, str);
890 }
891 
892 bool
893 parse_conf(const char *path)
894 {
895 	int error;
896 
897 	yyin = fopen(path, "r");
898 	if (yyin == NULL) {
899 		log_warn("unable to open configuration file %s", path);
900 		return (false);
901 	}
902 
903 	lineno = 1;
904 	yyrestart(yyin);
905 	error = yyparse();
906 	fclose(yyin);
907 
908 	return (error == 0);
909 }
910