1216295Ssyrinx%{
2216295Ssyrinx/*-
3216295Ssyrinx * SPDX-License-Identifier: BSD-2-Clause
4216295Ssyrinx *
5216295Ssyrinx * Copyright (c) 2012 The FreeBSD Foundation
6216295Ssyrinx *
7216295Ssyrinx * This software was developed by Edward Tomasz Napierala under sponsorship
8216295Ssyrinx * from the FreeBSD Foundation.
9216295Ssyrinx *
10216295Ssyrinx * Redistribution and use in source and binary forms, with or without
11216295Ssyrinx * modification, are permitted provided that the following conditions
12216295Ssyrinx * are met:
13216295Ssyrinx * 1. Redistributions of source code must retain the above copyright
14216295Ssyrinx *    notice, this list of conditions and the following disclaimer.
15216295Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright
16216295Ssyrinx *    notice, this list of conditions and the following disclaimer in the
17216295Ssyrinx *    documentation and/or other materials provided with the distribution.
18216295Ssyrinx *
19216295Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20216295Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21216295Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22216295Ssyrinx * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23216295Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24216295Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25216295Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26216295Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27216295Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28216295Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29216295Ssyrinx * SUCH DAMAGE.
30216295Ssyrinx */
31216295Ssyrinx
32216295Ssyrinx#include <sys/queue.h>
33216295Ssyrinx#include <sys/types.h>
34216295Ssyrinx#include <sys/stat.h>
35216295Ssyrinx#include <assert.h>
36216295Ssyrinx#include <stdio.h>
37216295Ssyrinx#include <stdlib.h>
38216295Ssyrinx#include <string.h>
39216295Ssyrinx
40216295Ssyrinx#include "ctld.h"
41216295Ssyrinx#include <netinet/in.h>
42216295Ssyrinx#include <netinet/ip.h>
43216295Ssyrinx
44216295Ssyrinxextern FILE *yyin;
45216295Ssyrinxextern char *yytext;
46216295Ssyrinxextern int lineno;
47216295Ssyrinx
48216295Ssyrinxstatic struct conf *conf = NULL;
49216295Ssyrinxstatic struct auth_group *auth_group = NULL;
50216295Ssyrinxstatic struct portal_group *portal_group = NULL;
51216295Ssyrinxstatic struct target *target = NULL;
52216295Ssyrinxstatic struct lun *lun = NULL;
53216295Ssyrinx
54216295Ssyrinxextern void	yyerror(const char *);
55216295Ssyrinxextern void	yyrestart(FILE *);
56310903Sngie
57216295Ssyrinx%}
58216295Ssyrinx
59216295Ssyrinx%token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
60216295Ssyrinx%token CLOSING_BRACKET CTL_LUN DEBUG DEVICE_ID DEVICE_TYPE
61216295Ssyrinx%token DISCOVERY_AUTH_GROUP DISCOVERY_FILTER DSCP FOREIGN
62216295Ssyrinx%token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
63216295Ssyrinx%token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
64216295Ssyrinx%token PATH PCP PIDFILE PORT PORTAL_GROUP REDIRECT SEMICOLON SERIAL
65216295Ssyrinx%token SIZE STR TAG TARGET TIMEOUT
66216295Ssyrinx%token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
67216295Ssyrinx%token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7
68216295Ssyrinx
69216295Ssyrinx%union
70216295Ssyrinx{
71216295Ssyrinx	char *str;
72216295Ssyrinx}
73216295Ssyrinx
74216295Ssyrinx%token <str> STR
75216295Ssyrinx
76216295Ssyrinx%%
77216295Ssyrinx
78216295Ssyrinxstatements:
79216295Ssyrinx	|
80216295Ssyrinx	statements statement
81216295Ssyrinx	|
82216295Ssyrinx	statements statement SEMICOLON
83216295Ssyrinx	;
84216295Ssyrinx
85216295Ssyrinxstatement:
86216295Ssyrinx	debug
87216295Ssyrinx	|
88216295Ssyrinx	timeout
89216295Ssyrinx	|
90216295Ssyrinx	maxproc
91216295Ssyrinx	|
92216295Ssyrinx	pidfile
93216295Ssyrinx	|
94216295Ssyrinx	isns_server
95216295Ssyrinx	|
96216295Ssyrinx	isns_period
97216295Ssyrinx	|
98216295Ssyrinx	isns_timeout
99216295Ssyrinx	|
100216295Ssyrinx	auth_group
101216295Ssyrinx	|
102216295Ssyrinx	portal_group
103216295Ssyrinx	|
104216295Ssyrinx	lun
105216295Ssyrinx	|
106216295Ssyrinx	target
107216295Ssyrinx	;
108216295Ssyrinx
109216295Ssyrinxdebug:		DEBUG STR
110216295Ssyrinx	{
111216295Ssyrinx		uint64_t tmp;
112216295Ssyrinx
113216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
114216295Ssyrinx			yyerror("invalid numeric value");
115216295Ssyrinx			free($2);
116216295Ssyrinx			return (1);
117216295Ssyrinx		}
118216295Ssyrinx
119216295Ssyrinx		conf->conf_debug = tmp;
120216295Ssyrinx	}
121216295Ssyrinx	;
122216295Ssyrinx
123216295Ssyrinxtimeout:	TIMEOUT STR
124216295Ssyrinx	{
125216295Ssyrinx		uint64_t tmp;
126216295Ssyrinx
127216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
128216295Ssyrinx			yyerror("invalid numeric value");
129216295Ssyrinx			free($2);
130216295Ssyrinx			return (1);
131216295Ssyrinx		}
132216295Ssyrinx
133216295Ssyrinx		conf->conf_timeout = tmp;
134216295Ssyrinx	}
135216295Ssyrinx	;
136216295Ssyrinx
137216295Ssyrinxmaxproc:	MAXPROC STR
138216295Ssyrinx	{
139216295Ssyrinx		uint64_t tmp;
140216295Ssyrinx
141216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
142216295Ssyrinx			yyerror("invalid numeric value");
143300475Sngie			free($2);
144300475Sngie			return (1);
145300475Sngie		}
146216295Ssyrinx
147216295Ssyrinx		conf->conf_maxproc = tmp;
148216295Ssyrinx	}
149216295Ssyrinx	;
150216295Ssyrinx
151216295Ssyrinxpidfile:	PIDFILE STR
152216295Ssyrinx	{
153216295Ssyrinx		if (conf->conf_pidfile_path != NULL) {
154216295Ssyrinx			log_warnx("pidfile specified more than once");
155216295Ssyrinx			free($2);
156216295Ssyrinx			return (1);
157216295Ssyrinx		}
158216295Ssyrinx		conf->conf_pidfile_path = $2;
159216295Ssyrinx	}
160216295Ssyrinx	;
161216295Ssyrinx
162216295Ssyrinxisns_server:	ISNS_SERVER STR
163216295Ssyrinx	{
164216295Ssyrinx		int error;
165216295Ssyrinx
166216295Ssyrinx		error = isns_new(conf, $2);
167216295Ssyrinx		free($2);
168216295Ssyrinx		if (error != 0)
169216295Ssyrinx			return (1);
170216295Ssyrinx	}
171216295Ssyrinx	;
172216295Ssyrinx
173216295Ssyrinxisns_period:	ISNS_PERIOD STR
174216295Ssyrinx	{
175216295Ssyrinx		uint64_t tmp;
176216295Ssyrinx
177216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
178216295Ssyrinx			yyerror("invalid numeric value");
179216295Ssyrinx			free($2);
180216295Ssyrinx			return (1);
181216295Ssyrinx		}
182216295Ssyrinx
183216295Ssyrinx		conf->conf_isns_period = tmp;
184216295Ssyrinx	}
185216295Ssyrinx	;
186216295Ssyrinx
187216295Ssyrinxisns_timeout:	ISNS_TIMEOUT STR
188216295Ssyrinx	{
189216295Ssyrinx		uint64_t tmp;
190216295Ssyrinx
191216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
192216295Ssyrinx			yyerror("invalid numeric value");
193216295Ssyrinx			free($2);
194216295Ssyrinx			return (1);
195216295Ssyrinx		}
196216295Ssyrinx
197216295Ssyrinx		conf->conf_isns_timeout = tmp;
198216295Ssyrinx	}
199216295Ssyrinx	;
200216295Ssyrinx
201216295Ssyrinxauth_group:	AUTH_GROUP auth_group_name
202216295Ssyrinx    OPENING_BRACKET auth_group_entries CLOSING_BRACKET
203216295Ssyrinx	{
204216295Ssyrinx		auth_group = NULL;
205216295Ssyrinx	}
206216295Ssyrinx	;
207216295Ssyrinx
208216295Ssyrinxauth_group_name:	STR
209216295Ssyrinx	{
210216295Ssyrinx		/*
211216295Ssyrinx		 * Make it possible to redefine default
212216295Ssyrinx		 * auth-group. but only once.
213216295Ssyrinx		 */
214216295Ssyrinx		if (strcmp($1, "default") == 0 &&
215216295Ssyrinx		    conf->conf_default_ag_defined == false) {
216216295Ssyrinx			auth_group = auth_group_find(conf, $1);
217216295Ssyrinx			conf->conf_default_ag_defined = true;
218216295Ssyrinx		} else {
219216295Ssyrinx			auth_group = auth_group_new(conf, $1);
220216295Ssyrinx		}
221216295Ssyrinx		free($1);
222216295Ssyrinx		if (auth_group == NULL)
223216295Ssyrinx			return (1);
224216295Ssyrinx	}
225216295Ssyrinx	;
226216295Ssyrinx
227216295Ssyrinxauth_group_entries:
228216295Ssyrinx	|
229216295Ssyrinx	auth_group_entries auth_group_entry
230216295Ssyrinx	|
231216295Ssyrinx	auth_group_entries auth_group_entry SEMICOLON
232216295Ssyrinx	;
233216295Ssyrinx
234216295Ssyrinxauth_group_entry:
235216295Ssyrinx	auth_group_auth_type
236216295Ssyrinx	|
237216295Ssyrinx	auth_group_chap
238216295Ssyrinx	|
239216295Ssyrinx	auth_group_chap_mutual
240216295Ssyrinx	|
241216295Ssyrinx	auth_group_initiator_name
242216295Ssyrinx	|
243216295Ssyrinx	auth_group_initiator_portal
244216295Ssyrinx	;
245216295Ssyrinx
246216295Ssyrinxauth_group_auth_type:	AUTH_TYPE STR
247216295Ssyrinx	{
248216295Ssyrinx		int error;
249216295Ssyrinx
250216295Ssyrinx		error = auth_group_set_type(auth_group, $2);
251216295Ssyrinx		free($2);
252216295Ssyrinx		if (error != 0)
253216295Ssyrinx			return (1);
254216295Ssyrinx	}
255216295Ssyrinx	;
256216295Ssyrinx
257216295Ssyrinxauth_group_chap:	CHAP STR STR
258216295Ssyrinx	{
259216295Ssyrinx		const struct auth *ca;
260216295Ssyrinx
261216295Ssyrinx		ca = auth_new_chap(auth_group, $2, $3);
262216295Ssyrinx		free($2);
263216295Ssyrinx		free($3);
264216295Ssyrinx		if (ca == NULL)
265216295Ssyrinx			return (1);
266216295Ssyrinx	}
267216295Ssyrinx	;
268216295Ssyrinx
269216295Ssyrinxauth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
270216295Ssyrinx	{
271216295Ssyrinx		const struct auth *ca;
272216295Ssyrinx
273216295Ssyrinx		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
274216295Ssyrinx		free($2);
275216295Ssyrinx		free($3);
276216295Ssyrinx		free($4);
277216295Ssyrinx		free($5);
278216295Ssyrinx		if (ca == NULL)
279216295Ssyrinx			return (1);
280216295Ssyrinx	}
281216295Ssyrinx	;
282216295Ssyrinx
283216295Ssyrinxauth_group_initiator_name:	INITIATOR_NAME STR
284216295Ssyrinx	{
285216295Ssyrinx		const struct auth_name *an;
286216295Ssyrinx
287216295Ssyrinx		an = auth_name_new(auth_group, $2);
288216295Ssyrinx		free($2);
289216295Ssyrinx		if (an == NULL)
290216295Ssyrinx			return (1);
291216295Ssyrinx	}
292216295Ssyrinx	;
293216295Ssyrinx
294216295Ssyrinxauth_group_initiator_portal:	INITIATOR_PORTAL STR
295216295Ssyrinx	{
296216295Ssyrinx		const struct auth_portal *ap;
297216295Ssyrinx
298216295Ssyrinx		ap = auth_portal_new(auth_group, $2);
299216295Ssyrinx		free($2);
300216295Ssyrinx		if (ap == NULL)
301216295Ssyrinx			return (1);
302216295Ssyrinx	}
303216295Ssyrinx	;
304300475Sngie
305216295Ssyrinxportal_group:	PORTAL_GROUP portal_group_name
306216295Ssyrinx    OPENING_BRACKET portal_group_entries CLOSING_BRACKET
307216295Ssyrinx	{
308216295Ssyrinx		portal_group = NULL;
309216295Ssyrinx	}
310216295Ssyrinx	;
311300475Sngie
312300475Sngieportal_group_name:	STR
313300475Sngie	{
314300475Sngie		/*
315300475Sngie		 * Make it possible to redefine default
316216295Ssyrinx		 * portal-group. but only once.
317216295Ssyrinx		 */
318216295Ssyrinx		if (strcmp($1, "default") == 0 &&
319216295Ssyrinx		    conf->conf_default_pg_defined == false) {
320216295Ssyrinx			portal_group = portal_group_find(conf, $1);
321216295Ssyrinx			conf->conf_default_pg_defined = true;
322216295Ssyrinx		} else {
323216295Ssyrinx			portal_group = portal_group_new(conf, $1);
324216295Ssyrinx		}
325216295Ssyrinx		free($1);
326216295Ssyrinx		if (portal_group == NULL)
327216295Ssyrinx			return (1);
328216295Ssyrinx	}
329216295Ssyrinx	;
330216295Ssyrinx
331216295Ssyrinxportal_group_entries:
332216295Ssyrinx	|
333216295Ssyrinx	portal_group_entries portal_group_entry
334216295Ssyrinx	|
335216295Ssyrinx	portal_group_entries portal_group_entry SEMICOLON
336216295Ssyrinx	;
337216295Ssyrinx
338216295Ssyrinxportal_group_entry:
339216295Ssyrinx	portal_group_discovery_auth_group
340216295Ssyrinx	|
341216295Ssyrinx	portal_group_discovery_filter
342216295Ssyrinx	|
343216295Ssyrinx	portal_group_foreign
344216295Ssyrinx	|
345216295Ssyrinx	portal_group_listen
346216295Ssyrinx	|
347216295Ssyrinx	portal_group_listen_iser
348216295Ssyrinx	|
349216295Ssyrinx	portal_group_offload
350216295Ssyrinx	|
351216295Ssyrinx	portal_group_option
352216295Ssyrinx	|
353216295Ssyrinx	portal_group_redirect
354216295Ssyrinx	|
355216295Ssyrinx	portal_group_tag
356216295Ssyrinx	|
357216295Ssyrinx	portal_group_dscp
358216295Ssyrinx	|
359216295Ssyrinx	portal_group_pcp
360216295Ssyrinx	;
361216295Ssyrinx
362216295Ssyrinxportal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
363216295Ssyrinx	{
364216295Ssyrinx		if (portal_group->pg_discovery_auth_group != NULL) {
365216295Ssyrinx			log_warnx("discovery-auth-group for portal-group "
366216295Ssyrinx			    "\"%s\" specified more than once",
367216295Ssyrinx			    portal_group->pg_name);
368216295Ssyrinx			return (1);
369216295Ssyrinx		}
370216295Ssyrinx		portal_group->pg_discovery_auth_group =
371216295Ssyrinx		    auth_group_find(conf, $2);
372216295Ssyrinx		if (portal_group->pg_discovery_auth_group == NULL) {
373216295Ssyrinx			log_warnx("unknown discovery-auth-group \"%s\" "
374216295Ssyrinx			    "for portal-group \"%s\"",
375216295Ssyrinx			    $2, portal_group->pg_name);
376216295Ssyrinx			return (1);
377216295Ssyrinx		}
378216295Ssyrinx		free($2);
379216295Ssyrinx	}
380216295Ssyrinx	;
381216295Ssyrinx
382216295Ssyrinxportal_group_discovery_filter:	DISCOVERY_FILTER STR
383216295Ssyrinx	{
384216295Ssyrinx		int error;
385216295Ssyrinx
386216295Ssyrinx		error = portal_group_set_filter(portal_group, $2);
387216295Ssyrinx		free($2);
388216295Ssyrinx		if (error != 0)
389216295Ssyrinx			return (1);
390216295Ssyrinx	}
391216295Ssyrinx	;
392216295Ssyrinx
393216295Ssyrinxportal_group_foreign:	FOREIGN
394216295Ssyrinx	{
395216295Ssyrinx
396216295Ssyrinx		portal_group->pg_foreign = 1;
397216295Ssyrinx	}
398216295Ssyrinx	;
399216295Ssyrinx
400216295Ssyrinxportal_group_listen:	LISTEN STR
401216295Ssyrinx	{
402216295Ssyrinx		int error;
403216295Ssyrinx
404216295Ssyrinx		error = portal_group_add_listen(portal_group, $2, false);
405216295Ssyrinx		free($2);
406216295Ssyrinx		if (error != 0)
407216295Ssyrinx			return (1);
408216295Ssyrinx	}
409216295Ssyrinx	;
410216295Ssyrinx
411216295Ssyrinxportal_group_listen_iser:	LISTEN_ISER STR
412216295Ssyrinx	{
413216295Ssyrinx		int error;
414216295Ssyrinx
415216295Ssyrinx		error = portal_group_add_listen(portal_group, $2, true);
416216295Ssyrinx		free($2);
417216295Ssyrinx		if (error != 0)
418216295Ssyrinx			return (1);
419216295Ssyrinx	}
420216295Ssyrinx	;
421216295Ssyrinx
422216295Ssyrinxportal_group_offload:	OFFLOAD STR
423216295Ssyrinx	{
424216295Ssyrinx		int error;
425216295Ssyrinx
426216295Ssyrinx		error = portal_group_set_offload(portal_group, $2);
427216295Ssyrinx		free($2);
428216295Ssyrinx		if (error != 0)
429216295Ssyrinx			return (1);
430216295Ssyrinx	}
431216295Ssyrinx	;
432216295Ssyrinx
433216295Ssyrinxportal_group_option:	OPTION STR STR
434216295Ssyrinx	{
435216295Ssyrinx		struct option *o;
436216295Ssyrinx
437216295Ssyrinx		o = option_new(&portal_group->pg_options, $2, $3);
438216295Ssyrinx		free($2);
439216295Ssyrinx		free($3);
440216295Ssyrinx		if (o == NULL)
441216295Ssyrinx			return (1);
442216295Ssyrinx	}
443216295Ssyrinx	;
444216295Ssyrinx
445216295Ssyrinxportal_group_redirect:	REDIRECT STR
446216295Ssyrinx	{
447216295Ssyrinx		int error;
448216295Ssyrinx
449216295Ssyrinx		error = portal_group_set_redirection(portal_group, $2);
450216295Ssyrinx		free($2);
451216295Ssyrinx		if (error != 0)
452216295Ssyrinx			return (1);
453216295Ssyrinx	}
454216295Ssyrinx	;
455216295Ssyrinx
456216295Ssyrinxportal_group_tag:	TAG STR
457216295Ssyrinx	{
458216295Ssyrinx		uint64_t tmp;
459216295Ssyrinx
460216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
461216295Ssyrinx			yyerror("invalid numeric value");
462216295Ssyrinx			free($2);
463216295Ssyrinx			return (1);
464216295Ssyrinx		}
465216295Ssyrinx
466216295Ssyrinx		portal_group->pg_tag = tmp;
467216295Ssyrinx	}
468216295Ssyrinx	;
469216295Ssyrinx
470216295Ssyrinxportal_group_dscp
471216295Ssyrinx: DSCP STR
472216295Ssyrinx	{
473216295Ssyrinx		uint64_t tmp;
474216295Ssyrinx
475216295Ssyrinx		if (strcmp($2, "0x") == 0) {
476216295Ssyrinx			tmp = strtol($2 + 2, NULL, 16);
477216295Ssyrinx		} else if (expand_number($2, &tmp) != 0) {
478216295Ssyrinx			yyerror("invalid numeric value");
479216295Ssyrinx			free($2);
480216295Ssyrinx			return(1);
481216295Ssyrinx		}
482216295Ssyrinx		if (tmp >= 0x40) {
483216295Ssyrinx			yyerror("invalid dscp value");
484216295Ssyrinx			return(1);
485216295Ssyrinx		}
486310903Sngie
487216295Ssyrinx		portal_group->pg_dscp = tmp;
488216295Ssyrinx	}
489216295Ssyrinx| DSCP BE	{ portal_group->pg_dscp = IPTOS_DSCP_CS0  >> 2 ; }
490216295Ssyrinx| DSCP EF	{ portal_group->pg_dscp = IPTOS_DSCP_EF   >> 2 ; }
491216295Ssyrinx| DSCP CS0	{ portal_group->pg_dscp = IPTOS_DSCP_CS0  >> 2 ; }
492216295Ssyrinx| DSCP CS1	{ portal_group->pg_dscp = IPTOS_DSCP_CS1  >> 2 ; }
493216295Ssyrinx| DSCP CS2	{ portal_group->pg_dscp = IPTOS_DSCP_CS2  >> 2 ; }
494216295Ssyrinx| DSCP CS3	{ portal_group->pg_dscp = IPTOS_DSCP_CS3  >> 2 ; }
495216295Ssyrinx| DSCP CS4	{ portal_group->pg_dscp = IPTOS_DSCP_CS4  >> 2 ; }
496216295Ssyrinx| DSCP CS5	{ portal_group->pg_dscp = IPTOS_DSCP_CS5  >> 2 ; }
497216295Ssyrinx| DSCP CS6	{ portal_group->pg_dscp = IPTOS_DSCP_CS6  >> 2 ; }
498216295Ssyrinx| DSCP CS7	{ portal_group->pg_dscp = IPTOS_DSCP_CS7  >> 2 ; }
499216295Ssyrinx| DSCP AF11	{ portal_group->pg_dscp = IPTOS_DSCP_AF11 >> 2 ; }
500216295Ssyrinx| DSCP AF12	{ portal_group->pg_dscp = IPTOS_DSCP_AF12 >> 2 ; }
501216295Ssyrinx| DSCP AF13	{ portal_group->pg_dscp = IPTOS_DSCP_AF13 >> 2 ; }
502216295Ssyrinx| DSCP AF21	{ portal_group->pg_dscp = IPTOS_DSCP_AF21 >> 2 ; }
503216295Ssyrinx| DSCP AF22	{ portal_group->pg_dscp = IPTOS_DSCP_AF22 >> 2 ; }
504216295Ssyrinx| DSCP AF23	{ portal_group->pg_dscp = IPTOS_DSCP_AF23 >> 2 ; }
505216295Ssyrinx| DSCP AF31	{ portal_group->pg_dscp = IPTOS_DSCP_AF31 >> 2 ; }
506216295Ssyrinx| DSCP AF32	{ portal_group->pg_dscp = IPTOS_DSCP_AF32 >> 2 ; }
507216295Ssyrinx| DSCP AF33	{ portal_group->pg_dscp = IPTOS_DSCP_AF33 >> 2 ; }
508216295Ssyrinx| DSCP AF41	{ portal_group->pg_dscp = IPTOS_DSCP_AF41 >> 2 ; }
509216295Ssyrinx| DSCP AF42	{ portal_group->pg_dscp = IPTOS_DSCP_AF42 >> 2 ; }
510216295Ssyrinx| DSCP AF43	{ portal_group->pg_dscp = IPTOS_DSCP_AF43 >> 2 ; }
511216295Ssyrinx	;
512216295Ssyrinx
513216295Ssyrinxportal_group_pcp:	PCP STR
514216295Ssyrinx	{
515216295Ssyrinx		uint64_t tmp;
516300475Sngie
517216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
518216295Ssyrinx			yyerror("invalid numeric value");
519216295Ssyrinx			free($2);
520216295Ssyrinx			return (1);
521216295Ssyrinx		}
522216295Ssyrinx		if (tmp > 7) {
523216295Ssyrinx			yyerror("invalid pcp value");
524216295Ssyrinx			free($2);
525216295Ssyrinx			return (1);
526216295Ssyrinx		}
527216295Ssyrinx
528216295Ssyrinx		portal_group->pg_pcp = tmp;
529216295Ssyrinx	}
530216295Ssyrinx	;
531216295Ssyrinx
532216295Ssyrinxlun:	LUN lun_name
533216295Ssyrinx    OPENING_BRACKET lun_entries CLOSING_BRACKET
534216295Ssyrinx	{
535300475Sngie		lun = NULL;
536216295Ssyrinx	}
537216295Ssyrinx	;
538216295Ssyrinx
539216295Ssyrinxlun_name:	STR
540216295Ssyrinx	{
541216295Ssyrinx		lun = lun_new(conf, $1);
542310903Sngie		free($1);
543216295Ssyrinx		if (lun == NULL)
544216295Ssyrinx			return (1);
545216295Ssyrinx	}
546216295Ssyrinx	;
547216295Ssyrinx
548216295Ssyrinxtarget:	TARGET target_name
549216295Ssyrinx    OPENING_BRACKET target_entries CLOSING_BRACKET
550300475Sngie	{
551216295Ssyrinx		target = NULL;
552216295Ssyrinx	}
553216295Ssyrinx	;
554216295Ssyrinx
555216295Ssyrinxtarget_name:	STR
556216295Ssyrinx	{
557216295Ssyrinx		target = target_new(conf, $1);
558216295Ssyrinx		free($1);
559216295Ssyrinx		if (target == NULL)
560216295Ssyrinx			return (1);
561216295Ssyrinx	}
562216295Ssyrinx	;
563216295Ssyrinx
564216295Ssyrinxtarget_entries:
565216295Ssyrinx	|
566216295Ssyrinx	target_entries target_entry
567216295Ssyrinx	|
568216295Ssyrinx	target_entries target_entry SEMICOLON
569216295Ssyrinx	;
570216295Ssyrinx
571216295Ssyrinxtarget_entry:
572216295Ssyrinx	target_alias
573216295Ssyrinx	|
574216295Ssyrinx	target_auth_group
575216295Ssyrinx	|
576216295Ssyrinx	target_auth_type
577216295Ssyrinx	|
578216295Ssyrinx	target_chap
579216295Ssyrinx	|
580216295Ssyrinx	target_chap_mutual
581216295Ssyrinx	|
582216295Ssyrinx	target_initiator_name
583216295Ssyrinx	|
584216295Ssyrinx	target_initiator_portal
585216295Ssyrinx	|
586216295Ssyrinx	target_portal_group
587216295Ssyrinx	|
588216295Ssyrinx	target_port
589216295Ssyrinx	|
590216295Ssyrinx	target_redirect
591216295Ssyrinx	|
592216295Ssyrinx	target_lun
593216295Ssyrinx	|
594216295Ssyrinx	target_lun_ref
595216295Ssyrinx	;
596216295Ssyrinx
597216295Ssyrinxtarget_alias:	ALIAS STR
598216295Ssyrinx	{
599216295Ssyrinx		if (target->t_alias != NULL) {
600216295Ssyrinx			log_warnx("alias for target \"%s\" "
601216295Ssyrinx			    "specified more than once", target->t_name);
602216295Ssyrinx			return (1);
603216295Ssyrinx		}
604216295Ssyrinx		target->t_alias = $2;
605216295Ssyrinx	}
606216295Ssyrinx	;
607216295Ssyrinx
608216295Ssyrinxtarget_auth_group:	AUTH_GROUP STR
609216295Ssyrinx	{
610216295Ssyrinx		if (target->t_auth_group != NULL) {
611216295Ssyrinx			if (target->t_auth_group->ag_name != NULL)
612216295Ssyrinx				log_warnx("auth-group for target \"%s\" "
613216295Ssyrinx				    "specified more than once", target->t_name);
614216295Ssyrinx			else
615216295Ssyrinx				log_warnx("cannot use both auth-group and explicit "
616216295Ssyrinx				    "authorisations for target \"%s\"",
617216295Ssyrinx				    target->t_name);
618216295Ssyrinx			return (1);
619216295Ssyrinx		}
620216295Ssyrinx		target->t_auth_group = auth_group_find(conf, $2);
621216295Ssyrinx		if (target->t_auth_group == NULL) {
622216295Ssyrinx			log_warnx("unknown auth-group \"%s\" for target "
623216295Ssyrinx			    "\"%s\"", $2, target->t_name);
624216295Ssyrinx			return (1);
625216295Ssyrinx		}
626216295Ssyrinx		free($2);
627216295Ssyrinx	}
628216295Ssyrinx	;
629216295Ssyrinx
630216295Ssyrinxtarget_auth_type:	AUTH_TYPE STR
631216295Ssyrinx	{
632216295Ssyrinx		int error;
633300475Sngie
634216295Ssyrinx		if (target->t_auth_group != NULL) {
635216295Ssyrinx			if (target->t_auth_group->ag_name != NULL) {
636216295Ssyrinx				log_warnx("cannot use both auth-group and "
637300475Sngie				    "auth-type for target \"%s\"",
638216295Ssyrinx				    target->t_name);
639216295Ssyrinx				return (1);
640216295Ssyrinx			}
641216295Ssyrinx		} else {
642216295Ssyrinx			target->t_auth_group = auth_group_new(conf, NULL);
643216295Ssyrinx			if (target->t_auth_group == NULL) {
644216295Ssyrinx				free($2);
645216295Ssyrinx				return (1);
646216295Ssyrinx			}
647216295Ssyrinx			target->t_auth_group->ag_target = target;
648216295Ssyrinx		}
649216295Ssyrinx		error = auth_group_set_type(target->t_auth_group, $2);
650216295Ssyrinx		free($2);
651216295Ssyrinx		if (error != 0)
652216295Ssyrinx			return (1);
653216295Ssyrinx	}
654216295Ssyrinx	;
655216295Ssyrinx
656216295Ssyrinxtarget_chap:	CHAP STR STR
657216295Ssyrinx	{
658216295Ssyrinx		const struct auth *ca;
659216295Ssyrinx
660216295Ssyrinx		if (target->t_auth_group != NULL) {
661216295Ssyrinx			if (target->t_auth_group->ag_name != NULL) {
662216295Ssyrinx				log_warnx("cannot use both auth-group and "
663216295Ssyrinx				    "chap for target \"%s\"",
664216295Ssyrinx				    target->t_name);
665216295Ssyrinx				free($2);
666216295Ssyrinx				free($3);
667216295Ssyrinx				return (1);
668216295Ssyrinx			}
669216295Ssyrinx		} else {
670216295Ssyrinx			target->t_auth_group = auth_group_new(conf, NULL);
671216295Ssyrinx			if (target->t_auth_group == NULL) {
672216295Ssyrinx				free($2);
673216295Ssyrinx				free($3);
674216295Ssyrinx				return (1);
675216295Ssyrinx			}
676216295Ssyrinx			target->t_auth_group->ag_target = target;
677216295Ssyrinx		}
678216295Ssyrinx		ca = auth_new_chap(target->t_auth_group, $2, $3);
679216295Ssyrinx		free($2);
680216295Ssyrinx		free($3);
681216295Ssyrinx		if (ca == NULL)
682216295Ssyrinx			return (1);
683216295Ssyrinx	}
684216295Ssyrinx	;
685216295Ssyrinx
686216295Ssyrinxtarget_chap_mutual:	CHAP_MUTUAL STR STR STR STR
687216295Ssyrinx	{
688216295Ssyrinx		const struct auth *ca;
689216295Ssyrinx
690216295Ssyrinx		if (target->t_auth_group != NULL) {
691216295Ssyrinx			if (target->t_auth_group->ag_name != NULL) {
692216295Ssyrinx				log_warnx("cannot use both auth-group and "
693216295Ssyrinx				    "chap-mutual for target \"%s\"",
694299016Sngie				    target->t_name);
695216295Ssyrinx				free($2);
696216295Ssyrinx				free($3);
697216295Ssyrinx				free($4);
698216295Ssyrinx				free($5);
699216295Ssyrinx				return (1);
700216295Ssyrinx			}
701216295Ssyrinx		} else {
702216295Ssyrinx			target->t_auth_group = auth_group_new(conf, NULL);
703216295Ssyrinx			if (target->t_auth_group == NULL) {
704216295Ssyrinx				free($2);
705216295Ssyrinx				free($3);
706300475Sngie				free($4);
707216295Ssyrinx				free($5);
708216295Ssyrinx				return (1);
709216295Ssyrinx			}
710216295Ssyrinx			target->t_auth_group->ag_target = target;
711216295Ssyrinx		}
712216295Ssyrinx		ca = auth_new_chap_mutual(target->t_auth_group,
713216295Ssyrinx		    $2, $3, $4, $5);
714216295Ssyrinx		free($2);
715216295Ssyrinx		free($3);
716216295Ssyrinx		free($4);
717216295Ssyrinx		free($5);
718216295Ssyrinx		if (ca == NULL)
719216295Ssyrinx			return (1);
720216295Ssyrinx	}
721216295Ssyrinx	;
722216295Ssyrinx
723216295Ssyrinxtarget_initiator_name:	INITIATOR_NAME STR
724216295Ssyrinx	{
725216295Ssyrinx		const struct auth_name *an;
726216295Ssyrinx
727216295Ssyrinx		if (target->t_auth_group != NULL) {
728216295Ssyrinx			if (target->t_auth_group->ag_name != NULL) {
729216295Ssyrinx				log_warnx("cannot use both auth-group and "
730216295Ssyrinx				    "initiator-name for target \"%s\"",
731216295Ssyrinx				    target->t_name);
732216295Ssyrinx				free($2);
733216295Ssyrinx				return (1);
734216295Ssyrinx			}
735216295Ssyrinx		} else {
736216295Ssyrinx			target->t_auth_group = auth_group_new(conf, NULL);
737216295Ssyrinx			if (target->t_auth_group == NULL) {
738216295Ssyrinx				free($2);
739216295Ssyrinx				return (1);
740216295Ssyrinx			}
741216295Ssyrinx			target->t_auth_group->ag_target = target;
742216295Ssyrinx		}
743216295Ssyrinx		an = auth_name_new(target->t_auth_group, $2);
744216295Ssyrinx		free($2);
745216295Ssyrinx		if (an == NULL)
746216295Ssyrinx			return (1);
747216295Ssyrinx	}
748216295Ssyrinx	;
749216295Ssyrinx
750216295Ssyrinxtarget_initiator_portal:	INITIATOR_PORTAL STR
751216295Ssyrinx	{
752216295Ssyrinx		const struct auth_portal *ap;
753216295Ssyrinx
754216295Ssyrinx		if (target->t_auth_group != NULL) {
755216295Ssyrinx			if (target->t_auth_group->ag_name != NULL) {
756216295Ssyrinx				log_warnx("cannot use both auth-group and "
757216295Ssyrinx				    "initiator-portal for target \"%s\"",
758216295Ssyrinx				    target->t_name);
759300475Sngie				free($2);
760216295Ssyrinx				return (1);
761216295Ssyrinx			}
762216295Ssyrinx		} else {
763216295Ssyrinx			target->t_auth_group = auth_group_new(conf, NULL);
764216295Ssyrinx			if (target->t_auth_group == NULL) {
765300475Sngie				free($2);
766300475Sngie				return (1);
767216295Ssyrinx			}
768216295Ssyrinx			target->t_auth_group->ag_target = target;
769216295Ssyrinx		}
770300475Sngie		ap = auth_portal_new(target->t_auth_group, $2);
771300475Sngie		free($2);
772216295Ssyrinx		if (ap == NULL)
773216295Ssyrinx			return (1);
774216295Ssyrinx	}
775216295Ssyrinx	;
776216295Ssyrinx
777216295Ssyrinxtarget_portal_group:	PORTAL_GROUP STR STR
778216295Ssyrinx	{
779216295Ssyrinx		struct portal_group *tpg;
780216295Ssyrinx		struct auth_group *tag;
781216295Ssyrinx		struct port *tp;
782216295Ssyrinx
783216295Ssyrinx		tpg = portal_group_find(conf, $2);
784216295Ssyrinx		if (tpg == NULL) {
785216295Ssyrinx			log_warnx("unknown portal-group \"%s\" for target "
786216295Ssyrinx			    "\"%s\"", $2, target->t_name);
787216295Ssyrinx			free($2);
788216295Ssyrinx			free($3);
789216295Ssyrinx			return (1);
790216295Ssyrinx		}
791216295Ssyrinx		tag = auth_group_find(conf, $3);
792216295Ssyrinx		if (tag == NULL) {
793216295Ssyrinx			log_warnx("unknown auth-group \"%s\" for target "
794216295Ssyrinx			    "\"%s\"", $3, target->t_name);
795216295Ssyrinx			free($2);
796216295Ssyrinx			free($3);
797216295Ssyrinx			return (1);
798216295Ssyrinx		}
799216295Ssyrinx		tp = port_new(conf, target, tpg);
800216295Ssyrinx		if (tp == NULL) {
801216295Ssyrinx			log_warnx("can't link portal-group \"%s\" to target "
802216295Ssyrinx			    "\"%s\"", $2, target->t_name);
803216295Ssyrinx			free($2);
804216295Ssyrinx			return (1);
805216295Ssyrinx		}
806216295Ssyrinx		tp->p_auth_group = tag;
807216295Ssyrinx		free($2);
808216295Ssyrinx		free($3);
809310903Sngie	}
810216295Ssyrinx	|		PORTAL_GROUP STR
811216295Ssyrinx	{
812216295Ssyrinx		struct portal_group *tpg;
813216295Ssyrinx		struct port *tp;
814216295Ssyrinx
815216295Ssyrinx		tpg = portal_group_find(conf, $2);
816216295Ssyrinx		if (tpg == NULL) {
817216295Ssyrinx			log_warnx("unknown portal-group \"%s\" for target "
818216295Ssyrinx			    "\"%s\"", $2, target->t_name);
819216295Ssyrinx			free($2);
820216295Ssyrinx			return (1);
821216295Ssyrinx		}
822216295Ssyrinx		tp = port_new(conf, target, tpg);
823216295Ssyrinx		if (tp == NULL) {
824216295Ssyrinx			log_warnx("can't link portal-group \"%s\" to target "
825216295Ssyrinx			    "\"%s\"", $2, target->t_name);
826216295Ssyrinx			free($2);
827216295Ssyrinx			return (1);
828216295Ssyrinx		}
829216295Ssyrinx		free($2);
830216295Ssyrinx	}
831216295Ssyrinx	;
832216295Ssyrinx
833216295Ssyrinxtarget_port:	PORT STR
834216295Ssyrinx	{
835216295Ssyrinx		struct pport *pp;
836216295Ssyrinx		struct port *tp;
837216295Ssyrinx		int ret, i_pp, i_vp = 0;
838216295Ssyrinx
839216295Ssyrinx		ret = sscanf($2, "ioctl/%d/%d", &i_pp, &i_vp);
840216295Ssyrinx		if (ret > 0) {
841216295Ssyrinx			tp = port_new_ioctl(conf, target, i_pp, i_vp);
842216295Ssyrinx			if (tp == NULL) {
843216295Ssyrinx				log_warnx("can't create new ioctl port for "
844216295Ssyrinx				    "target \"%s\"", target->t_name);
845216295Ssyrinx				free($2);
846216295Ssyrinx				return (1);
847216295Ssyrinx			}
848216295Ssyrinx		} else {
849216295Ssyrinx			pp = pport_find(conf, $2);
850216295Ssyrinx			if (pp == NULL) {
851216295Ssyrinx				log_warnx("unknown port \"%s\" for target \"%s\"",
852216295Ssyrinx				    $2, target->t_name);
853216295Ssyrinx				free($2);
854216295Ssyrinx				return (1);
855216295Ssyrinx			}
856300475Sngie			if (!TAILQ_EMPTY(&pp->pp_ports)) {
857216295Ssyrinx				log_warnx("can't link port \"%s\" to target \"%s\", "
858216295Ssyrinx				    "port already linked to some target",
859216295Ssyrinx				    $2, target->t_name);
860216295Ssyrinx				free($2);
861216295Ssyrinx				return (1);
862216295Ssyrinx			}
863216295Ssyrinx			tp = port_new_pp(conf, target, pp);
864216295Ssyrinx			if (tp == NULL) {
865216295Ssyrinx				log_warnx("can't link port \"%s\" to target \"%s\"",
866216295Ssyrinx				    $2, target->t_name);
867216295Ssyrinx				free($2);
868216295Ssyrinx				return (1);
869216295Ssyrinx			}
870216295Ssyrinx		}
871216295Ssyrinx
872216295Ssyrinx		free($2);
873216295Ssyrinx	}
874216295Ssyrinx	;
875216295Ssyrinx
876216295Ssyrinxtarget_redirect:	REDIRECT STR
877216295Ssyrinx	{
878216295Ssyrinx		int error;
879216295Ssyrinx
880216295Ssyrinx		error = target_set_redirection(target, $2);
881216295Ssyrinx		free($2);
882300475Sngie		if (error != 0)
883216295Ssyrinx			return (1);
884216295Ssyrinx	}
885216295Ssyrinx	;
886216295Ssyrinx
887216295Ssyrinxtarget_lun:	LUN lun_number
888216295Ssyrinx    OPENING_BRACKET lun_entries CLOSING_BRACKET
889216295Ssyrinx	{
890216295Ssyrinx		lun = NULL;
891216295Ssyrinx	}
892216295Ssyrinx	;
893216295Ssyrinx
894216295Ssyrinxlun_number:	STR
895216295Ssyrinx	{
896216295Ssyrinx		uint64_t tmp;
897216295Ssyrinx		int ret;
898216295Ssyrinx		char *name;
899216295Ssyrinx
900216295Ssyrinx		if (expand_number($1, &tmp) != 0) {
901216295Ssyrinx			yyerror("invalid numeric value");
902216295Ssyrinx			free($1);
903216295Ssyrinx			return (1);
904216295Ssyrinx		}
905216295Ssyrinx		if (tmp >= MAX_LUNS) {
906216295Ssyrinx			yyerror("LU number is too big");
907216295Ssyrinx			free($1);
908216295Ssyrinx			return (1);
909216295Ssyrinx		}
910216295Ssyrinx
911216295Ssyrinx		ret = asprintf(&name, "%s,lun,%ju", target->t_name, tmp);
912216295Ssyrinx		if (ret <= 0)
913216295Ssyrinx			log_err(1, "asprintf");
914216295Ssyrinx		lun = lun_new(conf, name);
915216295Ssyrinx		if (lun == NULL)
916216295Ssyrinx			return (1);
917216295Ssyrinx
918216295Ssyrinx		lun_set_scsiname(lun, name);
919216295Ssyrinx		target->t_luns[tmp] = lun;
920216295Ssyrinx	}
921216295Ssyrinx	;
922216295Ssyrinx
923216295Ssyrinxtarget_lun_ref:	LUN STR STR
924216295Ssyrinx	{
925216295Ssyrinx		uint64_t tmp;
926216295Ssyrinx
927216295Ssyrinx		if (expand_number($2, &tmp) != 0) {
928216295Ssyrinx			yyerror("invalid numeric value");
929216295Ssyrinx			free($2);
930216295Ssyrinx			free($3);
931216295Ssyrinx			return (1);
932216295Ssyrinx		}
933216295Ssyrinx		free($2);
934216295Ssyrinx		if (tmp >= MAX_LUNS) {
935216295Ssyrinx			yyerror("LU number is too big");
936216295Ssyrinx			free($3);
937216295Ssyrinx			return (1);
938216295Ssyrinx		}
939300475Sngie
940216295Ssyrinx		lun = lun_find(conf, $3);
941216295Ssyrinx		free($3);
942216295Ssyrinx		if (lun == NULL)
943216295Ssyrinx			return (1);
944216295Ssyrinx
945216295Ssyrinx		target->t_luns[tmp] = lun;
946216295Ssyrinx	}
947216295Ssyrinx	;
948216295Ssyrinx
949216295Ssyrinxlun_entries:
950216295Ssyrinx	|
951216295Ssyrinx	lun_entries lun_entry
952216295Ssyrinx	|
953216295Ssyrinx	lun_entries lun_entry SEMICOLON
954216295Ssyrinx	;
955216295Ssyrinx
956216295Ssyrinxlun_entry:
957216295Ssyrinx	lun_backend
958216295Ssyrinx	|
959216295Ssyrinx	lun_blocksize
960216295Ssyrinx	|
961216295Ssyrinx	lun_device_id
962216295Ssyrinx	|
963216295Ssyrinx	lun_device_type
964216295Ssyrinx	|
965216295Ssyrinx	lun_ctl_lun
966216295Ssyrinx	|
967216295Ssyrinx	lun_option
968216295Ssyrinx	|
969	lun_path
970	|
971	lun_serial
972	|
973	lun_size
974	;
975
976lun_backend:	BACKEND STR
977	{
978		if (lun->l_backend != NULL) {
979			log_warnx("backend for lun \"%s\" "
980			    "specified more than once",
981			    lun->l_name);
982			free($2);
983			return (1);
984		}
985		lun_set_backend(lun, $2);
986		free($2);
987	}
988	;
989
990lun_blocksize:	BLOCKSIZE STR
991	{
992		uint64_t tmp;
993
994		if (expand_number($2, &tmp) != 0) {
995			yyerror("invalid numeric value");
996			free($2);
997			return (1);
998		}
999
1000		if (lun->l_blocksize != 0) {
1001			log_warnx("blocksize for lun \"%s\" "
1002			    "specified more than once",
1003			    lun->l_name);
1004			return (1);
1005		}
1006		lun_set_blocksize(lun, tmp);
1007	}
1008	;
1009
1010lun_device_id:	DEVICE_ID STR
1011	{
1012		if (lun->l_device_id != NULL) {
1013			log_warnx("device_id for lun \"%s\" "
1014			    "specified more than once",
1015			    lun->l_name);
1016			free($2);
1017			return (1);
1018		}
1019		lun_set_device_id(lun, $2);
1020		free($2);
1021	}
1022	;
1023
1024lun_device_type:	DEVICE_TYPE STR
1025	{
1026		uint64_t tmp;
1027
1028		if (strcasecmp($2, "disk") == 0 ||
1029		    strcasecmp($2, "direct") == 0)
1030			tmp = 0;
1031		else if (strcasecmp($2, "processor") == 0)
1032			tmp = 3;
1033		else if (strcasecmp($2, "cd") == 0 ||
1034		    strcasecmp($2, "cdrom") == 0 ||
1035		    strcasecmp($2, "dvd") == 0 ||
1036		    strcasecmp($2, "dvdrom") == 0)
1037			tmp = 5;
1038		else if (expand_number($2, &tmp) != 0 ||
1039		    tmp > 15) {
1040			yyerror("invalid numeric value");
1041			free($2);
1042			return (1);
1043		}
1044
1045		lun_set_device_type(lun, tmp);
1046	}
1047	;
1048
1049lun_ctl_lun:	CTL_LUN STR
1050	{
1051		uint64_t tmp;
1052
1053		if (expand_number($2, &tmp) != 0) {
1054			yyerror("invalid numeric value");
1055			free($2);
1056			return (1);
1057		}
1058
1059		if (lun->l_ctl_lun >= 0) {
1060			log_warnx("ctl_lun for lun \"%s\" "
1061			    "specified more than once",
1062			    lun->l_name);
1063			return (1);
1064		}
1065		lun_set_ctl_lun(lun, tmp);
1066	}
1067	;
1068
1069lun_option:	OPTION STR STR
1070	{
1071		struct option *o;
1072
1073		o = option_new(&lun->l_options, $2, $3);
1074		free($2);
1075		free($3);
1076		if (o == NULL)
1077			return (1);
1078	}
1079	;
1080
1081lun_path:	PATH STR
1082	{
1083		if (lun->l_path != NULL) {
1084			log_warnx("path for lun \"%s\" "
1085			    "specified more than once",
1086			    lun->l_name);
1087			free($2);
1088			return (1);
1089		}
1090		lun_set_path(lun, $2);
1091		free($2);
1092	}
1093	;
1094
1095lun_serial:	SERIAL STR
1096	{
1097		if (lun->l_serial != NULL) {
1098			log_warnx("serial for lun \"%s\" "
1099			    "specified more than once",
1100			    lun->l_name);
1101			free($2);
1102			return (1);
1103		}
1104		lun_set_serial(lun, $2);
1105		free($2);
1106	}
1107	;
1108
1109lun_size:	SIZE STR
1110	{
1111		uint64_t tmp;
1112
1113		if (expand_number($2, &tmp) != 0) {
1114			yyerror("invalid numeric value");
1115			free($2);
1116			return (1);
1117		}
1118
1119		if (lun->l_size != 0) {
1120			log_warnx("size for lun \"%s\" "
1121			    "specified more than once",
1122			    lun->l_name);
1123			return (1);
1124		}
1125		lun_set_size(lun, tmp);
1126	}
1127	;
1128%%
1129
1130void
1131yyerror(const char *str)
1132{
1133
1134	log_warnx("error in configuration file at line %d near '%s': %s",
1135	    lineno, yytext, str);
1136}
1137
1138int
1139parse_conf(struct conf *newconf, const char *path)
1140{
1141	int error;
1142
1143	conf = newconf;
1144	yyin = fopen(path, "r");
1145	if (yyin == NULL) {
1146		log_warn("unable to open configuration file %s", path);
1147		return (1);
1148	}
1149
1150	lineno = 1;
1151	yyrestart(yyin);
1152	error = yyparse();
1153	auth_group = NULL;
1154	portal_group = NULL;
1155	target = NULL;
1156	lun = NULL;
1157	fclose(yyin);
1158
1159	return (error);
1160}
1161