]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/jail/jailparse.y
snmp_pf: use libpfctl's pfctl_get_rules_info() rather than DIOCGETRULES
[FreeBSD/FreeBSD.git] / usr.sbin / jail / jailparse.y
1 %{
2 /*-
3  * SPDX-License-Identifier: BSD-2-Clause
4  *
5  * Copyright (c) 2011 James Gritton
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 #include <err.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "jailp.h"
36
37 #ifdef DEBUG
38 #define YYDEBUG 1
39 #endif
40
41 static struct cfjail *current_jail;
42 static struct cfjail *global_jail;
43 %}
44
45 %union {
46         struct cfparam          *p;
47         struct cfstrings        *ss;
48         struct cfstring         *s;
49         char                    *cs;
50 }
51
52 %token      PLEQ
53 %token <cs> STR STR1 VAR VAR1
54
55 %type <p>  param name
56 %type <ss> value
57 %type <s>  string
58
59 %pure-parser
60
61 %lex-param { void *scanner }
62 %parse-param { void *scanner }
63
64 %%
65
66 /*
67  * A config file is a list of jails and parameters.  Parameters are
68  * added to the current jail, otherwise to a global pesudo-jail.
69  */
70 conf    :
71         | conf jail
72         | conf param ';'
73         {
74                 if (!special_param($2, scanner)) {
75                         struct cfjail *j = current_jail;
76
77                         if (j == NULL) {
78                                 if (global_jail == NULL) {
79                                         global_jail = add_jail();
80                                         global_jail->name = estrdup("*");
81                                 }
82                                 j = global_jail;
83                         }
84                         TAILQ_INSERT_TAIL(&j->params, $2, tq);
85                 }
86         }
87         | conf ';'
88         ;
89
90 jail    : jail_name '{' conf '}'
91         {
92                 current_jail = current_jail->cfparent;
93         }
94         ;
95
96 jail_name : STR
97         {
98                 struct cfjail *j = add_jail();
99
100                 if (current_jail == NULL)
101                         j->name = $1;
102                 else {
103                         /*
104                          * A nested jail definition becomes
105                          * a hierarchically-named sub-jail.
106                          */
107                         size_t parentlen = strlen(current_jail->name);
108                         j->name = emalloc(parentlen + strlen($1) + 2);
109                         strcpy(j->name, current_jail->name);
110                         j->name[parentlen++] = '.';
111                         strcpy(j->name + parentlen, $1);
112                         free($1);
113                 }
114                 j->cfparent = current_jail;
115                 current_jail = j;
116         }
117         ;
118
119 /*
120  * Parameters have a name and an optional list of value strings,
121  * which may have "+=" or "=" preceding them.
122  */
123 param   : name
124         {
125                 $$ = $1;
126         }
127         | name '=' value
128         {
129                 $$ = $1;
130                 TAILQ_CONCAT(&$$->val, $3, tq);
131                 free($3);
132         }
133         | name PLEQ value
134         {
135                 $$ = $1;
136                 TAILQ_CONCAT(&$$->val, $3, tq);
137                 $$->flags |= PF_APPEND;
138                 free($3);
139         }
140         | name value
141         {
142                 $$ = $1;
143                 TAILQ_CONCAT(&$$->val, $2, tq);
144                 $$->flags |= PF_NAMEVAL;
145                 free($2);
146         }
147         | error
148         ;
149
150 /*
151  * A parameter has a fixed name.  A variable definition looks just like a
152  * parameter except that the name is a variable.
153  */
154 name    : STR
155         {
156                 $$ = emalloc(sizeof(struct cfparam));
157                 $$->name = $1;
158                 TAILQ_INIT(&$$->val);
159                 $$->flags = 0;
160         }
161         | VAR
162         {
163                 $$ = emalloc(sizeof(struct cfparam));
164                 $$->name = $1;
165                 TAILQ_INIT(&$$->val);
166                 $$->flags = PF_VAR;
167         }
168         ;
169
170 value   : string
171         {
172                 $$ = emalloc(sizeof(struct cfstrings));
173                 TAILQ_INIT($$);
174                 TAILQ_INSERT_TAIL($$, $1, tq);
175         }
176         | value ',' string
177         {
178                 $$ = $1;
179                 TAILQ_INSERT_TAIL($$, $3, tq);
180         }
181         ;
182
183 /*
184  * Strings may be passed in pieces, because of quoting and/or variable
185  * interpolation.  Reassemble them into a single string.
186  */
187 string  : STR
188         {
189                 $$ = emalloc(sizeof(struct cfstring));
190                 $$->s = $1;
191                 $$->len = strlen($1);
192                 STAILQ_INIT(&$$->vars);
193         }
194         | VAR
195         {
196                 struct cfvar *v;
197
198                 $$ = emalloc(sizeof(struct cfstring));
199                 $$->s = estrdup("");
200                 $$->len = 0;
201                 STAILQ_INIT(&$$->vars);
202                 v = emalloc(sizeof(struct cfvar));
203                 v->name = $1;
204                 v->pos = 0;
205                 STAILQ_INSERT_TAIL(&$$->vars, v, tq);
206         }
207         | string STR1
208         {
209                 size_t len1;
210
211                 $$ = $1;
212                 len1 = strlen($2);
213                 $$->s = erealloc($$->s, $$->len + len1 + 1);
214                 strcpy($$->s + $$->len, $2);
215                 free($2);
216                 $$->len += len1;
217         }
218         | string VAR1
219         {
220                 struct cfvar *v;
221
222                 $$ = $1;
223                 v = emalloc(sizeof(struct cfvar));
224                 v->name = $2;
225                 v->pos = $$->len;
226                 STAILQ_INSERT_TAIL(&$$->vars, v, tq);
227         }
228         ;
229
230 %%
231
232 extern int YYLEX_DECL();
233
234 static void
235 YYERROR_DECL()
236 {
237         if (!yyget_text(scanner))
238                 warnx("%s line %d: %s",
239                     yyget_extra(scanner)->cfname, yyget_lineno(scanner), s);
240         else if (!yyget_text(scanner)[0])
241                 warnx("%s: unexpected EOF",
242                     yyget_extra(scanner)->cfname);
243         else
244                 warnx("%s line %d: %s: %s",
245                     yyget_extra(scanner)->cfname, yyget_lineno(scanner),
246                     yyget_text(scanner), s);
247 }
248
249 /* Handle special parameters (i.e. the include directive).
250  * Return true if the parameter was specially handled.
251  */
252 static int
253 special_param(struct cfparam *p, void *scanner)
254 {
255         if ((p->flags & (PF_VAR | PF_APPEND | PF_NAMEVAL)) != PF_NAMEVAL
256             || strcmp(p->name, ".include"))
257                 return 0;
258         struct cfstring *s;
259         TAILQ_FOREACH(s, &p->val, tq) {
260                 if (STAILQ_EMPTY(&s->vars))
261                         include_config(scanner, s->s);
262                 else {
263                         warnx("%s line %d: "
264                             "variables not permitted in '.include' filename",
265                             yyget_extra(scanner)->cfname,
266                             yyget_lineno(scanner));
267                         yyget_extra(scanner)->error = 1;
268                 }
269         }
270         free_param_strings(p);
271         free(p);
272         return 1;
273 }