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