parse.y revision 275247
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 275247 2014-11-29 15:37:51Z 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
62275247Strasz%token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
63275247Strasz%token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION
64275247Strasz%token PATH PIDFILE PORTAL_GROUP SEMICOLON SERIAL SIZE STR TARGET TIMEOUT
65255570Strasz
66255570Strasz%union
67255570Strasz{
68255570Strasz	char *str;
69255570Strasz}
70255570Strasz
71255570Strasz%token <str> STR
72255570Strasz
73255570Strasz%%
74255570Strasz
75255570Straszstatements:
76255570Strasz	|
77255570Strasz	statements statement
78275246Strasz	|
79275246Strasz	statements statement SEMICOLON
80255570Strasz	;
81255570Strasz
82255570Straszstatement:
83263722Strasz	debug
84255570Strasz	|
85263722Strasz	timeout
86255570Strasz	|
87263722Strasz	maxproc
88255570Strasz	|
89263722Strasz	pidfile
90255570Strasz	|
91274939Smav	isns_server
92274939Smav	|
93274939Smav	isns_period
94274939Smav	|
95274939Smav	isns_timeout
96274939Smav	|
97263722Strasz	auth_group
98255570Strasz	|
99263722Strasz	portal_group
100255570Strasz	|
101263722Strasz	target
102255570Strasz	;
103255570Strasz
104275186Straszdebug:		DEBUG STR
105255570Strasz	{
106275186Strasz		uint64_t tmp;
107275186Strasz
108275186Strasz		if (expand_number($2, &tmp) != 0) {
109275187Strasz			yyerror("invalid numeric value");
110275186Strasz			free($2);
111275186Strasz			return (1);
112275186Strasz		}
113275186Strasz
114275186Strasz		conf->conf_debug = tmp;
115255570Strasz	}
116255570Strasz	;
117255570Strasz
118275186Strasztimeout:	TIMEOUT STR
119255570Strasz	{
120275186Strasz		uint64_t tmp;
121275186Strasz
122275186Strasz		if (expand_number($2, &tmp) != 0) {
123275187Strasz			yyerror("invalid numeric value");
124275186Strasz			free($2);
125275186Strasz			return (1);
126275186Strasz		}
127275186Strasz
128275186Strasz		conf->conf_timeout = tmp;
129255570Strasz	}
130255570Strasz	;
131255570Strasz
132275186Straszmaxproc:	MAXPROC STR
133255570Strasz	{
134275186Strasz		uint64_t tmp;
135275186Strasz
136275186Strasz		if (expand_number($2, &tmp) != 0) {
137275187Strasz			yyerror("invalid numeric value");
138275186Strasz			free($2);
139275186Strasz			return (1);
140275186Strasz		}
141275186Strasz
142275186Strasz		conf->conf_maxproc = tmp;
143255570Strasz	}
144255570Strasz	;
145255570Strasz
146263722Straszpidfile:	PIDFILE STR
147255570Strasz	{
148255570Strasz		if (conf->conf_pidfile_path != NULL) {
149255570Strasz			log_warnx("pidfile specified more than once");
150255570Strasz			free($2);
151255570Strasz			return (1);
152255570Strasz		}
153255570Strasz		conf->conf_pidfile_path = $2;
154255570Strasz	}
155255570Strasz	;
156255570Strasz
157274939Smavisns_server:	ISNS_SERVER STR
158274939Smav	{
159274939Smav		int error;
160274939Smav
161274939Smav		error = isns_new(conf, $2);
162274939Smav		free($2);
163274939Smav		if (error != 0)
164274939Smav			return (1);
165274939Smav	}
166274939Smav	;
167274939Smav
168275187Straszisns_period:	ISNS_PERIOD STR
169274939Smav	{
170275187Strasz		uint64_t tmp;
171275187Strasz
172275187Strasz		if (expand_number($2, &tmp) != 0) {
173275187Strasz			yyerror("invalid numeric value");
174275187Strasz			free($2);
175275187Strasz			return (1);
176275187Strasz		}
177275187Strasz
178275187Strasz		conf->conf_isns_period = tmp;
179274939Smav	}
180274939Smav	;
181274939Smav
182275187Straszisns_timeout:	ISNS_TIMEOUT STR
183274939Smav	{
184275187Strasz		uint64_t tmp;
185275187Strasz
186275187Strasz		if (expand_number($2, &tmp) != 0) {
187275187Strasz			yyerror("invalid numeric value");
188275187Strasz			free($2);
189275187Strasz			return (1);
190275187Strasz		}
191275187Strasz
192275187Strasz		conf->conf_isns_timeout = tmp;
193274939Smav	}
194274939Smav	;
195274939Smav
196263722Straszauth_group:	AUTH_GROUP auth_group_name
197255570Strasz    OPENING_BRACKET auth_group_entries CLOSING_BRACKET
198255570Strasz	{
199255570Strasz		auth_group = NULL;
200255570Strasz	}
201255570Strasz	;
202255570Strasz
203255570Straszauth_group_name:	STR
204255570Strasz	{
205263726Strasz		/*
206263726Strasz		 * Make it possible to redefine default
207263726Strasz		 * auth-group. but only once.
208263726Strasz		 */
209263726Strasz		if (strcmp($1, "default") == 0 &&
210263726Strasz		    conf->conf_default_ag_defined == false) {
211263726Strasz			auth_group = auth_group_find(conf, $1);
212263726Strasz			conf->conf_default_ag_defined = true;
213263726Strasz		} else {
214263726Strasz			auth_group = auth_group_new(conf, $1);
215263726Strasz		}
216255570Strasz		free($1);
217255570Strasz		if (auth_group == NULL)
218255570Strasz			return (1);
219255570Strasz	}
220255570Strasz	;
221255570Strasz
222255570Straszauth_group_entries:
223255570Strasz	|
224255570Strasz	auth_group_entries auth_group_entry
225275246Strasz	|
226275246Strasz	auth_group_entries auth_group_entry SEMICOLON
227255570Strasz	;
228255570Strasz
229255570Straszauth_group_entry:
230263724Strasz	auth_group_auth_type
231263724Strasz	|
232255570Strasz	auth_group_chap
233255570Strasz	|
234255570Strasz	auth_group_chap_mutual
235263720Strasz	|
236263720Strasz	auth_group_initiator_name
237263720Strasz	|
238263720Strasz	auth_group_initiator_portal
239255570Strasz	;
240255570Strasz
241263724Straszauth_group_auth_type:	AUTH_TYPE STR
242263724Strasz	{
243263724Strasz		int error;
244263724Strasz
245275245Strasz		error = auth_group_set_type(auth_group, $2);
246263724Strasz		free($2);
247263724Strasz		if (error != 0)
248263724Strasz			return (1);
249263724Strasz	}
250263724Strasz	;
251263724Strasz
252255570Straszauth_group_chap:	CHAP STR STR
253255570Strasz	{
254255570Strasz		const struct auth *ca;
255255570Strasz
256255570Strasz		ca = auth_new_chap(auth_group, $2, $3);
257255570Strasz		free($2);
258255570Strasz		free($3);
259255570Strasz		if (ca == NULL)
260255570Strasz			return (1);
261255570Strasz	}
262255570Strasz	;
263255570Strasz
264255570Straszauth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
265255570Strasz	{
266255570Strasz		const struct auth *ca;
267255570Strasz
268255570Strasz		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
269255570Strasz		free($2);
270255570Strasz		free($3);
271255570Strasz		free($4);
272255570Strasz		free($5);
273255570Strasz		if (ca == NULL)
274255570Strasz			return (1);
275255570Strasz	}
276255570Strasz	;
277255570Strasz
278263720Straszauth_group_initiator_name:	INITIATOR_NAME STR
279263720Strasz	{
280263720Strasz		const struct auth_name *an;
281263720Strasz
282263720Strasz		an = auth_name_new(auth_group, $2);
283263720Strasz		free($2);
284263720Strasz		if (an == NULL)
285263720Strasz			return (1);
286263720Strasz	}
287263720Strasz	;
288263720Strasz
289263720Straszauth_group_initiator_portal:	INITIATOR_PORTAL STR
290263720Strasz	{
291263720Strasz		const struct auth_portal *ap;
292263720Strasz
293263720Strasz		ap = auth_portal_new(auth_group, $2);
294263720Strasz		free($2);
295263720Strasz		if (ap == NULL)
296263720Strasz			return (1);
297263720Strasz	}
298263720Strasz	;
299263720Strasz
300263722Straszportal_group:	PORTAL_GROUP portal_group_name
301255570Strasz    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
302255570Strasz	{
303255570Strasz		portal_group = NULL;
304255570Strasz	}
305255570Strasz	;
306255570Strasz
307255570Straszportal_group_name:	STR
308255570Strasz	{
309263725Strasz		/*
310263725Strasz		 * Make it possible to redefine default
311263725Strasz		 * portal-group. but only once.
312263725Strasz		 */
313263725Strasz		if (strcmp($1, "default") == 0 &&
314263725Strasz		    conf->conf_default_pg_defined == false) {
315263725Strasz			portal_group = portal_group_find(conf, $1);
316263725Strasz			conf->conf_default_pg_defined = true;
317263725Strasz		} else {
318263725Strasz			portal_group = portal_group_new(conf, $1);
319263725Strasz		}
320255570Strasz		free($1);
321255570Strasz		if (portal_group == NULL)
322255570Strasz			return (1);
323255570Strasz	}
324255570Strasz	;
325255570Strasz
326255570Straszportal_group_entries:
327255570Strasz	|
328255570Strasz	portal_group_entries portal_group_entry
329275246Strasz	|
330275246Strasz	portal_group_entries portal_group_entry SEMICOLON
331255570Strasz	;
332255570Strasz
333255570Straszportal_group_entry:
334255570Strasz	portal_group_discovery_auth_group
335255570Strasz	|
336275244Strasz	portal_group_discovery_filter
337275244Strasz	|
338255570Strasz	portal_group_listen
339255570Strasz	|
340255570Strasz	portal_group_listen_iser
341255570Strasz	;
342255570Strasz
343255570Straszportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
344255570Strasz	{
345255570Strasz		if (portal_group->pg_discovery_auth_group != NULL) {
346255570Strasz			log_warnx("discovery-auth-group for portal-group "
347255570Strasz			    "\"%s\" specified more than once",
348255570Strasz			    portal_group->pg_name);
349255570Strasz			return (1);
350255570Strasz		}
351255570Strasz		portal_group->pg_discovery_auth_group =
352255570Strasz		    auth_group_find(conf, $2);
353255570Strasz		if (portal_group->pg_discovery_auth_group == NULL) {
354255570Strasz			log_warnx("unknown discovery-auth-group \"%s\" "
355255570Strasz			    "for portal-group \"%s\"",
356255570Strasz			    $2, portal_group->pg_name);
357255570Strasz			return (1);
358255570Strasz		}
359255570Strasz		free($2);
360255570Strasz	}
361255570Strasz	;
362255570Strasz
363275244Straszportal_group_discovery_filter:	DISCOVERY_FILTER STR
364275244Strasz	{
365275244Strasz		int error;
366275244Strasz
367275245Strasz		error = portal_group_set_filter(portal_group, $2);
368275244Strasz		free($2);
369275244Strasz		if (error != 0)
370275244Strasz			return (1);
371275244Strasz	}
372275244Strasz	;
373275244Strasz
374255570Straszportal_group_listen:	LISTEN STR
375255570Strasz	{
376255570Strasz		int error;
377255570Strasz
378255570Strasz		error = portal_group_add_listen(portal_group, $2, false);
379255570Strasz		free($2);
380255570Strasz		if (error != 0)
381255570Strasz			return (1);
382255570Strasz	}
383255570Strasz	;
384255570Strasz
385255570Straszportal_group_listen_iser:	LISTEN_ISER STR
386255570Strasz	{
387255570Strasz		int error;
388255570Strasz
389255570Strasz		error = portal_group_add_listen(portal_group, $2, true);
390255570Strasz		free($2);
391255570Strasz		if (error != 0)
392255570Strasz			return (1);
393255570Strasz	}
394255570Strasz	;
395255570Strasz
396263722Strasztarget:	TARGET target_name
397255570Strasz    OPENING_BRACKET target_entries CLOSING_BRACKET
398255570Strasz	{
399255570Strasz		target = NULL;
400255570Strasz	}
401255570Strasz	;
402255570Strasz
403263722Strasztarget_name:	STR
404255570Strasz	{
405255570Strasz		target = target_new(conf, $1);
406255570Strasz		free($1);
407255570Strasz		if (target == NULL)
408255570Strasz			return (1);
409255570Strasz	}
410255570Strasz	;
411255570Strasz
412255570Strasztarget_entries:
413255570Strasz	|
414255570Strasz	target_entries target_entry
415275246Strasz	|
416275246Strasz	target_entries target_entry SEMICOLON
417255570Strasz	;
418255570Strasz
419255570Strasztarget_entry:
420263722Strasz	target_alias
421255570Strasz	|
422263722Strasz	target_auth_group
423255570Strasz	|
424263724Strasz	target_auth_type
425263724Strasz	|
426263722Strasz	target_chap
427255570Strasz	|
428263722Strasz	target_chap_mutual
429255570Strasz	|
430263722Strasz	target_initiator_name
431263720Strasz	|
432263722Strasz	target_initiator_portal
433263720Strasz	|
434263722Strasz	target_portal_group
435255570Strasz	|
436263722Strasz	target_lun
437255570Strasz	;
438255570Strasz
439263722Strasztarget_alias:	ALIAS STR
440255570Strasz	{
441255570Strasz		if (target->t_alias != NULL) {
442255570Strasz			log_warnx("alias for target \"%s\" "
443263723Strasz			    "specified more than once", target->t_name);
444255570Strasz			return (1);
445255570Strasz		}
446255570Strasz		target->t_alias = $2;
447255570Strasz	}
448255570Strasz	;
449255570Strasz
450263722Strasztarget_auth_group:	AUTH_GROUP STR
451255570Strasz	{
452255570Strasz		if (target->t_auth_group != NULL) {
453255570Strasz			if (target->t_auth_group->ag_name != NULL)
454255570Strasz				log_warnx("auth-group for target \"%s\" "
455263723Strasz				    "specified more than once", target->t_name);
456255570Strasz			else
457263724Strasz				log_warnx("cannot use both auth-group and explicit "
458255570Strasz				    "authorisations for target \"%s\"",
459263723Strasz				    target->t_name);
460255570Strasz			return (1);
461255570Strasz		}
462255570Strasz		target->t_auth_group = auth_group_find(conf, $2);
463255570Strasz		if (target->t_auth_group == NULL) {
464255570Strasz			log_warnx("unknown auth-group \"%s\" for target "
465263723Strasz			    "\"%s\"", $2, target->t_name);
466255570Strasz			return (1);
467255570Strasz		}
468255570Strasz		free($2);
469255570Strasz	}
470255570Strasz	;
471255570Strasz
472263724Strasztarget_auth_type:	AUTH_TYPE STR
473263724Strasz	{
474263724Strasz		int error;
475263724Strasz
476263724Strasz		if (target->t_auth_group != NULL) {
477263724Strasz			if (target->t_auth_group->ag_name != NULL) {
478263724Strasz				log_warnx("cannot use both auth-group and "
479263724Strasz				    "auth-type for target \"%s\"",
480263724Strasz				    target->t_name);
481263724Strasz				return (1);
482263724Strasz			}
483263724Strasz		} else {
484263724Strasz			target->t_auth_group = auth_group_new(conf, NULL);
485263724Strasz			if (target->t_auth_group == NULL) {
486263724Strasz				free($2);
487263724Strasz				return (1);
488263724Strasz			}
489263724Strasz			target->t_auth_group->ag_target = target;
490263724Strasz		}
491275245Strasz		error = auth_group_set_type(target->t_auth_group, $2);
492263724Strasz		free($2);
493263724Strasz		if (error != 0)
494263724Strasz			return (1);
495263724Strasz	}
496263724Strasz	;
497263724Strasz
498263722Strasztarget_chap:	CHAP STR STR
499255570Strasz	{
500255570Strasz		const struct auth *ca;
501255570Strasz
502255570Strasz		if (target->t_auth_group != NULL) {
503255570Strasz			if (target->t_auth_group->ag_name != NULL) {
504263724Strasz				log_warnx("cannot use both auth-group and "
505263724Strasz				    "chap for target \"%s\"",
506263723Strasz				    target->t_name);
507255570Strasz				free($2);
508255570Strasz				free($3);
509255570Strasz				return (1);
510255570Strasz			}
511255570Strasz		} else {
512255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
513255570Strasz			if (target->t_auth_group == NULL) {
514255570Strasz				free($2);
515255570Strasz				free($3);
516255570Strasz				return (1);
517255570Strasz			}
518255570Strasz			target->t_auth_group->ag_target = target;
519255570Strasz		}
520255570Strasz		ca = auth_new_chap(target->t_auth_group, $2, $3);
521255570Strasz		free($2);
522255570Strasz		free($3);
523255570Strasz		if (ca == NULL)
524255570Strasz			return (1);
525255570Strasz	}
526255570Strasz	;
527255570Strasz
528263722Strasztarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
529255570Strasz	{
530255570Strasz		const struct auth *ca;
531255570Strasz
532255570Strasz		if (target->t_auth_group != NULL) {
533255570Strasz			if (target->t_auth_group->ag_name != NULL) {
534263724Strasz				log_warnx("cannot use both auth-group and "
535263724Strasz				    "chap-mutual for target \"%s\"",
536263723Strasz				    target->t_name);
537255570Strasz				free($2);
538255570Strasz				free($3);
539255570Strasz				free($4);
540255570Strasz				free($5);
541255570Strasz				return (1);
542255570Strasz			}
543255570Strasz		} else {
544255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
545255570Strasz			if (target->t_auth_group == NULL) {
546255570Strasz				free($2);
547255570Strasz				free($3);
548255570Strasz				free($4);
549255570Strasz				free($5);
550255570Strasz				return (1);
551255570Strasz			}
552255570Strasz			target->t_auth_group->ag_target = target;
553255570Strasz		}
554255570Strasz		ca = auth_new_chap_mutual(target->t_auth_group,
555255570Strasz		    $2, $3, $4, $5);
556255570Strasz		free($2);
557255570Strasz		free($3);
558255570Strasz		free($4);
559255570Strasz		free($5);
560255570Strasz		if (ca == NULL)
561255570Strasz			return (1);
562255570Strasz	}
563255570Strasz	;
564255570Strasz
565263722Strasztarget_initiator_name:	INITIATOR_NAME STR
566263720Strasz	{
567263720Strasz		const struct auth_name *an;
568263720Strasz
569263720Strasz		if (target->t_auth_group != NULL) {
570263720Strasz			if (target->t_auth_group->ag_name != NULL) {
571263724Strasz				log_warnx("cannot use both auth-group and "
572263720Strasz				    "initiator-name for target \"%s\"",
573263723Strasz				    target->t_name);
574263720Strasz				free($2);
575263720Strasz				return (1);
576263720Strasz			}
577263720Strasz		} else {
578263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
579263720Strasz			if (target->t_auth_group == NULL) {
580263720Strasz				free($2);
581263720Strasz				return (1);
582263720Strasz			}
583263720Strasz			target->t_auth_group->ag_target = target;
584263720Strasz		}
585263720Strasz		an = auth_name_new(target->t_auth_group, $2);
586263720Strasz		free($2);
587263720Strasz		if (an == NULL)
588263720Strasz			return (1);
589263720Strasz	}
590263720Strasz	;
591263720Strasz
592263722Strasztarget_initiator_portal:	INITIATOR_PORTAL STR
593263720Strasz	{
594263720Strasz		const struct auth_portal *ap;
595263720Strasz
596263720Strasz		if (target->t_auth_group != NULL) {
597263720Strasz			if (target->t_auth_group->ag_name != NULL) {
598263724Strasz				log_warnx("cannot use both auth-group and "
599263720Strasz				    "initiator-portal for target \"%s\"",
600263723Strasz				    target->t_name);
601263720Strasz				free($2);
602263720Strasz				return (1);
603263720Strasz			}
604263720Strasz		} else {
605263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
606263720Strasz			if (target->t_auth_group == NULL) {
607263720Strasz				free($2);
608263720Strasz				return (1);
609263720Strasz			}
610263720Strasz			target->t_auth_group->ag_target = target;
611263720Strasz		}
612263720Strasz		ap = auth_portal_new(target->t_auth_group, $2);
613263720Strasz		free($2);
614263720Strasz		if (ap == NULL)
615263720Strasz			return (1);
616263720Strasz	}
617263720Strasz	;
618263720Strasz
619263722Strasztarget_portal_group:	PORTAL_GROUP STR
620255570Strasz	{
621255570Strasz		if (target->t_portal_group != NULL) {
622255570Strasz			log_warnx("portal-group for target \"%s\" "
623263723Strasz			    "specified more than once", target->t_name);
624255570Strasz			free($2);
625255570Strasz			return (1);
626255570Strasz		}
627255570Strasz		target->t_portal_group = portal_group_find(conf, $2);
628255570Strasz		if (target->t_portal_group == NULL) {
629255570Strasz			log_warnx("unknown portal-group \"%s\" for target "
630263723Strasz			    "\"%s\"", $2, target->t_name);
631255570Strasz			free($2);
632255570Strasz			return (1);
633255570Strasz		}
634255570Strasz		free($2);
635255570Strasz	}
636255570Strasz	;
637255570Strasz
638263722Strasztarget_lun:	LUN lun_number
639263722Strasz    OPENING_BRACKET lun_entries CLOSING_BRACKET
640255570Strasz	{
641255570Strasz		lun = NULL;
642255570Strasz	}
643255570Strasz	;
644255570Strasz
645275186Straszlun_number:	STR
646255570Strasz	{
647275186Strasz		uint64_t tmp;
648275186Strasz
649275186Strasz		if (expand_number($1, &tmp) != 0) {
650275187Strasz			yyerror("invalid numeric value");
651275186Strasz			free($1);
652275186Strasz			return (1);
653275186Strasz		}
654275186Strasz
655275186Strasz		lun = lun_new(target, tmp);
656255570Strasz		if (lun == NULL)
657255570Strasz			return (1);
658255570Strasz	}
659255570Strasz	;
660255570Strasz
661263722Straszlun_entries:
662255570Strasz	|
663263722Strasz	lun_entries lun_entry
664275246Strasz	|
665275246Strasz	lun_entries lun_entry SEMICOLON
666255570Strasz	;
667255570Strasz
668263722Straszlun_entry:
669263722Strasz	lun_backend
670255570Strasz	|
671263722Strasz	lun_blocksize
672255570Strasz	|
673263722Strasz	lun_device_id
674255570Strasz	|
675263722Strasz	lun_option
676255570Strasz	|
677263722Strasz	lun_path
678255570Strasz	|
679263722Strasz	lun_serial
680255570Strasz	|
681263722Strasz	lun_size
682255570Strasz	;
683255570Strasz
684263722Straszlun_backend:	BACKEND STR
685255570Strasz	{
686255570Strasz		if (lun->l_backend != NULL) {
687255570Strasz			log_warnx("backend for lun %d, target \"%s\" "
688255570Strasz			    "specified more than once",
689263723Strasz			    lun->l_lun, target->t_name);
690255570Strasz			free($2);
691255570Strasz			return (1);
692255570Strasz		}
693255570Strasz		lun_set_backend(lun, $2);
694255570Strasz		free($2);
695255570Strasz	}
696255570Strasz	;
697255570Strasz
698275186Straszlun_blocksize:	BLOCKSIZE STR
699255570Strasz	{
700275186Strasz		uint64_t tmp;
701275186Strasz
702275186Strasz		if (expand_number($2, &tmp) != 0) {
703275187Strasz			yyerror("invalid numeric value");
704275186Strasz			free($2);
705275186Strasz			return (1);
706275186Strasz		}
707275186Strasz
708255570Strasz		if (lun->l_blocksize != 0) {
709255570Strasz			log_warnx("blocksize for lun %d, target \"%s\" "
710255570Strasz			    "specified more than once",
711263723Strasz			    lun->l_lun, target->t_name);
712255570Strasz			return (1);
713255570Strasz		}
714275186Strasz		lun_set_blocksize(lun, tmp);
715255570Strasz	}
716255570Strasz	;
717255570Strasz
718263722Straszlun_device_id:	DEVICE_ID STR
719255570Strasz	{
720255570Strasz		if (lun->l_device_id != NULL) {
721255570Strasz			log_warnx("device_id for lun %d, target \"%s\" "
722255570Strasz			    "specified more than once",
723263723Strasz			    lun->l_lun, target->t_name);
724255570Strasz			free($2);
725255570Strasz			return (1);
726255570Strasz		}
727255570Strasz		lun_set_device_id(lun, $2);
728255570Strasz		free($2);
729255570Strasz	}
730255570Strasz	;
731255570Strasz
732263722Straszlun_option:	OPTION STR STR
733255570Strasz	{
734255570Strasz		struct lun_option *clo;
735274870Strasz
736255570Strasz		clo = lun_option_new(lun, $2, $3);
737255570Strasz		free($2);
738255570Strasz		free($3);
739255570Strasz		if (clo == NULL)
740255570Strasz			return (1);
741255570Strasz	}
742255570Strasz	;
743255570Strasz
744263722Straszlun_path:	PATH STR
745255570Strasz	{
746255570Strasz		if (lun->l_path != NULL) {
747255570Strasz			log_warnx("path for lun %d, target \"%s\" "
748255570Strasz			    "specified more than once",
749263723Strasz			    lun->l_lun, target->t_name);
750255570Strasz			free($2);
751255570Strasz			return (1);
752255570Strasz		}
753255570Strasz		lun_set_path(lun, $2);
754255570Strasz		free($2);
755255570Strasz	}
756255570Strasz	;
757255570Strasz
758263722Straszlun_serial:	SERIAL STR
759255570Strasz	{
760255570Strasz		if (lun->l_serial != NULL) {
761255570Strasz			log_warnx("serial for lun %d, target \"%s\" "
762255570Strasz			    "specified more than once",
763263723Strasz			    lun->l_lun, target->t_name);
764255570Strasz			free($2);
765255570Strasz			return (1);
766255570Strasz		}
767255570Strasz		lun_set_serial(lun, $2);
768255570Strasz		free($2);
769275186Strasz	}
770275186Strasz	;
771275186Strasz
772275186Straszlun_size:	SIZE STR
773267962Sjpaetzel	{
774275186Strasz		uint64_t tmp;
775267962Sjpaetzel
776275186Strasz		if (expand_number($2, &tmp) != 0) {
777275187Strasz			yyerror("invalid numeric value");
778275186Strasz			free($2);
779267962Sjpaetzel			return (1);
780267962Sjpaetzel		}
781255570Strasz
782255570Strasz		if (lun->l_size != 0) {
783255570Strasz			log_warnx("size for lun %d, target \"%s\" "
784255570Strasz			    "specified more than once",
785263723Strasz			    lun->l_lun, target->t_name);
786255570Strasz			return (1);
787255570Strasz		}
788275186Strasz		lun_set_size(lun, tmp);
789255570Strasz	}
790255570Strasz	;
791255570Strasz%%
792255570Strasz
793255570Straszvoid
794255570Straszyyerror(const char *str)
795255570Strasz{
796255570Strasz
797255570Strasz	log_warnx("error in configuration file at line %d near '%s': %s",
798255570Strasz	    lineno, yytext, str);
799255570Strasz}
800255570Strasz
801255570Straszstatic void
802255570Straszcheck_perms(const char *path)
803255570Strasz{
804255570Strasz	struct stat sb;
805255570Strasz	int error;
806255570Strasz
807255570Strasz	error = stat(path, &sb);
808255570Strasz	if (error != 0) {
809255570Strasz		log_warn("stat");
810255570Strasz		return;
811255570Strasz	}
812255570Strasz	if (sb.st_mode & S_IWOTH) {
813255570Strasz		log_warnx("%s is world-writable", path);
814255570Strasz	} else if (sb.st_mode & S_IROTH) {
815255570Strasz		log_warnx("%s is world-readable", path);
816255570Strasz	} else if (sb.st_mode & S_IXOTH) {
817255570Strasz		/*
818255570Strasz		 * Ok, this one doesn't matter, but still do it,
819255570Strasz		 * just for consistency.
820255570Strasz		 */
821255570Strasz		log_warnx("%s is world-executable", path);
822255570Strasz	}
823255570Strasz
824255570Strasz	/*
825255570Strasz	 * XXX: Should we also check for owner != 0?
826255570Strasz	 */
827255570Strasz}
828255570Strasz
829255570Straszstruct conf *
830255570Straszconf_new_from_file(const char *path)
831255570Strasz{
832255570Strasz	struct auth_group *ag;
833255570Strasz	struct portal_group *pg;
834255570Strasz	int error;
835255570Strasz
836255570Strasz	log_debugx("obtaining configuration from %s", path);
837255570Strasz
838255570Strasz	conf = conf_new();
839255570Strasz
840263726Strasz	ag = auth_group_new(conf, "default");
841263726Strasz	assert(ag != NULL);
842263726Strasz
843255570Strasz	ag = auth_group_new(conf, "no-authentication");
844263725Strasz	assert(ag != NULL);
845255570Strasz	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
846255570Strasz
847255570Strasz	ag = auth_group_new(conf, "no-access");
848263725Strasz	assert(ag != NULL);
849263729Strasz	ag->ag_type = AG_TYPE_DENY;
850255570Strasz
851255570Strasz	pg = portal_group_new(conf, "default");
852263725Strasz	assert(pg != NULL);
853255570Strasz
854255570Strasz	yyin = fopen(path, "r");
855255570Strasz	if (yyin == NULL) {
856255570Strasz		log_warn("unable to open configuration file %s", path);
857255570Strasz		conf_delete(conf);
858255570Strasz		return (NULL);
859255570Strasz	}
860255570Strasz	check_perms(path);
861263715Strasz	lineno = 1;
862255570Strasz	yyrestart(yyin);
863255570Strasz	error = yyparse();
864255570Strasz	auth_group = NULL;
865255570Strasz	portal_group = NULL;
866255570Strasz	target = NULL;
867255570Strasz	lun = NULL;
868255570Strasz	fclose(yyin);
869255570Strasz	if (error != 0) {
870255570Strasz		conf_delete(conf);
871255570Strasz		return (NULL);
872255570Strasz	}
873255570Strasz
874263726Strasz	if (conf->conf_default_ag_defined == false) {
875263726Strasz		log_debugx("auth-group \"default\" not defined; "
876263726Strasz		    "going with defaults");
877263726Strasz		ag = auth_group_find(conf, "default");
878263726Strasz		assert(ag != NULL);
879263729Strasz		ag->ag_type = AG_TYPE_DENY;
880263726Strasz	}
881263726Strasz
882263725Strasz	if (conf->conf_default_pg_defined == false) {
883263725Strasz		log_debugx("portal-group \"default\" not defined; "
884263725Strasz		    "going with defaults");
885263725Strasz		pg = portal_group_find(conf, "default");
886263725Strasz		assert(pg != NULL);
887263725Strasz		portal_group_add_listen(pg, "0.0.0.0:3260", false);
888263725Strasz		portal_group_add_listen(pg, "[::]:3260", false);
889263725Strasz	}
890263725Strasz
891265511Strasz	conf->conf_kernel_port_on = true;
892265511Strasz
893255570Strasz	error = conf_verify(conf);
894255570Strasz	if (error != 0) {
895255570Strasz		conf_delete(conf);
896255570Strasz		return (NULL);
897255570Strasz	}
898255570Strasz
899255570Strasz	return (conf);
900255570Strasz}
901