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 __FBSDID("$FreeBSD$"); 32 33 #include <err.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "jailp.h" 38 39 #ifdef DEBUG 40 #define YYDEBUG 1 41 #endif 42 43 static struct cfjail *current_jail; 44 static struct cfjail *global_jail; 45 %} 46 47 %union { 48 struct cfparam *p; 49 struct cfstrings *ss; 50 struct cfstring *s; 51 char *cs; 52 } 53 54 %token PLEQ 55 %token <cs> STR STR1 VAR VAR1 56 57 %type <p> param name 58 %type <ss> value 59 %type <s> string 60 61 %pure-parser 62 63 %lex-param { void *scanner } 64 %parse-param { void *scanner } 65 66 %% 67 68 /* 69 * A config file is a list of jails and parameters. Parameters are 70 * added to the current jail, otherwise to a global pesudo-jail. 71 */ 72 conf : 73 | conf jail 74 | conf param ';' 75 { 76 struct cfjail *j = current_jail; 77 78 if (j == NULL) { 79 if (global_jail == NULL) { 80 global_jail = add_jail(); 81 global_jail->name = estrdup("*"); 82 } 83 j = global_jail; 84 } 85 TAILQ_INSERT_TAIL(&j->params, $2, tq); 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 free($2); 145 } 146 | error 147 ; 148 149 /* 150 * A parameter has a fixed name. A variable definition looks just like a 151 * parameter except that the name is a variable. 152 */ 153 name : STR 154 { 155 $$ = emalloc(sizeof(struct cfparam)); 156 $$->name = $1; 157 TAILQ_INIT(&$$->val); 158 $$->flags = 0; 159 } 160 | VAR 161 { 162 $$ = emalloc(sizeof(struct cfparam)); 163 $$->name = $1; 164 TAILQ_INIT(&$$->val); 165 $$->flags = PF_VAR; 166 } 167 ; 168 169 value : string 170 { 171 $$ = emalloc(sizeof(struct cfstrings)); 172 TAILQ_INIT($$); 173 TAILQ_INSERT_TAIL($$, $1, tq); 174 } 175 | value ',' string 176 { 177 $$ = $1; 178 TAILQ_INSERT_TAIL($$, $3, tq); 179 } 180 ; 181 182 /* 183 * Strings may be passed in pieces, because of quoting and/or variable 184 * interpolation. Reassemble them into a single string. 185 */ 186 string : STR 187 { 188 $$ = emalloc(sizeof(struct cfstring)); 189 $$->s = $1; 190 $$->len = strlen($1); 191 STAILQ_INIT(&$$->vars); 192 } 193 | VAR 194 { 195 struct cfvar *v; 196 197 $$ = emalloc(sizeof(struct cfstring)); 198 $$->s = estrdup(""); 199 $$->len = 0; 200 STAILQ_INIT(&$$->vars); 201 v = emalloc(sizeof(struct cfvar)); 202 v->name = $1; 203 v->pos = 0; 204 STAILQ_INSERT_TAIL(&$$->vars, v, tq); 205 } 206 | string STR1 207 { 208 size_t len1; 209 210 $$ = $1; 211 len1 = strlen($2); 212 $$->s = erealloc($$->s, $$->len + len1 + 1); 213 strcpy($$->s + $$->len, $2); 214 free($2); 215 $$->len += len1; 216 } 217 | string VAR1 218 { 219 struct cfvar *v; 220 221 $$ = $1; 222 v = emalloc(sizeof(struct cfvar)); 223 v->name = $2; 224 v->pos = $$->len; 225 STAILQ_INSERT_TAIL(&$$->vars, v, tq); 226 } 227 ; 228 229 %% 230 231 extern int YYLEX_DECL(); 232 233 extern struct cflex *yyget_extra(void *scanner); 234 extern int yyget_lineno(void *scanner); 235 extern char *yyget_text(void *scanner); 236 237 static void 238 YYERROR_DECL() 239 { 240 if (!yyget_text(scanner)) 241 warnx("%s line %d: %s", 242 yyget_extra(scanner)->cfname, yyget_lineno(scanner), s); 243 else if (!yyget_text(scanner)[0]) 244 warnx("%s: unexpected EOF", 245 yyget_extra(scanner)->cfname); 246 else 247 warnx("%s line %d: %s: %s", 248 yyget_extra(scanner)->cfname, yyget_lineno(scanner), 249 yyget_text(scanner), s); 250 } 251