parse.y revision 301033
1255570Strasz%{
2255570Strasz/*-
3255570Strasz * Copyright (c) 2012 The FreeBSD Foundation
4255570Strasz * All rights reserved.
5255570Strasz *
6255570Strasz * This software was developed by Edward Tomasz Napierala under sponsorship
7255570Strasz * from the FreeBSD Foundation.
8255570Strasz *
9255570Strasz * Redistribution and use in source and binary forms, with or without
10255570Strasz * modification, are permitted provided that the following conditions
11255570Strasz * are met:
12255570Strasz * 1. Redistributions of source code must retain the above copyright
13255570Strasz *    notice, this list of conditions and the following disclaimer.
14255570Strasz * 2. Redistributions in binary form must reproduce the above copyright
15255570Strasz *    notice, this list of conditions and the following disclaimer in the
16255570Strasz *    documentation and/or other materials provided with the distribution.
17255570Strasz *
18255570Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21255570Strasz * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28255570Strasz * SUCH DAMAGE.
29255570Strasz *
30255570Strasz * $FreeBSD: head/usr.bin/iscsictl/parse.y 301033 2016-05-31 11:32:07Z trasz $
31255570Strasz */
32255570Strasz
33255570Strasz#include <sys/queue.h>
34255570Strasz#include <sys/types.h>
35255570Strasz#include <sys/stat.h>
36255570Strasz#include <assert.h>
37255570Strasz#include <stdio.h>
38255570Strasz#include <stdint.h>
39255570Strasz#include <stdlib.h>
40255570Strasz#include <string.h>
41255570Strasz
42281461Strasz#include <libxo/xo.h>
43281461Strasz
44255570Strasz#include "iscsictl.h"
45255570Strasz
46255570Straszextern FILE *yyin;
47255570Straszextern char *yytext;
48255570Straszextern int lineno;
49255570Strasz
50255570Straszstatic struct conf *conf;
51255570Straszstatic struct target *target;
52255570Strasz
53255570Straszextern void	yyerror(const char *);
54255570Straszextern int	yylex(void);
55255570Straszextern void	yyrestart(FILE *);
56255570Strasz
57255570Strasz%}
58255570Strasz
59301033Strasz%token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
60255570Strasz%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
61278232Strasz%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
62278232Strasz%token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET
63255570Strasz
64255570Strasz%union
65255570Strasz{
66255570Strasz	char *str;
67255570Strasz}
68255570Strasz
69255570Strasz%token <str> STR
70255570Strasz
71255570Strasz%%
72255570Strasz
73261711Strasztargets:
74255570Strasz	|
75261711Strasz	targets target
76255570Strasz	;
77255570Strasz
78261711Strasztarget:		STR OPENING_BRACKET target_entries CLOSING_BRACKET
79255570Strasz	{
80255570Strasz		if (target_find(conf, $1) != NULL)
81281461Strasz			xo_errx(1, "duplicated target %s", $1);
82255570Strasz		target->t_nickname = $1;
83255570Strasz		target = target_new(conf);
84255570Strasz	}
85255570Strasz	;
86255570Strasz
87255570Strasztarget_entries:
88255570Strasz	|
89255570Strasz	target_entries target_entry
90261714Strasz	|
91261714Strasz	target_entries target_entry SEMICOLON
92255570Strasz	;
93255570Strasz
94255570Strasztarget_entry:
95261711Strasz	target_name
96255570Strasz	|
97261711Strasz	target_address
98255570Strasz	|
99261711Strasz	initiator_name
100255570Strasz	|
101261711Strasz	initiator_address
102255570Strasz	|
103261711Strasz	initiator_alias
104255570Strasz	|
105261711Strasz	user
106255570Strasz	|
107261711Strasz	secret
108255570Strasz	|
109261711Strasz	mutual_user
110255570Strasz	|
111261711Strasz	mutual_secret
112255570Strasz	|
113261711Strasz	auth_method
114255570Strasz	|
115261711Strasz	header_digest
116255570Strasz	|
117261711Strasz	data_digest
118255570Strasz	|
119261711Strasz	session_type
120255570Strasz	|
121301033Strasz	enable
122301033Strasz	|
123278232Strasz	offload
124278232Strasz	|
125261711Strasz	protocol
126255570Strasz	|
127261711Strasz	ignored
128255570Strasz	;
129255570Strasz
130261711Strasztarget_name:	TARGET_NAME EQUALS STR
131255570Strasz	{
132255570Strasz		if (target->t_name != NULL)
133281461Strasz			xo_errx(1, "duplicated TargetName at line %d", lineno);
134255570Strasz		target->t_name = $3;
135255570Strasz	}
136255570Strasz	;
137255570Strasz
138261711Strasztarget_address:	TARGET_ADDRESS EQUALS STR
139255570Strasz	{
140255570Strasz		if (target->t_address != NULL)
141281461Strasz			xo_errx(1, "duplicated TargetAddress at line %d", lineno);
142255570Strasz		target->t_address = $3;
143255570Strasz	}
144255570Strasz	;
145255570Strasz
146261711Straszinitiator_name:	INITIATOR_NAME EQUALS STR
147255570Strasz	{
148255570Strasz		if (target->t_initiator_name != NULL)
149281461Strasz			xo_errx(1, "duplicated InitiatorName at line %d", lineno);
150255570Strasz		target->t_initiator_name = $3;
151255570Strasz	}
152255570Strasz	;
153255570Strasz
154261711Straszinitiator_address:	INITIATOR_ADDRESS EQUALS STR
155255570Strasz	{
156255570Strasz		if (target->t_initiator_address != NULL)
157281461Strasz			xo_errx(1, "duplicated InitiatorAddress at line %d", lineno);
158255570Strasz		target->t_initiator_address = $3;
159255570Strasz	}
160255570Strasz	;
161255570Strasz
162261711Straszinitiator_alias:	INITIATOR_ALIAS EQUALS STR
163255570Strasz	{
164255570Strasz		if (target->t_initiator_alias != NULL)
165281461Strasz			xo_errx(1, "duplicated InitiatorAlias at line %d", lineno);
166255570Strasz		target->t_initiator_alias = $3;
167255570Strasz	}
168255570Strasz	;
169255570Strasz
170261711Straszuser:		USER EQUALS STR
171255570Strasz	{
172255570Strasz		if (target->t_user != NULL)
173281461Strasz			xo_errx(1, "duplicated chapIName at line %d", lineno);
174255570Strasz		target->t_user = $3;
175255570Strasz	}
176255570Strasz	;
177255570Strasz
178261711Straszsecret:		SECRET EQUALS STR
179255570Strasz	{
180255570Strasz		if (target->t_secret != NULL)
181281461Strasz			xo_errx(1, "duplicated chapSecret at line %d", lineno);
182255570Strasz		target->t_secret = $3;
183255570Strasz	}
184255570Strasz	;
185255570Strasz
186261711Straszmutual_user:	MUTUAL_USER EQUALS STR
187255570Strasz	{
188255570Strasz		if (target->t_mutual_user != NULL)
189281461Strasz			xo_errx(1, "duplicated tgtChapName at line %d", lineno);
190255570Strasz		target->t_mutual_user = $3;
191255570Strasz	}
192255570Strasz	;
193255570Strasz
194261711Straszmutual_secret:	MUTUAL_SECRET EQUALS STR
195255570Strasz	{
196255570Strasz		if (target->t_mutual_secret != NULL)
197281461Strasz			xo_errx(1, "duplicated tgtChapSecret at line %d", lineno);
198255570Strasz		target->t_mutual_secret = $3;
199255570Strasz	}
200255570Strasz	;
201255570Strasz
202261711Straszauth_method:	AUTH_METHOD EQUALS STR
203255570Strasz	{
204255570Strasz		if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
205281461Strasz			xo_errx(1, "duplicated AuthMethod at line %d", lineno);
206255570Strasz		if (strcasecmp($3, "none") == 0)
207255570Strasz			target->t_auth_method = AUTH_METHOD_NONE;
208255570Strasz		else if (strcasecmp($3, "chap") == 0)
209255570Strasz			target->t_auth_method = AUTH_METHOD_CHAP;
210255570Strasz		else
211281461Strasz			xo_errx(1, "invalid AuthMethod at line %d; "
212261713Strasz			    "must be either \"none\" or \"CHAP\"", lineno);
213255570Strasz	}
214255570Strasz	;
215255570Strasz
216261711Straszheader_digest:	HEADER_DIGEST EQUALS STR
217255570Strasz	{
218255570Strasz		if (target->t_header_digest != DIGEST_UNSPECIFIED)
219281461Strasz			xo_errx(1, "duplicated HeaderDigest at line %d", lineno);
220255570Strasz		if (strcasecmp($3, "none") == 0)
221255570Strasz			target->t_header_digest = DIGEST_NONE;
222255570Strasz		else if (strcasecmp($3, "CRC32C") == 0)
223255570Strasz			target->t_header_digest = DIGEST_CRC32C;
224255570Strasz		else
225281461Strasz			xo_errx(1, "invalid HeaderDigest at line %d; "
226261713Strasz			    "must be either \"none\" or \"CRC32C\"", lineno);
227255570Strasz	}
228255570Strasz	;
229255570Strasz
230261711Straszdata_digest:	DATA_DIGEST EQUALS STR
231255570Strasz	{
232255570Strasz		if (target->t_data_digest != DIGEST_UNSPECIFIED)
233281461Strasz			xo_errx(1, "duplicated DataDigest at line %d", lineno);
234255570Strasz		if (strcasecmp($3, "none") == 0)
235255570Strasz			target->t_data_digest = DIGEST_NONE;
236255570Strasz		else if (strcasecmp($3, "CRC32C") == 0)
237255570Strasz			target->t_data_digest = DIGEST_CRC32C;
238255570Strasz		else
239281461Strasz			xo_errx(1, "invalid DataDigest at line %d; "
240261713Strasz			    "must be either \"none\" or \"CRC32C\"", lineno);
241255570Strasz	}
242255570Strasz	;
243255570Strasz
244261711Straszsession_type:	SESSION_TYPE EQUALS STR
245255570Strasz	{
246255570Strasz		if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
247281461Strasz			xo_errx(1, "duplicated SessionType at line %d", lineno);
248255570Strasz		if (strcasecmp($3, "normal") == 0)
249255570Strasz			target->t_session_type = SESSION_TYPE_NORMAL;
250255570Strasz		else if (strcasecmp($3, "discovery") == 0)
251255570Strasz			target->t_session_type = SESSION_TYPE_DISCOVERY;
252255570Strasz		else
253281461Strasz			xo_errx(1, "invalid SessionType at line %d; "
254261713Strasz			    "must be either \"normal\" or \"discovery\"", lineno);
255255570Strasz	}
256255570Strasz	;
257255570Strasz
258301033Straszenable:		ENABLE EQUALS STR
259301033Strasz	{
260301033Strasz		if (target->t_enable != ENABLE_UNSPECIFIED)
261301033Strasz			xo_errx(1, "duplicated enable at line %d", lineno);
262301033Strasz		target->t_enable = parse_enable($3);
263301033Strasz		if (target->t_enable == ENABLE_UNSPECIFIED)
264301033Strasz			xo_errx(1, "invalid enable at line %d; "
265301033Strasz			    "must be either \"on\" or \"off\"", lineno);
266301033Strasz	}
267301033Strasz	;
268301033Strasz
269278232Straszoffload:	OFFLOAD EQUALS STR
270278232Strasz	{
271278232Strasz		if (target->t_offload != NULL)
272281461Strasz			xo_errx(1, "duplicated offload at line %d", lineno);
273278232Strasz		target->t_offload = $3;
274278232Strasz	}
275278232Strasz	;
276278232Strasz
277261711Straszprotocol:	PROTOCOL EQUALS STR
278255570Strasz	{
279255570Strasz		if (target->t_protocol != PROTOCOL_UNSPECIFIED)
280281461Strasz			xo_errx(1, "duplicated protocol at line %d", lineno);
281255570Strasz		if (strcasecmp($3, "iscsi") == 0)
282255570Strasz			target->t_protocol = PROTOCOL_ISCSI;
283255570Strasz		else if (strcasecmp($3, "iser") == 0)
284255570Strasz			target->t_protocol = PROTOCOL_ISER;
285255570Strasz		else
286281461Strasz			xo_errx(1, "invalid protocol at line %d; "
287261713Strasz			    "must be either \"iscsi\" or \"iser\"", lineno);
288255570Strasz	}
289255570Strasz	;
290255570Strasz
291261711Straszignored:	IGNORED EQUALS STR
292255570Strasz	{
293281461Strasz		xo_warnx("obsolete statement ignored at line %d", lineno);
294255570Strasz	}
295255570Strasz	;
296255570Strasz
297255570Strasz%%
298255570Strasz
299255570Straszvoid
300255570Straszyyerror(const char *str)
301255570Strasz{
302255570Strasz
303281461Strasz	xo_errx(1, "error in configuration file at line %d near '%s': %s",
304261713Strasz	    lineno, yytext, str);
305255570Strasz}
306255570Strasz
307255570Straszstatic void
308255570Straszcheck_perms(const char *path)
309255570Strasz{
310255570Strasz	struct stat sb;
311255570Strasz	int error;
312255570Strasz
313255570Strasz	error = stat(path, &sb);
314255570Strasz	if (error != 0) {
315281461Strasz		xo_warn("stat");
316255570Strasz		return;
317255570Strasz	}
318255570Strasz	if (sb.st_mode & S_IWOTH) {
319281461Strasz		xo_warnx("%s is world-writable", path);
320255570Strasz	} else if (sb.st_mode & S_IROTH) {
321281461Strasz		xo_warnx("%s is world-readable", path);
322255570Strasz	} else if (sb.st_mode & S_IXOTH) {
323255570Strasz		/*
324255570Strasz		 * Ok, this one doesn't matter, but still do it,
325255570Strasz		 * just for consistency.
326255570Strasz		 */
327281461Strasz		xo_warnx("%s is world-executable", path);
328255570Strasz	}
329255570Strasz
330255570Strasz	/*
331255570Strasz	 * XXX: Should we also check for owner != 0?
332255570Strasz	 */
333255570Strasz}
334255570Strasz
335255570Straszstruct conf *
336255570Straszconf_new_from_file(const char *path)
337255570Strasz{
338255570Strasz	int error;
339255570Strasz
340255570Strasz	conf = conf_new();
341255570Strasz	target = target_new(conf);
342255570Strasz
343255570Strasz	yyin = fopen(path, "r");
344255570Strasz	if (yyin == NULL)
345281461Strasz		xo_err(1, "unable to open configuration file %s", path);
346255570Strasz	check_perms(path);
347261713Strasz	lineno = 1;
348255570Strasz	yyrestart(yyin);
349255570Strasz	error = yyparse();
350255570Strasz	assert(error == 0);
351255570Strasz	fclose(yyin);
352255570Strasz
353255570Strasz	assert(target->t_nickname == NULL);
354255570Strasz	target_delete(target);
355255570Strasz
356255570Strasz	conf_verify(conf);
357255570Strasz
358255570Strasz	return (conf);
359255570Strasz}
360