3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * Copyright (c) 2012 The FreeBSD Foundation
7 * This software was developed by Edward Tomasz Napierala under sponsorship
8 * from the FreeBSD Foundation.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/queue.h>
35 #include <sys/types.h>
46 #include <netinet/in.h>
47 #include <netinet/ip.h>
53 static struct conf *conf;
54 static struct target *target;
56 extern void yyerror(const char *);
57 extern int yylex(void);
58 extern void yyrestart(FILE *);
62 %token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
63 %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
64 %token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
65 %token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET DSCP
66 %token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
67 %token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7
83 target: STR OPENING_BRACKET target_entries CLOSING_BRACKET
85 if (target_find(conf, $1) != NULL)
86 xo_errx(1, "duplicated target %s", $1);
87 target->t_nickname = $1;
88 target = target_new(conf);
94 target_entries target_entry
96 target_entries target_entry SEMICOLON
139 target_name: TARGET_NAME EQUALS STR
141 if (target->t_name != NULL)
142 xo_errx(1, "duplicated TargetName at line %d", lineno);
147 target_address: TARGET_ADDRESS EQUALS STR
149 if (target->t_address != NULL)
150 xo_errx(1, "duplicated TargetAddress at line %d", lineno);
151 target->t_address = $3;
155 initiator_name: INITIATOR_NAME EQUALS STR
157 if (target->t_initiator_name != NULL)
158 xo_errx(1, "duplicated InitiatorName at line %d", lineno);
159 target->t_initiator_name = $3;
163 initiator_address: INITIATOR_ADDRESS EQUALS STR
165 if (target->t_initiator_address != NULL)
166 xo_errx(1, "duplicated InitiatorAddress at line %d", lineno);
167 target->t_initiator_address = $3;
171 initiator_alias: INITIATOR_ALIAS EQUALS STR
173 if (target->t_initiator_alias != NULL)
174 xo_errx(1, "duplicated InitiatorAlias at line %d", lineno);
175 target->t_initiator_alias = $3;
179 user: USER EQUALS STR
181 if (target->t_user != NULL)
182 xo_errx(1, "duplicated chapIName at line %d", lineno);
187 secret: SECRET EQUALS STR
189 if (target->t_secret != NULL)
190 xo_errx(1, "duplicated chapSecret at line %d", lineno);
191 target->t_secret = $3;
195 mutual_user: MUTUAL_USER EQUALS STR
197 if (target->t_mutual_user != NULL)
198 xo_errx(1, "duplicated tgtChapName at line %d", lineno);
199 target->t_mutual_user = $3;
203 mutual_secret: MUTUAL_SECRET EQUALS STR
205 if (target->t_mutual_secret != NULL)
206 xo_errx(1, "duplicated tgtChapSecret at line %d", lineno);
207 target->t_mutual_secret = $3;
211 auth_method: AUTH_METHOD EQUALS STR
213 if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
214 xo_errx(1, "duplicated AuthMethod at line %d", lineno);
215 if (strcasecmp($3, "none") == 0)
216 target->t_auth_method = AUTH_METHOD_NONE;
217 else if (strcasecmp($3, "chap") == 0)
218 target->t_auth_method = AUTH_METHOD_CHAP;
220 xo_errx(1, "invalid AuthMethod at line %d; "
221 "must be either \"none\" or \"CHAP\"", lineno);
225 header_digest: HEADER_DIGEST EQUALS STR
227 if (target->t_header_digest != DIGEST_UNSPECIFIED)
228 xo_errx(1, "duplicated HeaderDigest at line %d", lineno);
229 if (strcasecmp($3, "none") == 0)
230 target->t_header_digest = DIGEST_NONE;
231 else if (strcasecmp($3, "CRC32C") == 0)
232 target->t_header_digest = DIGEST_CRC32C;
234 xo_errx(1, "invalid HeaderDigest at line %d; "
235 "must be either \"none\" or \"CRC32C\"", lineno);
239 data_digest: DATA_DIGEST EQUALS STR
241 if (target->t_data_digest != DIGEST_UNSPECIFIED)
242 xo_errx(1, "duplicated DataDigest at line %d", lineno);
243 if (strcasecmp($3, "none") == 0)
244 target->t_data_digest = DIGEST_NONE;
245 else if (strcasecmp($3, "CRC32C") == 0)
246 target->t_data_digest = DIGEST_CRC32C;
248 xo_errx(1, "invalid DataDigest at line %d; "
249 "must be either \"none\" or \"CRC32C\"", lineno);
253 session_type: SESSION_TYPE EQUALS STR
255 if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
256 xo_errx(1, "duplicated SessionType at line %d", lineno);
257 if (strcasecmp($3, "normal") == 0)
258 target->t_session_type = SESSION_TYPE_NORMAL;
259 else if (strcasecmp($3, "discovery") == 0)
260 target->t_session_type = SESSION_TYPE_DISCOVERY;
262 xo_errx(1, "invalid SessionType at line %d; "
263 "must be either \"normal\" or \"discovery\"", lineno);
267 enable: ENABLE EQUALS STR
269 if (target->t_enable != ENABLE_UNSPECIFIED)
270 xo_errx(1, "duplicated enable at line %d", lineno);
271 target->t_enable = parse_enable($3);
272 if (target->t_enable == ENABLE_UNSPECIFIED)
273 xo_errx(1, "invalid enable at line %d; "
274 "must be either \"on\" or \"off\"", lineno);
278 offload: OFFLOAD EQUALS STR
280 if (target->t_offload != NULL)
281 xo_errx(1, "duplicated offload at line %d", lineno);
282 target->t_offload = $3;
286 protocol: PROTOCOL EQUALS STR
288 if (target->t_protocol != PROTOCOL_UNSPECIFIED)
289 xo_errx(1, "duplicated protocol at line %d", lineno);
290 if (strcasecmp($3, "iscsi") == 0)
291 target->t_protocol = PROTOCOL_ISCSI;
292 else if (strcasecmp($3, "iser") == 0)
293 target->t_protocol = PROTOCOL_ISER;
295 xo_errx(1, "invalid protocol at line %d; "
296 "must be either \"iscsi\" or \"iser\"", lineno);
300 ignored: IGNORED EQUALS STR
302 xo_warnx("obsolete statement ignored at line %d", lineno);
306 dscp: DSCP EQUALS STR
310 if (target->t_dscp != -1)
311 xo_errx(1, "duplicated dscp at line %d", lineno);
312 if (strcmp($3, "0x") == 0) {
313 tmp = strtol($3 + 2, NULL, 16);
314 } else if (expand_number($3, &tmp) != 0) {
315 yyerror("invalid numeric value");
320 yyerror("invalid dscp value");
324 target->t_dscp = tmp;
326 | DSCP EQUALS BE { target->t_dscp = IPTOS_DSCP_CS0 >> 2 ; }
327 | DSCP EQUALS EF { target->t_dscp = IPTOS_DSCP_EF >> 2 ; }
328 | DSCP EQUALS CS0 { target->t_dscp = IPTOS_DSCP_CS0 >> 2 ; }
329 | DSCP EQUALS CS1 { target->t_dscp = IPTOS_DSCP_CS1 >> 2 ; }
330 | DSCP EQUALS CS2 { target->t_dscp = IPTOS_DSCP_CS2 >> 2 ; }
331 | DSCP EQUALS CS3 { target->t_dscp = IPTOS_DSCP_CS3 >> 2 ; }
332 | DSCP EQUALS CS4 { target->t_dscp = IPTOS_DSCP_CS4 >> 2 ; }
333 | DSCP EQUALS CS5 { target->t_dscp = IPTOS_DSCP_CS5 >> 2 ; }
334 | DSCP EQUALS CS6 { target->t_dscp = IPTOS_DSCP_CS6 >> 2 ; }
335 | DSCP EQUALS CS7 { target->t_dscp = IPTOS_DSCP_CS7 >> 2 ; }
336 | DSCP EQUALS AF11 { target->t_dscp = IPTOS_DSCP_AF11 >> 2 ; }
337 | DSCP EQUALS AF12 { target->t_dscp = IPTOS_DSCP_AF12 >> 2 ; }
338 | DSCP EQUALS AF13 { target->t_dscp = IPTOS_DSCP_AF13 >> 2 ; }
339 | DSCP EQUALS AF21 { target->t_dscp = IPTOS_DSCP_AF21 >> 2 ; }
340 | DSCP EQUALS AF22 { target->t_dscp = IPTOS_DSCP_AF22 >> 2 ; }
341 | DSCP EQUALS AF23 { target->t_dscp = IPTOS_DSCP_AF23 >> 2 ; }
342 | DSCP EQUALS AF31 { target->t_dscp = IPTOS_DSCP_AF31 >> 2 ; }
343 | DSCP EQUALS AF32 { target->t_dscp = IPTOS_DSCP_AF32 >> 2 ; }
344 | DSCP EQUALS AF33 { target->t_dscp = IPTOS_DSCP_AF33 >> 2 ; }
345 | DSCP EQUALS AF41 { target->t_dscp = IPTOS_DSCP_AF41 >> 2 ; }
346 | DSCP EQUALS AF42 { target->t_dscp = IPTOS_DSCP_AF42 >> 2 ; }
347 | DSCP EQUALS AF43 { target->t_dscp = IPTOS_DSCP_AF43 >> 2 ; }
354 if (target->t_pcp != -1)
355 xo_errx(1, "duplicated pcp at line %d", lineno);
357 if (expand_number($3, &tmp) != 0) {
358 yyerror("invalid numeric value");
362 if (!((tmp >=0) && (tmp <= 7))) {
363 yyerror("invalid pcp value");
374 yyerror(const char *str)
377 xo_errx(1, "error in configuration file at line %d near '%s': %s",
378 lineno, yytext, str);
382 check_perms(const char *path)
387 error = stat(path, &sb);
392 if (sb.st_mode & S_IWOTH) {
393 xo_warnx("%s is world-writable", path);
394 } else if (sb.st_mode & S_IROTH) {
395 xo_warnx("%s is world-readable", path);
396 } else if (sb.st_mode & S_IXOTH) {
398 * Ok, this one doesn't matter, but still do it,
399 * just for consistency.
401 xo_warnx("%s is world-executable", path);
405 * XXX: Should we also check for owner != 0?
410 conf_new_from_file(const char *path)
415 target = target_new(conf);
417 yyin = fopen(path, "r");
419 xo_err(1, "unable to open configuration file %s", path);
427 assert(target->t_nickname == NULL);
428 target_delete(target);