]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/iscsictl/parse.y
ident(1): Normalizing date format
[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 void     yyrestart(FILE *);
58
59 %}
60
61 %token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
62 %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
63 %token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
64 %token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET DSCP
65 %token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
66 %token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7
67
68 %union
69 {
70         char *str;
71 }
72
73 %token <str> STR
74
75 %%
76
77 targets:
78         |
79         targets target
80         ;
81
82 target:         STR OPENING_BRACKET target_entries CLOSING_BRACKET
83         {
84                 if (target_find(conf, $1) != NULL)
85                         xo_errx(1, "duplicated target %s", $1);
86                 target->t_nickname = $1;
87                 target = target_new(conf);
88         }
89         ;
90
91 target_entries:
92         |
93         target_entries target_entry
94         |
95         target_entries target_entry SEMICOLON
96         ;
97
98 target_entry:
99         target_name
100         |
101         target_address
102         |
103         initiator_name
104         |
105         initiator_address
106         |
107         initiator_alias
108         |
109         user
110         |
111         secret
112         |
113         mutual_user
114         |
115         mutual_secret
116         |
117         auth_method
118         |
119         header_digest
120         |
121         data_digest
122         |
123         session_type
124         |
125         enable
126         |
127         offload
128         |
129         protocol
130         |
131         ignored
132         |
133         dscp
134         |
135         pcp
136         ;
137
138 target_name:    TARGET_NAME EQUALS STR
139         {
140                 if (target->t_name != NULL)
141                         xo_errx(1, "duplicated TargetName at line %d", lineno);
142                 target->t_name = $3;
143         }
144         ;
145
146 target_address: TARGET_ADDRESS EQUALS STR
147         {
148                 if (target->t_address != NULL)
149                         xo_errx(1, "duplicated TargetAddress at line %d", lineno);
150                 target->t_address = $3;
151         }
152         ;
153
154 initiator_name: INITIATOR_NAME EQUALS STR
155         {
156                 if (target->t_initiator_name != NULL)
157                         xo_errx(1, "duplicated InitiatorName at line %d", lineno);
158                 target->t_initiator_name = $3;
159         }
160         ;
161
162 initiator_address:      INITIATOR_ADDRESS EQUALS STR
163         {
164                 if (target->t_initiator_address != NULL)
165                         xo_errx(1, "duplicated InitiatorAddress at line %d", lineno);
166                 target->t_initiator_address = $3;
167         }
168         ;
169
170 initiator_alias:        INITIATOR_ALIAS EQUALS STR
171         {
172                 if (target->t_initiator_alias != NULL)
173                         xo_errx(1, "duplicated InitiatorAlias at line %d", lineno);
174                 target->t_initiator_alias = $3;
175         }
176         ;
177
178 user:           USER EQUALS STR
179         {
180                 if (target->t_user != NULL)
181                         xo_errx(1, "duplicated chapIName at line %d", lineno);
182                 target->t_user = $3;
183         }
184         ;
185
186 secret:         SECRET EQUALS STR
187         {
188                 if (target->t_secret != NULL)
189                         xo_errx(1, "duplicated chapSecret at line %d", lineno);
190                 target->t_secret = $3;
191         }
192         ;
193
194 mutual_user:    MUTUAL_USER EQUALS STR
195         {
196                 if (target->t_mutual_user != NULL)
197                         xo_errx(1, "duplicated tgtChapName at line %d", lineno);
198                 target->t_mutual_user = $3;
199         }
200         ;
201
202 mutual_secret:  MUTUAL_SECRET EQUALS STR
203         {
204                 if (target->t_mutual_secret != NULL)
205                         xo_errx(1, "duplicated tgtChapSecret at line %d", lineno);
206                 target->t_mutual_secret = $3;
207         }
208         ;
209
210 auth_method:    AUTH_METHOD EQUALS STR
211         {
212                 if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
213                         xo_errx(1, "duplicated AuthMethod at line %d", lineno);
214                 if (strcasecmp($3, "none") == 0)
215                         target->t_auth_method = AUTH_METHOD_NONE;
216                 else if (strcasecmp($3, "chap") == 0)
217                         target->t_auth_method = AUTH_METHOD_CHAP;
218                 else
219                         xo_errx(1, "invalid AuthMethod at line %d; "
220                             "must be either \"none\" or \"CHAP\"", lineno);
221         }
222         ;
223
224 header_digest:  HEADER_DIGEST EQUALS STR
225         {
226                 if (target->t_header_digest != DIGEST_UNSPECIFIED)
227                         xo_errx(1, "duplicated HeaderDigest at line %d", lineno);
228                 if (strcasecmp($3, "none") == 0)
229                         target->t_header_digest = DIGEST_NONE;
230                 else if (strcasecmp($3, "CRC32C") == 0)
231                         target->t_header_digest = DIGEST_CRC32C;
232                 else
233                         xo_errx(1, "invalid HeaderDigest at line %d; "
234                             "must be either \"none\" or \"CRC32C\"", lineno);
235         }
236         ;
237
238 data_digest:    DATA_DIGEST EQUALS STR
239         {
240                 if (target->t_data_digest != DIGEST_UNSPECIFIED)
241                         xo_errx(1, "duplicated DataDigest at line %d", lineno);
242                 if (strcasecmp($3, "none") == 0)
243                         target->t_data_digest = DIGEST_NONE;
244                 else if (strcasecmp($3, "CRC32C") == 0)
245                         target->t_data_digest = DIGEST_CRC32C;
246                 else
247                         xo_errx(1, "invalid DataDigest at line %d; "
248                             "must be either \"none\" or \"CRC32C\"", lineno);
249         }
250         ;
251
252 session_type:   SESSION_TYPE EQUALS STR
253         {
254                 if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
255                         xo_errx(1, "duplicated SessionType at line %d", lineno);
256                 if (strcasecmp($3, "normal") == 0)
257                         target->t_session_type = SESSION_TYPE_NORMAL;
258                 else if (strcasecmp($3, "discovery") == 0)
259                         target->t_session_type = SESSION_TYPE_DISCOVERY;
260                 else
261                         xo_errx(1, "invalid SessionType at line %d; "
262                             "must be either \"normal\" or \"discovery\"", lineno);
263         }
264         ;
265
266 enable:         ENABLE EQUALS STR
267         {
268                 if (target->t_enable != ENABLE_UNSPECIFIED)
269                         xo_errx(1, "duplicated enable at line %d", lineno);
270                 target->t_enable = parse_enable($3);
271                 if (target->t_enable == ENABLE_UNSPECIFIED)
272                         xo_errx(1, "invalid enable at line %d; "
273                             "must be either \"on\" or \"off\"", lineno);
274         }
275         ;
276
277 offload:        OFFLOAD EQUALS STR
278         {
279                 if (target->t_offload != NULL)
280                         xo_errx(1, "duplicated offload at line %d", lineno);
281                 target->t_offload = $3;
282         }
283         ;
284
285 protocol:       PROTOCOL EQUALS STR
286         {
287                 if (target->t_protocol != PROTOCOL_UNSPECIFIED)
288                         xo_errx(1, "duplicated protocol at line %d", lineno);
289                 if (strcasecmp($3, "iscsi") == 0)
290                         target->t_protocol = PROTOCOL_ISCSI;
291                 else if (strcasecmp($3, "iser") == 0)
292                         target->t_protocol = PROTOCOL_ISER;
293                 else
294                         xo_errx(1, "invalid protocol at line %d; "
295                             "must be either \"iscsi\" or \"iser\"", lineno);
296         }
297         ;
298
299 ignored:        IGNORED EQUALS STR
300         {
301                 xo_warnx("obsolete statement ignored at line %d", lineno);
302         }
303         ;
304
305 dscp:           DSCP EQUALS STR
306         {
307                 uint64_t tmp;
308
309                 if (target->t_dscp != -1)
310                         xo_errx(1, "duplicated dscp at line %d", lineno);
311                 if (strcmp($3, "0x") == 0) {
312                         tmp = strtol($3 + 2, NULL, 16);
313                 } else if (expand_number($3, &tmp) != 0) {
314                         yyerror("invalid numeric value");
315                         free($3);
316                         return(1);
317                 }
318                 if (tmp >= 0x40) {
319                         yyerror("invalid dscp value");
320                         return(1);
321                 }
322
323                 target->t_dscp = tmp;
324         }
325         | DSCP EQUALS BE        { target->t_dscp = IPTOS_DSCP_CS0  >> 2 ; }
326         | DSCP EQUALS EF        { target->t_dscp = IPTOS_DSCP_EF   >> 2 ; }
327         | DSCP EQUALS CS0       { target->t_dscp = IPTOS_DSCP_CS0  >> 2 ; }
328         | DSCP EQUALS CS1       { target->t_dscp = IPTOS_DSCP_CS1  >> 2 ; }
329         | DSCP EQUALS CS2       { target->t_dscp = IPTOS_DSCP_CS2  >> 2 ; }
330         | DSCP EQUALS CS3       { target->t_dscp = IPTOS_DSCP_CS3  >> 2 ; }
331         | DSCP EQUALS CS4       { target->t_dscp = IPTOS_DSCP_CS4  >> 2 ; }
332         | DSCP EQUALS CS5       { target->t_dscp = IPTOS_DSCP_CS5  >> 2 ; }
333         | DSCP EQUALS CS6       { target->t_dscp = IPTOS_DSCP_CS6  >> 2 ; }
334         | DSCP EQUALS CS7       { target->t_dscp = IPTOS_DSCP_CS7  >> 2 ; }
335         | DSCP EQUALS AF11      { target->t_dscp = IPTOS_DSCP_AF11 >> 2 ; }
336         | DSCP EQUALS AF12      { target->t_dscp = IPTOS_DSCP_AF12 >> 2 ; }
337         | DSCP EQUALS AF13      { target->t_dscp = IPTOS_DSCP_AF13 >> 2 ; }
338         | DSCP EQUALS AF21      { target->t_dscp = IPTOS_DSCP_AF21 >> 2 ; }
339         | DSCP EQUALS AF22      { target->t_dscp = IPTOS_DSCP_AF22 >> 2 ; }
340         | DSCP EQUALS AF23      { target->t_dscp = IPTOS_DSCP_AF23 >> 2 ; }
341         | DSCP EQUALS AF31      { target->t_dscp = IPTOS_DSCP_AF31 >> 2 ; }
342         | DSCP EQUALS AF32      { target->t_dscp = IPTOS_DSCP_AF32 >> 2 ; }
343         | DSCP EQUALS AF33      { target->t_dscp = IPTOS_DSCP_AF33 >> 2 ; }
344         | DSCP EQUALS AF41      { target->t_dscp = IPTOS_DSCP_AF41 >> 2 ; }
345         | DSCP EQUALS AF42      { target->t_dscp = IPTOS_DSCP_AF42 >> 2 ; }
346         | DSCP EQUALS AF43      { target->t_dscp = IPTOS_DSCP_AF43 >> 2 ; }
347         ;
348
349 pcp:    PCP EQUALS STR
350         {
351                 uint64_t tmp;
352
353                 if (target->t_pcp != -1)
354                         xo_errx(1, "duplicated pcp at line %d", lineno);
355
356                 if (expand_number($3, &tmp) != 0) {
357                         yyerror("invalid numeric value");
358                         free($3);
359                         return(1);
360                 }
361                 if (tmp > 7) {
362                         yyerror("invalid pcp value");
363                         return(1);
364                 }
365
366                 target->t_pcp = tmp;
367         }
368         ;
369
370 %%
371
372 void
373 yyerror(const char *str)
374 {
375
376         xo_errx(1, "error in configuration file at line %d near '%s': %s",
377             lineno, yytext, str);
378 }
379
380 static void
381 check_perms(const char *path)
382 {
383         struct stat sb;
384         int error;
385
386         error = stat(path, &sb);
387         if (error != 0) {
388                 xo_warn("stat");
389                 return;
390         }
391         if (sb.st_mode & S_IWOTH) {
392                 xo_warnx("%s is world-writable", path);
393         } else if (sb.st_mode & S_IROTH) {
394                 xo_warnx("%s is world-readable", path);
395         } else if (sb.st_mode & S_IXOTH) {
396                 /*
397                  * Ok, this one doesn't matter, but still do it,
398                  * just for consistency.
399                  */
400                 xo_warnx("%s is world-executable", path);
401         }
402
403         /*
404          * XXX: Should we also check for owner != 0?
405          */
406 }
407
408 struct conf *
409 conf_new_from_file(const char *path)
410 {
411         int error;
412
413         conf = conf_new();
414         target = target_new(conf);
415
416         yyin = fopen(path, "r");
417         if (yyin == NULL)
418                 xo_err(1, "unable to open configuration file %s", path);
419         check_perms(path);
420         lineno = 1;
421         yyrestart(yyin);
422         error = yyparse();
423         assert(error == 0);
424         fclose(yyin);
425
426         assert(target->t_nickname == NULL);
427         target_delete(target);
428
429         conf_verify(conf);
430
431         return (conf);
432 }