parse.y revision 279002
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 279002 2015-02-19 14:31:16Z mav $
31255570Strasz */
32255570Strasz
33255570Strasz#include <sys/queue.h>
34255570Strasz#include <sys/types.h>
35255570Strasz#include <sys/stat.h>
36255570Strasz#include <assert.h>
37255570Strasz#include <stdio.h>
38255570Strasz#include <stdint.h>
39255570Strasz#include <stdlib.h>
40255570Strasz#include <string.h>
41255570Strasz
42255570Strasz#include "ctld.h"
43255570Strasz
44255570Straszextern FILE *yyin;
45255570Straszextern char *yytext;
46255570Straszextern int lineno;
47255570Strasz
48255570Straszstatic struct conf *conf = NULL;
49255570Straszstatic struct auth_group *auth_group = NULL;
50255570Straszstatic struct portal_group *portal_group = NULL;
51255570Straszstatic struct target *target = NULL;
52255570Straszstatic struct lun *lun = NULL;
53255570Strasz
54255570Straszextern void	yyerror(const char *);
55255570Straszextern int	yylex(void);
56255570Straszextern void	yyrestart(FILE *);
57255570Strasz
58255570Strasz%}
59255570Strasz
60263724Strasz%token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
61275244Strasz%token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER
62275247Strasz%token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
63275247Strasz%token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION
64275642Strasz%token PATH PIDFILE PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
65275642Strasz%token TARGET TIMEOUT
66255570Strasz
67255570Strasz%union
68255570Strasz{
69255570Strasz	char *str;
70255570Strasz}
71255570Strasz
72255570Strasz%token <str> STR
73255570Strasz
74255570Strasz%%
75255570Strasz
76255570Straszstatements:
77255570Strasz	|
78255570Strasz	statements statement
79275246Strasz	|
80275246Strasz	statements statement SEMICOLON
81255570Strasz	;
82255570Strasz
83255570Straszstatement:
84263722Strasz	debug
85255570Strasz	|
86263722Strasz	timeout
87255570Strasz	|
88263722Strasz	maxproc
89255570Strasz	|
90263722Strasz	pidfile
91255570Strasz	|
92274939Smav	isns_server
93274939Smav	|
94274939Smav	isns_period
95274939Smav	|
96274939Smav	isns_timeout
97274939Smav	|
98263722Strasz	auth_group
99255570Strasz	|
100263722Strasz	portal_group
101255570Strasz	|
102279002Smav	lun
103279002Smav	|
104263722Strasz	target
105255570Strasz	;
106255570Strasz
107275186Straszdebug:		DEBUG STR
108255570Strasz	{
109275186Strasz		uint64_t tmp;
110275186Strasz
111275186Strasz		if (expand_number($2, &tmp) != 0) {
112275187Strasz			yyerror("invalid numeric value");
113275186Strasz			free($2);
114275186Strasz			return (1);
115275186Strasz		}
116275186Strasz
117275186Strasz		conf->conf_debug = tmp;
118255570Strasz	}
119255570Strasz	;
120255570Strasz
121275186Strasztimeout:	TIMEOUT STR
122255570Strasz	{
123275186Strasz		uint64_t tmp;
124275186Strasz
125275186Strasz		if (expand_number($2, &tmp) != 0) {
126275187Strasz			yyerror("invalid numeric value");
127275186Strasz			free($2);
128275186Strasz			return (1);
129275186Strasz		}
130275186Strasz
131275186Strasz		conf->conf_timeout = tmp;
132255570Strasz	}
133255570Strasz	;
134255570Strasz
135275186Straszmaxproc:	MAXPROC STR
136255570Strasz	{
137275186Strasz		uint64_t tmp;
138275186Strasz
139275186Strasz		if (expand_number($2, &tmp) != 0) {
140275187Strasz			yyerror("invalid numeric value");
141275186Strasz			free($2);
142275186Strasz			return (1);
143275186Strasz		}
144275186Strasz
145275186Strasz		conf->conf_maxproc = tmp;
146255570Strasz	}
147255570Strasz	;
148255570Strasz
149263722Straszpidfile:	PIDFILE STR
150255570Strasz	{
151255570Strasz		if (conf->conf_pidfile_path != NULL) {
152255570Strasz			log_warnx("pidfile specified more than once");
153255570Strasz			free($2);
154255570Strasz			return (1);
155255570Strasz		}
156255570Strasz		conf->conf_pidfile_path = $2;
157255570Strasz	}
158255570Strasz	;
159255570Strasz
160274939Smavisns_server:	ISNS_SERVER STR
161274939Smav	{
162274939Smav		int error;
163274939Smav
164274939Smav		error = isns_new(conf, $2);
165274939Smav		free($2);
166274939Smav		if (error != 0)
167274939Smav			return (1);
168274939Smav	}
169274939Smav	;
170274939Smav
171275187Straszisns_period:	ISNS_PERIOD STR
172274939Smav	{
173275187Strasz		uint64_t tmp;
174275187Strasz
175275187Strasz		if (expand_number($2, &tmp) != 0) {
176275187Strasz			yyerror("invalid numeric value");
177275187Strasz			free($2);
178275187Strasz			return (1);
179275187Strasz		}
180275187Strasz
181275187Strasz		conf->conf_isns_period = tmp;
182274939Smav	}
183274939Smav	;
184274939Smav
185275187Straszisns_timeout:	ISNS_TIMEOUT STR
186274939Smav	{
187275187Strasz		uint64_t tmp;
188275187Strasz
189275187Strasz		if (expand_number($2, &tmp) != 0) {
190275187Strasz			yyerror("invalid numeric value");
191275187Strasz			free($2);
192275187Strasz			return (1);
193275187Strasz		}
194275187Strasz
195275187Strasz		conf->conf_isns_timeout = tmp;
196274939Smav	}
197274939Smav	;
198274939Smav
199263722Straszauth_group:	AUTH_GROUP auth_group_name
200255570Strasz    OPENING_BRACKET auth_group_entries CLOSING_BRACKET
201255570Strasz	{
202255570Strasz		auth_group = NULL;
203255570Strasz	}
204255570Strasz	;
205255570Strasz
206255570Straszauth_group_name:	STR
207255570Strasz	{
208263726Strasz		/*
209263726Strasz		 * Make it possible to redefine default
210263726Strasz		 * auth-group. but only once.
211263726Strasz		 */
212263726Strasz		if (strcmp($1, "default") == 0 &&
213263726Strasz		    conf->conf_default_ag_defined == false) {
214263726Strasz			auth_group = auth_group_find(conf, $1);
215263726Strasz			conf->conf_default_ag_defined = true;
216263726Strasz		} else {
217263726Strasz			auth_group = auth_group_new(conf, $1);
218263726Strasz		}
219255570Strasz		free($1);
220255570Strasz		if (auth_group == NULL)
221255570Strasz			return (1);
222255570Strasz	}
223255570Strasz	;
224255570Strasz
225255570Straszauth_group_entries:
226255570Strasz	|
227255570Strasz	auth_group_entries auth_group_entry
228275246Strasz	|
229275246Strasz	auth_group_entries auth_group_entry SEMICOLON
230255570Strasz	;
231255570Strasz
232255570Straszauth_group_entry:
233263724Strasz	auth_group_auth_type
234263724Strasz	|
235255570Strasz	auth_group_chap
236255570Strasz	|
237255570Strasz	auth_group_chap_mutual
238263720Strasz	|
239263720Strasz	auth_group_initiator_name
240263720Strasz	|
241263720Strasz	auth_group_initiator_portal
242255570Strasz	;
243255570Strasz
244263724Straszauth_group_auth_type:	AUTH_TYPE STR
245263724Strasz	{
246263724Strasz		int error;
247263724Strasz
248275245Strasz		error = auth_group_set_type(auth_group, $2);
249263724Strasz		free($2);
250263724Strasz		if (error != 0)
251263724Strasz			return (1);
252263724Strasz	}
253263724Strasz	;
254263724Strasz
255255570Straszauth_group_chap:	CHAP STR STR
256255570Strasz	{
257255570Strasz		const struct auth *ca;
258255570Strasz
259255570Strasz		ca = auth_new_chap(auth_group, $2, $3);
260255570Strasz		free($2);
261255570Strasz		free($3);
262255570Strasz		if (ca == NULL)
263255570Strasz			return (1);
264255570Strasz	}
265255570Strasz	;
266255570Strasz
267255570Straszauth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
268255570Strasz	{
269255570Strasz		const struct auth *ca;
270255570Strasz
271255570Strasz		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
272255570Strasz		free($2);
273255570Strasz		free($3);
274255570Strasz		free($4);
275255570Strasz		free($5);
276255570Strasz		if (ca == NULL)
277255570Strasz			return (1);
278255570Strasz	}
279255570Strasz	;
280255570Strasz
281263720Straszauth_group_initiator_name:	INITIATOR_NAME STR
282263720Strasz	{
283263720Strasz		const struct auth_name *an;
284263720Strasz
285263720Strasz		an = auth_name_new(auth_group, $2);
286263720Strasz		free($2);
287263720Strasz		if (an == NULL)
288263720Strasz			return (1);
289263720Strasz	}
290263720Strasz	;
291263720Strasz
292263720Straszauth_group_initiator_portal:	INITIATOR_PORTAL STR
293263720Strasz	{
294263720Strasz		const struct auth_portal *ap;
295263720Strasz
296263720Strasz		ap = auth_portal_new(auth_group, $2);
297263720Strasz		free($2);
298263720Strasz		if (ap == NULL)
299263720Strasz			return (1);
300263720Strasz	}
301263720Strasz	;
302263720Strasz
303263722Straszportal_group:	PORTAL_GROUP portal_group_name
304255570Strasz    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
305255570Strasz	{
306255570Strasz		portal_group = NULL;
307255570Strasz	}
308255570Strasz	;
309255570Strasz
310255570Straszportal_group_name:	STR
311255570Strasz	{
312263725Strasz		/*
313263725Strasz		 * Make it possible to redefine default
314263725Strasz		 * portal-group. but only once.
315263725Strasz		 */
316263725Strasz		if (strcmp($1, "default") == 0 &&
317263725Strasz		    conf->conf_default_pg_defined == false) {
318263725Strasz			portal_group = portal_group_find(conf, $1);
319263725Strasz			conf->conf_default_pg_defined = true;
320263725Strasz		} else {
321263725Strasz			portal_group = portal_group_new(conf, $1);
322263725Strasz		}
323255570Strasz		free($1);
324255570Strasz		if (portal_group == NULL)
325255570Strasz			return (1);
326255570Strasz	}
327255570Strasz	;
328255570Strasz
329255570Straszportal_group_entries:
330255570Strasz	|
331255570Strasz	portal_group_entries portal_group_entry
332275246Strasz	|
333275246Strasz	portal_group_entries portal_group_entry SEMICOLON
334255570Strasz	;
335255570Strasz
336255570Straszportal_group_entry:
337255570Strasz	portal_group_discovery_auth_group
338255570Strasz	|
339275244Strasz	portal_group_discovery_filter
340275244Strasz	|
341255570Strasz	portal_group_listen
342255570Strasz	|
343255570Strasz	portal_group_listen_iser
344275642Strasz	|
345275642Strasz	portal_group_redirect
346255570Strasz	;
347255570Strasz
348255570Straszportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
349255570Strasz	{
350255570Strasz		if (portal_group->pg_discovery_auth_group != NULL) {
351255570Strasz			log_warnx("discovery-auth-group for portal-group "
352255570Strasz			    "\"%s\" specified more than once",
353255570Strasz			    portal_group->pg_name);
354255570Strasz			return (1);
355255570Strasz		}
356255570Strasz		portal_group->pg_discovery_auth_group =
357255570Strasz		    auth_group_find(conf, $2);
358255570Strasz		if (portal_group->pg_discovery_auth_group == NULL) {
359255570Strasz			log_warnx("unknown discovery-auth-group \"%s\" "
360255570Strasz			    "for portal-group \"%s\"",
361255570Strasz			    $2, portal_group->pg_name);
362255570Strasz			return (1);
363255570Strasz		}
364255570Strasz		free($2);
365255570Strasz	}
366255570Strasz	;
367255570Strasz
368275244Straszportal_group_discovery_filter:	DISCOVERY_FILTER STR
369275244Strasz	{
370275244Strasz		int error;
371275244Strasz
372275245Strasz		error = portal_group_set_filter(portal_group, $2);
373275244Strasz		free($2);
374275244Strasz		if (error != 0)
375275244Strasz			return (1);
376275244Strasz	}
377275244Strasz	;
378275244Strasz
379255570Straszportal_group_listen:	LISTEN STR
380255570Strasz	{
381255570Strasz		int error;
382255570Strasz
383255570Strasz		error = portal_group_add_listen(portal_group, $2, false);
384255570Strasz		free($2);
385255570Strasz		if (error != 0)
386255570Strasz			return (1);
387255570Strasz	}
388255570Strasz	;
389255570Strasz
390255570Straszportal_group_listen_iser:	LISTEN_ISER STR
391255570Strasz	{
392255570Strasz		int error;
393255570Strasz
394255570Strasz		error = portal_group_add_listen(portal_group, $2, true);
395255570Strasz		free($2);
396255570Strasz		if (error != 0)
397255570Strasz			return (1);
398255570Strasz	}
399255570Strasz	;
400255570Strasz
401275642Straszportal_group_redirect:	REDIRECT STR
402275642Strasz	{
403275642Strasz		int error;
404275642Strasz
405275642Strasz		error = portal_group_set_redirection(portal_group, $2);
406275642Strasz		free($2);
407275642Strasz		if (error != 0)
408275642Strasz			return (1);
409275642Strasz	}
410275642Strasz	;
411275642Strasz
412279002Smavlun:	LUN lun_name
413279002Smav    OPENING_BRACKET lun_entries CLOSING_BRACKET
414279002Smav	{
415279002Smav		lun = NULL;
416279002Smav	}
417279002Smav	;
418279002Smav
419279002Smavlun_name:	STR
420279002Smav	{
421279002Smav		lun = lun_new(conf, $1);
422279002Smav		free($1);
423279002Smav		if (lun == NULL)
424279002Smav			return (1);
425279002Smav	}
426279002Smav	;
427279002Smav
428263722Strasztarget:	TARGET target_name
429255570Strasz    OPENING_BRACKET target_entries CLOSING_BRACKET
430255570Strasz	{
431255570Strasz		target = NULL;
432255570Strasz	}
433255570Strasz	;
434255570Strasz
435263722Strasztarget_name:	STR
436255570Strasz	{
437255570Strasz		target = target_new(conf, $1);
438255570Strasz		free($1);
439255570Strasz		if (target == NULL)
440255570Strasz			return (1);
441255570Strasz	}
442255570Strasz	;
443255570Strasz
444255570Strasztarget_entries:
445255570Strasz	|
446255570Strasz	target_entries target_entry
447275246Strasz	|
448275246Strasz	target_entries target_entry SEMICOLON
449255570Strasz	;
450255570Strasz
451255570Strasztarget_entry:
452263722Strasz	target_alias
453255570Strasz	|
454263722Strasz	target_auth_group
455255570Strasz	|
456263724Strasz	target_auth_type
457263724Strasz	|
458263722Strasz	target_chap
459255570Strasz	|
460263722Strasz	target_chap_mutual
461255570Strasz	|
462263722Strasz	target_initiator_name
463263720Strasz	|
464263722Strasz	target_initiator_portal
465263720Strasz	|
466263722Strasz	target_portal_group
467255570Strasz	|
468275642Strasz	target_redirect
469275642Strasz	|
470263722Strasz	target_lun
471279002Smav	|
472279002Smav	target_lun_ref
473255570Strasz	;
474255570Strasz
475263722Strasztarget_alias:	ALIAS STR
476255570Strasz	{
477255570Strasz		if (target->t_alias != NULL) {
478255570Strasz			log_warnx("alias for target \"%s\" "
479263723Strasz			    "specified more than once", target->t_name);
480255570Strasz			return (1);
481255570Strasz		}
482255570Strasz		target->t_alias = $2;
483255570Strasz	}
484255570Strasz	;
485255570Strasz
486263722Strasztarget_auth_group:	AUTH_GROUP STR
487255570Strasz	{
488255570Strasz		if (target->t_auth_group != NULL) {
489255570Strasz			if (target->t_auth_group->ag_name != NULL)
490255570Strasz				log_warnx("auth-group for target \"%s\" "
491263723Strasz				    "specified more than once", target->t_name);
492255570Strasz			else
493263724Strasz				log_warnx("cannot use both auth-group and explicit "
494255570Strasz				    "authorisations for target \"%s\"",
495263723Strasz				    target->t_name);
496255570Strasz			return (1);
497255570Strasz		}
498255570Strasz		target->t_auth_group = auth_group_find(conf, $2);
499255570Strasz		if (target->t_auth_group == NULL) {
500255570Strasz			log_warnx("unknown auth-group \"%s\" for target "
501263723Strasz			    "\"%s\"", $2, target->t_name);
502255570Strasz			return (1);
503255570Strasz		}
504255570Strasz		free($2);
505255570Strasz	}
506255570Strasz	;
507255570Strasz
508263724Strasztarget_auth_type:	AUTH_TYPE STR
509263724Strasz	{
510263724Strasz		int error;
511263724Strasz
512263724Strasz		if (target->t_auth_group != NULL) {
513263724Strasz			if (target->t_auth_group->ag_name != NULL) {
514263724Strasz				log_warnx("cannot use both auth-group and "
515263724Strasz				    "auth-type for target \"%s\"",
516263724Strasz				    target->t_name);
517263724Strasz				return (1);
518263724Strasz			}
519263724Strasz		} else {
520263724Strasz			target->t_auth_group = auth_group_new(conf, NULL);
521263724Strasz			if (target->t_auth_group == NULL) {
522263724Strasz				free($2);
523263724Strasz				return (1);
524263724Strasz			}
525263724Strasz			target->t_auth_group->ag_target = target;
526263724Strasz		}
527275245Strasz		error = auth_group_set_type(target->t_auth_group, $2);
528263724Strasz		free($2);
529263724Strasz		if (error != 0)
530263724Strasz			return (1);
531263724Strasz	}
532263724Strasz	;
533263724Strasz
534263722Strasztarget_chap:	CHAP STR STR
535255570Strasz	{
536255570Strasz		const struct auth *ca;
537255570Strasz
538255570Strasz		if (target->t_auth_group != NULL) {
539255570Strasz			if (target->t_auth_group->ag_name != NULL) {
540263724Strasz				log_warnx("cannot use both auth-group and "
541263724Strasz				    "chap for target \"%s\"",
542263723Strasz				    target->t_name);
543255570Strasz				free($2);
544255570Strasz				free($3);
545255570Strasz				return (1);
546255570Strasz			}
547255570Strasz		} else {
548255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
549255570Strasz			if (target->t_auth_group == NULL) {
550255570Strasz				free($2);
551255570Strasz				free($3);
552255570Strasz				return (1);
553255570Strasz			}
554255570Strasz			target->t_auth_group->ag_target = target;
555255570Strasz		}
556255570Strasz		ca = auth_new_chap(target->t_auth_group, $2, $3);
557255570Strasz		free($2);
558255570Strasz		free($3);
559255570Strasz		if (ca == NULL)
560255570Strasz			return (1);
561255570Strasz	}
562255570Strasz	;
563255570Strasz
564263722Strasztarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
565255570Strasz	{
566255570Strasz		const struct auth *ca;
567255570Strasz
568255570Strasz		if (target->t_auth_group != NULL) {
569255570Strasz			if (target->t_auth_group->ag_name != NULL) {
570263724Strasz				log_warnx("cannot use both auth-group and "
571263724Strasz				    "chap-mutual for target \"%s\"",
572263723Strasz				    target->t_name);
573255570Strasz				free($2);
574255570Strasz				free($3);
575255570Strasz				free($4);
576255570Strasz				free($5);
577255570Strasz				return (1);
578255570Strasz			}
579255570Strasz		} else {
580255570Strasz			target->t_auth_group = auth_group_new(conf, NULL);
581255570Strasz			if (target->t_auth_group == NULL) {
582255570Strasz				free($2);
583255570Strasz				free($3);
584255570Strasz				free($4);
585255570Strasz				free($5);
586255570Strasz				return (1);
587255570Strasz			}
588255570Strasz			target->t_auth_group->ag_target = target;
589255570Strasz		}
590255570Strasz		ca = auth_new_chap_mutual(target->t_auth_group,
591255570Strasz		    $2, $3, $4, $5);
592255570Strasz		free($2);
593255570Strasz		free($3);
594255570Strasz		free($4);
595255570Strasz		free($5);
596255570Strasz		if (ca == NULL)
597255570Strasz			return (1);
598255570Strasz	}
599255570Strasz	;
600255570Strasz
601263722Strasztarget_initiator_name:	INITIATOR_NAME STR
602263720Strasz	{
603263720Strasz		const struct auth_name *an;
604263720Strasz
605263720Strasz		if (target->t_auth_group != NULL) {
606263720Strasz			if (target->t_auth_group->ag_name != NULL) {
607263724Strasz				log_warnx("cannot use both auth-group and "
608263720Strasz				    "initiator-name for target \"%s\"",
609263723Strasz				    target->t_name);
610263720Strasz				free($2);
611263720Strasz				return (1);
612263720Strasz			}
613263720Strasz		} else {
614263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
615263720Strasz			if (target->t_auth_group == NULL) {
616263720Strasz				free($2);
617263720Strasz				return (1);
618263720Strasz			}
619263720Strasz			target->t_auth_group->ag_target = target;
620263720Strasz		}
621263720Strasz		an = auth_name_new(target->t_auth_group, $2);
622263720Strasz		free($2);
623263720Strasz		if (an == NULL)
624263720Strasz			return (1);
625263720Strasz	}
626263720Strasz	;
627263720Strasz
628263722Strasztarget_initiator_portal:	INITIATOR_PORTAL STR
629263720Strasz	{
630263720Strasz		const struct auth_portal *ap;
631263720Strasz
632263720Strasz		if (target->t_auth_group != NULL) {
633263720Strasz			if (target->t_auth_group->ag_name != NULL) {
634263724Strasz				log_warnx("cannot use both auth-group and "
635263720Strasz				    "initiator-portal for target \"%s\"",
636263723Strasz				    target->t_name);
637263720Strasz				free($2);
638263720Strasz				return (1);
639263720Strasz			}
640263720Strasz		} else {
641263720Strasz			target->t_auth_group = auth_group_new(conf, NULL);
642263720Strasz			if (target->t_auth_group == NULL) {
643263720Strasz				free($2);
644263720Strasz				return (1);
645263720Strasz			}
646263720Strasz			target->t_auth_group->ag_target = target;
647263720Strasz		}
648263720Strasz		ap = auth_portal_new(target->t_auth_group, $2);
649263720Strasz		free($2);
650263720Strasz		if (ap == NULL)
651263720Strasz			return (1);
652263720Strasz	}
653263720Strasz	;
654263720Strasz
655263722Strasztarget_portal_group:	PORTAL_GROUP STR
656255570Strasz	{
657255570Strasz		if (target->t_portal_group != NULL) {
658255570Strasz			log_warnx("portal-group for target \"%s\" "
659263723Strasz			    "specified more than once", target->t_name);
660255570Strasz			free($2);
661255570Strasz			return (1);
662255570Strasz		}
663255570Strasz		target->t_portal_group = portal_group_find(conf, $2);
664255570Strasz		if (target->t_portal_group == NULL) {
665255570Strasz			log_warnx("unknown portal-group \"%s\" for target "
666263723Strasz			    "\"%s\"", $2, target->t_name);
667255570Strasz			free($2);
668255570Strasz			return (1);
669255570Strasz		}
670255570Strasz		free($2);
671255570Strasz	}
672255570Strasz	;
673255570Strasz
674275642Strasztarget_redirect:	REDIRECT STR
675275642Strasz	{
676275642Strasz		int error;
677275642Strasz
678275642Strasz		error = target_set_redirection(target, $2);
679275642Strasz		free($2);
680275642Strasz		if (error != 0)
681275642Strasz			return (1);
682275642Strasz	}
683275642Strasz	;
684275642Strasz
685263722Strasztarget_lun:	LUN lun_number
686263722Strasz    OPENING_BRACKET lun_entries CLOSING_BRACKET
687255570Strasz	{
688255570Strasz		lun = NULL;
689255570Strasz	}
690255570Strasz	;
691255570Strasz
692275186Straszlun_number:	STR
693255570Strasz	{
694275186Strasz		uint64_t tmp;
695279002Smav		char *name;
696275186Strasz
697275186Strasz		if (expand_number($1, &tmp) != 0) {
698275187Strasz			yyerror("invalid numeric value");
699275186Strasz			free($1);
700275186Strasz			return (1);
701275186Strasz		}
702275186Strasz
703279002Smav		asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
704279002Smav		lun = lun_new(conf, name);
705255570Strasz		if (lun == NULL)
706255570Strasz			return (1);
707279002Smav
708279002Smav		lun_set_scsiname(lun, name);
709279002Smav		target->t_luns[tmp] = lun;
710255570Strasz	}
711255570Strasz	;
712255570Strasz
713279002Smavtarget_lun_ref:	LUN STR STR
714279002Smav	{
715279002Smav		uint64_t tmp;
716279002Smav
717279002Smav		if (expand_number($2, &tmp) != 0) {
718279002Smav			yyerror("invalid numeric value");
719279002Smav			free($2);
720279002Smav			free($3);
721279002Smav			return (1);
722279002Smav		}
723279002Smav		free($2);
724279002Smav
725279002Smav		lun = lun_find(conf, $3);
726279002Smav		free($3);
727279002Smav		if (lun == NULL)
728279002Smav			return (1);
729279002Smav
730279002Smav		target->t_luns[tmp] = lun;
731279002Smav	}
732279002Smav	;
733279002Smav
734263722Straszlun_entries:
735255570Strasz	|
736263722Strasz	lun_entries lun_entry
737275246Strasz	|
738275246Strasz	lun_entries lun_entry SEMICOLON
739255570Strasz	;
740255570Strasz
741263722Straszlun_entry:
742263722Strasz	lun_backend
743255570Strasz	|
744263722Strasz	lun_blocksize
745255570Strasz	|
746263722Strasz	lun_device_id
747255570Strasz	|
748263722Strasz	lun_option
749255570Strasz	|
750263722Strasz	lun_path
751255570Strasz	|
752263722Strasz	lun_serial
753255570Strasz	|
754263722Strasz	lun_size
755255570Strasz	;
756255570Strasz
757263722Straszlun_backend:	BACKEND STR
758255570Strasz	{
759255570Strasz		if (lun->l_backend != NULL) {
760279002Smav			log_warnx("backend for lun \"%s\" "
761255570Strasz			    "specified more than once",
762279002Smav			    lun->l_name);
763255570Strasz			free($2);
764255570Strasz			return (1);
765255570Strasz		}
766255570Strasz		lun_set_backend(lun, $2);
767255570Strasz		free($2);
768255570Strasz	}
769255570Strasz	;
770255570Strasz
771275186Straszlun_blocksize:	BLOCKSIZE STR
772255570Strasz	{
773275186Strasz		uint64_t tmp;
774275186Strasz
775275186Strasz		if (expand_number($2, &tmp) != 0) {
776275187Strasz			yyerror("invalid numeric value");
777275186Strasz			free($2);
778275186Strasz			return (1);
779275186Strasz		}
780275186Strasz
781255570Strasz		if (lun->l_blocksize != 0) {
782279002Smav			log_warnx("blocksize for lun \"%s\" "
783255570Strasz			    "specified more than once",
784279002Smav			    lun->l_name);
785255570Strasz			return (1);
786255570Strasz		}
787275186Strasz		lun_set_blocksize(lun, tmp);
788255570Strasz	}
789255570Strasz	;
790255570Strasz
791263722Straszlun_device_id:	DEVICE_ID STR
792255570Strasz	{
793255570Strasz		if (lun->l_device_id != NULL) {
794279002Smav			log_warnx("device_id for lun \"%s\" "
795255570Strasz			    "specified more than once",
796279002Smav			    lun->l_name);
797255570Strasz			free($2);
798255570Strasz			return (1);
799255570Strasz		}
800255570Strasz		lun_set_device_id(lun, $2);
801255570Strasz		free($2);
802255570Strasz	}
803255570Strasz	;
804255570Strasz
805263722Straszlun_option:	OPTION STR STR
806255570Strasz	{
807255570Strasz		struct lun_option *clo;
808274870Strasz
809255570Strasz		clo = lun_option_new(lun, $2, $3);
810255570Strasz		free($2);
811255570Strasz		free($3);
812255570Strasz		if (clo == NULL)
813255570Strasz			return (1);
814255570Strasz	}
815255570Strasz	;
816255570Strasz
817263722Straszlun_path:	PATH STR
818255570Strasz	{
819255570Strasz		if (lun->l_path != NULL) {
820279002Smav			log_warnx("path for lun \"%s\" "
821255570Strasz			    "specified more than once",
822279002Smav			    lun->l_name);
823255570Strasz			free($2);
824255570Strasz			return (1);
825255570Strasz		}
826255570Strasz		lun_set_path(lun, $2);
827255570Strasz		free($2);
828255570Strasz	}
829255570Strasz	;
830255570Strasz
831263722Straszlun_serial:	SERIAL STR
832255570Strasz	{
833255570Strasz		if (lun->l_serial != NULL) {
834279002Smav			log_warnx("serial for lun \"%s\" "
835255570Strasz			    "specified more than once",
836279002Smav			    lun->l_name);
837255570Strasz			free($2);
838255570Strasz			return (1);
839255570Strasz		}
840255570Strasz		lun_set_serial(lun, $2);
841255570Strasz		free($2);
842275186Strasz	}
843275186Strasz	;
844275186Strasz
845275186Straszlun_size:	SIZE STR
846267962Sjpaetzel	{
847275186Strasz		uint64_t tmp;
848267962Sjpaetzel
849275186Strasz		if (expand_number($2, &tmp) != 0) {
850275187Strasz			yyerror("invalid numeric value");
851275186Strasz			free($2);
852267962Sjpaetzel			return (1);
853267962Sjpaetzel		}
854255570Strasz
855255570Strasz		if (lun->l_size != 0) {
856279002Smav			log_warnx("size for lun \"%s\" "
857255570Strasz			    "specified more than once",
858279002Smav			    lun->l_name);
859255570Strasz			return (1);
860255570Strasz		}
861275186Strasz		lun_set_size(lun, tmp);
862255570Strasz	}
863255570Strasz	;
864255570Strasz%%
865255570Strasz
866255570Straszvoid
867255570Straszyyerror(const char *str)
868255570Strasz{
869255570Strasz
870255570Strasz	log_warnx("error in configuration file at line %d near '%s': %s",
871255570Strasz	    lineno, yytext, str);
872255570Strasz}
873255570Strasz
874255570Straszstatic void
875255570Straszcheck_perms(const char *path)
876255570Strasz{
877255570Strasz	struct stat sb;
878255570Strasz	int error;
879255570Strasz
880255570Strasz	error = stat(path, &sb);
881255570Strasz	if (error != 0) {
882255570Strasz		log_warn("stat");
883255570Strasz		return;
884255570Strasz	}
885255570Strasz	if (sb.st_mode & S_IWOTH) {
886255570Strasz		log_warnx("%s is world-writable", path);
887255570Strasz	} else if (sb.st_mode & S_IROTH) {
888255570Strasz		log_warnx("%s is world-readable", path);
889255570Strasz	} else if (sb.st_mode & S_IXOTH) {
890255570Strasz		/*
891255570Strasz		 * Ok, this one doesn't matter, but still do it,
892255570Strasz		 * just for consistency.
893255570Strasz		 */
894255570Strasz		log_warnx("%s is world-executable", path);
895255570Strasz	}
896255570Strasz
897255570Strasz	/*
898255570Strasz	 * XXX: Should we also check for owner != 0?
899255570Strasz	 */
900255570Strasz}
901255570Strasz
902255570Straszstruct conf *
903255570Straszconf_new_from_file(const char *path)
904255570Strasz{
905255570Strasz	struct auth_group *ag;
906255570Strasz	struct portal_group *pg;
907255570Strasz	int error;
908255570Strasz
909255570Strasz	log_debugx("obtaining configuration from %s", path);
910255570Strasz
911255570Strasz	conf = conf_new();
912255570Strasz
913263726Strasz	ag = auth_group_new(conf, "default");
914263726Strasz	assert(ag != NULL);
915263726Strasz
916255570Strasz	ag = auth_group_new(conf, "no-authentication");
917263725Strasz	assert(ag != NULL);
918255570Strasz	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
919255570Strasz
920255570Strasz	ag = auth_group_new(conf, "no-access");
921263725Strasz	assert(ag != NULL);
922263729Strasz	ag->ag_type = AG_TYPE_DENY;
923255570Strasz
924255570Strasz	pg = portal_group_new(conf, "default");
925263725Strasz	assert(pg != NULL);
926255570Strasz
927255570Strasz	yyin = fopen(path, "r");
928255570Strasz	if (yyin == NULL) {
929255570Strasz		log_warn("unable to open configuration file %s", path);
930255570Strasz		conf_delete(conf);
931255570Strasz		return (NULL);
932255570Strasz	}
933255570Strasz	check_perms(path);
934263715Strasz	lineno = 1;
935255570Strasz	yyrestart(yyin);
936255570Strasz	error = yyparse();
937255570Strasz	auth_group = NULL;
938255570Strasz	portal_group = NULL;
939255570Strasz	target = NULL;
940255570Strasz	lun = NULL;
941255570Strasz	fclose(yyin);
942255570Strasz	if (error != 0) {
943255570Strasz		conf_delete(conf);
944255570Strasz		return (NULL);
945255570Strasz	}
946255570Strasz
947263726Strasz	if (conf->conf_default_ag_defined == false) {
948263726Strasz		log_debugx("auth-group \"default\" not defined; "
949263726Strasz		    "going with defaults");
950263726Strasz		ag = auth_group_find(conf, "default");
951263726Strasz		assert(ag != NULL);
952263729Strasz		ag->ag_type = AG_TYPE_DENY;
953263726Strasz	}
954263726Strasz
955263725Strasz	if (conf->conf_default_pg_defined == false) {
956263725Strasz		log_debugx("portal-group \"default\" not defined; "
957263725Strasz		    "going with defaults");
958263725Strasz		pg = portal_group_find(conf, "default");
959263725Strasz		assert(pg != NULL);
960263725Strasz		portal_group_add_listen(pg, "0.0.0.0:3260", false);
961263725Strasz		portal_group_add_listen(pg, "[::]:3260", false);
962263725Strasz	}
963263725Strasz
964265511Strasz	conf->conf_kernel_port_on = true;
965265511Strasz
966255570Strasz	error = conf_verify(conf);
967255570Strasz	if (error != 0) {
968255570Strasz		conf_delete(conf);
969255570Strasz		return (NULL);
970255570Strasz	}
971255570Strasz
972255570Strasz	return (conf);
973255570Strasz}
974