parse.y revision 275244
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: stable/10/usr.sbin/ctld/parse.y 275244 2014-11-29 15:32:15Z 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
42255570Strasz#include "ctld.h"
43255570Strasz
44255570Straszextern FILE *yyin;
45255570Straszextern char *yytext;
46255570Straszextern int lineno;
47255570Strasz
48255570Straszstatic struct conf *conf = NULL;
49255570Straszstatic struct auth_group *auth_group = NULL;
50255570Straszstatic struct portal_group *portal_group = NULL;
51255570Straszstatic struct target *target = NULL;
52255570Straszstatic struct lun *lun = NULL;
53255570Strasz
54255570Straszextern void	yyerror(const char *);
55255570Straszextern int	yylex(void);
56255570Straszextern void	yyrestart(FILE *);
57255570Strasz
58255570Strasz%}
59255570Strasz
60263724Strasz%token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
61275244Strasz%token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER
62275244Strasz%token INITIATOR_NAME INITIATOR_PORTAL LISTEN LISTEN_ISER LUN MAXPROC
63275244Strasz%token OPENING_BRACKET OPTION PATH PIDFILE PORTAL_GROUP SERIAL SIZE STR
64275244Strasz%token TARGET TIMEOUT ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
65255570Strasz
66255570Strasz%union
67255570Strasz{
68255570Strasz	char *str;
69255570Strasz}
70255570Strasz
71255570Strasz%token <str> STR
72255570Strasz
73255570Strasz%%
74255570Strasz
75255570Straszstatements:
76255570Strasz	|
77255570Strasz	statements statement
78255570Strasz	;
79255570Strasz
80255570Straszstatement:
81263722Strasz	debug
82255570Strasz	|
83263722Strasz	timeout
84255570Strasz	|
85263722Strasz	maxproc
86255570Strasz	|
87263722Strasz	pidfile
88255570Strasz	|
89274939Smav	isns_server
90274939Smav	|
91274939Smav	isns_period
92274939Smav	|
93274939Smav	isns_timeout
94274939Smav	|
95263722Strasz	auth_group
96255570Strasz	|
97263722Strasz	portal_group
98255570Strasz	|
99263722Strasz	target
100255570Strasz	;
101255570Strasz
102275186Straszdebug:		DEBUG STR
103255570Strasz	{
104275186Strasz		uint64_t tmp;
105275186Strasz
106275186Strasz		if (expand_number($2, &tmp) != 0) {
107275187Strasz			yyerror("invalid numeric value");
108275186Strasz			free($2);
109275186Strasz			return (1);
110275186Strasz		}
111275186Strasz
112275186Strasz		conf->conf_debug = tmp;
113255570Strasz	}
114255570Strasz	;
115255570Strasz
116275186Strasztimeout:	TIMEOUT STR
117255570Strasz	{
118275186Strasz		uint64_t tmp;
119275186Strasz
120275186Strasz		if (expand_number($2, &tmp) != 0) {
121275187Strasz			yyerror("invalid numeric value");
122275186Strasz			free($2);
123275186Strasz			return (1);
124275186Strasz		}
125275186Strasz
126275186Strasz		conf->conf_timeout = tmp;
127255570Strasz	}
128255570Strasz	;
129255570Strasz
130275186Straszmaxproc:	MAXPROC STR
131255570Strasz	{
132275186Strasz		uint64_t tmp;
133275186Strasz
134275186Strasz		if (expand_number($2, &tmp) != 0) {
135275187Strasz			yyerror("invalid numeric value");
136275186Strasz			free($2);
137275186Strasz			return (1);
138275186Strasz		}
139275186Strasz
140275186Strasz		conf->conf_maxproc = tmp;
141255570Strasz	}
142255570Strasz	;
143255570Strasz
144263722Straszpidfile:	PIDFILE STR
145255570Strasz	{
146255570Strasz		if (conf->conf_pidfile_path != NULL) {
147255570Strasz			log_warnx("pidfile specified more than once");
148255570Strasz			free($2);
149255570Strasz			return (1);
150255570Strasz		}
151255570Strasz		conf->conf_pidfile_path = $2;
152255570Strasz	}
153255570Strasz	;
154255570Strasz
155274939Smavisns_server:	ISNS_SERVER STR
156274939Smav	{
157274939Smav		int error;
158274939Smav
159274939Smav		error = isns_new(conf, $2);
160274939Smav		free($2);
161274939Smav		if (error != 0)
162274939Smav			return (1);
163274939Smav	}
164274939Smav	;
165274939Smav
166275187Straszisns_period:	ISNS_PERIOD STR
167274939Smav	{
168275187Strasz		uint64_t tmp;
169275187Strasz
170275187Strasz		if (expand_number($2, &tmp) != 0) {
171275187Strasz			yyerror("invalid numeric value");
172275187Strasz			free($2);
173275187Strasz			return (1);
174275187Strasz		}
175275187Strasz
176275187Strasz		conf->conf_isns_period = tmp;
177274939Smav	}
178274939Smav	;
179274939Smav
180275187Straszisns_timeout:	ISNS_TIMEOUT STR
181274939Smav	{
182275187Strasz		uint64_t tmp;
183275187Strasz
184275187Strasz		if (expand_number($2, &tmp) != 0) {
185275187Strasz			yyerror("invalid numeric value");
186275187Strasz			free($2);
187275187Strasz			return (1);
188275187Strasz		}
189275187Strasz
190275187Strasz		conf->conf_isns_timeout = tmp;
191274939Smav	}
192274939Smav	;
193274939Smav
194263722Straszauth_group:	AUTH_GROUP auth_group_name
195255570Strasz    OPENING_BRACKET auth_group_entries CLOSING_BRACKET
196255570Strasz	{
197255570Strasz		auth_group = NULL;
198255570Strasz	}
199255570Strasz	;
200255570Strasz
201255570Straszauth_group_name:	STR
202255570Strasz	{
203263726Strasz		/*
204263726Strasz		 * Make it possible to redefine default
205263726Strasz		 * auth-group. but only once.
206263726Strasz		 */
207263726Strasz		if (strcmp($1, "default") == 0 &&
208263726Strasz		    conf->conf_default_ag_defined == false) {
209263726Strasz			auth_group = auth_group_find(conf, $1);
210263726Strasz			conf->conf_default_ag_defined = true;
211263726Strasz		} else {
212263726Strasz			auth_group = auth_group_new(conf, $1);
213263726Strasz		}
214255570Strasz		free($1);
215255570Strasz		if (auth_group == NULL)
216255570Strasz			return (1);
217255570Strasz	}
218255570Strasz	;
219255570Strasz
220255570Straszauth_group_entries:
221255570Strasz	|
222255570Strasz	auth_group_entries auth_group_entry
223255570Strasz	;
224255570Strasz
225255570Straszauth_group_entry:
226263724Strasz	auth_group_auth_type
227263724Strasz	|
228255570Strasz	auth_group_chap
229255570Strasz	|
230255570Strasz	auth_group_chap_mutual
231263720Strasz	|
232263720Strasz	auth_group_initiator_name
233263720Strasz	|
234263720Strasz	auth_group_initiator_portal
235255570Strasz	;
236255570Strasz
237263724Straszauth_group_auth_type:	AUTH_TYPE STR
238263724Strasz	{
239263724Strasz		int error;
240263724Strasz
241263724Strasz		error = auth_group_set_type_str(auth_group, $2);
242263724Strasz		free($2);
243263724Strasz		if (error != 0)
244263724Strasz			return (1);
245263724Strasz	}
246263724Strasz	;
247263724Strasz
248255570Straszauth_group_chap:	CHAP STR STR
249255570Strasz	{
250255570Strasz		const struct auth *ca;
251255570Strasz
252255570Strasz		ca = auth_new_chap(auth_group, $2, $3);
253255570Strasz		free($2);
254255570Strasz		free($3);
255255570Strasz		if (ca == NULL)
256255570Strasz			return (1);
257255570Strasz	}
258255570Strasz	;
259255570Strasz
260255570Straszauth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
261255570Strasz	{
262255570Strasz		const struct auth *ca;
263255570Strasz
264255570Strasz		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
265255570Strasz		free($2);
266255570Strasz		free($3);
267255570Strasz		free($4);
268255570Strasz		free($5);
269255570Strasz		if (ca == NULL)
270255570Strasz			return (1);
271255570Strasz	}
272255570Strasz	;
273255570Strasz
274263720Straszauth_group_initiator_name:	INITIATOR_NAME STR
275263720Strasz	{
276263720Strasz		const struct auth_name *an;
277263720Strasz
278263720Strasz		an = auth_name_new(auth_group, $2);
279263720Strasz		free($2);
280263720Strasz		if (an == NULL)
281263720Strasz			return (1);
282263720Strasz	}
283263720Strasz	;
284263720Strasz
285263720Straszauth_group_initiator_portal:	INITIATOR_PORTAL STR
286263720Strasz	{
287263720Strasz		const struct auth_portal *ap;
288263720Strasz
289263720Strasz		ap = auth_portal_new(auth_group, $2);
290263720Strasz		free($2);
291263720Strasz		if (ap == NULL)
292263720Strasz			return (1);
293263720Strasz	}
294263720Strasz	;
295263720Strasz
296263722Straszportal_group:	PORTAL_GROUP portal_group_name
297255570Strasz    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
298255570Strasz	{
299255570Strasz		portal_group = NULL;
300255570Strasz	}
301255570Strasz	;
302255570Strasz
303255570Straszportal_group_name:	STR
304255570Strasz	{
305263725Strasz		/*
306263725Strasz		 * Make it possible to redefine default
307263725Strasz		 * portal-group. but only once.
308263725Strasz		 */
309263725Strasz		if (strcmp($1, "default") == 0 &&
310263725Strasz		    conf->conf_default_pg_defined == false) {
311263725Strasz			portal_group = portal_group_find(conf, $1);
312263725Strasz			conf->conf_default_pg_defined = true;
313263725Strasz		} else {
314263725Strasz			portal_group = portal_group_new(conf, $1);
315263725Strasz		}
316255570Strasz		free($1);
317255570Strasz		if (portal_group == NULL)
318255570Strasz			return (1);
319255570Strasz	}
320255570Strasz	;
321255570Strasz
322255570Straszportal_group_entries:
323255570Strasz	|
324255570Strasz	portal_group_entries portal_group_entry
325255570Strasz	;
326255570Strasz
327255570Straszportal_group_entry:
328255570Strasz	portal_group_discovery_auth_group
329255570Strasz	|
330275244Strasz	portal_group_discovery_filter
331275244Strasz	|
332255570Strasz	portal_group_listen
333255570Strasz	|
334255570Strasz	portal_group_listen_iser
335255570Strasz	;
336255570Strasz
337255570Straszportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
338255570Strasz	{
339255570Strasz		if (portal_group->pg_discovery_auth_group != NULL) {
340255570Strasz			log_warnx("discovery-auth-group for portal-group "
341255570Strasz			    "\"%s\" specified more than once",
342255570Strasz			    portal_group->pg_name);
343255570Strasz			return (1);
344255570Strasz		}
345255570Strasz		portal_group->pg_discovery_auth_group =
346255570Strasz		    auth_group_find(conf, $2);
347255570Strasz		if (portal_group->pg_discovery_auth_group == NULL) {
348255570Strasz			log_warnx("unknown discovery-auth-group \"%s\" "
349255570Strasz			    "for portal-group \"%s\"",
350255570Strasz			    $2, portal_group->pg_name);
351255570Strasz			return (1);
352255570Strasz		}
353255570Strasz		free($2);
354255570Strasz	}
355255570Strasz	;
356255570Strasz
357275244Straszportal_group_discovery_filter:	DISCOVERY_FILTER STR
358275244Strasz	{
359275244Strasz		int error;
360275244Strasz
361275244Strasz		error = portal_group_set_filter_str(portal_group, $2);
362275244Strasz		free($2);
363275244Strasz		if (error != 0)
364275244Strasz			return (1);
365275244Strasz	}
366275244Strasz	;
367275244Strasz
368255570Straszportal_group_listen:	LISTEN STR
369255570Strasz	{
370255570Strasz		int error;
371255570Strasz
372255570Strasz		error = portal_group_add_listen(portal_group, $2, false);
373255570Strasz		free($2);
374255570Strasz		if (error != 0)
375255570Strasz			return (1);
376255570Strasz	}
377255570Strasz	;
378255570Strasz
379255570Straszportal_group_listen_iser:	LISTEN_ISER STR
380255570Strasz	{
381255570Strasz		int error;
382255570Strasz
383255570Strasz		error = portal_group_add_listen(portal_group, $2, true);
384255570Strasz		free($2);
385255570Strasz		if (error != 0)
386255570Strasz			return (1);
387255570Strasz	}
388255570Strasz	;
389255570Strasz
390263722Strasztarget:	TARGET target_name
391255570Strasz    OPENING_BRACKET target_entries CLOSING_BRACKET
392255570Strasz	{
393255570Strasz		target = NULL;
394255570Strasz	}
395255570Strasz	;
396255570Strasz
397263722Strasztarget_name:	STR
398255570Strasz	{
399255570Strasz		target = target_new(conf, $1);
400255570Strasz		free($1);
401255570Strasz		if (target == NULL)
402255570Strasz			return (1);
403255570Strasz	}
404255570Strasz	;
405255570Strasz
406255570Strasztarget_entries:
407255570Strasz	|
408255570Strasz	target_entries target_entry
409255570Strasz	;
410255570Strasz
411255570Strasztarget_entry:
412263722Strasz	target_alias
413255570Strasz	|
414263722Strasz	target_auth_group
415255570Strasz	|
416263724Strasz	target_auth_type
417263724Strasz	|
418263722Strasz	target_chap
419255570Strasz	|
420263722Strasz	target_chap_mutual
421255570Strasz	|
422263722Strasz	target_initiator_name
423263720Strasz	|
424263722Strasz	target_initiator_portal
425263720Strasz	|
426263722Strasz	target_portal_group
427255570Strasz	|
428263722Strasz	target_lun
429255570Strasz	;
430255570Strasz
431263722Strasztarget_alias:	ALIAS STR
432255570Strasz	{
433255570Strasz		if (target->t_alias != NULL) {
434255570Strasz			log_warnx("alias for target \"%s\" "
435263723Strasz			    "specified more than once", target->t_name);
436255570Strasz			return (1);
437255570Strasz		}
438255570Strasz		target->t_alias = $2;
439255570Strasz	}
440255570Strasz	;
441255570Strasz
442263722Strasztarget_auth_group:	AUTH_GROUP STR
443255570Strasz	{
444255570Strasz		if (target->t_auth_group != NULL) {
445255570Strasz			if (target->t_auth_group->ag_name != NULL)
446255570Strasz				log_warnx("auth-group for target \"%s\" "
447263723Strasz				    "specified more than once", target->t_name);
448255570Strasz			else
449263724Strasz				log_warnx("cannot use both auth-group and explicit "
450255570Strasz				    "authorisations for target \"%s\"",
451263723Strasz				    target->t_name);
452255570Strasz			return (1);
453255570Strasz		}
454255570Strasz		target->t_auth_group = auth_group_find(conf, $2);
455255570Strasz		if (target->t_auth_group == NULL) {
456255570Strasz			log_warnx("unknown auth-group \"%s\" for target "
457263723Strasz			    "\"%s\"", $2, target->t_name);
458255570Strasz			return (1);
459255570Strasz		}
460255570Strasz		free($2);
461255570Strasz	}
462255570Strasz	;
463255570Strasz
464263724Strasztarget_auth_type:	AUTH_TYPE STR
465263724Strasz	{
466263724Strasz		int error;
467263724Strasz
468263724Strasz		if (target->t_auth_group != NULL) {
469263724Strasz			if (target->t_auth_group->ag_name != NULL) {
470263724Strasz				log_warnx("cannot use both auth-group and "
471263724Strasz				    "auth-type for target \"%s\"",
472263724Strasz				    target->t_name);
473263724Strasz				return (1);
474263724Strasz			}
475263724Strasz		} else {
476263724Strasz			target->t_auth_group = auth_group_new(conf, NULL);
477263724Strasz			if (target->t_auth_group == NULL) {
478263724Strasz				free($2);
479263724Strasz				return (1);
480263724Strasz			}
481263724Strasz			target->t_auth_group->ag_target = target;
482263724Strasz		}
483263724Strasz		error = auth_group_set_type_str(target->t_auth_group, $2);
484263724Strasz		free($2);
485263724Strasz		if (error != 0)
486263724Strasz			return (1);
487263724Strasz	}
488263724Strasz	;
489263724Strasz
490263722Strasztarget_chap:	CHAP STR STR
491255570Strasz	{
492255570Strasz		const struct auth *ca;
493255570Strasz
494255570Strasz		if (target->t_auth_group != NULL) {
495255570Strasz			if (target->t_auth_group->ag_name != NULL) {
496263724Strasz				log_warnx("cannot use both auth-group and "
497263724Strasz				    "chap for target \"%s\"",
498263723Strasz				    target->t_name);
499255570Strasz				free($2);
500255570Strasz				free($3);
501255570Strasz				return (1);
502255570Strasz			}
503255570Strasz		} else {
504255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
505255570Strasz			if (target->t_auth_group == NULL) {
506255570Strasz				free($2);
507255570Strasz				free($3);
508255570Strasz				return (1);
509255570Strasz			}
510255570Strasz			target->t_auth_group->ag_target = target;
511255570Strasz		}
512255570Strasz		ca = auth_new_chap(target->t_auth_group, $2, $3);
513255570Strasz		free($2);
514255570Strasz		free($3);
515255570Strasz		if (ca == NULL)
516255570Strasz			return (1);
517255570Strasz	}
518255570Strasz	;
519255570Strasz
520263722Strasztarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
521255570Strasz	{
522255570Strasz		const struct auth *ca;
523255570Strasz
524255570Strasz		if (target->t_auth_group != NULL) {
525255570Strasz			if (target->t_auth_group->ag_name != NULL) {
526263724Strasz				log_warnx("cannot use both auth-group and "
527263724Strasz				    "chap-mutual for target \"%s\"",
528263723Strasz				    target->t_name);
529255570Strasz				free($2);
530255570Strasz				free($3);
531255570Strasz				free($4);
532255570Strasz				free($5);
533255570Strasz				return (1);
534255570Strasz			}
535255570Strasz		} else {
536255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
537255570Strasz			if (target->t_auth_group == NULL) {
538255570Strasz				free($2);
539255570Strasz				free($3);
540255570Strasz				free($4);
541255570Strasz				free($5);
542255570Strasz				return (1);
543255570Strasz			}
544255570Strasz			target->t_auth_group->ag_target = target;
545255570Strasz		}
546255570Strasz		ca = auth_new_chap_mutual(target->t_auth_group,
547255570Strasz		    $2, $3, $4, $5);
548255570Strasz		free($2);
549255570Strasz		free($3);
550255570Strasz		free($4);
551255570Strasz		free($5);
552255570Strasz		if (ca == NULL)
553255570Strasz			return (1);
554255570Strasz	}
555255570Strasz	;
556255570Strasz
557263722Strasztarget_initiator_name:	INITIATOR_NAME STR
558263720Strasz	{
559263720Strasz		const struct auth_name *an;
560263720Strasz
561263720Strasz		if (target->t_auth_group != NULL) {
562263720Strasz			if (target->t_auth_group->ag_name != NULL) {
563263724Strasz				log_warnx("cannot use both auth-group and "
564263720Strasz				    "initiator-name for target \"%s\"",
565263723Strasz				    target->t_name);
566263720Strasz				free($2);
567263720Strasz				return (1);
568263720Strasz			}
569263720Strasz		} else {
570263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
571263720Strasz			if (target->t_auth_group == NULL) {
572263720Strasz				free($2);
573263720Strasz				return (1);
574263720Strasz			}
575263720Strasz			target->t_auth_group->ag_target = target;
576263720Strasz		}
577263720Strasz		an = auth_name_new(target->t_auth_group, $2);
578263720Strasz		free($2);
579263720Strasz		if (an == NULL)
580263720Strasz			return (1);
581263720Strasz	}
582263720Strasz	;
583263720Strasz
584263722Strasztarget_initiator_portal:	INITIATOR_PORTAL STR
585263720Strasz	{
586263720Strasz		const struct auth_portal *ap;
587263720Strasz
588263720Strasz		if (target->t_auth_group != NULL) {
589263720Strasz			if (target->t_auth_group->ag_name != NULL) {
590263724Strasz				log_warnx("cannot use both auth-group and "
591263720Strasz				    "initiator-portal for target \"%s\"",
592263723Strasz				    target->t_name);
593263720Strasz				free($2);
594263720Strasz				return (1);
595263720Strasz			}
596263720Strasz		} else {
597263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
598263720Strasz			if (target->t_auth_group == NULL) {
599263720Strasz				free($2);
600263720Strasz				return (1);
601263720Strasz			}
602263720Strasz			target->t_auth_group->ag_target = target;
603263720Strasz		}
604263720Strasz		ap = auth_portal_new(target->t_auth_group, $2);
605263720Strasz		free($2);
606263720Strasz		if (ap == NULL)
607263720Strasz			return (1);
608263720Strasz	}
609263720Strasz	;
610263720Strasz
611263722Strasztarget_portal_group:	PORTAL_GROUP STR
612255570Strasz	{
613255570Strasz		if (target->t_portal_group != NULL) {
614255570Strasz			log_warnx("portal-group for target \"%s\" "
615263723Strasz			    "specified more than once", target->t_name);
616255570Strasz			free($2);
617255570Strasz			return (1);
618255570Strasz		}
619255570Strasz		target->t_portal_group = portal_group_find(conf, $2);
620255570Strasz		if (target->t_portal_group == NULL) {
621255570Strasz			log_warnx("unknown portal-group \"%s\" for target "
622263723Strasz			    "\"%s\"", $2, target->t_name);
623255570Strasz			free($2);
624255570Strasz			return (1);
625255570Strasz		}
626255570Strasz		free($2);
627255570Strasz	}
628255570Strasz	;
629255570Strasz
630263722Strasztarget_lun:	LUN lun_number
631263722Strasz    OPENING_BRACKET lun_entries CLOSING_BRACKET
632255570Strasz	{
633255570Strasz		lun = NULL;
634255570Strasz	}
635255570Strasz	;
636255570Strasz
637275186Straszlun_number:	STR
638255570Strasz	{
639275186Strasz		uint64_t tmp;
640275186Strasz
641275186Strasz		if (expand_number($1, &tmp) != 0) {
642275187Strasz			yyerror("invalid numeric value");
643275186Strasz			free($1);
644275186Strasz			return (1);
645275186Strasz		}
646275186Strasz
647275186Strasz		lun = lun_new(target, tmp);
648255570Strasz		if (lun == NULL)
649255570Strasz			return (1);
650255570Strasz	}
651255570Strasz	;
652255570Strasz
653263722Straszlun_entries:
654255570Strasz	|
655263722Strasz	lun_entries lun_entry
656255570Strasz	;
657255570Strasz
658263722Straszlun_entry:
659263722Strasz	lun_backend
660255570Strasz	|
661263722Strasz	lun_blocksize
662255570Strasz	|
663263722Strasz	lun_device_id
664255570Strasz	|
665263722Strasz	lun_option
666255570Strasz	|
667263722Strasz	lun_path
668255570Strasz	|
669263722Strasz	lun_serial
670255570Strasz	|
671263722Strasz	lun_size
672255570Strasz	;
673255570Strasz
674263722Straszlun_backend:	BACKEND STR
675255570Strasz	{
676255570Strasz		if (lun->l_backend != NULL) {
677255570Strasz			log_warnx("backend for lun %d, target \"%s\" "
678255570Strasz			    "specified more than once",
679263723Strasz			    lun->l_lun, target->t_name);
680255570Strasz			free($2);
681255570Strasz			return (1);
682255570Strasz		}
683255570Strasz		lun_set_backend(lun, $2);
684255570Strasz		free($2);
685255570Strasz	}
686255570Strasz	;
687255570Strasz
688275186Straszlun_blocksize:	BLOCKSIZE STR
689255570Strasz	{
690275186Strasz		uint64_t tmp;
691275186Strasz
692275186Strasz		if (expand_number($2, &tmp) != 0) {
693275187Strasz			yyerror("invalid numeric value");
694275186Strasz			free($2);
695275186Strasz			return (1);
696275186Strasz		}
697275186Strasz
698255570Strasz		if (lun->l_blocksize != 0) {
699255570Strasz			log_warnx("blocksize for lun %d, target \"%s\" "
700255570Strasz			    "specified more than once",
701263723Strasz			    lun->l_lun, target->t_name);
702255570Strasz			return (1);
703255570Strasz		}
704275186Strasz		lun_set_blocksize(lun, tmp);
705255570Strasz	}
706255570Strasz	;
707255570Strasz
708263722Straszlun_device_id:	DEVICE_ID STR
709255570Strasz	{
710255570Strasz		if (lun->l_device_id != NULL) {
711255570Strasz			log_warnx("device_id for lun %d, target \"%s\" "
712255570Strasz			    "specified more than once",
713263723Strasz			    lun->l_lun, target->t_name);
714255570Strasz			free($2);
715255570Strasz			return (1);
716255570Strasz		}
717255570Strasz		lun_set_device_id(lun, $2);
718255570Strasz		free($2);
719255570Strasz	}
720255570Strasz	;
721255570Strasz
722263722Straszlun_option:	OPTION STR STR
723255570Strasz	{
724255570Strasz		struct lun_option *clo;
725274870Strasz
726255570Strasz		clo = lun_option_new(lun, $2, $3);
727255570Strasz		free($2);
728255570Strasz		free($3);
729255570Strasz		if (clo == NULL)
730255570Strasz			return (1);
731255570Strasz	}
732255570Strasz	;
733255570Strasz
734263722Straszlun_path:	PATH STR
735255570Strasz	{
736255570Strasz		if (lun->l_path != NULL) {
737255570Strasz			log_warnx("path for lun %d, target \"%s\" "
738255570Strasz			    "specified more than once",
739263723Strasz			    lun->l_lun, target->t_name);
740255570Strasz			free($2);
741255570Strasz			return (1);
742255570Strasz		}
743255570Strasz		lun_set_path(lun, $2);
744255570Strasz		free($2);
745255570Strasz	}
746255570Strasz	;
747255570Strasz
748263722Straszlun_serial:	SERIAL STR
749255570Strasz	{
750255570Strasz		if (lun->l_serial != NULL) {
751255570Strasz			log_warnx("serial for lun %d, target \"%s\" "
752255570Strasz			    "specified more than once",
753263723Strasz			    lun->l_lun, target->t_name);
754255570Strasz			free($2);
755255570Strasz			return (1);
756255570Strasz		}
757255570Strasz		lun_set_serial(lun, $2);
758255570Strasz		free($2);
759275186Strasz	}
760275186Strasz	;
761275186Strasz
762275186Straszlun_size:	SIZE STR
763267962Sjpaetzel	{
764275186Strasz		uint64_t tmp;
765267962Sjpaetzel
766275186Strasz		if (expand_number($2, &tmp) != 0) {
767275187Strasz			yyerror("invalid numeric value");
768275186Strasz			free($2);
769267962Sjpaetzel			return (1);
770267962Sjpaetzel		}
771255570Strasz
772255570Strasz		if (lun->l_size != 0) {
773255570Strasz			log_warnx("size for lun %d, target \"%s\" "
774255570Strasz			    "specified more than once",
775263723Strasz			    lun->l_lun, target->t_name);
776255570Strasz			return (1);
777255570Strasz		}
778275186Strasz		lun_set_size(lun, tmp);
779255570Strasz	}
780255570Strasz	;
781255570Strasz%%
782255570Strasz
783255570Straszvoid
784255570Straszyyerror(const char *str)
785255570Strasz{
786255570Strasz
787255570Strasz	log_warnx("error in configuration file at line %d near '%s': %s",
788255570Strasz	    lineno, yytext, str);
789255570Strasz}
790255570Strasz
791255570Straszstatic void
792255570Straszcheck_perms(const char *path)
793255570Strasz{
794255570Strasz	struct stat sb;
795255570Strasz	int error;
796255570Strasz
797255570Strasz	error = stat(path, &sb);
798255570Strasz	if (error != 0) {
799255570Strasz		log_warn("stat");
800255570Strasz		return;
801255570Strasz	}
802255570Strasz	if (sb.st_mode & S_IWOTH) {
803255570Strasz		log_warnx("%s is world-writable", path);
804255570Strasz	} else if (sb.st_mode & S_IROTH) {
805255570Strasz		log_warnx("%s is world-readable", path);
806255570Strasz	} else if (sb.st_mode & S_IXOTH) {
807255570Strasz		/*
808255570Strasz		 * Ok, this one doesn't matter, but still do it,
809255570Strasz		 * just for consistency.
810255570Strasz		 */
811255570Strasz		log_warnx("%s is world-executable", path);
812255570Strasz	}
813255570Strasz
814255570Strasz	/*
815255570Strasz	 * XXX: Should we also check for owner != 0?
816255570Strasz	 */
817255570Strasz}
818255570Strasz
819255570Straszstruct conf *
820255570Straszconf_new_from_file(const char *path)
821255570Strasz{
822255570Strasz	struct auth_group *ag;
823255570Strasz	struct portal_group *pg;
824255570Strasz	int error;
825255570Strasz
826255570Strasz	log_debugx("obtaining configuration from %s", path);
827255570Strasz
828255570Strasz	conf = conf_new();
829255570Strasz
830263726Strasz	ag = auth_group_new(conf, "default");
831263726Strasz	assert(ag != NULL);
832263726Strasz
833255570Strasz	ag = auth_group_new(conf, "no-authentication");
834263725Strasz	assert(ag != NULL);
835255570Strasz	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
836255570Strasz
837255570Strasz	ag = auth_group_new(conf, "no-access");
838263725Strasz	assert(ag != NULL);
839263729Strasz	ag->ag_type = AG_TYPE_DENY;
840255570Strasz
841255570Strasz	pg = portal_group_new(conf, "default");
842263725Strasz	assert(pg != NULL);
843255570Strasz
844255570Strasz	yyin = fopen(path, "r");
845255570Strasz	if (yyin == NULL) {
846255570Strasz		log_warn("unable to open configuration file %s", path);
847255570Strasz		conf_delete(conf);
848255570Strasz		return (NULL);
849255570Strasz	}
850255570Strasz	check_perms(path);
851263715Strasz	lineno = 1;
852255570Strasz	yyrestart(yyin);
853255570Strasz	error = yyparse();
854255570Strasz	auth_group = NULL;
855255570Strasz	portal_group = NULL;
856255570Strasz	target = NULL;
857255570Strasz	lun = NULL;
858255570Strasz	fclose(yyin);
859255570Strasz	if (error != 0) {
860255570Strasz		conf_delete(conf);
861255570Strasz		return (NULL);
862255570Strasz	}
863255570Strasz
864263726Strasz	if (conf->conf_default_ag_defined == false) {
865263726Strasz		log_debugx("auth-group \"default\" not defined; "
866263726Strasz		    "going with defaults");
867263726Strasz		ag = auth_group_find(conf, "default");
868263726Strasz		assert(ag != NULL);
869263729Strasz		ag->ag_type = AG_TYPE_DENY;
870263726Strasz	}
871263726Strasz
872263725Strasz	if (conf->conf_default_pg_defined == false) {
873263725Strasz		log_debugx("portal-group \"default\" not defined; "
874263725Strasz		    "going with defaults");
875263725Strasz		pg = portal_group_find(conf, "default");
876263725Strasz		assert(pg != NULL);
877263725Strasz		portal_group_add_listen(pg, "0.0.0.0:3260", false);
878263725Strasz		portal_group_add_listen(pg, "[::]:3260", false);
879263725Strasz	}
880263725Strasz
881265511Strasz	conf->conf_kernel_port_on = true;
882265511Strasz
883255570Strasz	error = conf_verify(conf);
884255570Strasz	if (error != 0) {
885255570Strasz		conf_delete(conf);
886255570Strasz		return (NULL);
887255570Strasz	}
888255570Strasz
889255570Strasz	return (conf);
890255570Strasz}
891