1 /*- 2 * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 /* 28 | $Id: config.c,v 2.1 2006/11/12 08:06:51 danny Exp danny $ 29 */ 30 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <time.h> 38 #include <ctype.h> 39 #include <camlib.h> 40 41 #include "iscsi.h" 42 #include "iscontrol.h" 43 44 /* 45 | ints 46 */ 47 #define OPT_port 1 48 #define OPT_tags 2 49 50 #define OPT_maxConnections 3 51 #define OPT_maxRecvDataSegmentLength 4 52 #define OPT_maxXmitDataSegmentLength 5 53 #define OPT_maxBurstLength 6 54 #define OPT_firstBurstLength 7 55 #define OPT_defaultTime2Wait 8 56 #define OPT_defaultTime2Retain 9 57 #define OPT_maxOutstandingR2T 10 58 #define OPT_errorRecoveryLevel 11 59 #define OPT_targetPortalGroupTag 12 60 #define OPT_headerDigest 13 61 #define OPT_dataDigest 14 62 /* 63 | Booleans 64 */ 65 #define OPT_initialR2T 16 66 #define OPT_immediateData 17 67 #define OPT_dataPDUInOrder 18 68 #define OPT_dataSequenceInOrder 19 69 /* 70 | strings 71 */ 72 #define OPT_sessionType 15 73 74 #define OPT_targetAddress 21 75 #define OPT_targetAlias 22 76 #define OPT_targetName 23 77 #define OPT_initiatorName 24 78 #define OPT_initiatorAlias 25 79 #define OPT_authMethod 26 80 81 #define OPT_chapSecret 27 82 #define OPT_chapIName 28 83 #define OPT_chapDigest 29 84 #define OPT_tgtChapName 30 85 #define OPT_tgtChapSecret 31 86 #define OPT_tgtChallengeLen 32 87 /* 88 | private 89 */ 90 #define OPT_maxluns 33 91 #define OPT_iqn 34 92 #define OPT_sockbufsize 35 93 94 #define _OFF(v) (offsetof(isc_opt_t *), (v)) 95 #define _E(u, s, v) {.usage=u, .scope=s, .name=#v, .tokenID=OPT_##v} 96 97 textkey_t keyMap[] = { 98 _E(U_PR, S_PR, port), 99 _E(U_PR, S_PR, tags), 100 _E(U_PR, S_PR, maxluns), 101 _E(U_PR, S_PR, sockbufsize), 102 103 _E(U_PR, S_PR, iqn), 104 _E(U_PR, S_PR, chapSecret), 105 _E(U_PR, S_PR, chapIName), 106 _E(U_PR, S_PR, chapDigest), 107 _E(U_PR, S_PR, tgtChapName), 108 _E(U_PR, S_PR, tgtChapSecret), 109 _E(U_PR, S_PR, tgtChallengeLen), 110 111 _E(U_IO, S_CO, headerDigest), 112 _E(U_IO, S_CO, dataDigest), 113 114 _E(U_IO, S_CO, authMethod), 115 116 _E(U_LO, S_SW, maxConnections), 117 _E(U_IO, S_SW, targetName), 118 119 _E(U_IO, S_SW, initiatorName), 120 _E(U_ALL,S_SW, targetAlias), 121 _E(U_ALL,S_SW, initiatorAlias), 122 _E(U_ALL,S_SW, targetAddress), 123 124 _E(U_ALL,S_SW, targetPortalGroupTag), 125 126 _E(U_LO, S_SW, initialR2T), 127 _E(U_LO, S_SW, immediateData), 128 129 _E(U_ALL,S_CO, maxRecvDataSegmentLength), 130 _E(U_ALL,S_CO, maxXmitDataSegmentLength), 131 132 _E(U_LO, S_SW, maxBurstLength), 133 _E(U_LO, S_SW, firstBurstLength), 134 _E(U_LO, S_SW, defaultTime2Wait), 135 _E(U_LO, S_SW, defaultTime2Retain), 136 137 _E(U_LO, S_SW, maxOutstandingR2T), 138 _E(U_LO, S_SW, dataPDUInOrder), 139 _E(U_LO, S_SW, dataSequenceInOrder), 140 141 _E(U_LO, S_SW, errorRecoveryLevel), 142 143 _E(U_LO, S_SW, sessionType), 144 145 {0, 0, 0, 0} 146 }; 147 148 #define _OPT_INT(w) strtol((char *)w, NULL, 0) 149 #define _OPT_STR(w) (char *)(w) 150 151 static __inline int 152 _OPT_BOOL(char *w) 153 { 154 if(isalpha(*w)) 155 return strcasecmp(w, "TRUE") == 0; 156 else 157 return _OPT_INT(w); 158 } 159 160 #define _CASE(k, v) case OPT_##k: op->k = v; break 161 static void 162 setOption(isc_opt_t *op, int which, void *rval) 163 { 164 switch(which) { 165 _CASE(port, _OPT_INT(rval)); 166 _CASE(tags, _OPT_INT(rval)); 167 _CASE(maxluns, _OPT_INT(rval)); 168 _CASE(iqn, _OPT_STR(rval)); 169 _CASE(sockbufsize, _OPT_INT(rval)); 170 171 _CASE(maxConnections, _OPT_INT(rval)); 172 _CASE(maxRecvDataSegmentLength, _OPT_INT(rval)); 173 _CASE(maxXmitDataSegmentLength, _OPT_INT(rval)); 174 _CASE(maxBurstLength, _OPT_INT(rval)); 175 _CASE(firstBurstLength, _OPT_INT(rval)); 176 _CASE(defaultTime2Wait, _OPT_INT(rval)); 177 _CASE(defaultTime2Retain, _OPT_INT(rval)); 178 _CASE(maxOutstandingR2T, _OPT_INT(rval)); 179 _CASE(errorRecoveryLevel, _OPT_INT(rval)); 180 _CASE(targetPortalGroupTag, _OPT_INT(rval)); 181 _CASE(headerDigest, _OPT_STR(rval)); 182 _CASE(dataDigest, _OPT_STR(rval)); 183 184 _CASE(targetAddress, _OPT_STR(rval)); 185 _CASE(targetAlias, _OPT_STR(rval)); 186 _CASE(targetName, _OPT_STR(rval)); 187 _CASE(initiatorName, _OPT_STR(rval)); 188 _CASE(initiatorAlias, _OPT_STR(rval)); 189 _CASE(authMethod, _OPT_STR(rval)); 190 _CASE(chapSecret, _OPT_STR(rval)); 191 _CASE(chapIName, _OPT_STR(rval)); 192 _CASE(chapDigest, _OPT_STR(rval)); 193 194 _CASE(tgtChapName, _OPT_STR(rval)); 195 _CASE(tgtChapSecret, _OPT_STR(rval)); 196 197 _CASE(initialR2T, _OPT_BOOL(rval)); 198 _CASE(immediateData, _OPT_BOOL(rval)); 199 _CASE(dataPDUInOrder, _OPT_BOOL(rval)); 200 _CASE(dataSequenceInOrder, _OPT_BOOL(rval)); 201 } 202 } 203 204 static char * 205 getline(FILE *fd) 206 { 207 static char *sp, line[BUFSIZ]; 208 char *lp, *p; 209 210 do { 211 if(sp == NULL) 212 sp = fgets(line, sizeof line, fd); 213 214 if((lp = sp) == NULL) 215 break; 216 if((p = strchr(lp, '\n')) != NULL) 217 *p = 0; 218 if((p = strchr(lp, '#')) != NULL) 219 *p = 0; 220 if((p = strchr(lp, ';')) != NULL) { 221 *p++ = 0; 222 sp = p; 223 } else 224 sp = NULL; 225 if(*lp) 226 return lp; 227 } while (feof(fd) == 0); 228 return NULL; 229 } 230 231 static int 232 getConfig(FILE *fd, char *key, char **Ar, int *nargs) 233 { 234 char *lp, *p, **ar; 235 int state, len, n; 236 237 ar = Ar; 238 if(key) 239 len = strlen(key); 240 else 241 len = 0; 242 state = 0; 243 while((lp = getline(fd)) != NULL) { 244 for(; isspace(*lp); lp++) 245 ; 246 switch(state) { 247 case 0: 248 if((p = strchr(lp, '{')) != NULL) { 249 n = 0; 250 while((--p > lp) && *p && isspace(*p)); 251 n = p - lp; 252 if(len && strncmp(lp, key, MAX(n, len)) == 0) 253 state = 2; 254 else 255 state = 1; 256 continue; 257 } 258 break; 259 260 case 1: 261 if(*lp == '}') 262 state = 0; 263 continue; 264 265 case 2: 266 if(*lp == '}') 267 goto done; 268 269 break; 270 } 271 272 273 for(p = &lp[strlen(lp)-1]; isspace(*p); p--) 274 *p = 0; 275 if((*nargs)-- > 0) 276 *ar++ = strdup(lp); 277 } 278 279 done: 280 if(*nargs > 0) 281 *ar = NULL; 282 *nargs = ar - Ar; 283 return ar - Ar; 284 } 285 286 static textkey_t * 287 keyLookup(char *key) 288 { 289 textkey_t *tk; 290 291 for(tk = keyMap; tk->name; tk++) { 292 if(strcasecmp(key, tk->name) == 0) 293 return tk; 294 } 295 return NULL; 296 } 297 298 static void 299 puke(isc_opt_t *op) 300 { 301 printf("%24s = %d\n", "port", op->port); 302 printf("%24s = %d\n", "tags", op->tags); 303 printf("%24s = %d\n", "maxluns", op->maxluns); 304 printf("%24s = %s\n", "iqn", op->iqn); 305 306 printf("%24s = %d\n", "maxConnections", op->maxConnections); 307 printf("%24s = %d\n", "maxRecvDataSegmentLength", op->maxRecvDataSegmentLength); 308 printf("%24s = %d\n", "maxXmitDataSegmentLength", op->maxRecvDataSegmentLength); 309 printf("%24s = %d\n", "maxBurstLength", op->maxBurstLength); 310 printf("%24s = %d\n", "firstBurstLength", op->firstBurstLength); 311 printf("%24s = %d\n", "defaultTime2Wait", op->defaultTime2Wait); 312 printf("%24s = %d\n", "defaultTime2Retain", op->defaultTime2Retain); 313 printf("%24s = %d\n", "maxOutstandingR2T", op->maxOutstandingR2T); 314 printf("%24s = %d\n", "errorRecoveryLevel", op->errorRecoveryLevel); 315 printf("%24s = %d\n", "targetPortalGroupTag", op->targetPortalGroupTag); 316 317 printf("%24s = %s\n", "headerDigest", op->headerDigest); 318 printf("%24s = %s\n", "dataDigest", op->dataDigest); 319 320 printf("%24s = %d\n", "initialR2T", op->initialR2T); 321 printf("%24s = %d\n", "immediateData", op->immediateData); 322 printf("%24s = %d\n", "dataPDUInOrder", op->dataPDUInOrder); 323 printf("%24s = %d\n", "dataSequenceInOrder", op->dataSequenceInOrder); 324 325 printf("%24s = %s\n", "sessionType", op->sessionType); 326 printf("%24s = %s\n", "targetAddress", op->targetAddress); 327 printf("%24s = %s\n", "targetAlias", op->targetAlias); 328 printf("%24s = %s\n", "targetName", op->targetName); 329 printf("%24s = %s\n", "initiatorName", op->initiatorName); 330 printf("%24s = %s\n", "initiatorAlias", op->initiatorAlias); 331 printf("%24s = %s\n", "authMethod", op->authMethod); 332 printf("%24s = %s\n", "chapSecret", op->chapSecret); 333 printf("%24s = %s\n", "chapIName", op->chapIName); 334 printf("%24s = %s\n", "tgtChapName", op->tgtChapName); 335 printf("%24s = %s\n", "tgtChapSecret", op->tgtChapSecret); 336 printf("%24s = %d\n", "tgttgtChallengeLen", op->tgtChallengeLen); 337 } 338 339 void 340 parseArgs(int nargs, char **args, isc_opt_t *op) 341 { 342 char **ar; 343 char *p, *v; 344 textkey_t *tk; 345 346 for(ar = args; nargs > 0; nargs--, ar++) { 347 p = strchr(*ar, '='); 348 if(p == NULL) 349 continue; 350 *p = 0; 351 v = p + 1; 352 while(isspace(*--p)) 353 *p = 0; 354 while(isspace(*v)) 355 v++; 356 if((tk = keyLookup(*ar)) == NULL) 357 continue; 358 setOption(op, tk->tokenID, v); 359 } 360 } 361 362 void 363 parseConfig(FILE *fd, char *key, isc_opt_t *op) 364 { 365 char *Ar[256]; 366 int cc; 367 368 cc = 256; 369 if(getConfig(fd, key, Ar, &cc)) 370 parseArgs(cc, Ar, op); 371 if(vflag) 372 puke(op); 373 } 374