]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.bin/iscsictl/parse.y
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / usr.bin / iscsictl / parse.y
1 %{
2 /*-
3  * Copyright (c) 2012 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by Edward Tomasz Napierala under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include <sys/queue.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <assert.h>
37 #include <err.h>
38 #include <stdio.h>
39 #include <stdint.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "iscsictl.h"
44
45 extern FILE *yyin;
46 extern char *yytext;
47 extern int lineno;
48
49 static struct conf *conf;
50 static struct target *target;
51
52 extern void     yyerror(const char *);
53 extern int      yylex(void);
54 extern void     yyrestart(FILE *);
55
56 %}
57
58 %token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
59 %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
60 %token MUTUAL_USER MUTUAL_SECRET SESSION_TYPE PROTOCOL IGNORED
61 %token EQUALS OPENING_BRACKET CLOSING_BRACKET
62
63 %union
64 {
65         char *str;
66 }
67
68 %token <str> STR
69
70 %%
71
72 statements:
73         |
74         statements target_statement
75         ;
76
77 target_statement:       STR OPENING_BRACKET target_entries CLOSING_BRACKET
78         {
79                 if (target_find(conf, $1) != NULL)
80                         errx(1, "duplicated target %s", $1);
81                 target->t_nickname = $1;
82                 target = target_new(conf);
83         }
84         ;
85
86 target_entries:
87         |
88         target_entries target_entry
89         ;
90
91 target_entry:
92         target_name_statement
93         |
94         target_address_statement
95         |
96         initiator_name_statement
97         |
98         initiator_address_statement
99         |
100         initiator_alias_statement
101         |
102         user_statement
103         |
104         secret_statement
105         |
106         mutual_user_statement
107         |
108         mutual_secret_statement
109         |
110         auth_method_statement
111         |
112         header_digest_statement
113         |
114         data_digest_statement
115         |
116         session_type_statement
117         |
118         protocol_statement
119         |
120         ignored_statement
121         ;
122
123 target_name_statement:  TARGET_NAME EQUALS STR
124         {
125                 if (target->t_name != NULL)
126                         errx(1, "duplicated TargetName at line %d", lineno + 1);
127                 target->t_name = $3;
128         }
129         ;
130
131 target_address_statement:       TARGET_ADDRESS EQUALS STR
132         {
133                 if (target->t_address != NULL)
134                         errx(1, "duplicated TargetAddress at line %d", lineno + 1);
135                 target->t_address = $3;
136         }
137         ;
138
139 initiator_name_statement:       INITIATOR_NAME EQUALS STR
140         {
141                 if (target->t_initiator_name != NULL)
142                         errx(1, "duplicated InitiatorName at line %d", lineno + 1);
143                 target->t_initiator_name = $3;
144         }
145         ;
146
147 initiator_address_statement:    INITIATOR_ADDRESS EQUALS STR
148         {
149                 if (target->t_initiator_address != NULL)
150                         errx(1, "duplicated InitiatorAddress at line %d", lineno + 1);
151                 target->t_initiator_address = $3;
152         }
153         ;
154
155 initiator_alias_statement:      INITIATOR_ALIAS EQUALS STR
156         {
157                 if (target->t_initiator_alias != NULL)
158                         errx(1, "duplicated InitiatorAlias at line %d", lineno + 1);
159                 target->t_initiator_alias = $3;
160         }
161         ;
162
163 user_statement:         USER EQUALS STR
164         {
165                 if (target->t_user != NULL)
166                         errx(1, "duplicated chapIName at line %d", lineno + 1);
167                 target->t_user = $3;
168         }
169         ;
170
171 secret_statement:       SECRET EQUALS STR
172         {
173                 if (target->t_secret != NULL)
174                         errx(1, "duplicated chapSecret at line %d", lineno + 1);
175                 target->t_secret = $3;
176         }
177         ;
178
179 mutual_user_statement:  MUTUAL_USER EQUALS STR
180         {
181                 if (target->t_mutual_user != NULL)
182                         errx(1, "duplicated tgtChapName at line %d", lineno + 1);
183                 target->t_mutual_user = $3;
184         }
185         ;
186
187 mutual_secret_statement:MUTUAL_SECRET EQUALS STR
188         {
189                 if (target->t_mutual_secret != NULL)
190                         errx(1, "duplicated tgtChapSecret at line %d", lineno + 1);
191                 target->t_mutual_secret = $3;
192         }
193         ;
194
195 auth_method_statement:  AUTH_METHOD EQUALS STR
196         {
197                 if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
198                         errx(1, "duplicated AuthMethod at line %d", lineno + 1);
199                 if (strcasecmp($3, "none") == 0)
200                         target->t_auth_method = AUTH_METHOD_NONE;
201                 else if (strcasecmp($3, "chap") == 0)
202                         target->t_auth_method = AUTH_METHOD_CHAP;
203                 else
204                         errx(1, "invalid AuthMethod at line %d; "
205                             "must be either \"none\" or \"CHAP\"", lineno + 1);
206         }
207         ;
208
209 header_digest_statement:        HEADER_DIGEST EQUALS STR
210         {
211                 if (target->t_header_digest != DIGEST_UNSPECIFIED)
212                         errx(1, "duplicated HeaderDigest at line %d", lineno + 1);
213                 if (strcasecmp($3, "none") == 0)
214                         target->t_header_digest = DIGEST_NONE;
215                 else if (strcasecmp($3, "CRC32C") == 0)
216                         target->t_header_digest = DIGEST_CRC32C;
217                 else
218                         errx(1, "invalid HeaderDigest at line %d; "
219                             "must be either \"none\" or \"CRC32C\"", lineno + 1);
220         }
221         ;
222
223 data_digest_statement:  DATA_DIGEST EQUALS STR
224         {
225                 if (target->t_data_digest != DIGEST_UNSPECIFIED)
226                         errx(1, "duplicated DataDigest at line %d", lineno + 1);
227                 if (strcasecmp($3, "none") == 0)
228                         target->t_data_digest = DIGEST_NONE;
229                 else if (strcasecmp($3, "CRC32C") == 0)
230                         target->t_data_digest = DIGEST_CRC32C;
231                 else
232                         errx(1, "invalid DataDigest at line %d; "
233                             "must be either \"none\" or \"CRC32C\"", lineno + 1);
234         }
235         ;
236
237 session_type_statement: SESSION_TYPE EQUALS STR
238         {
239                 if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
240                         errx(1, "duplicated SessionType at line %d", lineno + 1);
241                 if (strcasecmp($3, "normal") == 0)
242                         target->t_session_type = SESSION_TYPE_NORMAL;
243                 else if (strcasecmp($3, "discovery") == 0)
244                         target->t_session_type = SESSION_TYPE_DISCOVERY;
245                 else
246                         errx(1, "invalid SessionType at line %d; "
247                             "must be either \"normal\" or \"discovery\"", lineno + 1);
248         }
249         ;
250
251 protocol_statement:     PROTOCOL EQUALS STR
252         {
253                 if (target->t_protocol != PROTOCOL_UNSPECIFIED)
254                         errx(1, "duplicated protocol at line %d", lineno + 1);
255                 if (strcasecmp($3, "iscsi") == 0)
256                         target->t_protocol = PROTOCOL_ISCSI;
257                 else if (strcasecmp($3, "iser") == 0)
258                         target->t_protocol = PROTOCOL_ISER;
259                 else
260                         errx(1, "invalid protocol at line %d; "
261                             "must be either \"iscsi\" or \"iser\"", lineno + 1);
262         }
263         ;
264
265 ignored_statement: IGNORED EQUALS STR
266         {
267                 warnx("obsolete statement ignored at line %d", lineno + 1);
268         }
269         ;
270
271 %%
272
273 void
274 yyerror(const char *str)
275 {
276
277         errx(1, "error in configuration file at line %d near '%s': %s",
278             lineno + 1, yytext, str);
279 }
280
281 static void
282 check_perms(const char *path)
283 {
284         struct stat sb;
285         int error;
286
287         error = stat(path, &sb);
288         if (error != 0) {
289                 warn("stat");
290                 return;
291         }
292         if (sb.st_mode & S_IWOTH) {
293                 warnx("%s is world-writable", path);
294         } else if (sb.st_mode & S_IROTH) {
295                 warnx("%s is world-readable", path);
296         } else if (sb.st_mode & S_IXOTH) {
297                 /*
298                  * Ok, this one doesn't matter, but still do it,
299                  * just for consistency.
300                  */
301                 warnx("%s is world-executable", path);
302         }
303
304         /*
305          * XXX: Should we also check for owner != 0?
306          */
307 }
308
309 struct conf *
310 conf_new_from_file(const char *path)
311 {
312         int error;
313
314         conf = conf_new();
315         target = target_new(conf);
316
317         yyin = fopen(path, "r");
318         if (yyin == NULL)
319                 err(1, "unable to open configuration file %s", path);
320         check_perms(path);
321         lineno = 0;
322         yyrestart(yyin);
323         error = yyparse();
324         assert(error == 0);
325         fclose(yyin);
326
327         assert(target->t_nickname == NULL);
328         target_delete(target);
329
330         conf_verify(conf);
331
332         return (conf);
333 }