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$
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	{
135263726Strasz		/*
136263726Strasz		 * Make it possible to redefine default
137263726Strasz		 * auth-group. but only once.
138263726Strasz		 */
139263726Strasz		if (strcmp($1, "default") == 0 &&
140263726Strasz		    conf->conf_default_ag_defined == false) {
141263726Strasz			auth_group = auth_group_find(conf, $1);
142263726Strasz			conf->conf_default_ag_defined = true;
143263726Strasz		} else {
144263726Strasz			auth_group = auth_group_new(conf, $1);
145263726Strasz		}
146255570Strasz		free($1);
147255570Strasz		if (auth_group == NULL)
148255570Strasz			return (1);
149255570Strasz	}
150255570Strasz	;
151255570Strasz
152255570Straszauth_group_entries:
153255570Strasz	|
154255570Strasz	auth_group_entries auth_group_entry
155255570Strasz	;
156255570Strasz
157255570Straszauth_group_entry:
158263724Strasz	auth_group_auth_type
159263724Strasz	|
160255570Strasz	auth_group_chap
161255570Strasz	|
162255570Strasz	auth_group_chap_mutual
163263720Strasz	|
164263720Strasz	auth_group_initiator_name
165263720Strasz	|
166263720Strasz	auth_group_initiator_portal
167255570Strasz	;
168255570Strasz
169263724Straszauth_group_auth_type:	AUTH_TYPE STR
170263724Strasz	{
171263724Strasz		int error;
172263724Strasz
173263724Strasz		error = auth_group_set_type_str(auth_group, $2);
174263724Strasz		free($2);
175263724Strasz		if (error != 0)
176263724Strasz			return (1);
177263724Strasz	}
178263724Strasz	;
179263724Strasz
180255570Straszauth_group_chap:	CHAP STR STR
181255570Strasz	{
182255570Strasz		const struct auth *ca;
183255570Strasz
184255570Strasz		ca = auth_new_chap(auth_group, $2, $3);
185255570Strasz		free($2);
186255570Strasz		free($3);
187255570Strasz		if (ca == NULL)
188255570Strasz			return (1);
189255570Strasz	}
190255570Strasz	;
191255570Strasz
192255570Straszauth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
193255570Strasz	{
194255570Strasz		const struct auth *ca;
195255570Strasz
196255570Strasz		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
197255570Strasz		free($2);
198255570Strasz		free($3);
199255570Strasz		free($4);
200255570Strasz		free($5);
201255570Strasz		if (ca == NULL)
202255570Strasz			return (1);
203255570Strasz	}
204255570Strasz	;
205255570Strasz
206263720Straszauth_group_initiator_name:	INITIATOR_NAME STR
207263720Strasz	{
208263720Strasz		const struct auth_name *an;
209263720Strasz
210263720Strasz		an = auth_name_new(auth_group, $2);
211263720Strasz		free($2);
212263720Strasz		if (an == NULL)
213263720Strasz			return (1);
214263720Strasz	}
215263720Strasz	;
216263720Strasz
217263720Straszauth_group_initiator_portal:	INITIATOR_PORTAL STR
218263720Strasz	{
219263720Strasz		const struct auth_portal *ap;
220263720Strasz
221263720Strasz		ap = auth_portal_new(auth_group, $2);
222263720Strasz		free($2);
223263720Strasz		if (ap == NULL)
224263720Strasz			return (1);
225263720Strasz	}
226263720Strasz	;
227263720Strasz
228263722Straszportal_group:	PORTAL_GROUP portal_group_name
229255570Strasz    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
230255570Strasz	{
231255570Strasz		portal_group = NULL;
232255570Strasz	}
233255570Strasz	;
234255570Strasz
235255570Straszportal_group_name:	STR
236255570Strasz	{
237263725Strasz		/*
238263725Strasz		 * Make it possible to redefine default
239263725Strasz		 * portal-group. but only once.
240263725Strasz		 */
241263725Strasz		if (strcmp($1, "default") == 0 &&
242263725Strasz		    conf->conf_default_pg_defined == false) {
243263725Strasz			portal_group = portal_group_find(conf, $1);
244263725Strasz			conf->conf_default_pg_defined = true;
245263725Strasz		} else {
246263725Strasz			portal_group = portal_group_new(conf, $1);
247263725Strasz		}
248255570Strasz		free($1);
249255570Strasz		if (portal_group == NULL)
250255570Strasz			return (1);
251255570Strasz	}
252255570Strasz	;
253255570Strasz
254255570Straszportal_group_entries:
255255570Strasz	|
256255570Strasz	portal_group_entries portal_group_entry
257255570Strasz	;
258255570Strasz
259255570Straszportal_group_entry:
260255570Strasz	portal_group_discovery_auth_group
261255570Strasz	|
262255570Strasz	portal_group_listen
263255570Strasz	|
264255570Strasz	portal_group_listen_iser
265255570Strasz	;
266255570Strasz
267255570Straszportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
268255570Strasz	{
269255570Strasz		if (portal_group->pg_discovery_auth_group != NULL) {
270255570Strasz			log_warnx("discovery-auth-group for portal-group "
271255570Strasz			    "\"%s\" specified more than once",
272255570Strasz			    portal_group->pg_name);
273255570Strasz			return (1);
274255570Strasz		}
275255570Strasz		portal_group->pg_discovery_auth_group =
276255570Strasz		    auth_group_find(conf, $2);
277255570Strasz		if (portal_group->pg_discovery_auth_group == NULL) {
278255570Strasz			log_warnx("unknown discovery-auth-group \"%s\" "
279255570Strasz			    "for portal-group \"%s\"",
280255570Strasz			    $2, portal_group->pg_name);
281255570Strasz			return (1);
282255570Strasz		}
283255570Strasz		free($2);
284255570Strasz	}
285255570Strasz	;
286255570Strasz
287255570Straszportal_group_listen:	LISTEN STR
288255570Strasz	{
289255570Strasz		int error;
290255570Strasz
291255570Strasz		error = portal_group_add_listen(portal_group, $2, false);
292255570Strasz		free($2);
293255570Strasz		if (error != 0)
294255570Strasz			return (1);
295255570Strasz	}
296255570Strasz	;
297255570Strasz
298255570Straszportal_group_listen_iser:	LISTEN_ISER STR
299255570Strasz	{
300255570Strasz		int error;
301255570Strasz
302255570Strasz		error = portal_group_add_listen(portal_group, $2, true);
303255570Strasz		free($2);
304255570Strasz		if (error != 0)
305255570Strasz			return (1);
306255570Strasz	}
307255570Strasz	;
308255570Strasz
309263722Strasztarget:	TARGET target_name
310255570Strasz    OPENING_BRACKET target_entries CLOSING_BRACKET
311255570Strasz	{
312255570Strasz		target = NULL;
313255570Strasz	}
314255570Strasz	;
315255570Strasz
316263722Strasztarget_name:	STR
317255570Strasz	{
318255570Strasz		target = target_new(conf, $1);
319255570Strasz		free($1);
320255570Strasz		if (target == NULL)
321255570Strasz			return (1);
322255570Strasz	}
323255570Strasz	;
324255570Strasz
325255570Strasztarget_entries:
326255570Strasz	|
327255570Strasz	target_entries target_entry
328255570Strasz	;
329255570Strasz
330255570Strasztarget_entry:
331263722Strasz	target_alias
332255570Strasz	|
333263722Strasz	target_auth_group
334255570Strasz	|
335263724Strasz	target_auth_type
336263724Strasz	|
337263722Strasz	target_chap
338255570Strasz	|
339263722Strasz	target_chap_mutual
340255570Strasz	|
341263722Strasz	target_initiator_name
342263720Strasz	|
343263722Strasz	target_initiator_portal
344263720Strasz	|
345263722Strasz	target_portal_group
346255570Strasz	|
347263722Strasz	target_lun
348255570Strasz	;
349255570Strasz
350263722Strasztarget_alias:	ALIAS STR
351255570Strasz	{
352255570Strasz		if (target->t_alias != NULL) {
353255570Strasz			log_warnx("alias for target \"%s\" "
354263723Strasz			    "specified more than once", target->t_name);
355255570Strasz			return (1);
356255570Strasz		}
357255570Strasz		target->t_alias = $2;
358255570Strasz	}
359255570Strasz	;
360255570Strasz
361263722Strasztarget_auth_group:	AUTH_GROUP STR
362255570Strasz	{
363255570Strasz		if (target->t_auth_group != NULL) {
364255570Strasz			if (target->t_auth_group->ag_name != NULL)
365255570Strasz				log_warnx("auth-group for target \"%s\" "
366263723Strasz				    "specified more than once", target->t_name);
367255570Strasz			else
368263724Strasz				log_warnx("cannot use both auth-group and explicit "
369255570Strasz				    "authorisations for target \"%s\"",
370263723Strasz				    target->t_name);
371255570Strasz			return (1);
372255570Strasz		}
373255570Strasz		target->t_auth_group = auth_group_find(conf, $2);
374255570Strasz		if (target->t_auth_group == NULL) {
375255570Strasz			log_warnx("unknown auth-group \"%s\" for target "
376263723Strasz			    "\"%s\"", $2, target->t_name);
377255570Strasz			return (1);
378255570Strasz		}
379255570Strasz		free($2);
380255570Strasz	}
381255570Strasz	;
382255570Strasz
383263724Strasztarget_auth_type:	AUTH_TYPE STR
384263724Strasz	{
385263724Strasz		int error;
386263724Strasz
387263724Strasz		if (target->t_auth_group != NULL) {
388263724Strasz			if (target->t_auth_group->ag_name != NULL) {
389263724Strasz				log_warnx("cannot use both auth-group and "
390263724Strasz				    "auth-type for target \"%s\"",
391263724Strasz				    target->t_name);
392263724Strasz				return (1);
393263724Strasz			}
394263724Strasz		} else {
395263724Strasz			target->t_auth_group = auth_group_new(conf, NULL);
396263724Strasz			if (target->t_auth_group == NULL) {
397263724Strasz				free($2);
398263724Strasz				return (1);
399263724Strasz			}
400263724Strasz			target->t_auth_group->ag_target = target;
401263724Strasz		}
402263724Strasz		error = auth_group_set_type_str(target->t_auth_group, $2);
403263724Strasz		free($2);
404263724Strasz		if (error != 0)
405263724Strasz			return (1);
406263724Strasz	}
407263724Strasz	;
408263724Strasz
409263722Strasztarget_chap:	CHAP STR STR
410255570Strasz	{
411255570Strasz		const struct auth *ca;
412255570Strasz
413255570Strasz		if (target->t_auth_group != NULL) {
414255570Strasz			if (target->t_auth_group->ag_name != NULL) {
415263724Strasz				log_warnx("cannot use both auth-group and "
416263724Strasz				    "chap for target \"%s\"",
417263723Strasz				    target->t_name);
418255570Strasz				free($2);
419255570Strasz				free($3);
420255570Strasz				return (1);
421255570Strasz			}
422255570Strasz		} else {
423255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
424255570Strasz			if (target->t_auth_group == NULL) {
425255570Strasz				free($2);
426255570Strasz				free($3);
427255570Strasz				return (1);
428255570Strasz			}
429255570Strasz			target->t_auth_group->ag_target = target;
430255570Strasz		}
431255570Strasz		ca = auth_new_chap(target->t_auth_group, $2, $3);
432255570Strasz		free($2);
433255570Strasz		free($3);
434255570Strasz		if (ca == NULL)
435255570Strasz			return (1);
436255570Strasz	}
437255570Strasz	;
438255570Strasz
439263722Strasztarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
440255570Strasz	{
441255570Strasz		const struct auth *ca;
442255570Strasz
443255570Strasz		if (target->t_auth_group != NULL) {
444255570Strasz			if (target->t_auth_group->ag_name != NULL) {
445263724Strasz				log_warnx("cannot use both auth-group and "
446263724Strasz				    "chap-mutual for target \"%s\"",
447263723Strasz				    target->t_name);
448255570Strasz				free($2);
449255570Strasz				free($3);
450255570Strasz				free($4);
451255570Strasz				free($5);
452255570Strasz				return (1);
453255570Strasz			}
454255570Strasz		} else {
455255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
456255570Strasz			if (target->t_auth_group == NULL) {
457255570Strasz				free($2);
458255570Strasz				free($3);
459255570Strasz				free($4);
460255570Strasz				free($5);
461255570Strasz				return (1);
462255570Strasz			}
463255570Strasz			target->t_auth_group->ag_target = target;
464255570Strasz		}
465255570Strasz		ca = auth_new_chap_mutual(target->t_auth_group,
466255570Strasz		    $2, $3, $4, $5);
467255570Strasz		free($2);
468255570Strasz		free($3);
469255570Strasz		free($4);
470255570Strasz		free($5);
471255570Strasz		if (ca == NULL)
472255570Strasz			return (1);
473255570Strasz	}
474255570Strasz	;
475255570Strasz
476263722Strasztarget_initiator_name:	INITIATOR_NAME STR
477263720Strasz	{
478263720Strasz		const struct auth_name *an;
479263720Strasz
480263720Strasz		if (target->t_auth_group != NULL) {
481263720Strasz			if (target->t_auth_group->ag_name != NULL) {
482263724Strasz				log_warnx("cannot use both auth-group and "
483263720Strasz				    "initiator-name for target \"%s\"",
484263723Strasz				    target->t_name);
485263720Strasz				free($2);
486263720Strasz				return (1);
487263720Strasz			}
488263720Strasz		} else {
489263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
490263720Strasz			if (target->t_auth_group == NULL) {
491263720Strasz				free($2);
492263720Strasz				return (1);
493263720Strasz			}
494263720Strasz			target->t_auth_group->ag_target = target;
495263720Strasz		}
496263720Strasz		an = auth_name_new(target->t_auth_group, $2);
497263720Strasz		free($2);
498263720Strasz		if (an == NULL)
499263720Strasz			return (1);
500263720Strasz	}
501263720Strasz	;
502263720Strasz
503263722Strasztarget_initiator_portal:	INITIATOR_PORTAL STR
504263720Strasz	{
505263720Strasz		const struct auth_portal *ap;
506263720Strasz
507263720Strasz		if (target->t_auth_group != NULL) {
508263720Strasz			if (target->t_auth_group->ag_name != NULL) {
509263724Strasz				log_warnx("cannot use both auth-group and "
510263720Strasz				    "initiator-portal for target \"%s\"",
511263723Strasz				    target->t_name);
512263720Strasz				free($2);
513263720Strasz				return (1);
514263720Strasz			}
515263720Strasz		} else {
516263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
517263720Strasz			if (target->t_auth_group == NULL) {
518263720Strasz				free($2);
519263720Strasz				return (1);
520263720Strasz			}
521263720Strasz			target->t_auth_group->ag_target = target;
522263720Strasz		}
523263720Strasz		ap = auth_portal_new(target->t_auth_group, $2);
524263720Strasz		free($2);
525263720Strasz		if (ap == NULL)
526263720Strasz			return (1);
527263720Strasz	}
528263720Strasz	;
529263720Strasz
530263722Strasztarget_portal_group:	PORTAL_GROUP STR
531255570Strasz	{
532255570Strasz		if (target->t_portal_group != NULL) {
533255570Strasz			log_warnx("portal-group for target \"%s\" "
534263723Strasz			    "specified more than once", target->t_name);
535255570Strasz			free($2);
536255570Strasz			return (1);
537255570Strasz		}
538255570Strasz		target->t_portal_group = portal_group_find(conf, $2);
539255570Strasz		if (target->t_portal_group == NULL) {
540255570Strasz			log_warnx("unknown portal-group \"%s\" for target "
541263723Strasz			    "\"%s\"", $2, target->t_name);
542255570Strasz			free($2);
543255570Strasz			return (1);
544255570Strasz		}
545255570Strasz		free($2);
546255570Strasz	}
547255570Strasz	;
548255570Strasz
549263722Strasztarget_lun:	LUN lun_number
550263722Strasz    OPENING_BRACKET lun_entries CLOSING_BRACKET
551255570Strasz	{
552255570Strasz		lun = NULL;
553255570Strasz	}
554255570Strasz	;
555255570Strasz
556255570Straszlun_number:	NUM
557255570Strasz	{
558255570Strasz		lun = lun_new(target, $1);
559255570Strasz		if (lun == NULL)
560255570Strasz			return (1);
561255570Strasz	}
562255570Strasz	;
563255570Strasz
564263722Straszlun_entries:
565255570Strasz	|
566263722Strasz	lun_entries lun_entry
567255570Strasz	;
568255570Strasz
569263722Straszlun_entry:
570263722Strasz	lun_backend
571255570Strasz	|
572263722Strasz	lun_blocksize
573255570Strasz	|
574263722Strasz	lun_device_id
575255570Strasz	|
576263722Strasz	lun_option
577255570Strasz	|
578263722Strasz	lun_path
579255570Strasz	|
580263722Strasz	lun_serial
581255570Strasz	|
582263722Strasz	lun_size
583255570Strasz	;
584255570Strasz
585263722Straszlun_backend:	BACKEND STR
586255570Strasz	{
587255570Strasz		if (lun->l_backend != NULL) {
588255570Strasz			log_warnx("backend for lun %d, target \"%s\" "
589255570Strasz			    "specified more than once",
590263723Strasz			    lun->l_lun, target->t_name);
591255570Strasz			free($2);
592255570Strasz			return (1);
593255570Strasz		}
594255570Strasz		lun_set_backend(lun, $2);
595255570Strasz		free($2);
596255570Strasz	}
597255570Strasz	;
598255570Strasz
599263722Straszlun_blocksize:	BLOCKSIZE NUM
600255570Strasz	{
601255570Strasz		if (lun->l_blocksize != 0) {
602255570Strasz			log_warnx("blocksize for lun %d, target \"%s\" "
603255570Strasz			    "specified more than once",
604263723Strasz			    lun->l_lun, target->t_name);
605255570Strasz			return (1);
606255570Strasz		}
607255570Strasz		lun_set_blocksize(lun, $2);
608255570Strasz	}
609255570Strasz	;
610255570Strasz
611263722Straszlun_device_id:	DEVICE_ID STR
612255570Strasz	{
613255570Strasz		if (lun->l_device_id != NULL) {
614255570Strasz			log_warnx("device_id for lun %d, target \"%s\" "
615255570Strasz			    "specified more than once",
616263723Strasz			    lun->l_lun, target->t_name);
617255570Strasz			free($2);
618255570Strasz			return (1);
619255570Strasz		}
620255570Strasz		lun_set_device_id(lun, $2);
621255570Strasz		free($2);
622255570Strasz	}
623255570Strasz	;
624255570Strasz
625263722Straszlun_option:	OPTION STR STR
626255570Strasz	{
627255570Strasz		struct lun_option *clo;
628255570Strasz
629255570Strasz		clo = lun_option_new(lun, $2, $3);
630255570Strasz		free($2);
631255570Strasz		free($3);
632255570Strasz		if (clo == NULL)
633255570Strasz			return (1);
634255570Strasz	}
635255570Strasz	;
636255570Strasz
637263722Straszlun_path:	PATH STR
638255570Strasz	{
639255570Strasz		if (lun->l_path != NULL) {
640255570Strasz			log_warnx("path for lun %d, target \"%s\" "
641255570Strasz			    "specified more than once",
642263723Strasz			    lun->l_lun, target->t_name);
643255570Strasz			free($2);
644255570Strasz			return (1);
645255570Strasz		}
646255570Strasz		lun_set_path(lun, $2);
647255570Strasz		free($2);
648255570Strasz	}
649255570Strasz	;
650255570Strasz
651263722Straszlun_serial:	SERIAL STR
652255570Strasz	{
653255570Strasz		if (lun->l_serial != NULL) {
654255570Strasz			log_warnx("serial for lun %d, target \"%s\" "
655255570Strasz			    "specified more than once",
656263723Strasz			    lun->l_lun, target->t_name);
657255570Strasz			free($2);
658255570Strasz			return (1);
659255570Strasz		}
660255570Strasz		lun_set_serial(lun, $2);
661255570Strasz		free($2);
662267962Sjpaetzel	} |	SERIAL NUM
663267962Sjpaetzel	{
664267962Sjpaetzel		char *str = NULL;
665267962Sjpaetzel
666267962Sjpaetzel		if (lun->l_serial != NULL) {
667267962Sjpaetzel			log_warnx("serial for lun %d, target \"%s\" "
668267962Sjpaetzel			    "specified more than once",
669267962Sjpaetzel			    lun->l_lun, target->t_name);
670267962Sjpaetzel			return (1);
671267962Sjpaetzel		}
672267962Sjpaetzel		asprintf(&str, "%ju", $2);
673267962Sjpaetzel		lun_set_serial(lun, str);
674267962Sjpaetzel		free(str);
675255570Strasz	}
676255570Strasz	;
677255570Strasz
678263722Straszlun_size:	SIZE NUM
679255570Strasz	{
680255570Strasz		if (lun->l_size != 0) {
681255570Strasz			log_warnx("size for lun %d, target \"%s\" "
682255570Strasz			    "specified more than once",
683263723Strasz			    lun->l_lun, target->t_name);
684255570Strasz			return (1);
685255570Strasz		}
686255570Strasz		lun_set_size(lun, $2);
687255570Strasz	}
688255570Strasz	;
689255570Strasz%%
690255570Strasz
691255570Straszvoid
692255570Straszyyerror(const char *str)
693255570Strasz{
694255570Strasz
695255570Strasz	log_warnx("error in configuration file at line %d near '%s': %s",
696255570Strasz	    lineno, yytext, str);
697255570Strasz}
698255570Strasz
699255570Straszstatic void
700255570Straszcheck_perms(const char *path)
701255570Strasz{
702255570Strasz	struct stat sb;
703255570Strasz	int error;
704255570Strasz
705255570Strasz	error = stat(path, &sb);
706255570Strasz	if (error != 0) {
707255570Strasz		log_warn("stat");
708255570Strasz		return;
709255570Strasz	}
710255570Strasz	if (sb.st_mode & S_IWOTH) {
711255570Strasz		log_warnx("%s is world-writable", path);
712255570Strasz	} else if (sb.st_mode & S_IROTH) {
713255570Strasz		log_warnx("%s is world-readable", path);
714255570Strasz	} else if (sb.st_mode & S_IXOTH) {
715255570Strasz		/*
716255570Strasz		 * Ok, this one doesn't matter, but still do it,
717255570Strasz		 * just for consistency.
718255570Strasz		 */
719255570Strasz		log_warnx("%s is world-executable", path);
720255570Strasz	}
721255570Strasz
722255570Strasz	/*
723255570Strasz	 * XXX: Should we also check for owner != 0?
724255570Strasz	 */
725255570Strasz}
726255570Strasz
727255570Straszstruct conf *
728255570Straszconf_new_from_file(const char *path)
729255570Strasz{
730255570Strasz	struct auth_group *ag;
731255570Strasz	struct portal_group *pg;
732255570Strasz	int error;
733255570Strasz
734255570Strasz	log_debugx("obtaining configuration from %s", path);
735255570Strasz
736255570Strasz	conf = conf_new();
737255570Strasz
738263726Strasz	ag = auth_group_new(conf, "default");
739263726Strasz	assert(ag != NULL);
740263726Strasz
741255570Strasz	ag = auth_group_new(conf, "no-authentication");
742263725Strasz	assert(ag != NULL);
743255570Strasz	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
744255570Strasz
745255570Strasz	ag = auth_group_new(conf, "no-access");
746263725Strasz	assert(ag != NULL);
747263729Strasz	ag->ag_type = AG_TYPE_DENY;
748255570Strasz
749255570Strasz	pg = portal_group_new(conf, "default");
750263725Strasz	assert(pg != NULL);
751255570Strasz
752255570Strasz	yyin = fopen(path, "r");
753255570Strasz	if (yyin == NULL) {
754255570Strasz		log_warn("unable to open configuration file %s", path);
755255570Strasz		conf_delete(conf);
756255570Strasz		return (NULL);
757255570Strasz	}
758255570Strasz	check_perms(path);
759263715Strasz	lineno = 1;
760255570Strasz	yyrestart(yyin);
761255570Strasz	error = yyparse();
762255570Strasz	auth_group = NULL;
763255570Strasz	portal_group = NULL;
764255570Strasz	target = NULL;
765255570Strasz	lun = NULL;
766255570Strasz	fclose(yyin);
767255570Strasz	if (error != 0) {
768255570Strasz		conf_delete(conf);
769255570Strasz		return (NULL);
770255570Strasz	}
771255570Strasz
772263726Strasz	if (conf->conf_default_ag_defined == false) {
773263726Strasz		log_debugx("auth-group \"default\" not defined; "
774263726Strasz		    "going with defaults");
775263726Strasz		ag = auth_group_find(conf, "default");
776263726Strasz		assert(ag != NULL);
777263729Strasz		ag->ag_type = AG_TYPE_DENY;
778263726Strasz	}
779263726Strasz
780263725Strasz	if (conf->conf_default_pg_defined == false) {
781263725Strasz		log_debugx("portal-group \"default\" not defined; "
782263725Strasz		    "going with defaults");
783263725Strasz		pg = portal_group_find(conf, "default");
784263725Strasz		assert(pg != NULL);
785263725Strasz		portal_group_add_listen(pg, "0.0.0.0:3260", false);
786263725Strasz		portal_group_add_listen(pg, "[::]:3260", false);
787263725Strasz	}
788263725Strasz
789265511Strasz	conf->conf_kernel_port_on = true;
790265511Strasz
791255570Strasz	error = conf_verify(conf);
792255570Strasz	if (error != 0) {
793255570Strasz		conf_delete(conf);
794255570Strasz		return (NULL);
795255570Strasz	}
796255570Strasz
797255570Strasz	return (conf);
798255570Strasz}
799