parse.y revision 263722
1219019Sgabor%{
2219019Sgabor/*-
3219019Sgabor * Copyright (c) 2012 The FreeBSD Foundation
4219019Sgabor * All rights reserved.
5219019Sgabor *
6219019Sgabor * This software was developed by Edward Tomasz Napierala under sponsorship
7219019Sgabor * from the FreeBSD Foundation.
8219019Sgabor *
9219019Sgabor * Redistribution and use in source and binary forms, with or without
10219019Sgabor * modification, are permitted provided that the following conditions
11219019Sgabor * are met:
12219019Sgabor * 1. Redistributions of source code must retain the above copyright
13219019Sgabor *    notice, this list of conditions and the following disclaimer.
14219019Sgabor * 2. Redistributions in binary form must reproduce the above copyright
15219019Sgabor *    notice, this list of conditions and the following disclaimer in the
16219019Sgabor *    documentation and/or other materials provided with the distribution.
17219019Sgabor *
18219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19219019Sgabor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20219019Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21219019Sgabor * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22219019Sgabor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23219019Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24219019Sgabor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25219019Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26219019Sgabor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27219019Sgabor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28219019Sgabor * SUCH DAMAGE.
29219019Sgabor *
30219019Sgabor * $FreeBSD: stable/10/usr.sbin/ctld/parse.y 263722 2014-03-25 12:08:35Z trasz $
31219019Sgabor */
32219019Sgabor
33219019Sgabor#include <sys/queue.h>
34219019Sgabor#include <sys/types.h>
35219019Sgabor#include <sys/stat.h>
36219019Sgabor#include <assert.h>
37219019Sgabor#include <stdio.h>
38219019Sgabor#include <stdint.h>
39219019Sgabor#include <stdlib.h>
40219019Sgabor#include <string.h>
41219019Sgabor
42219019Sgabor#include "ctld.h"
43219019Sgabor
44219019Sgaborextern FILE *yyin;
45219019Sgaborextern char *yytext;
46219019Sgaborextern int lineno;
47219019Sgabor
48219019Sgaborstatic struct conf *conf = NULL;
49219019Sgaborstatic struct auth_group *auth_group = NULL;
50219019Sgaborstatic struct portal_group *portal_group = NULL;
51219019Sgaborstatic struct target *target = NULL;
52219019Sgaborstatic struct lun *lun = NULL;
53219019Sgabor
54219019Sgaborextern void	yyerror(const char *);
55219019Sgaborextern int	yylex(void);
56219019Sgaborextern void	yyrestart(FILE *);
57219019Sgabor
58219019Sgabor%}
59219019Sgabor
60219019Sgabor%token ALIAS AUTH_GROUP BACKEND BLOCKSIZE CHAP CHAP_MUTUAL CLOSING_BRACKET
61219019Sgabor%token DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP INITIATOR_NAME INITIATOR_PORTAL
62219019Sgabor%token LISTEN LISTEN_ISER LUN MAXPROC NUM OPENING_BRACKET OPTION PATH PIDFILE
63219019Sgabor%token PORTAL_GROUP SERIAL SIZE STR TARGET TIMEOUT
64219019Sgabor
65219019Sgabor%union
66219019Sgabor{
67219019Sgabor	uint64_t num;
68219019Sgabor	char *str;
69219019Sgabor}
70219019Sgabor
71219019Sgabor%token <num> NUM
72219019Sgabor%token <str> STR
73219019Sgabor
74219019Sgabor%%
75219019Sgabor
76219019Sgaborstatements:
77219019Sgabor	|
78219019Sgabor	statements statement
79219019Sgabor	;
80219019Sgabor
81219019Sgaborstatement:
82219019Sgabor	debug
83219019Sgabor	|
84219019Sgabor	timeout
85219019Sgabor	|
86219019Sgabor	maxproc
87219019Sgabor	|
88219019Sgabor	pidfile
89219019Sgabor	|
90219019Sgabor	auth_group
91219019Sgabor	|
92219019Sgabor	portal_group
93219019Sgabor	|
94219019Sgabor	target
95219019Sgabor	;
96219019Sgabor
97219019Sgabordebug:		DEBUG NUM
98219019Sgabor	{
99219019Sgabor		conf->conf_debug = $2;
100219019Sgabor	}
101219019Sgabor	;
102219019Sgabor
103219019Sgabortimeout:	TIMEOUT NUM
104219019Sgabor	{
105219019Sgabor		conf->conf_timeout = $2;
106219019Sgabor	}
107219019Sgabor	;
108219019Sgabor
109219019Sgabormaxproc:	MAXPROC NUM
110219019Sgabor	{
111219019Sgabor		conf->conf_maxproc = $2;
112219019Sgabor	}
113219019Sgabor	;
114219019Sgabor
115219019Sgaborpidfile:	PIDFILE STR
116219019Sgabor	{
117219019Sgabor		if (conf->conf_pidfile_path != NULL) {
118219019Sgabor			log_warnx("pidfile specified more than once");
119219019Sgabor			free($2);
120219019Sgabor			return (1);
121219019Sgabor		}
122219019Sgabor		conf->conf_pidfile_path = $2;
123219019Sgabor	}
124219019Sgabor	;
125219019Sgabor
126219019Sgaborauth_group:	AUTH_GROUP auth_group_name
127219019Sgabor    OPENING_BRACKET auth_group_entries CLOSING_BRACKET
128219019Sgabor	{
129219019Sgabor		auth_group = NULL;
130219019Sgabor	}
131219019Sgabor	;
132219019Sgabor
133219019Sgaborauth_group_name:	STR
134219019Sgabor	{
135219019Sgabor		auth_group = auth_group_new(conf, $1);
136219019Sgabor		free($1);
137219019Sgabor		if (auth_group == NULL)
138219019Sgabor			return (1);
139219019Sgabor	}
140219019Sgabor	;
141219019Sgabor
142219019Sgaborauth_group_entries:
143219019Sgabor	|
144219019Sgabor	auth_group_entries auth_group_entry
145219019Sgabor	;
146219019Sgabor
147219019Sgaborauth_group_entry:
148219019Sgabor	auth_group_chap
149219019Sgabor	|
150219019Sgabor	auth_group_chap_mutual
151219019Sgabor	|
152219019Sgabor	auth_group_initiator_name
153219019Sgabor	|
154219019Sgabor	auth_group_initiator_portal
155219019Sgabor	;
156219019Sgabor
157219019Sgaborauth_group_chap:	CHAP STR STR
158219019Sgabor	{
159219019Sgabor		const struct auth *ca;
160219019Sgabor
161219019Sgabor		ca = auth_new_chap(auth_group, $2, $3);
162219019Sgabor		free($2);
163219019Sgabor		free($3);
164219019Sgabor		if (ca == NULL)
165219019Sgabor			return (1);
166219019Sgabor	}
167219019Sgabor	;
168219019Sgabor
169219019Sgaborauth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
170219019Sgabor	{
171219019Sgabor		const struct auth *ca;
172219019Sgabor
173219019Sgabor		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
174219019Sgabor		free($2);
175219019Sgabor		free($3);
176219019Sgabor		free($4);
177219019Sgabor		free($5);
178219019Sgabor		if (ca == NULL)
179219019Sgabor			return (1);
180219019Sgabor	}
181219019Sgabor	;
182219019Sgabor
183219019Sgaborauth_group_initiator_name:	INITIATOR_NAME STR
184219019Sgabor	{
185219019Sgabor		const struct auth_name *an;
186219019Sgabor
187219019Sgabor		an = auth_name_new(auth_group, $2);
188219019Sgabor		free($2);
189219019Sgabor		if (an == NULL)
190219019Sgabor			return (1);
191219019Sgabor	}
192219019Sgabor	;
193219019Sgabor
194219019Sgaborauth_group_initiator_portal:	INITIATOR_PORTAL STR
195219019Sgabor	{
196219019Sgabor		const struct auth_portal *ap;
197219019Sgabor
198219019Sgabor		ap = auth_portal_new(auth_group, $2);
199219019Sgabor		free($2);
200219019Sgabor		if (ap == NULL)
201219019Sgabor			return (1);
202219019Sgabor	}
203219019Sgabor	;
204219019Sgabor
205219019Sgaborportal_group:	PORTAL_GROUP portal_group_name
206219019Sgabor    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
207219019Sgabor	{
208219019Sgabor		portal_group = NULL;
209219019Sgabor	}
210219019Sgabor	;
211219019Sgabor
212219019Sgaborportal_group_name:	STR
213219019Sgabor	{
214219019Sgabor		portal_group = portal_group_new(conf, $1);
215219019Sgabor		free($1);
216219019Sgabor		if (portal_group == NULL)
217219019Sgabor			return (1);
218219019Sgabor	}
219219019Sgabor	;
220219019Sgabor
221219019Sgaborportal_group_entries:
222219019Sgabor	|
223219019Sgabor	portal_group_entries portal_group_entry
224219019Sgabor	;
225219019Sgabor
226219019Sgaborportal_group_entry:
227219019Sgabor	portal_group_discovery_auth_group
228219019Sgabor	|
229219019Sgabor	portal_group_listen
230219019Sgabor	|
231219019Sgabor	portal_group_listen_iser
232219019Sgabor	;
233219019Sgabor
234219019Sgaborportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
235219019Sgabor	{
236219019Sgabor		if (portal_group->pg_discovery_auth_group != NULL) {
237219019Sgabor			log_warnx("discovery-auth-group for portal-group "
238219019Sgabor			    "\"%s\" specified more than once",
239219019Sgabor			    portal_group->pg_name);
240219019Sgabor			return (1);
241219019Sgabor		}
242219019Sgabor		portal_group->pg_discovery_auth_group =
243219019Sgabor		    auth_group_find(conf, $2);
244219019Sgabor		if (portal_group->pg_discovery_auth_group == NULL) {
245219019Sgabor			log_warnx("unknown discovery-auth-group \"%s\" "
246219019Sgabor			    "for portal-group \"%s\"",
247219019Sgabor			    $2, portal_group->pg_name);
248219019Sgabor			return (1);
249219019Sgabor		}
250219019Sgabor		free($2);
251219019Sgabor	}
252219019Sgabor	;
253219019Sgabor
254219019Sgaborportal_group_listen:	LISTEN STR
255219019Sgabor	{
256219019Sgabor		int error;
257219019Sgabor
258219019Sgabor		error = portal_group_add_listen(portal_group, $2, false);
259219019Sgabor		free($2);
260219019Sgabor		if (error != 0)
261219019Sgabor			return (1);
262219019Sgabor	}
263219019Sgabor	;
264219019Sgabor
265219019Sgaborportal_group_listen_iser:	LISTEN_ISER STR
266219019Sgabor	{
267219019Sgabor		int error;
268219019Sgabor
269219019Sgabor		error = portal_group_add_listen(portal_group, $2, true);
270219019Sgabor		free($2);
271219019Sgabor		if (error != 0)
272219019Sgabor			return (1);
273219019Sgabor	}
274219019Sgabor	;
275219019Sgabor
276219019Sgabortarget:	TARGET target_name
277219019Sgabor    OPENING_BRACKET target_entries CLOSING_BRACKET
278219019Sgabor	{
279219019Sgabor		target = NULL;
280219019Sgabor	}
281219019Sgabor	;
282219019Sgabor
283219019Sgabortarget_name:	STR
284219019Sgabor	{
285219019Sgabor		target = target_new(conf, $1);
286219019Sgabor		free($1);
287219019Sgabor		if (target == NULL)
288219019Sgabor			return (1);
289219019Sgabor	}
290219019Sgabor	;
291219019Sgabor
292219019Sgabortarget_entries:
293219019Sgabor	|
294219019Sgabor	target_entries target_entry
295219019Sgabor	;
296219019Sgabor
297219019Sgabortarget_entry:
298219019Sgabor	target_alias
299219019Sgabor	|
300219019Sgabor	target_auth_group
301219019Sgabor	|
302219019Sgabor	target_chap
303219019Sgabor	|
304219019Sgabor	target_chap_mutual
305219019Sgabor	|
306219019Sgabor	target_initiator_name
307219019Sgabor	|
308219019Sgabor	target_initiator_portal
309219019Sgabor	|
310219019Sgabor	target_portal_group
311219019Sgabor	|
312219019Sgabor	target_lun
313219019Sgabor	;
314219019Sgabor
315219019Sgabortarget_alias:	ALIAS STR
316219019Sgabor	{
317219019Sgabor		if (target->t_alias != NULL) {
318219019Sgabor			log_warnx("alias for target \"%s\" "
319219019Sgabor			    "specified more than once", target->t_iqn);
320219019Sgabor			return (1);
321219019Sgabor		}
322219019Sgabor		target->t_alias = $2;
323219019Sgabor	}
324219019Sgabor	;
325219019Sgabor
326219019Sgabortarget_auth_group:	AUTH_GROUP STR
327219019Sgabor	{
328219019Sgabor		if (target->t_auth_group != NULL) {
329219019Sgabor			if (target->t_auth_group->ag_name != NULL)
330219019Sgabor				log_warnx("auth-group for target \"%s\" "
331219019Sgabor				    "specified more than once", target->t_iqn);
332219019Sgabor			else
333219019Sgabor				log_warnx("cannot mix auth-group with explicit "
334219019Sgabor				    "authorisations for target \"%s\"",
335219019Sgabor				    target->t_iqn);
336219019Sgabor			return (1);
337219019Sgabor		}
338219019Sgabor		target->t_auth_group = auth_group_find(conf, $2);
339219019Sgabor		if (target->t_auth_group == NULL) {
340219019Sgabor			log_warnx("unknown auth-group \"%s\" for target "
341219019Sgabor			    "\"%s\"", $2, target->t_iqn);
342219019Sgabor			return (1);
343219019Sgabor		}
344219019Sgabor		free($2);
345219019Sgabor	}
346219019Sgabor	;
347219019Sgabor
348219019Sgabortarget_chap:	CHAP STR STR
349219019Sgabor	{
350219019Sgabor		const struct auth *ca;
351219019Sgabor
352219019Sgabor		if (target->t_auth_group != NULL) {
353219019Sgabor			if (target->t_auth_group->ag_name != NULL) {
354219019Sgabor				log_warnx("cannot mix auth-group with explicit "
355219019Sgabor				    "authorisations for target \"%s\"",
356219019Sgabor				    target->t_iqn);
357219019Sgabor				free($2);
358219019Sgabor				free($3);
359219019Sgabor				return (1);
360219019Sgabor			}
361219019Sgabor		} else {
362219019Sgabor			target->t_auth_group = auth_group_new(conf, NULL);
363219019Sgabor			if (target->t_auth_group == NULL) {
364219019Sgabor				free($2);
365219019Sgabor				free($3);
366219019Sgabor				return (1);
367219019Sgabor			}
368219019Sgabor			target->t_auth_group->ag_target = target;
369219019Sgabor		}
370219019Sgabor		ca = auth_new_chap(target->t_auth_group, $2, $3);
371219019Sgabor		free($2);
372219019Sgabor		free($3);
373219019Sgabor		if (ca == NULL)
374219019Sgabor			return (1);
375219019Sgabor	}
376219019Sgabor	;
377219019Sgabor
378219019Sgabortarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
379219019Sgabor	{
380219019Sgabor		const struct auth *ca;
381219019Sgabor
382219019Sgabor		if (target->t_auth_group != NULL) {
383219019Sgabor			if (target->t_auth_group->ag_name != NULL) {
384219019Sgabor				log_warnx("cannot mix auth-group with explicit "
385219019Sgabor				    "authorisations for target \"%s\"",
386219019Sgabor				    target->t_iqn);
387219019Sgabor				free($2);
388219019Sgabor				free($3);
389219019Sgabor				free($4);
390219019Sgabor				free($5);
391219019Sgabor				return (1);
392219019Sgabor			}
393219019Sgabor		} else {
394219019Sgabor			target->t_auth_group = auth_group_new(conf, NULL);
395219019Sgabor			if (target->t_auth_group == NULL) {
396219019Sgabor				free($2);
397219019Sgabor				free($3);
398219019Sgabor				free($4);
399219019Sgabor				free($5);
400219019Sgabor				return (1);
401219019Sgabor			}
402219019Sgabor			target->t_auth_group->ag_target = target;
403219019Sgabor		}
404219019Sgabor		ca = auth_new_chap_mutual(target->t_auth_group,
405219019Sgabor		    $2, $3, $4, $5);
406219019Sgabor		free($2);
407219019Sgabor		free($3);
408219019Sgabor		free($4);
409219019Sgabor		free($5);
410219019Sgabor		if (ca == NULL)
411219019Sgabor			return (1);
412219019Sgabor	}
413219019Sgabor	;
414219019Sgabor
415219019Sgabortarget_initiator_name:	INITIATOR_NAME STR
416219019Sgabor	{
417219019Sgabor		const struct auth_name *an;
418219019Sgabor
419219019Sgabor		if (target->t_auth_group != NULL) {
420219019Sgabor			if (target->t_auth_group->ag_name != NULL) {
421219019Sgabor				log_warnx("cannot mix auth-group with "
422219019Sgabor				    "initiator-name for target \"%s\"",
423219019Sgabor				    target->t_iqn);
424219019Sgabor				free($2);
425219019Sgabor				return (1);
426219019Sgabor			}
427219019Sgabor		} else {
428219019Sgabor			target->t_auth_group = auth_group_new(conf, NULL);
429219019Sgabor			if (target->t_auth_group == NULL) {
430219019Sgabor				free($2);
431219019Sgabor				return (1);
432219019Sgabor			}
433219019Sgabor			target->t_auth_group->ag_target = target;
434219019Sgabor		}
435219019Sgabor		an = auth_name_new(target->t_auth_group, $2);
436219019Sgabor		free($2);
437219019Sgabor		if (an == NULL)
438219019Sgabor			return (1);
439219019Sgabor	}
440219019Sgabor	;
441219019Sgabor
442219019Sgabortarget_initiator_portal:	INITIATOR_PORTAL STR
443219019Sgabor	{
444219019Sgabor		const struct auth_portal *ap;
445219019Sgabor
446219019Sgabor		if (target->t_auth_group != NULL) {
447219019Sgabor			if (target->t_auth_group->ag_name != NULL) {
448219019Sgabor				log_warnx("cannot mix auth-group with "
449219019Sgabor				    "initiator-portal for target \"%s\"",
450219019Sgabor				    target->t_iqn);
451219019Sgabor				free($2);
452219019Sgabor				return (1);
453219019Sgabor			}
454219019Sgabor		} else {
455219019Sgabor			target->t_auth_group = auth_group_new(conf, NULL);
456219019Sgabor			if (target->t_auth_group == NULL) {
457219019Sgabor				free($2);
458219019Sgabor				return (1);
459219019Sgabor			}
460219019Sgabor			target->t_auth_group->ag_target = target;
461219019Sgabor		}
462219019Sgabor		ap = auth_portal_new(target->t_auth_group, $2);
463219019Sgabor		free($2);
464219019Sgabor		if (ap == NULL)
465219019Sgabor			return (1);
466219019Sgabor	}
467219019Sgabor	;
468219019Sgabor
469219019Sgabortarget_portal_group:	PORTAL_GROUP STR
470219019Sgabor	{
471219019Sgabor		if (target->t_portal_group != NULL) {
472219019Sgabor			log_warnx("portal-group for target \"%s\" "
473219019Sgabor			    "specified more than once", target->t_iqn);
474219019Sgabor			free($2);
475219019Sgabor			return (1);
476219019Sgabor		}
477219019Sgabor		target->t_portal_group = portal_group_find(conf, $2);
478219019Sgabor		if (target->t_portal_group == NULL) {
479219019Sgabor			log_warnx("unknown portal-group \"%s\" for target "
480219019Sgabor			    "\"%s\"", $2, target->t_iqn);
481219019Sgabor			free($2);
482219019Sgabor			return (1);
483219019Sgabor		}
484219019Sgabor		free($2);
485219019Sgabor	}
486219019Sgabor	;
487219019Sgabor
488219019Sgabortarget_lun:	LUN lun_number
489219019Sgabor    OPENING_BRACKET lun_entries CLOSING_BRACKET
490219019Sgabor	{
491219019Sgabor		lun = NULL;
492219019Sgabor	}
493219019Sgabor	;
494219019Sgabor
495219019Sgaborlun_number:	NUM
496219019Sgabor	{
497219019Sgabor		lun = lun_new(target, $1);
498219019Sgabor		if (lun == NULL)
499219019Sgabor			return (1);
500219019Sgabor	}
501219019Sgabor	;
502219019Sgabor
503219019Sgaborlun_entries:
504219019Sgabor	|
505219019Sgabor	lun_entries lun_entry
506219019Sgabor	;
507219019Sgabor
508219019Sgaborlun_entry:
509219019Sgabor	lun_backend
510219019Sgabor	|
511219019Sgabor	lun_blocksize
512219019Sgabor	|
513219019Sgabor	lun_device_id
514219019Sgabor	|
515219019Sgabor	lun_option
516219019Sgabor	|
517219019Sgabor	lun_path
518219019Sgabor	|
519219019Sgabor	lun_serial
520219019Sgabor	|
521219019Sgabor	lun_size
522219019Sgabor	;
523219019Sgabor
524219019Sgaborlun_backend:	BACKEND STR
525219019Sgabor	{
526219019Sgabor		if (lun->l_backend != NULL) {
527219019Sgabor			log_warnx("backend for lun %d, target \"%s\" "
528219019Sgabor			    "specified more than once",
529219019Sgabor			    lun->l_lun, target->t_iqn);
530219019Sgabor			free($2);
531219019Sgabor			return (1);
532219019Sgabor		}
533219019Sgabor		lun_set_backend(lun, $2);
534219019Sgabor		free($2);
535219019Sgabor	}
536219019Sgabor	;
537219019Sgabor
538219019Sgaborlun_blocksize:	BLOCKSIZE NUM
539219019Sgabor	{
540219019Sgabor		if (lun->l_blocksize != 0) {
541219019Sgabor			log_warnx("blocksize for lun %d, target \"%s\" "
542219019Sgabor			    "specified more than once",
543219019Sgabor			    lun->l_lun, target->t_iqn);
544219019Sgabor			return (1);
545219019Sgabor		}
546219019Sgabor		lun_set_blocksize(lun, $2);
547219019Sgabor	}
548219019Sgabor	;
549219019Sgabor
550219019Sgaborlun_device_id:	DEVICE_ID STR
551219019Sgabor	{
552219019Sgabor		if (lun->l_device_id != NULL) {
553219019Sgabor			log_warnx("device_id for lun %d, target \"%s\" "
554219019Sgabor			    "specified more than once",
555219019Sgabor			    lun->l_lun, target->t_iqn);
556219019Sgabor			free($2);
557219019Sgabor			return (1);
558219019Sgabor		}
559219019Sgabor		lun_set_device_id(lun, $2);
560219019Sgabor		free($2);
561219019Sgabor	}
562219019Sgabor	;
563219019Sgabor
564219019Sgaborlun_option:	OPTION STR STR
565219019Sgabor	{
566219019Sgabor		struct lun_option *clo;
567219019Sgabor
568219019Sgabor		clo = lun_option_new(lun, $2, $3);
569219019Sgabor		free($2);
570219019Sgabor		free($3);
571219019Sgabor		if (clo == NULL)
572219019Sgabor			return (1);
573219019Sgabor	}
574219019Sgabor	;
575219019Sgabor
576219019Sgaborlun_path:	PATH STR
577219019Sgabor	{
578219019Sgabor		if (lun->l_path != NULL) {
579219019Sgabor			log_warnx("path for lun %d, target \"%s\" "
580219019Sgabor			    "specified more than once",
581219019Sgabor			    lun->l_lun, target->t_iqn);
582219019Sgabor			free($2);
583219019Sgabor			return (1);
584219019Sgabor		}
585219019Sgabor		lun_set_path(lun, $2);
586219019Sgabor		free($2);
587219019Sgabor	}
588219019Sgabor	;
589219019Sgabor
590219019Sgaborlun_serial:	SERIAL STR
591219019Sgabor	{
592219019Sgabor		if (lun->l_serial != NULL) {
593219019Sgabor			log_warnx("serial for lun %d, target \"%s\" "
594219019Sgabor			    "specified more than once",
595219019Sgabor			    lun->l_lun, target->t_iqn);
596219019Sgabor			free($2);
597219019Sgabor			return (1);
598219019Sgabor		}
599219019Sgabor		lun_set_serial(lun, $2);
600219019Sgabor		free($2);
601219019Sgabor	}
602219019Sgabor	;
603219019Sgabor
604219019Sgaborlun_size:	SIZE NUM
605219019Sgabor	{
606219019Sgabor		if (lun->l_size != 0) {
607219019Sgabor			log_warnx("size for lun %d, target \"%s\" "
608219019Sgabor			    "specified more than once",
609219019Sgabor			    lun->l_lun, target->t_iqn);
610219019Sgabor			return (1);
611219019Sgabor		}
612219019Sgabor		lun_set_size(lun, $2);
613219019Sgabor	}
614219019Sgabor	;
615219019Sgabor%%
616219019Sgabor
617219019Sgaborvoid
618219019Sgaboryyerror(const char *str)
619219019Sgabor{
620219019Sgabor
621219019Sgabor	log_warnx("error in configuration file at line %d near '%s': %s",
622219019Sgabor	    lineno, yytext, str);
623219019Sgabor}
624219019Sgabor
625219019Sgaborstatic void
626219019Sgaborcheck_perms(const char *path)
627219019Sgabor{
628219019Sgabor	struct stat sb;
629219019Sgabor	int error;
630219019Sgabor
631219019Sgabor	error = stat(path, &sb);
632219019Sgabor	if (error != 0) {
633219019Sgabor		log_warn("stat");
634219019Sgabor		return;
635219019Sgabor	}
636219019Sgabor	if (sb.st_mode & S_IWOTH) {
637219019Sgabor		log_warnx("%s is world-writable", path);
638219019Sgabor	} else if (sb.st_mode & S_IROTH) {
639219019Sgabor		log_warnx("%s is world-readable", path);
640219019Sgabor	} else if (sb.st_mode & S_IXOTH) {
641219019Sgabor		/*
642219019Sgabor		 * Ok, this one doesn't matter, but still do it,
643219019Sgabor		 * just for consistency.
644219019Sgabor		 */
645219019Sgabor		log_warnx("%s is world-executable", path);
646219019Sgabor	}
647219019Sgabor
648219019Sgabor	/*
649219019Sgabor	 * XXX: Should we also check for owner != 0?
650219019Sgabor	 */
651219019Sgabor}
652219019Sgabor
653219019Sgaborstruct conf *
654219019Sgaborconf_new_from_file(const char *path)
655219019Sgabor{
656219019Sgabor	struct auth_group *ag;
657219019Sgabor	struct portal_group *pg;
658219019Sgabor	int error;
659219019Sgabor
660219019Sgabor	log_debugx("obtaining configuration from %s", path);
661219019Sgabor
662219019Sgabor	conf = conf_new();
663219019Sgabor
664219019Sgabor	ag = auth_group_new(conf, "no-authentication");
665219019Sgabor	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
666219019Sgabor
667219019Sgabor	/*
668219019Sgabor	 * Here, the type doesn't really matter, as the group doesn't contain
669219019Sgabor	 * any entries and thus will always deny access.
670219019Sgabor	 */
671219019Sgabor	ag = auth_group_new(conf, "no-access");
672219019Sgabor	ag->ag_type = AG_TYPE_CHAP;
673219019Sgabor
674219019Sgabor	pg = portal_group_new(conf, "default");
675219019Sgabor	portal_group_add_listen(pg, "0.0.0.0:3260", false);
676219019Sgabor	portal_group_add_listen(pg, "[::]:3260", false);
677219019Sgabor
678219019Sgabor	yyin = fopen(path, "r");
679219019Sgabor	if (yyin == NULL) {
680219019Sgabor		log_warn("unable to open configuration file %s", path);
681219019Sgabor		conf_delete(conf);
682219019Sgabor		return (NULL);
683219019Sgabor	}
684219019Sgabor	check_perms(path);
685219019Sgabor	lineno = 1;
686219019Sgabor	yyrestart(yyin);
687219019Sgabor	error = yyparse();
688219019Sgabor	auth_group = NULL;
689219019Sgabor	portal_group = NULL;
690219019Sgabor	target = NULL;
691219019Sgabor	lun = NULL;
692219019Sgabor	fclose(yyin);
693219019Sgabor	if (error != 0) {
694219019Sgabor		conf_delete(conf);
695219019Sgabor		return (NULL);
696219019Sgabor	}
697219019Sgabor
698219019Sgabor	error = conf_verify(conf);
699219019Sgabor	if (error != 0) {
700219019Sgabor		conf_delete(conf);
701219019Sgabor		return (NULL);
702219019Sgabor	}
703219019Sgabor
704219019Sgabor	return (conf);
705219019Sgabor}
706219019Sgabor