parse.y revision 263725
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 263725 2014-03-25 12:14:48Z 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
61263724Strasz%token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP INITIATOR_NAME
62263724Strasz%token INITIATOR_PORTAL LISTEN LISTEN_ISER LUN MAXPROC NUM OPENING_BRACKET
63263724Strasz%token OPTION PATH PIDFILE PORTAL_GROUP SERIAL SIZE STR TARGET TIMEOUT
64255570Strasz
65255570Strasz%union
66255570Strasz{
67255570Strasz	uint64_t num;
68255570Strasz	char *str;
69255570Strasz}
70255570Strasz
71255570Strasz%token <num> NUM
72255570Strasz%token <str> STR
73255570Strasz
74255570Strasz%%
75255570Strasz
76255570Straszstatements:
77255570Strasz	|
78255570Strasz	statements statement
79255570Strasz	;
80255570Strasz
81255570Straszstatement:
82263722Strasz	debug
83255570Strasz	|
84263722Strasz	timeout
85255570Strasz	|
86263722Strasz	maxproc
87255570Strasz	|
88263722Strasz	pidfile
89255570Strasz	|
90263722Strasz	auth_group
91255570Strasz	|
92263722Strasz	portal_group
93255570Strasz	|
94263722Strasz	target
95255570Strasz	;
96255570Strasz
97263722Straszdebug:		DEBUG NUM
98255570Strasz	{
99255570Strasz		conf->conf_debug = $2;
100255570Strasz	}
101255570Strasz	;
102255570Strasz
103263722Strasztimeout:	TIMEOUT NUM
104255570Strasz	{
105255570Strasz		conf->conf_timeout = $2;
106255570Strasz	}
107255570Strasz	;
108255570Strasz
109263722Straszmaxproc:	MAXPROC NUM
110255570Strasz	{
111255570Strasz		conf->conf_maxproc = $2;
112255570Strasz	}
113255570Strasz	;
114255570Strasz
115263722Straszpidfile:	PIDFILE STR
116255570Strasz	{
117255570Strasz		if (conf->conf_pidfile_path != NULL) {
118255570Strasz			log_warnx("pidfile specified more than once");
119255570Strasz			free($2);
120255570Strasz			return (1);
121255570Strasz		}
122255570Strasz		conf->conf_pidfile_path = $2;
123255570Strasz	}
124255570Strasz	;
125255570Strasz
126263722Straszauth_group:	AUTH_GROUP auth_group_name
127255570Strasz    OPENING_BRACKET auth_group_entries CLOSING_BRACKET
128255570Strasz	{
129255570Strasz		auth_group = NULL;
130255570Strasz	}
131255570Strasz	;
132255570Strasz
133255570Straszauth_group_name:	STR
134255570Strasz	{
135255570Strasz		auth_group = auth_group_new(conf, $1);
136255570Strasz		free($1);
137255570Strasz		if (auth_group == NULL)
138255570Strasz			return (1);
139255570Strasz	}
140255570Strasz	;
141255570Strasz
142255570Straszauth_group_entries:
143255570Strasz	|
144255570Strasz	auth_group_entries auth_group_entry
145255570Strasz	;
146255570Strasz
147255570Straszauth_group_entry:
148263724Strasz	auth_group_auth_type
149263724Strasz	|
150255570Strasz	auth_group_chap
151255570Strasz	|
152255570Strasz	auth_group_chap_mutual
153263720Strasz	|
154263720Strasz	auth_group_initiator_name
155263720Strasz	|
156263720Strasz	auth_group_initiator_portal
157255570Strasz	;
158255570Strasz
159263724Straszauth_group_auth_type:	AUTH_TYPE STR
160263724Strasz	{
161263724Strasz		int error;
162263724Strasz
163263724Strasz		error = auth_group_set_type_str(auth_group, $2);
164263724Strasz		free($2);
165263724Strasz		if (error != 0)
166263724Strasz			return (1);
167263724Strasz	}
168263724Strasz	;
169263724Strasz
170255570Straszauth_group_chap:	CHAP STR STR
171255570Strasz	{
172255570Strasz		const struct auth *ca;
173255570Strasz
174255570Strasz		ca = auth_new_chap(auth_group, $2, $3);
175255570Strasz		free($2);
176255570Strasz		free($3);
177255570Strasz		if (ca == NULL)
178255570Strasz			return (1);
179255570Strasz	}
180255570Strasz	;
181255570Strasz
182255570Straszauth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
183255570Strasz	{
184255570Strasz		const struct auth *ca;
185255570Strasz
186255570Strasz		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
187255570Strasz		free($2);
188255570Strasz		free($3);
189255570Strasz		free($4);
190255570Strasz		free($5);
191255570Strasz		if (ca == NULL)
192255570Strasz			return (1);
193255570Strasz	}
194255570Strasz	;
195255570Strasz
196263720Straszauth_group_initiator_name:	INITIATOR_NAME STR
197263720Strasz	{
198263720Strasz		const struct auth_name *an;
199263720Strasz
200263720Strasz		an = auth_name_new(auth_group, $2);
201263720Strasz		free($2);
202263720Strasz		if (an == NULL)
203263720Strasz			return (1);
204263720Strasz	}
205263720Strasz	;
206263720Strasz
207263720Straszauth_group_initiator_portal:	INITIATOR_PORTAL STR
208263720Strasz	{
209263720Strasz		const struct auth_portal *ap;
210263720Strasz
211263720Strasz		ap = auth_portal_new(auth_group, $2);
212263720Strasz		free($2);
213263720Strasz		if (ap == NULL)
214263720Strasz			return (1);
215263720Strasz	}
216263720Strasz	;
217263720Strasz
218263722Straszportal_group:	PORTAL_GROUP portal_group_name
219255570Strasz    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
220255570Strasz	{
221255570Strasz		portal_group = NULL;
222255570Strasz	}
223255570Strasz	;
224255570Strasz
225255570Straszportal_group_name:	STR
226255570Strasz	{
227263725Strasz		/*
228263725Strasz		 * Make it possible to redefine default
229263725Strasz		 * portal-group. but only once.
230263725Strasz		 */
231263725Strasz		if (strcmp($1, "default") == 0 &&
232263725Strasz		    conf->conf_default_pg_defined == false) {
233263725Strasz			portal_group = portal_group_find(conf, $1);
234263725Strasz			conf->conf_default_pg_defined = true;
235263725Strasz		} else {
236263725Strasz			portal_group = portal_group_new(conf, $1);
237263725Strasz		}
238255570Strasz		free($1);
239255570Strasz		if (portal_group == NULL)
240255570Strasz			return (1);
241255570Strasz	}
242255570Strasz	;
243255570Strasz
244255570Straszportal_group_entries:
245255570Strasz	|
246255570Strasz	portal_group_entries portal_group_entry
247255570Strasz	;
248255570Strasz
249255570Straszportal_group_entry:
250255570Strasz	portal_group_discovery_auth_group
251255570Strasz	|
252255570Strasz	portal_group_listen
253255570Strasz	|
254255570Strasz	portal_group_listen_iser
255255570Strasz	;
256255570Strasz
257255570Straszportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
258255570Strasz	{
259255570Strasz		if (portal_group->pg_discovery_auth_group != NULL) {
260255570Strasz			log_warnx("discovery-auth-group for portal-group "
261255570Strasz			    "\"%s\" specified more than once",
262255570Strasz			    portal_group->pg_name);
263255570Strasz			return (1);
264255570Strasz		}
265255570Strasz		portal_group->pg_discovery_auth_group =
266255570Strasz		    auth_group_find(conf, $2);
267255570Strasz		if (portal_group->pg_discovery_auth_group == NULL) {
268255570Strasz			log_warnx("unknown discovery-auth-group \"%s\" "
269255570Strasz			    "for portal-group \"%s\"",
270255570Strasz			    $2, portal_group->pg_name);
271255570Strasz			return (1);
272255570Strasz		}
273255570Strasz		free($2);
274255570Strasz	}
275255570Strasz	;
276255570Strasz
277255570Straszportal_group_listen:	LISTEN STR
278255570Strasz	{
279255570Strasz		int error;
280255570Strasz
281255570Strasz		error = portal_group_add_listen(portal_group, $2, false);
282255570Strasz		free($2);
283255570Strasz		if (error != 0)
284255570Strasz			return (1);
285255570Strasz	}
286255570Strasz	;
287255570Strasz
288255570Straszportal_group_listen_iser:	LISTEN_ISER STR
289255570Strasz	{
290255570Strasz		int error;
291255570Strasz
292255570Strasz		error = portal_group_add_listen(portal_group, $2, true);
293255570Strasz		free($2);
294255570Strasz		if (error != 0)
295255570Strasz			return (1);
296255570Strasz	}
297255570Strasz	;
298255570Strasz
299263722Strasztarget:	TARGET target_name
300255570Strasz    OPENING_BRACKET target_entries CLOSING_BRACKET
301255570Strasz	{
302255570Strasz		target = NULL;
303255570Strasz	}
304255570Strasz	;
305255570Strasz
306263722Strasztarget_name:	STR
307255570Strasz	{
308255570Strasz		target = target_new(conf, $1);
309255570Strasz		free($1);
310255570Strasz		if (target == NULL)
311255570Strasz			return (1);
312255570Strasz	}
313255570Strasz	;
314255570Strasz
315255570Strasztarget_entries:
316255570Strasz	|
317255570Strasz	target_entries target_entry
318255570Strasz	;
319255570Strasz
320255570Strasztarget_entry:
321263722Strasz	target_alias
322255570Strasz	|
323263722Strasz	target_auth_group
324255570Strasz	|
325263724Strasz	target_auth_type
326263724Strasz	|
327263722Strasz	target_chap
328255570Strasz	|
329263722Strasz	target_chap_mutual
330255570Strasz	|
331263722Strasz	target_initiator_name
332263720Strasz	|
333263722Strasz	target_initiator_portal
334263720Strasz	|
335263722Strasz	target_portal_group
336255570Strasz	|
337263722Strasz	target_lun
338255570Strasz	;
339255570Strasz
340263722Strasztarget_alias:	ALIAS STR
341255570Strasz	{
342255570Strasz		if (target->t_alias != NULL) {
343255570Strasz			log_warnx("alias for target \"%s\" "
344263723Strasz			    "specified more than once", target->t_name);
345255570Strasz			return (1);
346255570Strasz		}
347255570Strasz		target->t_alias = $2;
348255570Strasz	}
349255570Strasz	;
350255570Strasz
351263722Strasztarget_auth_group:	AUTH_GROUP STR
352255570Strasz	{
353255570Strasz		if (target->t_auth_group != NULL) {
354255570Strasz			if (target->t_auth_group->ag_name != NULL)
355255570Strasz				log_warnx("auth-group for target \"%s\" "
356263723Strasz				    "specified more than once", target->t_name);
357255570Strasz			else
358263724Strasz				log_warnx("cannot use both auth-group and explicit "
359255570Strasz				    "authorisations for target \"%s\"",
360263723Strasz				    target->t_name);
361255570Strasz			return (1);
362255570Strasz		}
363255570Strasz		target->t_auth_group = auth_group_find(conf, $2);
364255570Strasz		if (target->t_auth_group == NULL) {
365255570Strasz			log_warnx("unknown auth-group \"%s\" for target "
366263723Strasz			    "\"%s\"", $2, target->t_name);
367255570Strasz			return (1);
368255570Strasz		}
369255570Strasz		free($2);
370255570Strasz	}
371255570Strasz	;
372255570Strasz
373263724Strasztarget_auth_type:	AUTH_TYPE STR
374263724Strasz	{
375263724Strasz		int error;
376263724Strasz
377263724Strasz		if (target->t_auth_group != NULL) {
378263724Strasz			if (target->t_auth_group->ag_name != NULL) {
379263724Strasz				log_warnx("cannot use both auth-group and "
380263724Strasz				    "auth-type for target \"%s\"",
381263724Strasz				    target->t_name);
382263724Strasz				return (1);
383263724Strasz			}
384263724Strasz		} else {
385263724Strasz			target->t_auth_group = auth_group_new(conf, NULL);
386263724Strasz			if (target->t_auth_group == NULL) {
387263724Strasz				free($2);
388263724Strasz				return (1);
389263724Strasz			}
390263724Strasz			target->t_auth_group->ag_target = target;
391263724Strasz		}
392263724Strasz		error = auth_group_set_type_str(target->t_auth_group, $2);
393263724Strasz		free($2);
394263724Strasz		if (error != 0)
395263724Strasz			return (1);
396263724Strasz	}
397263724Strasz	;
398263724Strasz
399263722Strasztarget_chap:	CHAP STR STR
400255570Strasz	{
401255570Strasz		const struct auth *ca;
402255570Strasz
403255570Strasz		if (target->t_auth_group != NULL) {
404255570Strasz			if (target->t_auth_group->ag_name != NULL) {
405263724Strasz				log_warnx("cannot use both auth-group and "
406263724Strasz				    "chap for target \"%s\"",
407263723Strasz				    target->t_name);
408255570Strasz				free($2);
409255570Strasz				free($3);
410255570Strasz				return (1);
411255570Strasz			}
412255570Strasz		} else {
413255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
414255570Strasz			if (target->t_auth_group == NULL) {
415255570Strasz				free($2);
416255570Strasz				free($3);
417255570Strasz				return (1);
418255570Strasz			}
419255570Strasz			target->t_auth_group->ag_target = target;
420255570Strasz		}
421255570Strasz		ca = auth_new_chap(target->t_auth_group, $2, $3);
422255570Strasz		free($2);
423255570Strasz		free($3);
424255570Strasz		if (ca == NULL)
425255570Strasz			return (1);
426255570Strasz	}
427255570Strasz	;
428255570Strasz
429263722Strasztarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
430255570Strasz	{
431255570Strasz		const struct auth *ca;
432255570Strasz
433255570Strasz		if (target->t_auth_group != NULL) {
434255570Strasz			if (target->t_auth_group->ag_name != NULL) {
435263724Strasz				log_warnx("cannot use both auth-group and "
436263724Strasz				    "chap-mutual for target \"%s\"",
437263723Strasz				    target->t_name);
438255570Strasz				free($2);
439255570Strasz				free($3);
440255570Strasz				free($4);
441255570Strasz				free($5);
442255570Strasz				return (1);
443255570Strasz			}
444255570Strasz		} else {
445255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
446255570Strasz			if (target->t_auth_group == NULL) {
447255570Strasz				free($2);
448255570Strasz				free($3);
449255570Strasz				free($4);
450255570Strasz				free($5);
451255570Strasz				return (1);
452255570Strasz			}
453255570Strasz			target->t_auth_group->ag_target = target;
454255570Strasz		}
455255570Strasz		ca = auth_new_chap_mutual(target->t_auth_group,
456255570Strasz		    $2, $3, $4, $5);
457255570Strasz		free($2);
458255570Strasz		free($3);
459255570Strasz		free($4);
460255570Strasz		free($5);
461255570Strasz		if (ca == NULL)
462255570Strasz			return (1);
463255570Strasz	}
464255570Strasz	;
465255570Strasz
466263722Strasztarget_initiator_name:	INITIATOR_NAME STR
467263720Strasz	{
468263720Strasz		const struct auth_name *an;
469263720Strasz
470263720Strasz		if (target->t_auth_group != NULL) {
471263720Strasz			if (target->t_auth_group->ag_name != NULL) {
472263724Strasz				log_warnx("cannot use both auth-group and "
473263720Strasz				    "initiator-name for target \"%s\"",
474263723Strasz				    target->t_name);
475263720Strasz				free($2);
476263720Strasz				return (1);
477263720Strasz			}
478263720Strasz		} else {
479263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
480263720Strasz			if (target->t_auth_group == NULL) {
481263720Strasz				free($2);
482263720Strasz				return (1);
483263720Strasz			}
484263720Strasz			target->t_auth_group->ag_target = target;
485263720Strasz		}
486263720Strasz		an = auth_name_new(target->t_auth_group, $2);
487263720Strasz		free($2);
488263720Strasz		if (an == NULL)
489263720Strasz			return (1);
490263720Strasz	}
491263720Strasz	;
492263720Strasz
493263722Strasztarget_initiator_portal:	INITIATOR_PORTAL STR
494263720Strasz	{
495263720Strasz		const struct auth_portal *ap;
496263720Strasz
497263720Strasz		if (target->t_auth_group != NULL) {
498263720Strasz			if (target->t_auth_group->ag_name != NULL) {
499263724Strasz				log_warnx("cannot use both auth-group and "
500263720Strasz				    "initiator-portal for target \"%s\"",
501263723Strasz				    target->t_name);
502263720Strasz				free($2);
503263720Strasz				return (1);
504263720Strasz			}
505263720Strasz		} else {
506263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
507263720Strasz			if (target->t_auth_group == NULL) {
508263720Strasz				free($2);
509263720Strasz				return (1);
510263720Strasz			}
511263720Strasz			target->t_auth_group->ag_target = target;
512263720Strasz		}
513263720Strasz		ap = auth_portal_new(target->t_auth_group, $2);
514263720Strasz		free($2);
515263720Strasz		if (ap == NULL)
516263720Strasz			return (1);
517263720Strasz	}
518263720Strasz	;
519263720Strasz
520263722Strasztarget_portal_group:	PORTAL_GROUP STR
521255570Strasz	{
522255570Strasz		if (target->t_portal_group != NULL) {
523255570Strasz			log_warnx("portal-group for target \"%s\" "
524263723Strasz			    "specified more than once", target->t_name);
525255570Strasz			free($2);
526255570Strasz			return (1);
527255570Strasz		}
528255570Strasz		target->t_portal_group = portal_group_find(conf, $2);
529255570Strasz		if (target->t_portal_group == NULL) {
530255570Strasz			log_warnx("unknown portal-group \"%s\" for target "
531263723Strasz			    "\"%s\"", $2, target->t_name);
532255570Strasz			free($2);
533255570Strasz			return (1);
534255570Strasz		}
535255570Strasz		free($2);
536255570Strasz	}
537255570Strasz	;
538255570Strasz
539263722Strasztarget_lun:	LUN lun_number
540263722Strasz    OPENING_BRACKET lun_entries CLOSING_BRACKET
541255570Strasz	{
542255570Strasz		lun = NULL;
543255570Strasz	}
544255570Strasz	;
545255570Strasz
546255570Straszlun_number:	NUM
547255570Strasz	{
548255570Strasz		lun = lun_new(target, $1);
549255570Strasz		if (lun == NULL)
550255570Strasz			return (1);
551255570Strasz	}
552255570Strasz	;
553255570Strasz
554263722Straszlun_entries:
555255570Strasz	|
556263722Strasz	lun_entries lun_entry
557255570Strasz	;
558255570Strasz
559263722Straszlun_entry:
560263722Strasz	lun_backend
561255570Strasz	|
562263722Strasz	lun_blocksize
563255570Strasz	|
564263722Strasz	lun_device_id
565255570Strasz	|
566263722Strasz	lun_option
567255570Strasz	|
568263722Strasz	lun_path
569255570Strasz	|
570263722Strasz	lun_serial
571255570Strasz	|
572263722Strasz	lun_size
573255570Strasz	;
574255570Strasz
575263722Straszlun_backend:	BACKEND STR
576255570Strasz	{
577255570Strasz		if (lun->l_backend != NULL) {
578255570Strasz			log_warnx("backend for lun %d, target \"%s\" "
579255570Strasz			    "specified more than once",
580263723Strasz			    lun->l_lun, target->t_name);
581255570Strasz			free($2);
582255570Strasz			return (1);
583255570Strasz		}
584255570Strasz		lun_set_backend(lun, $2);
585255570Strasz		free($2);
586255570Strasz	}
587255570Strasz	;
588255570Strasz
589263722Straszlun_blocksize:	BLOCKSIZE NUM
590255570Strasz	{
591255570Strasz		if (lun->l_blocksize != 0) {
592255570Strasz			log_warnx("blocksize for lun %d, target \"%s\" "
593255570Strasz			    "specified more than once",
594263723Strasz			    lun->l_lun, target->t_name);
595255570Strasz			return (1);
596255570Strasz		}
597255570Strasz		lun_set_blocksize(lun, $2);
598255570Strasz	}
599255570Strasz	;
600255570Strasz
601263722Straszlun_device_id:	DEVICE_ID STR
602255570Strasz	{
603255570Strasz		if (lun->l_device_id != NULL) {
604255570Strasz			log_warnx("device_id for lun %d, target \"%s\" "
605255570Strasz			    "specified more than once",
606263723Strasz			    lun->l_lun, target->t_name);
607255570Strasz			free($2);
608255570Strasz			return (1);
609255570Strasz		}
610255570Strasz		lun_set_device_id(lun, $2);
611255570Strasz		free($2);
612255570Strasz	}
613255570Strasz	;
614255570Strasz
615263722Straszlun_option:	OPTION STR STR
616255570Strasz	{
617255570Strasz		struct lun_option *clo;
618255570Strasz
619255570Strasz		clo = lun_option_new(lun, $2, $3);
620255570Strasz		free($2);
621255570Strasz		free($3);
622255570Strasz		if (clo == NULL)
623255570Strasz			return (1);
624255570Strasz	}
625255570Strasz	;
626255570Strasz
627263722Straszlun_path:	PATH STR
628255570Strasz	{
629255570Strasz		if (lun->l_path != NULL) {
630255570Strasz			log_warnx("path for lun %d, target \"%s\" "
631255570Strasz			    "specified more than once",
632263723Strasz			    lun->l_lun, target->t_name);
633255570Strasz			free($2);
634255570Strasz			return (1);
635255570Strasz		}
636255570Strasz		lun_set_path(lun, $2);
637255570Strasz		free($2);
638255570Strasz	}
639255570Strasz	;
640255570Strasz
641263722Straszlun_serial:	SERIAL STR
642255570Strasz	{
643255570Strasz		if (lun->l_serial != NULL) {
644255570Strasz			log_warnx("serial for lun %d, target \"%s\" "
645255570Strasz			    "specified more than once",
646263723Strasz			    lun->l_lun, target->t_name);
647255570Strasz			free($2);
648255570Strasz			return (1);
649255570Strasz		}
650255570Strasz		lun_set_serial(lun, $2);
651255570Strasz		free($2);
652255570Strasz	}
653255570Strasz	;
654255570Strasz
655263722Straszlun_size:	SIZE NUM
656255570Strasz	{
657255570Strasz		if (lun->l_size != 0) {
658255570Strasz			log_warnx("size for lun %d, target \"%s\" "
659255570Strasz			    "specified more than once",
660263723Strasz			    lun->l_lun, target->t_name);
661255570Strasz			return (1);
662255570Strasz		}
663255570Strasz		lun_set_size(lun, $2);
664255570Strasz	}
665255570Strasz	;
666255570Strasz%%
667255570Strasz
668255570Straszvoid
669255570Straszyyerror(const char *str)
670255570Strasz{
671255570Strasz
672255570Strasz	log_warnx("error in configuration file at line %d near '%s': %s",
673255570Strasz	    lineno, yytext, str);
674255570Strasz}
675255570Strasz
676255570Straszstatic void
677255570Straszcheck_perms(const char *path)
678255570Strasz{
679255570Strasz	struct stat sb;
680255570Strasz	int error;
681255570Strasz
682255570Strasz	error = stat(path, &sb);
683255570Strasz	if (error != 0) {
684255570Strasz		log_warn("stat");
685255570Strasz		return;
686255570Strasz	}
687255570Strasz	if (sb.st_mode & S_IWOTH) {
688255570Strasz		log_warnx("%s is world-writable", path);
689255570Strasz	} else if (sb.st_mode & S_IROTH) {
690255570Strasz		log_warnx("%s is world-readable", path);
691255570Strasz	} else if (sb.st_mode & S_IXOTH) {
692255570Strasz		/*
693255570Strasz		 * Ok, this one doesn't matter, but still do it,
694255570Strasz		 * just for consistency.
695255570Strasz		 */
696255570Strasz		log_warnx("%s is world-executable", path);
697255570Strasz	}
698255570Strasz
699255570Strasz	/*
700255570Strasz	 * XXX: Should we also check for owner != 0?
701255570Strasz	 */
702255570Strasz}
703255570Strasz
704255570Straszstruct conf *
705255570Straszconf_new_from_file(const char *path)
706255570Strasz{
707255570Strasz	struct auth_group *ag;
708255570Strasz	struct portal_group *pg;
709255570Strasz	int error;
710255570Strasz
711255570Strasz	log_debugx("obtaining configuration from %s", path);
712255570Strasz
713255570Strasz	conf = conf_new();
714255570Strasz
715255570Strasz	ag = auth_group_new(conf, "no-authentication");
716263725Strasz	assert(ag != NULL);
717255570Strasz	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
718255570Strasz
719255570Strasz	/*
720255570Strasz	 * Here, the type doesn't really matter, as the group doesn't contain
721255570Strasz	 * any entries and thus will always deny access.
722255570Strasz	 */
723255570Strasz	ag = auth_group_new(conf, "no-access");
724263725Strasz	assert(ag != NULL);
725255570Strasz	ag->ag_type = AG_TYPE_CHAP;
726255570Strasz
727255570Strasz	pg = portal_group_new(conf, "default");
728263725Strasz	assert(pg != NULL);
729255570Strasz
730255570Strasz	yyin = fopen(path, "r");
731255570Strasz	if (yyin == NULL) {
732255570Strasz		log_warn("unable to open configuration file %s", path);
733255570Strasz		conf_delete(conf);
734255570Strasz		return (NULL);
735255570Strasz	}
736255570Strasz	check_perms(path);
737263715Strasz	lineno = 1;
738255570Strasz	yyrestart(yyin);
739255570Strasz	error = yyparse();
740255570Strasz	auth_group = NULL;
741255570Strasz	portal_group = NULL;
742255570Strasz	target = NULL;
743255570Strasz	lun = NULL;
744255570Strasz	fclose(yyin);
745255570Strasz	if (error != 0) {
746255570Strasz		conf_delete(conf);
747255570Strasz		return (NULL);
748255570Strasz	}
749255570Strasz
750263725Strasz	if (conf->conf_default_pg_defined == false) {
751263725Strasz		log_debugx("portal-group \"default\" not defined; "
752263725Strasz		    "going with defaults");
753263725Strasz		pg = portal_group_find(conf, "default");
754263725Strasz		assert(pg != NULL);
755263725Strasz		portal_group_add_listen(pg, "0.0.0.0:3260", false);
756263725Strasz		portal_group_add_listen(pg, "[::]:3260", false);
757263725Strasz	}
758263725Strasz
759255570Strasz	error = conf_verify(conf);
760255570Strasz	if (error != 0) {
761255570Strasz		conf_delete(conf);
762255570Strasz		return (NULL);
763255570Strasz	}
764255570Strasz
765255570Strasz	return (conf);
766255570Strasz}
767