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 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 offload 122 | 123 protocol 124 | 125 ignored 126 ; 127 128 target_name: TARGET_NAME EQUALS STR 129 { 130 if (target->t_name != NULL) 131 xo_errx(1, "duplicated TargetName at line %d", lineno); 132 target->t_name = $3; 133 } 134 ; 135 136 target_address: TARGET_ADDRESS EQUALS STR 137 { 138 if (target->t_address != NULL) 139 xo_errx(1, "duplicated TargetAddress at line %d", lineno); 140 target->t_address = $3; 141 } 142 ; 143 144 initiator_name: INITIATOR_NAME EQUALS STR 145 { 146 if (target->t_initiator_name != NULL) 147 xo_errx(1, "duplicated InitiatorName at line %d", lineno); 148 target->t_initiator_name = $3; 149 } 150 ; 151 152 initiator_address: INITIATOR_ADDRESS EQUALS STR 153 { 154 if (target->t_initiator_address != NULL) 155 xo_errx(1, "duplicated InitiatorAddress at line %d", lineno); 156 target->t_initiator_address = $3; 157 } 158 ; 159 160 initiator_alias: INITIATOR_ALIAS EQUALS STR 161 { 162 if (target->t_initiator_alias != NULL) 163 xo_errx(1, "duplicated InitiatorAlias at line %d", lineno); 164 target->t_initiator_alias = $3; 165 } 166 ; 167 168 user: USER EQUALS STR 169 { 170 if (target->t_user != NULL) 171 xo_errx(1, "duplicated chapIName at line %d", lineno); 172 target->t_user = $3; 173 } 174 ; 175 176 secret: SECRET EQUALS STR 177 { 178 if (target->t_secret != NULL) 179 xo_errx(1, "duplicated chapSecret at line %d", lineno); 180 target->t_secret = $3; 181 } 182 ; 183 184 mutual_user: MUTUAL_USER EQUALS STR 185 { 186 if (target->t_mutual_user != NULL) 187 xo_errx(1, "duplicated tgtChapName at line %d", lineno); 188 target->t_mutual_user = $3; 189 } 190 ; 191 192 mutual_secret: MUTUAL_SECRET EQUALS STR 193 { 194 if (target->t_mutual_secret != NULL) 195 xo_errx(1, "duplicated tgtChapSecret at line %d", lineno); 196 target->t_mutual_secret = $3; 197 } 198 ; 199 200 auth_method: AUTH_METHOD EQUALS STR 201 { 202 if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED) 203 xo_errx(1, "duplicated AuthMethod at line %d", lineno); 204 if (strcasecmp($3, "none") == 0) 205 target->t_auth_method = AUTH_METHOD_NONE; 206 else if (strcasecmp($3, "chap") == 0) 207 target->t_auth_method = AUTH_METHOD_CHAP; 208 else 209 xo_errx(1, "invalid AuthMethod at line %d; " 210 "must be either \"none\" or \"CHAP\"", lineno); 211 } 212 ; 213 214 header_digest: HEADER_DIGEST EQUALS STR 215 { 216 if (target->t_header_digest != DIGEST_UNSPECIFIED) 217 xo_errx(1, "duplicated HeaderDigest at line %d", lineno); 218 if (strcasecmp($3, "none") == 0) 219 target->t_header_digest = DIGEST_NONE; 220 else if (strcasecmp($3, "CRC32C") == 0) 221 target->t_header_digest = DIGEST_CRC32C; 222 else 223 xo_errx(1, "invalid HeaderDigest at line %d; " 224 "must be either \"none\" or \"CRC32C\"", lineno); 225 } 226 ; 227 228 data_digest: DATA_DIGEST EQUALS STR 229 { 230 if (target->t_data_digest != DIGEST_UNSPECIFIED) 231 xo_errx(1, "duplicated DataDigest at line %d", lineno); 232 if (strcasecmp($3, "none") == 0) 233 target->t_data_digest = DIGEST_NONE; 234 else if (strcasecmp($3, "CRC32C") == 0) 235 target->t_data_digest = DIGEST_CRC32C; 236 else 237 xo_errx(1, "invalid DataDigest at line %d; " 238 "must be either \"none\" or \"CRC32C\"", lineno); 239 } 240 ; 241 242 session_type: SESSION_TYPE EQUALS STR 243 { 244 if (target->t_session_type != SESSION_TYPE_UNSPECIFIED) 245 xo_errx(1, "duplicated SessionType at line %d", lineno); 246 if (strcasecmp($3, "normal") == 0) 247 target->t_session_type = SESSION_TYPE_NORMAL; 248 else if (strcasecmp($3, "discovery") == 0) 249 target->t_session_type = SESSION_TYPE_DISCOVERY; 250 else 251 xo_errx(1, "invalid SessionType at line %d; " 252 "must be either \"normal\" or \"discovery\"", lineno); 253 } 254 ; 255 256 offload: OFFLOAD EQUALS STR 257 { 258 if (target->t_offload != NULL) 259 xo_errx(1, "duplicated offload at line %d", lineno); 260 target->t_offload = $3; 261 } 262 ; 263 264 protocol: PROTOCOL EQUALS STR 265 { 266 if (target->t_protocol != PROTOCOL_UNSPECIFIED) 267 xo_errx(1, "duplicated protocol at line %d", lineno); 268 if (strcasecmp($3, "iscsi") == 0) 269 target->t_protocol = PROTOCOL_ISCSI; 270 else if (strcasecmp($3, "iser") == 0) 271 target->t_protocol = PROTOCOL_ISER; 272 else 273 xo_errx(1, "invalid protocol at line %d; " 274 "must be either \"iscsi\" or \"iser\"", lineno); 275 } 276 ; 277 278 ignored: IGNORED EQUALS STR 279 { 280 xo_warnx("obsolete statement ignored at line %d", lineno); 281 } 282 ; 283 284 %% 285 286 void 287 yyerror(const char *str) 288 { 289 290 xo_errx(1, "error in configuration file at line %d near '%s': %s", 291 lineno, yytext, str); 292 } 293 294 static void 295 check_perms(const char *path) 296 { 297 struct stat sb; 298 int error; 299 300 error = stat(path, &sb); 301 if (error != 0) { 302 xo_warn("stat"); 303 return; 304 } 305 if (sb.st_mode & S_IWOTH) { 306 xo_warnx("%s is world-writable", path); 307 } else if (sb.st_mode & S_IROTH) { 308 xo_warnx("%s is world-readable", path); 309 } else if (sb.st_mode & S_IXOTH) { 310 /* 311 * Ok, this one doesn't matter, but still do it, 312 * just for consistency. 313 */ 314 xo_warnx("%s is world-executable", path); 315 } 316 317 /* 318 * XXX: Should we also check for owner != 0? 319 */ 320 } 321 322 struct conf * 323 conf_new_from_file(const char *path) 324 { 325 int error; 326 327 conf = conf_new(); 328 target = target_new(conf); 329 330 yyin = fopen(path, "r"); 331 if (yyin == NULL) 332 xo_err(1, "unable to open configuration file %s", path); 333 check_perms(path); 334 lineno = 1; 335 yyrestart(yyin); 336 error = yyparse(); 337 assert(error == 0); 338 fclose(yyin); 339 340 assert(target->t_nickname == NULL); 341 target_delete(target); 342 343 conf_verify(conf); 344 345 return (conf); 346 } 347