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 <stdio.h> 38 #include <stdint.h> 39 #include <stdlib.h> 40 #include <string.h> 41 42 #include <libxo/xo.h> 43 44 #include "iscsictl.h" 45 46 extern FILE *yyin; 47 extern char *yytext; 48 extern int lineno; 49 50 static struct conf *conf; 51 static struct target *target; 52 53 extern void yyerror(const char *); 54 extern int yylex(void); 55 extern void yyrestart(FILE *); 56 57 %} 58 59 %token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS 60 %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET 61 %token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD 62 %token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET 63 64 %union 65 { 66 char *str; 67 } 68 69 %token <str> STR 70 71 %% 72 73 targets: 74 | 75 targets target 76 ; 77 78 target: STR OPENING_BRACKET target_entries CLOSING_BRACKET 79 { 80 if (target_find(conf, $1) != NULL) 81 xo_errx(1, "duplicated target %s", $1); 82 target->t_nickname = $1; 83 target = target_new(conf); 84 } 85 ; 86 87 target_entries: 88 | 89 target_entries target_entry 90 | 91 target_entries target_entry SEMICOLON 92 ; 93 94 target_entry: 95 target_name 96 | 97 target_address 98 | 99 initiator_name 100 | 101 initiator_address 102 | 103 initiator_alias 104 | 105 user 106 | 107 secret 108 | 109 mutual_user 110 | 111 mutual_secret 112 | 113 auth_method 114 | 115 header_digest 116 | 117 data_digest 118 | 119 session_type 120 | 121 enable 122 | 123 offload 124 | 125 protocol 126 | 127 ignored 128 ; 129 130 target_name: TARGET_NAME EQUALS STR 131 { 132 if (target->t_name != NULL) 133 xo_errx(1, "duplicated TargetName at line %d", lineno); 134 target->t_name = $3; 135 } 136 ; 137 138 target_address: TARGET_ADDRESS EQUALS STR 139 { 140 if (target->t_address != NULL) 141 xo_errx(1, "duplicated TargetAddress at line %d", lineno); 142 target->t_address = $3; 143 } 144 ; 145 146 initiator_name: INITIATOR_NAME EQUALS STR 147 { 148 if (target->t_initiator_name != NULL) 149 xo_errx(1, "duplicated InitiatorName at line %d", lineno); 150 target->t_initiator_name = $3; 151 } 152 ; 153 154 initiator_address: INITIATOR_ADDRESS EQUALS STR 155 { 156 if (target->t_initiator_address != NULL) 157 xo_errx(1, "duplicated InitiatorAddress at line %d", lineno); 158 target->t_initiator_address = $3; 159 } 160 ; 161 162 initiator_alias: INITIATOR_ALIAS EQUALS STR 163 { 164 if (target->t_initiator_alias != NULL) 165 xo_errx(1, "duplicated InitiatorAlias at line %d", lineno); 166 target->t_initiator_alias = $3; 167 } 168 ; 169 170 user: USER EQUALS STR 171 { 172 if (target->t_user != NULL) 173 xo_errx(1, "duplicated chapIName at line %d", lineno); 174 target->t_user = $3; 175 } 176 ; 177 178 secret: SECRET EQUALS STR 179 { 180 if (target->t_secret != NULL) 181 xo_errx(1, "duplicated chapSecret at line %d", lineno); 182 target->t_secret = $3; 183 } 184 ; 185 186 mutual_user: MUTUAL_USER EQUALS STR 187 { 188 if (target->t_mutual_user != NULL) 189 xo_errx(1, "duplicated tgtChapName at line %d", lineno); 190 target->t_mutual_user = $3; 191 } 192 ; 193 194 mutual_secret: MUTUAL_SECRET EQUALS STR 195 { 196 if (target->t_mutual_secret != NULL) 197 xo_errx(1, "duplicated tgtChapSecret at line %d", lineno); 198 target->t_mutual_secret = $3; 199 } 200 ; 201 202 auth_method: AUTH_METHOD EQUALS STR 203 { 204 if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED) 205 xo_errx(1, "duplicated AuthMethod at line %d", lineno); 206 if (strcasecmp($3, "none") == 0) 207 target->t_auth_method = AUTH_METHOD_NONE; 208 else if (strcasecmp($3, "chap") == 0) 209 target->t_auth_method = AUTH_METHOD_CHAP; 210 else 211 xo_errx(1, "invalid AuthMethod at line %d; " 212 "must be either \"none\" or \"CHAP\"", lineno); 213 } 214 ; 215 216 header_digest: HEADER_DIGEST EQUALS STR 217 { 218 if (target->t_header_digest != DIGEST_UNSPECIFIED) 219 xo_errx(1, "duplicated HeaderDigest at line %d", lineno); 220 if (strcasecmp($3, "none") == 0) 221 target->t_header_digest = DIGEST_NONE; 222 else if (strcasecmp($3, "CRC32C") == 0) 223 target->t_header_digest = DIGEST_CRC32C; 224 else 225 xo_errx(1, "invalid HeaderDigest at line %d; " 226 "must be either \"none\" or \"CRC32C\"", lineno); 227 } 228 ; 229 230 data_digest: DATA_DIGEST EQUALS STR 231 { 232 if (target->t_data_digest != DIGEST_UNSPECIFIED) 233 xo_errx(1, "duplicated DataDigest at line %d", lineno); 234 if (strcasecmp($3, "none") == 0) 235 target->t_data_digest = DIGEST_NONE; 236 else if (strcasecmp($3, "CRC32C") == 0) 237 target->t_data_digest = DIGEST_CRC32C; 238 else 239 xo_errx(1, "invalid DataDigest at line %d; " 240 "must be either \"none\" or \"CRC32C\"", lineno); 241 } 242 ; 243 244 session_type: SESSION_TYPE EQUALS STR 245 { 246 if (target->t_session_type != SESSION_TYPE_UNSPECIFIED) 247 xo_errx(1, "duplicated SessionType at line %d", lineno); 248 if (strcasecmp($3, "normal") == 0) 249 target->t_session_type = SESSION_TYPE_NORMAL; 250 else if (strcasecmp($3, "discovery") == 0) 251 target->t_session_type = SESSION_TYPE_DISCOVERY; 252 else 253 xo_errx(1, "invalid SessionType at line %d; " 254 "must be either \"normal\" or \"discovery\"", lineno); 255 } 256 ; 257 258 enable: ENABLE EQUALS STR 259 { 260 if (target->t_enable != ENABLE_UNSPECIFIED) 261 xo_errx(1, "duplicated enable at line %d", lineno); 262 target->t_enable = parse_enable($3); 263 if (target->t_enable == ENABLE_UNSPECIFIED) 264 xo_errx(1, "invalid enable at line %d; " 265 "must be either \"on\" or \"off\"", lineno); 266 } 267 ; 268 269 offload: OFFLOAD EQUALS STR 270 { 271 if (target->t_offload != NULL) 272 xo_errx(1, "duplicated offload at line %d", lineno); 273 target->t_offload = $3; 274 } 275 ; 276 277 protocol: PROTOCOL EQUALS STR 278 { 279 if (target->t_protocol != PROTOCOL_UNSPECIFIED) 280 xo_errx(1, "duplicated protocol at line %d", lineno); 281 if (strcasecmp($3, "iscsi") == 0) 282 target->t_protocol = PROTOCOL_ISCSI; 283 else if (strcasecmp($3, "iser") == 0) 284 target->t_protocol = PROTOCOL_ISER; 285 else 286 xo_errx(1, "invalid protocol at line %d; " 287 "must be either \"iscsi\" or \"iser\"", lineno); 288 } 289 ; 290 291 ignored: IGNORED EQUALS STR 292 { 293 xo_warnx("obsolete statement ignored at line %d", lineno); 294 } 295 ; 296 297 %% 298 299 void 300 yyerror(const char *str) 301 { 302 303 xo_errx(1, "error in configuration file at line %d near '%s': %s", 304 lineno, yytext, str); 305 } 306 307 static void 308 check_perms(const char *path) 309 { 310 struct stat sb; 311 int error; 312 313 error = stat(path, &sb); 314 if (error != 0) { 315 xo_warn("stat"); 316 return; 317 } 318 if (sb.st_mode & S_IWOTH) { 319 xo_warnx("%s is world-writable", path); 320 } else if (sb.st_mode & S_IROTH) { 321 xo_warnx("%s is world-readable", path); 322 } else if (sb.st_mode & S_IXOTH) { 323 /* 324 * Ok, this one doesn't matter, but still do it, 325 * just for consistency. 326 */ 327 xo_warnx("%s is world-executable", path); 328 } 329 330 /* 331 * XXX: Should we also check for owner != 0? 332 */ 333 } 334 335 struct conf * 336 conf_new_from_file(const char *path) 337 { 338 int error; 339 340 conf = conf_new(); 341 target = target_new(conf); 342 343 yyin = fopen(path, "r"); 344 if (yyin == NULL) 345 xo_err(1, "unable to open configuration file %s", path); 346 check_perms(path); 347 lineno = 1; 348 yyrestart(yyin); 349 error = yyparse(); 350 assert(error == 0); 351 fclose(yyin); 352 353 assert(target->t_nickname == NULL); 354 target_delete(target); 355 356 conf_verify(conf); 357 358 return (conf); 359 } 360