]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - usr.bin/iscsictl/parse.y
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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 SEMICOLON 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 targets:
73         |
74         targets target
75         ;
76
77 target:         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         target_entries target_entry SEMICOLON
91         ;
92
93 target_entry:
94         target_name
95         |
96         target_address
97         |
98         initiator_name
99         |
100         initiator_address
101         |
102         initiator_alias
103         |
104         user
105         |
106         secret
107         |
108         mutual_user
109         |
110         mutual_secret
111         |
112         auth_method
113         |
114         header_digest
115         |
116         data_digest
117         |
118         session_type
119         |
120         protocol
121         |
122         ignored
123         ;
124
125 target_name:    TARGET_NAME EQUALS STR
126         {
127                 if (target->t_name != NULL)
128                         errx(1, "duplicated TargetName at line %d", lineno);
129                 target->t_name = $3;
130         }
131         ;
132
133 target_address: TARGET_ADDRESS EQUALS STR
134         {
135                 if (target->t_address != NULL)
136                         errx(1, "duplicated TargetAddress at line %d", lineno);
137                 target->t_address = $3;
138         }
139         ;
140
141 initiator_name: INITIATOR_NAME EQUALS STR
142         {
143                 if (target->t_initiator_name != NULL)
144                         errx(1, "duplicated InitiatorName at line %d", lineno);
145                 target->t_initiator_name = $3;
146         }
147         ;
148
149 initiator_address:      INITIATOR_ADDRESS EQUALS STR
150         {
151                 if (target->t_initiator_address != NULL)
152                         errx(1, "duplicated InitiatorAddress at line %d", lineno);
153                 target->t_initiator_address = $3;
154         }
155         ;
156
157 initiator_alias:        INITIATOR_ALIAS EQUALS STR
158         {
159                 if (target->t_initiator_alias != NULL)
160                         errx(1, "duplicated InitiatorAlias at line %d", lineno);
161                 target->t_initiator_alias = $3;
162         }
163         ;
164
165 user:           USER EQUALS STR
166         {
167                 if (target->t_user != NULL)
168                         errx(1, "duplicated chapIName at line %d", lineno);
169                 target->t_user = $3;
170         }
171         ;
172
173 secret:         SECRET EQUALS STR
174         {
175                 if (target->t_secret != NULL)
176                         errx(1, "duplicated chapSecret at line %d", lineno);
177                 target->t_secret = $3;
178         }
179         ;
180
181 mutual_user:    MUTUAL_USER EQUALS STR
182         {
183                 if (target->t_mutual_user != NULL)
184                         errx(1, "duplicated tgtChapName at line %d", lineno);
185                 target->t_mutual_user = $3;
186         }
187         ;
188
189 mutual_secret:  MUTUAL_SECRET EQUALS STR
190         {
191                 if (target->t_mutual_secret != NULL)
192                         errx(1, "duplicated tgtChapSecret at line %d", lineno);
193                 target->t_mutual_secret = $3;
194         }
195         ;
196
197 auth_method:    AUTH_METHOD EQUALS STR
198         {
199                 if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
200                         errx(1, "duplicated AuthMethod at line %d", lineno);
201                 if (strcasecmp($3, "none") == 0)
202                         target->t_auth_method = AUTH_METHOD_NONE;
203                 else if (strcasecmp($3, "chap") == 0)
204                         target->t_auth_method = AUTH_METHOD_CHAP;
205                 else
206                         errx(1, "invalid AuthMethod at line %d; "
207                             "must be either \"none\" or \"CHAP\"", lineno);
208         }
209         ;
210
211 header_digest:  HEADER_DIGEST EQUALS STR
212         {
213                 if (target->t_header_digest != DIGEST_UNSPECIFIED)
214                         errx(1, "duplicated HeaderDigest at line %d", lineno);
215                 if (strcasecmp($3, "none") == 0)
216                         target->t_header_digest = DIGEST_NONE;
217                 else if (strcasecmp($3, "CRC32C") == 0)
218                         target->t_header_digest = DIGEST_CRC32C;
219                 else
220                         errx(1, "invalid HeaderDigest at line %d; "
221                             "must be either \"none\" or \"CRC32C\"", lineno);
222         }
223         ;
224
225 data_digest:    DATA_DIGEST EQUALS STR
226         {
227                 if (target->t_data_digest != DIGEST_UNSPECIFIED)
228                         errx(1, "duplicated DataDigest at line %d", lineno);
229                 if (strcasecmp($3, "none") == 0)
230                         target->t_data_digest = DIGEST_NONE;
231                 else if (strcasecmp($3, "CRC32C") == 0)
232                         target->t_data_digest = DIGEST_CRC32C;
233                 else
234                         errx(1, "invalid DataDigest at line %d; "
235                             "must be either \"none\" or \"CRC32C\"", lineno);
236         }
237         ;
238
239 session_type:   SESSION_TYPE EQUALS STR
240         {
241                 if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
242                         errx(1, "duplicated SessionType at line %d", lineno);
243                 if (strcasecmp($3, "normal") == 0)
244                         target->t_session_type = SESSION_TYPE_NORMAL;
245                 else if (strcasecmp($3, "discovery") == 0)
246                         target->t_session_type = SESSION_TYPE_DISCOVERY;
247                 else
248                         errx(1, "invalid SessionType at line %d; "
249                             "must be either \"normal\" or \"discovery\"", lineno);
250         }
251         ;
252
253 protocol:       PROTOCOL EQUALS STR
254         {
255                 if (target->t_protocol != PROTOCOL_UNSPECIFIED)
256                         errx(1, "duplicated protocol at line %d", lineno);
257                 if (strcasecmp($3, "iscsi") == 0)
258                         target->t_protocol = PROTOCOL_ISCSI;
259                 else if (strcasecmp($3, "iser") == 0)
260                         target->t_protocol = PROTOCOL_ISER;
261                 else
262                         errx(1, "invalid protocol at line %d; "
263                             "must be either \"iscsi\" or \"iser\"", lineno);
264         }
265         ;
266
267 ignored:        IGNORED EQUALS STR
268         {
269                 warnx("obsolete statement ignored at line %d", lineno);
270         }
271         ;
272
273 %%
274
275 void
276 yyerror(const char *str)
277 {
278
279         errx(1, "error in configuration file at line %d near '%s': %s",
280             lineno, yytext, str);
281 }
282
283 static void
284 check_perms(const char *path)
285 {
286         struct stat sb;
287         int error;
288
289         error = stat(path, &sb);
290         if (error != 0) {
291                 warn("stat");
292                 return;
293         }
294         if (sb.st_mode & S_IWOTH) {
295                 warnx("%s is world-writable", path);
296         } else if (sb.st_mode & S_IROTH) {
297                 warnx("%s is world-readable", path);
298         } else if (sb.st_mode & S_IXOTH) {
299                 /*
300                  * Ok, this one doesn't matter, but still do it,
301                  * just for consistency.
302                  */
303                 warnx("%s is world-executable", path);
304         }
305
306         /*
307          * XXX: Should we also check for owner != 0?
308          */
309 }
310
311 struct conf *
312 conf_new_from_file(const char *path)
313 {
314         int error;
315
316         conf = conf_new();
317         target = target_new(conf);
318
319         yyin = fopen(path, "r");
320         if (yyin == NULL)
321                 err(1, "unable to open configuration file %s", path);
322         check_perms(path);
323         lineno = 1;
324         yyrestart(yyin);
325         error = yyparse();
326         assert(error == 0);
327         fclose(yyin);
328
329         assert(target->t_nickname == NULL);
330         target_delete(target);
331
332         conf_verify(conf);
333
334         return (conf);
335 }