]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/iscsictl/parse.y
Drop "All rights reserved" from all my stuff. This includes
[FreeBSD/FreeBSD.git] / usr.bin / iscsictl / parse.y
1 %{
2 /*-
3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4  *
5  * Copyright (c) 2012 The FreeBSD Foundation
6  *
7  * This software was developed by Edward Tomasz Napierala under sponsorship
8  * from the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
18  *
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
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33
34 #include <sys/queue.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <assert.h>
38 #include <stdio.h>
39 #include <stdint.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include <libxo/xo.h>
44
45 #include "iscsictl.h"
46 #include <netinet/in.h>
47 #include <netinet/ip.h>
48
49 extern FILE *yyin;
50 extern char *yytext;
51 extern int lineno;
52
53 static struct conf *conf;
54 static struct target *target;
55
56 extern void     yyerror(const char *);
57 extern int      yylex(void);
58 extern void     yyrestart(FILE *);
59
60 %}
61
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
68
69 %union
70 {
71         char *str;
72 }
73
74 %token <str> STR
75
76 %%
77
78 targets:
79         |
80         targets target
81         ;
82
83 target:         STR OPENING_BRACKET target_entries CLOSING_BRACKET
84         {
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);
89         }
90         ;
91
92 target_entries:
93         |
94         target_entries target_entry
95         |
96         target_entries target_entry SEMICOLON
97         ;
98
99 target_entry:
100         target_name
101         |
102         target_address
103         |
104         initiator_name
105         |
106         initiator_address
107         |
108         initiator_alias
109         |
110         user
111         |
112         secret
113         |
114         mutual_user
115         |
116         mutual_secret
117         |
118         auth_method
119         |
120         header_digest
121         |
122         data_digest
123         |
124         session_type
125         |
126         enable
127         |
128         offload
129         |
130         protocol
131         |
132         ignored
133         |
134         dscp
135         |
136         pcp
137         ;
138
139 target_name:    TARGET_NAME EQUALS STR
140         {
141                 if (target->t_name != NULL)
142                         xo_errx(1, "duplicated TargetName at line %d", lineno);
143                 target->t_name = $3;
144         }
145         ;
146
147 target_address: TARGET_ADDRESS EQUALS STR
148         {
149                 if (target->t_address != NULL)
150                         xo_errx(1, "duplicated TargetAddress at line %d", lineno);
151                 target->t_address = $3;
152         }
153         ;
154
155 initiator_name: INITIATOR_NAME EQUALS STR
156         {
157                 if (target->t_initiator_name != NULL)
158                         xo_errx(1, "duplicated InitiatorName at line %d", lineno);
159                 target->t_initiator_name = $3;
160         }
161         ;
162
163 initiator_address:      INITIATOR_ADDRESS EQUALS STR
164         {
165                 if (target->t_initiator_address != NULL)
166                         xo_errx(1, "duplicated InitiatorAddress at line %d", lineno);
167                 target->t_initiator_address = $3;
168         }
169         ;
170
171 initiator_alias:        INITIATOR_ALIAS EQUALS STR
172         {
173                 if (target->t_initiator_alias != NULL)
174                         xo_errx(1, "duplicated InitiatorAlias at line %d", lineno);
175                 target->t_initiator_alias = $3;
176         }
177         ;
178
179 user:           USER EQUALS STR
180         {
181                 if (target->t_user != NULL)
182                         xo_errx(1, "duplicated chapIName at line %d", lineno);
183                 target->t_user = $3;
184         }
185         ;
186
187 secret:         SECRET EQUALS STR
188         {
189                 if (target->t_secret != NULL)
190                         xo_errx(1, "duplicated chapSecret at line %d", lineno);
191                 target->t_secret = $3;
192         }
193         ;
194
195 mutual_user:    MUTUAL_USER EQUALS STR
196         {
197                 if (target->t_mutual_user != NULL)
198                         xo_errx(1, "duplicated tgtChapName at line %d", lineno);
199                 target->t_mutual_user = $3;
200         }
201         ;
202
203 mutual_secret:  MUTUAL_SECRET EQUALS STR
204         {
205                 if (target->t_mutual_secret != NULL)
206                         xo_errx(1, "duplicated tgtChapSecret at line %d", lineno);
207                 target->t_mutual_secret = $3;
208         }
209         ;
210
211 auth_method:    AUTH_METHOD EQUALS STR
212         {
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;
219                 else
220                         xo_errx(1, "invalid AuthMethod at line %d; "
221                             "must be either \"none\" or \"CHAP\"", lineno);
222         }
223         ;
224
225 header_digest:  HEADER_DIGEST EQUALS STR
226         {
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;
233                 else
234                         xo_errx(1, "invalid HeaderDigest at line %d; "
235                             "must be either \"none\" or \"CRC32C\"", lineno);
236         }
237         ;
238
239 data_digest:    DATA_DIGEST EQUALS STR
240         {
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;
247                 else
248                         xo_errx(1, "invalid DataDigest at line %d; "
249                             "must be either \"none\" or \"CRC32C\"", lineno);
250         }
251         ;
252
253 session_type:   SESSION_TYPE EQUALS STR
254         {
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;
261                 else
262                         xo_errx(1, "invalid SessionType at line %d; "
263                             "must be either \"normal\" or \"discovery\"", lineno);
264         }
265         ;
266
267 enable:         ENABLE EQUALS STR
268         {
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);
275         }
276         ;
277
278 offload:        OFFLOAD EQUALS STR
279         {
280                 if (target->t_offload != NULL)
281                         xo_errx(1, "duplicated offload at line %d", lineno);
282                 target->t_offload = $3;
283         }
284         ;
285
286 protocol:       PROTOCOL EQUALS STR
287         {
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;
294                 else
295                         xo_errx(1, "invalid protocol at line %d; "
296                             "must be either \"iscsi\" or \"iser\"", lineno);
297         }
298         ;
299
300 ignored:        IGNORED EQUALS STR
301         {
302                 xo_warnx("obsolete statement ignored at line %d", lineno);
303         }
304         ;
305
306 dscp:           DSCP EQUALS STR
307         {
308                 uint64_t tmp;
309
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");
316                         free($3);
317                         return(1);
318                 }
319                 if (tmp >= 0x40) {
320                         yyerror("invalid dscp value");
321                         return(1);
322                 }
323
324                 target->t_dscp = tmp;
325         }
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 ; }
348         ;
349
350 pcp:    PCP EQUALS STR
351         {
352                 uint64_t tmp;
353
354                 if (target->t_pcp != -1)
355                         xo_errx(1, "duplicated pcp at line %d", lineno);
356
357                 if (expand_number($3, &tmp) != 0) {
358                         yyerror("invalid numeric value");
359                         free($3);
360                         return(1);
361                 }
362                 if (!((tmp >=0) && (tmp <= 7))) {
363                         yyerror("invalid pcp value");
364                         return(1);
365                 }
366
367                 target->t_pcp = tmp;
368         }
369         ;
370
371 %%
372
373 void
374 yyerror(const char *str)
375 {
376
377         xo_errx(1, "error in configuration file at line %d near '%s': %s",
378             lineno, yytext, str);
379 }
380
381 static void
382 check_perms(const char *path)
383 {
384         struct stat sb;
385         int error;
386
387         error = stat(path, &sb);
388         if (error != 0) {
389                 xo_warn("stat");
390                 return;
391         }
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) {
397                 /*
398                  * Ok, this one doesn't matter, but still do it,
399                  * just for consistency.
400                  */
401                 xo_warnx("%s is world-executable", path);
402         }
403
404         /*
405          * XXX: Should we also check for owner != 0?
406          */
407 }
408
409 struct conf *
410 conf_new_from_file(const char *path)
411 {
412         int error;
413
414         conf = conf_new();
415         target = target_new(conf);
416
417         yyin = fopen(path, "r");
418         if (yyin == NULL)
419                 xo_err(1, "unable to open configuration file %s", path);
420         check_perms(path);
421         lineno = 1;
422         yyrestart(yyin);
423         error = yyparse();
424         assert(error == 0);
425         fclose(yyin);
426
427         assert(target->t_nickname == NULL);
428         target_delete(target);
429
430         conf_verify(conf);
431
432         return (conf);
433 }