parse.y revision 263724
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 263724 2014-03-25 12:12:37Z 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	{
227255570Strasz		portal_group = portal_group_new(conf, $1);
228255570Strasz		free($1);
229255570Strasz		if (portal_group == NULL)
230255570Strasz			return (1);
231255570Strasz	}
232255570Strasz	;
233255570Strasz
234255570Straszportal_group_entries:
235255570Strasz	|
236255570Strasz	portal_group_entries portal_group_entry
237255570Strasz	;
238255570Strasz
239255570Straszportal_group_entry:
240255570Strasz	portal_group_discovery_auth_group
241255570Strasz	|
242255570Strasz	portal_group_listen
243255570Strasz	|
244255570Strasz	portal_group_listen_iser
245255570Strasz	;
246255570Strasz
247255570Straszportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
248255570Strasz	{
249255570Strasz		if (portal_group->pg_discovery_auth_group != NULL) {
250255570Strasz			log_warnx("discovery-auth-group for portal-group "
251255570Strasz			    "\"%s\" specified more than once",
252255570Strasz			    portal_group->pg_name);
253255570Strasz			return (1);
254255570Strasz		}
255255570Strasz		portal_group->pg_discovery_auth_group =
256255570Strasz		    auth_group_find(conf, $2);
257255570Strasz		if (portal_group->pg_discovery_auth_group == NULL) {
258255570Strasz			log_warnx("unknown discovery-auth-group \"%s\" "
259255570Strasz			    "for portal-group \"%s\"",
260255570Strasz			    $2, portal_group->pg_name);
261255570Strasz			return (1);
262255570Strasz		}
263255570Strasz		free($2);
264255570Strasz	}
265255570Strasz	;
266255570Strasz
267255570Straszportal_group_listen:	LISTEN STR
268255570Strasz	{
269255570Strasz		int error;
270255570Strasz
271255570Strasz		error = portal_group_add_listen(portal_group, $2, false);
272255570Strasz		free($2);
273255570Strasz		if (error != 0)
274255570Strasz			return (1);
275255570Strasz	}
276255570Strasz	;
277255570Strasz
278255570Straszportal_group_listen_iser:	LISTEN_ISER STR
279255570Strasz	{
280255570Strasz		int error;
281255570Strasz
282255570Strasz		error = portal_group_add_listen(portal_group, $2, true);
283255570Strasz		free($2);
284255570Strasz		if (error != 0)
285255570Strasz			return (1);
286255570Strasz	}
287255570Strasz	;
288255570Strasz
289263722Strasztarget:	TARGET target_name
290255570Strasz    OPENING_BRACKET target_entries CLOSING_BRACKET
291255570Strasz	{
292255570Strasz		target = NULL;
293255570Strasz	}
294255570Strasz	;
295255570Strasz
296263722Strasztarget_name:	STR
297255570Strasz	{
298255570Strasz		target = target_new(conf, $1);
299255570Strasz		free($1);
300255570Strasz		if (target == NULL)
301255570Strasz			return (1);
302255570Strasz	}
303255570Strasz	;
304255570Strasz
305255570Strasztarget_entries:
306255570Strasz	|
307255570Strasz	target_entries target_entry
308255570Strasz	;
309255570Strasz
310255570Strasztarget_entry:
311263722Strasz	target_alias
312255570Strasz	|
313263722Strasz	target_auth_group
314255570Strasz	|
315263724Strasz	target_auth_type
316263724Strasz	|
317263722Strasz	target_chap
318255570Strasz	|
319263722Strasz	target_chap_mutual
320255570Strasz	|
321263722Strasz	target_initiator_name
322263720Strasz	|
323263722Strasz	target_initiator_portal
324263720Strasz	|
325263722Strasz	target_portal_group
326255570Strasz	|
327263722Strasz	target_lun
328255570Strasz	;
329255570Strasz
330263722Strasztarget_alias:	ALIAS STR
331255570Strasz	{
332255570Strasz		if (target->t_alias != NULL) {
333255570Strasz			log_warnx("alias for target \"%s\" "
334263723Strasz			    "specified more than once", target->t_name);
335255570Strasz			return (1);
336255570Strasz		}
337255570Strasz		target->t_alias = $2;
338255570Strasz	}
339255570Strasz	;
340255570Strasz
341263722Strasztarget_auth_group:	AUTH_GROUP STR
342255570Strasz	{
343255570Strasz		if (target->t_auth_group != NULL) {
344255570Strasz			if (target->t_auth_group->ag_name != NULL)
345255570Strasz				log_warnx("auth-group for target \"%s\" "
346263723Strasz				    "specified more than once", target->t_name);
347255570Strasz			else
348263724Strasz				log_warnx("cannot use both auth-group and explicit "
349255570Strasz				    "authorisations for target \"%s\"",
350263723Strasz				    target->t_name);
351255570Strasz			return (1);
352255570Strasz		}
353255570Strasz		target->t_auth_group = auth_group_find(conf, $2);
354255570Strasz		if (target->t_auth_group == NULL) {
355255570Strasz			log_warnx("unknown auth-group \"%s\" for target "
356263723Strasz			    "\"%s\"", $2, target->t_name);
357255570Strasz			return (1);
358255570Strasz		}
359255570Strasz		free($2);
360255570Strasz	}
361255570Strasz	;
362255570Strasz
363263724Strasztarget_auth_type:	AUTH_TYPE STR
364263724Strasz	{
365263724Strasz		int error;
366263724Strasz
367263724Strasz		if (target->t_auth_group != NULL) {
368263724Strasz			if (target->t_auth_group->ag_name != NULL) {
369263724Strasz				log_warnx("cannot use both auth-group and "
370263724Strasz				    "auth-type for target \"%s\"",
371263724Strasz				    target->t_name);
372263724Strasz				return (1);
373263724Strasz			}
374263724Strasz		} else {
375263724Strasz			target->t_auth_group = auth_group_new(conf, NULL);
376263724Strasz			if (target->t_auth_group == NULL) {
377263724Strasz				free($2);
378263724Strasz				return (1);
379263724Strasz			}
380263724Strasz			target->t_auth_group->ag_target = target;
381263724Strasz		}
382263724Strasz		error = auth_group_set_type_str(target->t_auth_group, $2);
383263724Strasz		free($2);
384263724Strasz		if (error != 0)
385263724Strasz			return (1);
386263724Strasz	}
387263724Strasz	;
388263724Strasz
389263722Strasztarget_chap:	CHAP STR STR
390255570Strasz	{
391255570Strasz		const struct auth *ca;
392255570Strasz
393255570Strasz		if (target->t_auth_group != NULL) {
394255570Strasz			if (target->t_auth_group->ag_name != NULL) {
395263724Strasz				log_warnx("cannot use both auth-group and "
396263724Strasz				    "chap for target \"%s\"",
397263723Strasz				    target->t_name);
398255570Strasz				free($2);
399255570Strasz				free($3);
400255570Strasz				return (1);
401255570Strasz			}
402255570Strasz		} else {
403255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
404255570Strasz			if (target->t_auth_group == NULL) {
405255570Strasz				free($2);
406255570Strasz				free($3);
407255570Strasz				return (1);
408255570Strasz			}
409255570Strasz			target->t_auth_group->ag_target = target;
410255570Strasz		}
411255570Strasz		ca = auth_new_chap(target->t_auth_group, $2, $3);
412255570Strasz		free($2);
413255570Strasz		free($3);
414255570Strasz		if (ca == NULL)
415255570Strasz			return (1);
416255570Strasz	}
417255570Strasz	;
418255570Strasz
419263722Strasztarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
420255570Strasz	{
421255570Strasz		const struct auth *ca;
422255570Strasz
423255570Strasz		if (target->t_auth_group != NULL) {
424255570Strasz			if (target->t_auth_group->ag_name != NULL) {
425263724Strasz				log_warnx("cannot use both auth-group and "
426263724Strasz				    "chap-mutual for target \"%s\"",
427263723Strasz				    target->t_name);
428255570Strasz				free($2);
429255570Strasz				free($3);
430255570Strasz				free($4);
431255570Strasz				free($5);
432255570Strasz				return (1);
433255570Strasz			}
434255570Strasz		} else {
435255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
436255570Strasz			if (target->t_auth_group == NULL) {
437255570Strasz				free($2);
438255570Strasz				free($3);
439255570Strasz				free($4);
440255570Strasz				free($5);
441255570Strasz				return (1);
442255570Strasz			}
443255570Strasz			target->t_auth_group->ag_target = target;
444255570Strasz		}
445255570Strasz		ca = auth_new_chap_mutual(target->t_auth_group,
446255570Strasz		    $2, $3, $4, $5);
447255570Strasz		free($2);
448255570Strasz		free($3);
449255570Strasz		free($4);
450255570Strasz		free($5);
451255570Strasz		if (ca == NULL)
452255570Strasz			return (1);
453255570Strasz	}
454255570Strasz	;
455255570Strasz
456263722Strasztarget_initiator_name:	INITIATOR_NAME STR
457263720Strasz	{
458263720Strasz		const struct auth_name *an;
459263720Strasz
460263720Strasz		if (target->t_auth_group != NULL) {
461263720Strasz			if (target->t_auth_group->ag_name != NULL) {
462263724Strasz				log_warnx("cannot use both auth-group and "
463263720Strasz				    "initiator-name for target \"%s\"",
464263723Strasz				    target->t_name);
465263720Strasz				free($2);
466263720Strasz				return (1);
467263720Strasz			}
468263720Strasz		} else {
469263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
470263720Strasz			if (target->t_auth_group == NULL) {
471263720Strasz				free($2);
472263720Strasz				return (1);
473263720Strasz			}
474263720Strasz			target->t_auth_group->ag_target = target;
475263720Strasz		}
476263720Strasz		an = auth_name_new(target->t_auth_group, $2);
477263720Strasz		free($2);
478263720Strasz		if (an == NULL)
479263720Strasz			return (1);
480263720Strasz	}
481263720Strasz	;
482263720Strasz
483263722Strasztarget_initiator_portal:	INITIATOR_PORTAL STR
484263720Strasz	{
485263720Strasz		const struct auth_portal *ap;
486263720Strasz
487263720Strasz		if (target->t_auth_group != NULL) {
488263720Strasz			if (target->t_auth_group->ag_name != NULL) {
489263724Strasz				log_warnx("cannot use both auth-group and "
490263720Strasz				    "initiator-portal for target \"%s\"",
491263723Strasz				    target->t_name);
492263720Strasz				free($2);
493263720Strasz				return (1);
494263720Strasz			}
495263720Strasz		} else {
496263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
497263720Strasz			if (target->t_auth_group == NULL) {
498263720Strasz				free($2);
499263720Strasz				return (1);
500263720Strasz			}
501263720Strasz			target->t_auth_group->ag_target = target;
502263720Strasz		}
503263720Strasz		ap = auth_portal_new(target->t_auth_group, $2);
504263720Strasz		free($2);
505263720Strasz		if (ap == NULL)
506263720Strasz			return (1);
507263720Strasz	}
508263720Strasz	;
509263720Strasz
510263722Strasztarget_portal_group:	PORTAL_GROUP STR
511255570Strasz	{
512255570Strasz		if (target->t_portal_group != NULL) {
513255570Strasz			log_warnx("portal-group for target \"%s\" "
514263723Strasz			    "specified more than once", target->t_name);
515255570Strasz			free($2);
516255570Strasz			return (1);
517255570Strasz		}
518255570Strasz		target->t_portal_group = portal_group_find(conf, $2);
519255570Strasz		if (target->t_portal_group == NULL) {
520255570Strasz			log_warnx("unknown portal-group \"%s\" for target "
521263723Strasz			    "\"%s\"", $2, target->t_name);
522255570Strasz			free($2);
523255570Strasz			return (1);
524255570Strasz		}
525255570Strasz		free($2);
526255570Strasz	}
527255570Strasz	;
528255570Strasz
529263722Strasztarget_lun:	LUN lun_number
530263722Strasz    OPENING_BRACKET lun_entries CLOSING_BRACKET
531255570Strasz	{
532255570Strasz		lun = NULL;
533255570Strasz	}
534255570Strasz	;
535255570Strasz
536255570Straszlun_number:	NUM
537255570Strasz	{
538255570Strasz		lun = lun_new(target, $1);
539255570Strasz		if (lun == NULL)
540255570Strasz			return (1);
541255570Strasz	}
542255570Strasz	;
543255570Strasz
544263722Straszlun_entries:
545255570Strasz	|
546263722Strasz	lun_entries lun_entry
547255570Strasz	;
548255570Strasz
549263722Straszlun_entry:
550263722Strasz	lun_backend
551255570Strasz	|
552263722Strasz	lun_blocksize
553255570Strasz	|
554263722Strasz	lun_device_id
555255570Strasz	|
556263722Strasz	lun_option
557255570Strasz	|
558263722Strasz	lun_path
559255570Strasz	|
560263722Strasz	lun_serial
561255570Strasz	|
562263722Strasz	lun_size
563255570Strasz	;
564255570Strasz
565263722Straszlun_backend:	BACKEND STR
566255570Strasz	{
567255570Strasz		if (lun->l_backend != NULL) {
568255570Strasz			log_warnx("backend for lun %d, target \"%s\" "
569255570Strasz			    "specified more than once",
570263723Strasz			    lun->l_lun, target->t_name);
571255570Strasz			free($2);
572255570Strasz			return (1);
573255570Strasz		}
574255570Strasz		lun_set_backend(lun, $2);
575255570Strasz		free($2);
576255570Strasz	}
577255570Strasz	;
578255570Strasz
579263722Straszlun_blocksize:	BLOCKSIZE NUM
580255570Strasz	{
581255570Strasz		if (lun->l_blocksize != 0) {
582255570Strasz			log_warnx("blocksize for lun %d, target \"%s\" "
583255570Strasz			    "specified more than once",
584263723Strasz			    lun->l_lun, target->t_name);
585255570Strasz			return (1);
586255570Strasz		}
587255570Strasz		lun_set_blocksize(lun, $2);
588255570Strasz	}
589255570Strasz	;
590255570Strasz
591263722Straszlun_device_id:	DEVICE_ID STR
592255570Strasz	{
593255570Strasz		if (lun->l_device_id != NULL) {
594255570Strasz			log_warnx("device_id for lun %d, target \"%s\" "
595255570Strasz			    "specified more than once",
596263723Strasz			    lun->l_lun, target->t_name);
597255570Strasz			free($2);
598255570Strasz			return (1);
599255570Strasz		}
600255570Strasz		lun_set_device_id(lun, $2);
601255570Strasz		free($2);
602255570Strasz	}
603255570Strasz	;
604255570Strasz
605263722Straszlun_option:	OPTION STR STR
606255570Strasz	{
607255570Strasz		struct lun_option *clo;
608255570Strasz
609255570Strasz		clo = lun_option_new(lun, $2, $3);
610255570Strasz		free($2);
611255570Strasz		free($3);
612255570Strasz		if (clo == NULL)
613255570Strasz			return (1);
614255570Strasz	}
615255570Strasz	;
616255570Strasz
617263722Straszlun_path:	PATH STR
618255570Strasz	{
619255570Strasz		if (lun->l_path != NULL) {
620255570Strasz			log_warnx("path for lun %d, target \"%s\" "
621255570Strasz			    "specified more than once",
622263723Strasz			    lun->l_lun, target->t_name);
623255570Strasz			free($2);
624255570Strasz			return (1);
625255570Strasz		}
626255570Strasz		lun_set_path(lun, $2);
627255570Strasz		free($2);
628255570Strasz	}
629255570Strasz	;
630255570Strasz
631263722Straszlun_serial:	SERIAL STR
632255570Strasz	{
633255570Strasz		if (lun->l_serial != NULL) {
634255570Strasz			log_warnx("serial for lun %d, target \"%s\" "
635255570Strasz			    "specified more than once",
636263723Strasz			    lun->l_lun, target->t_name);
637255570Strasz			free($2);
638255570Strasz			return (1);
639255570Strasz		}
640255570Strasz		lun_set_serial(lun, $2);
641255570Strasz		free($2);
642255570Strasz	}
643255570Strasz	;
644255570Strasz
645263722Straszlun_size:	SIZE NUM
646255570Strasz	{
647255570Strasz		if (lun->l_size != 0) {
648255570Strasz			log_warnx("size for lun %d, target \"%s\" "
649255570Strasz			    "specified more than once",
650263723Strasz			    lun->l_lun, target->t_name);
651255570Strasz			return (1);
652255570Strasz		}
653255570Strasz		lun_set_size(lun, $2);
654255570Strasz	}
655255570Strasz	;
656255570Strasz%%
657255570Strasz
658255570Straszvoid
659255570Straszyyerror(const char *str)
660255570Strasz{
661255570Strasz
662255570Strasz	log_warnx("error in configuration file at line %d near '%s': %s",
663255570Strasz	    lineno, yytext, str);
664255570Strasz}
665255570Strasz
666255570Straszstatic void
667255570Straszcheck_perms(const char *path)
668255570Strasz{
669255570Strasz	struct stat sb;
670255570Strasz	int error;
671255570Strasz
672255570Strasz	error = stat(path, &sb);
673255570Strasz	if (error != 0) {
674255570Strasz		log_warn("stat");
675255570Strasz		return;
676255570Strasz	}
677255570Strasz	if (sb.st_mode & S_IWOTH) {
678255570Strasz		log_warnx("%s is world-writable", path);
679255570Strasz	} else if (sb.st_mode & S_IROTH) {
680255570Strasz		log_warnx("%s is world-readable", path);
681255570Strasz	} else if (sb.st_mode & S_IXOTH) {
682255570Strasz		/*
683255570Strasz		 * Ok, this one doesn't matter, but still do it,
684255570Strasz		 * just for consistency.
685255570Strasz		 */
686255570Strasz		log_warnx("%s is world-executable", path);
687255570Strasz	}
688255570Strasz
689255570Strasz	/*
690255570Strasz	 * XXX: Should we also check for owner != 0?
691255570Strasz	 */
692255570Strasz}
693255570Strasz
694255570Straszstruct conf *
695255570Straszconf_new_from_file(const char *path)
696255570Strasz{
697255570Strasz	struct auth_group *ag;
698255570Strasz	struct portal_group *pg;
699255570Strasz	int error;
700255570Strasz
701255570Strasz	log_debugx("obtaining configuration from %s", path);
702255570Strasz
703255570Strasz	conf = conf_new();
704255570Strasz
705255570Strasz	ag = auth_group_new(conf, "no-authentication");
706255570Strasz	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
707255570Strasz
708255570Strasz	/*
709255570Strasz	 * Here, the type doesn't really matter, as the group doesn't contain
710255570Strasz	 * any entries and thus will always deny access.
711255570Strasz	 */
712255570Strasz	ag = auth_group_new(conf, "no-access");
713255570Strasz	ag->ag_type = AG_TYPE_CHAP;
714255570Strasz
715255570Strasz	pg = portal_group_new(conf, "default");
716255570Strasz	portal_group_add_listen(pg, "0.0.0.0:3260", false);
717255570Strasz	portal_group_add_listen(pg, "[::]:3260", false);
718255570Strasz
719255570Strasz	yyin = fopen(path, "r");
720255570Strasz	if (yyin == NULL) {
721255570Strasz		log_warn("unable to open configuration file %s", path);
722255570Strasz		conf_delete(conf);
723255570Strasz		return (NULL);
724255570Strasz	}
725255570Strasz	check_perms(path);
726263715Strasz	lineno = 1;
727255570Strasz	yyrestart(yyin);
728255570Strasz	error = yyparse();
729255570Strasz	auth_group = NULL;
730255570Strasz	portal_group = NULL;
731255570Strasz	target = NULL;
732255570Strasz	lun = NULL;
733255570Strasz	fclose(yyin);
734255570Strasz	if (error != 0) {
735255570Strasz		conf_delete(conf);
736255570Strasz		return (NULL);
737255570Strasz	}
738255570Strasz
739255570Strasz	error = conf_verify(conf);
740255570Strasz	if (error != 0) {
741255570Strasz		conf_delete(conf);
742255570Strasz		return (NULL);
743255570Strasz	}
744255570Strasz
745255570Strasz	return (conf);
746255570Strasz}
747